Archipelago/worlds/smw/Aesthetics.py

1075 lines
71 KiB
Python
Raw Normal View History

SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
import json
import pkgutil
from worlds.AutoWorld import World
tileset_names = [
"grass_hills",
"grass_forest",
"grass_rocks",
"grass_clouds",
"grass_mountains",
"cave",
"cave_rocks",
"water",
"mushroom_rocks",
"mushroom_clouds",
"mushroom_forest",
"mushroom_hills",
"mushroom_stars",
"mushroom_cave",
"forest",
"logs",
"clouds",
"castle_pillars",
"castle_windows",
"castle_wall",
"castle_small_windows",
"ghost_house",
"ghost_house_exit",
"ship_exterior",
"ship_interior",
"switch_palace",
"yoshi_house"
]
map_names = [
"main",
"yoshi",
"vanilla",
"forest",
"valley",
"special",
"star"
]
level_palette_index = [
0xFF,0x03,0x09,0x01,0x15,0x0A,0x04,0x12,0x19,0x06,0x07,0x12,0x09,0x0F,0x13,0x09, # Levels 000-00F
0x03,0x07,0xFF,0x15,0x19,0x04,0x04,0xFF,0x17,0xFF,0x14,0x12,0x02,0x05,0xFF,0x11, # Levels 010-01F
0x12,0x15,0x04,0x02,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 020-02F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 030-03F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 040-04F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 050-05F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 060-06F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 070-07F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 080-08F
0xFF,0xFF,0xFF,0x12,0x12,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 090-09F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 0A0-0AF
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x19,0x08,0x09, # Levels 0B0-0BF
0x02,0x08,0x05,0x04,0x16,0x1A,0x04,0x02,0x0C,0x19,0x19,0x09,0xFF,0x02,0x02,0x02, # Levels 0C0-0CF
0x04,0x04,0x05,0x12,0x14,0xFF,0x12,0x10,0x05,0xFF,0x19,0x12,0x14,0x0F,0x15,0xFF, # Levels 0D0-0DF
0x12,0x12,0xFF,0x04,0x15,0xFF,0x19,0x14,0x12,0x05,0x05,0x16,0x15,0x15,0x15,0x12, # Levels 0E0-0EF
0x16,0x15,0x15,0x09,0x19,0x04,0x04,0x13,0x18,0x15,0x15,0x16,0x15,0x19,0x15,0x04, # Levels 0F0-0FF
0xFF,0x11,0x08,0x02,0x1A,0x00,0x01,0x15,0xFF,0x05,0x05,0x05,0xFF,0x11,0x12,0x05, # Levels 100-10F
0x12,0x14,0xFF,0x0D,0x15,0x06,0x05,0x05,0x05,0x0C,0x05,0x19,0x12,0x15,0x0E,0x01, # Levels 110-11F
0x07,0x19,0x0E,0x0E,0xFF,0x04,0x0E,0x02,0x02,0xFF,0x09,0x04,0x0B,0x02,0xFF,0xFF, # Levels 120-12F
0x07,0xFF,0x0C,0xFF,0x05,0x0C,0x0C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 130-13F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 140-14F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 150-15F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 160-16F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 170-17F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 180-18F
0xFF,0xFF,0xFF,0x12,0x12,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 190-19F
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, # Levels 1A0-1AF
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x19,0x19,0x12,0x02,0x05, # Levels 1B0-1BF
0x02,0x07,0x05,0x05,0x03,0x03,0x00,0xFF,0x0F,0x10,0x05,0x05,0x12,0x11,0x14,0x14, # Levels 1C0-1CF
0x11,0x12,0x12,0x12,0x11,0x03,0x03,0x19,0x19,0x15,0x16,0x15,0x15,0x15,0xFF,0x05, # Levels 1D0-1DF
0x10,0x02,0x06,0x06,0x19,0x05,0x16,0x16,0x15,0x15,0x15,0xFF,0x06,0x05,0x05,0x06, # Levels 1E0-1EF
0x05,0x05,0x12,0x14,0x12,0x05,0xFF,0x19,0x05,0x16,0x15,0x15,0x11,0x05,0x12,0x09 # Levels 1F0-1FF
]
mario_palettes = [
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0x1F, 0x39, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0xB6, 0x30, 0xDF, 0x35, 0xFF, 0x03], # Mario
[0x3F, 0x4F, 0x1D, 0x58, 0x40, 0x11, 0xE0, 0x3F, 0x07, 0x3C, 0xAE, 0x7C, 0xB3, 0x7D, 0x00, 0x2F, 0x5F, 0x16, 0xFF, 0x03], # Luigi
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0x1F, 0x03, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x16, 0x02, 0xDF, 0x35, 0xFF, 0x03], # Wario
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0x12, 0x7C, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x0D, 0x58, 0xDF, 0x35, 0xFF, 0x03], # Waluigi
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0x00, 0x7C, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x00, 0x58, 0xDF, 0x35, 0xFF, 0x03], # Geno
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0x1F, 0x7C, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x16, 0x58, 0xDF, 0x35, 0xFF, 0x03], # Princess
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0xE0, 0x00, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x80, 0x00, 0xDF, 0x35, 0xFF, 0x03], # Dark
[0x5F, 0x63, 0x1D, 0x58, 0x0A, 0x00, 0xFF, 0x01, 0xC4, 0x44, 0x08, 0x4E, 0x70, 0x67, 0x5F, 0x01, 0xDF, 0x35, 0xFF, 0x03], # Sponge
]
fire_mario_palettes = [
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x17, 0x00, 0x1F, 0x00, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Mario
[0x1F, 0x3B, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x40, 0x11, 0xE0, 0x01, 0xE0, 0x02, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Luigi
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x16, 0x02, 0x1F, 0x03, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Wario
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x0D, 0x58, 0x12, 0x7C, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Waluigi
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x00, 0x58, 0x00, 0x7C, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Geno
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x16, 0x58, 0x1F, 0x7C, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Princess
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x80, 0x00, 0xE0, 0x00, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Dark
[0x5F, 0x63, 0x1D, 0x58, 0x29, 0x25, 0xFF, 0x7F, 0x08, 0x00, 0x5F, 0x01, 0xFF, 0x01, 0x7B, 0x57, 0xDF, 0x0D, 0xFF, 0x03], # Sponge
]
ow_mario_palettes = [
[0x16, 0x00, 0x1F, 0x00], # Mario
[0x80, 0x02, 0xE0, 0x03], # Luigi
[0x16, 0x02, 0x1F, 0x03], # Wario
[0x0D, 0x58, 0x12, 0x7C], # Waluigi
[0x00, 0x58, 0x00, 0x7C], # Geno
[0x16, 0x58, 0x1F, 0x7C], # Princess
[0x80, 0x00, 0xE0, 0x00], # Dark
[0x5F, 0x01, 0xFF, 0x01], # Sponge
]
level_music_address_data = [
0x284DB,
0x284DC,
0x284DD,
0x284DE,
0x284DF,
0x284E0,
0x284E1,
0x284E2,
]
level_music_value_data = [
0x02,
0x06,
0x01,
0x08,
0x07,
0x03,
0x05,
0x12,
]
ow_music_address_data = [
[0x25BC8, 0x20D8A],
[0x25BC9, 0x20D8B],
[0x25BCA, 0x20D8C],
[0x25BCB, 0x20D8D],
[0x25BCC, 0x20D8E],
[0x25BCD, 0x20D8F],
[0x25BCE, 0x20D90],
[0x16C7]
]
ow_music_value_data = [
0x02,
0x03,
0x04,
0x06,
0x07,
0x09,
0x05,
0x01,
]
valid_foreground_palettes = {
0x00: [0x00, 0x01, 0x03, 0x04, 0x05, 0x07], # Normal 1
0x01: [0x03, 0x04, 0x05, 0x07], # Castle 1
0x02: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Rope 1
0x03: [0x02, 0x03, 0x04, 0x05, 0x07], # Underground 1
0x04: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Switch Palace 1
0x05: [0x04, 0x05], # Ghost House 1
0x06: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Rope 2
0x07: [0x00, 0x01, 0x03, 0x04, 0x05, 0x07], # Normal 2
0x08: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Rope 3
0x09: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Underground 2
0x0A: [0x01, 0x02, 0x03, 0x04, 0x05, 0x07], # Switch Palace 2
0x0B: [0x03, 0x04, 0x05, 0x07], # Castle 2
#0x0C: [], # Cloud/Forest
0x0D: [0x04, 0x05], # Ghost House 2
0x0E: [0x02, 0x03, 0x04, 0x05, 0x07], # Underground 3
}
valid_background_palettes = {
0x06861B: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Ghost House Exit
0xFFD900: [0x01], # P. Hills
0xFFDAB9: [0x04], # Water
0xFFDC71: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Hills & Clouds
0xFFDD44: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Clouds
0xFFDE54: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Small Hills
0xFFDF59: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Mountains & Clouds
0xFFE103: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Castle Pillars
0xFFE472: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Big Hills
0xFFE674: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Bonus
0xFFE684: [0x01, 0x03, 0x05, 0x06], # Stars
0xFFE7C0: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07], # Mountains
0xFFE8EE: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Empty/Layer 2
0xFFE8FE: [0x01, 0x06], # Cave
0xFFEC82: [0x00, 0x02, 0x03, 0x05, 0x06, 0x07], # Bushes
0xFFEF80: [0x01, 0x03, 0x05, 0x06], # Ghost House
0xFFF175: [0x00, 0x01, 0x02, 0x03, 0x05, 0x06], # Ghost Ship
0xFFF45A: [0x01, 0x03, 0x06], # Castle
}
valid_background_colors = {
0x06861B: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Ghost House Exit
0xFFD900: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # P. Hills
0xFFDAB9: [0x02, 0x03, 0x05], # Water
0xFFDC71: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Hills & Clouds
0xFFDD44: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Clouds
0xFFDE54: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Small Hills
0xFFDF59: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Mountains & Clouds
0xFFE103: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Castle Pillars
0xFFE472: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Big Hills
0xFFE674: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Bonus
0xFFE684: [0x02, 0x03, 0x04, 0x05], # Stars
0xFFE7C0: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Mountains
0xFFE8EE: [0x03, 0x05], # Empty/Layer 2
0xFFE8FE: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Cave
0xFFEC82: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Bushes
0xFFEF80: [0x03, 0x04], # Ghost House
0xFFF175: [0x02, 0x03, 0x04, 0x05], # Ghost Ship
0xFFF45A: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Castle
}
valid_ow_palettes = {
0x2D1E: [0x00, 0x01, 0x03], # Main OW
0x2D1F: [0x00, 0x03, 0x04], # Yoshi's Island
0x2D20: [0x00, 0x01, 0x03, 0x04], # Vanilla Dome
0x2D21: [0x00, 0x02, 0x03, 0x04], # Forest of Illusion
0x2D22: [0x00, 0x01, 0x03, 0x04], # Valley of Bowser
0x2D24: [0x00, 0x02, 0x03], # Star Road
}
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
valid_sfxs = [
[0x01, 1], # Jump
[0x01, 0], # Hit head
[0x02, 0], # Contact/Spinjump on an enemy
[0x03, 0], # Kick item
[0x04, 0], # Go in pipe, get hurt
[0x05, 0], # Midway point
[0x06, 0], # Yoshi gulp
[0x07, 0], # Dry bones collapse
[0x08, 0], # Kill enemy with a spin jump
[0x09, 0], # Fly with cape
[0x0A, 0], # Get powerup
[0x0B, 0], # ON/OFF switch
[0x0C, 0], # Carry item past the goal
[0x0D, 0], # Get cape
[0x0E, 0], # Swim
[0x0F, 0], # Hurt while flying
[0x10, 0], # Magikoopa shoot magic
[0x13, 0], # Enemy stomp #1
[0x14, 0], # Enemy stomp #2
[0x15, 0], # Enemy stomp #3
[0x16, 0], # Enemy stomp #4
[0x17, 0], # Enemy stomp #5
[0x18, 0], # Enemy stomp #6
[0x19, 0], # Enemy stomp #7
[0x1C, 0], # Yoshi Coin
[0x1E, 0], # P-Balloon
[0x1F, 0], # Koopaling defeated
[0x20, 0], # Yoshi spit
[0x23, 0], # Lemmy/Wendy falling
[0x25, 0], # Blargg roar
[0x26, 0], # Firework whistle
[0x27, 0], # Firework bang
[0x2A, 0], # Peach pops up from the Clown Car
[0x04, 1], # Grinder
[0x01, 3], # Coin
[0x02, 3], # Hit a ? block
[0x03, 3], # Hit a block with a vine inside
[0x04, 3], # Spin jump
[0x05, 3], # 1up
[0x06, 3], # Shatter block
[0x07, 3], # Shoot fireball
[0x08, 3], # Springboard
[0x09, 3], # Bullet bill
[0x0A, 3], # Egg hatch
[0x0B, 3], # Item going into item box
[0x0C, 3], # Item falls from item box
[0x0E, 3], # L/R scroll
[0x0F, 3], # Door
[0x13, 3], # Lose Yoshi
[0x14, 3], # SMW2: New level available
[0x15, 3], # OW tile reveal
[0x16, 3], # OW castle collapse
[0x17, 3], # Fire spit
[0x18, 3], # Thunder
[0x19, 3], # Clap
[0x1A, 3], # Castle bomb
[0x1C, 3], # OW switch palace block ejection
[0x1E, 3], # Whistle
[0x1F, 3], # Yoshi mount
[0x20, 3], # Lemmy/Wendy going in lava
[0x21, 3], # Yoshi's tongue
[0x22, 3], # Message box hit
[0x23, 3], # Landing in a level tile
[0x24, 3], # P-Switch running out
[0x25, 3], # Yoshi defeats an enemy
[0x26, 3], # Swooper
[0x27, 3], # Podoboo
[0x28, 3], # Enemy hurt
[0x29, 3], # Correct
[0x2A, 3], # Wrong
[0x2B, 3], # Firework whistle
[0x2C, 3] # Firework bang
]
game_sfx_calls = [
0x0565E, # Jump
0x1BABD, # Spin jump
0x06D41, # Hit head on ceiling
0x0B4F2, # Hit head on sprite
0x07EB5, # Shooting a fireball
0x0507B, # Cape spin
0x058A8, # Cape smash
0x075F3, # Taking damage
0x075E2, # Taking damage while flying
0x07919, # Something during a boss fight
0x05AA9, # Swim
0x1BC04, # Spin jump off water
0x05BA5, # Jump off a net
0x05BB2, # Punching a net
0x06C10, # Entering a door
0x05254, # Entering a pipe #1
0x07439, # Entering a pipe #2
0x052A5, # Shot from a diagonal pipe
0x072E8, # Hit a midway point
0x07236, # Hit a wrong block
0x07B7D, # Spawn a powerup during the goal tape
0x1C342, # Invisible mushroom spawn
0x04E3F, # Scrolling the screen with L/R
0x0AAFD, # Pressing a P-Switch
0x04557, # P-Switch running out
0x0BAD7, # Climbing door turning
0x0C109, # Break goal tape
0x0C548, # Putting item in item box
0x10012, # Trigger item box
0x2B34D, # Collecting a coin
0x07358, # Collecting a Yoshi Coin
0x0C57A, # Collecting a powerup (generic)
0x0C59C, # Collecting a feather
0x0C309, # Collecting a P-Balloon
0x0E6A9, # Bouncing off a springboard
0x1117D, # Bouncing off a note block
0x14DEC, # Bouncing off a wall springboard
0x1067F, # Block shattering
0x1081E, # Activate ON/OFF switch #1
0x1118C, # Activate ON/OFF switch #2
0x12045, # Fireballs hitting a block/sprite
0x12124, # Fireballs converting an enemy into a coin
0x12106, # Fireballs defeating a Chuck
0x18D7D, # Activating a message box
0x1C209, # Activating a red question block
0x0A290, # Baby Yoshi swallowing an item #1
0x1C037, # Baby Yoshi swallowing an item #2
0x0F756, # Yoshi egg hatching
0x0A2C5, # Yoshi growing #1
0x1C06C, # Yoshi growing #2
0x0ED5F, # Mounting Yoshi
0x0F71D, # Yoshi hurt
0x12481, # Yoshi hurt (projectiles)
0x0EF0E, # Yoshi flying
0x06F90, # Yoshi stomping an enemy
0x06FB6, # Yoshi ground pound (yellow shell)
0x07024, # Yoshi bounces off a triangle
0x11BE9, # Yoshi stomping the ground
0x0F0D3, # Yoshi swallowing a sprite
0x0F0FD, # Yoshi eating a green berry
0x1BA7D, # Yoshi sticking out tongue
0x0F5A1, # Yoshi unable to eat
0x0F2DF, # Yoshi spitting out an item
0x0F28F, # Yoshi spitting out flames
0x0F3EC, # Collecting Yoshi's wings (eaten)
0x0F6C8, # Collecting Yoshi's wings (touched)
0x7FE04, # Defeated sprite combo #1 (using Y index)
0x7FE0E, # Defeated sprite combo #2 (using Y index)
0x7FE18, # Defeated sprite combo #3 (using Y index)
0x7FE22, # Defeated sprite combo #4 (using Y index)
0x7FE2C, # Defeated sprite combo #5 (using Y index)
0x7FE36, # Defeated sprite combo #6 (using Y index)
0x7FE40, # Defeated sprite combo #7 (using Y index)
0x7FE4B, # Defeated sprite combo #1 (using X index)
0x7FE55, # Defeated sprite combo #2 (using X index)
0x7FE5F, # Defeated sprite combo #3 (using X index)
0x7FE69, # Defeated sprite combo #4 (using X index)
0x7FE73, # Defeated sprite combo #5 (using X index)
0x7FE7D, # Defeated sprite combo #6 (using X index)
0x7FE87, # Defeated sprite combo #7 (using X index)
0x0A728, # Kicking a carryable item
0x0B12F, # Kicking a stunned and vulnerable enemy
0x0A8D8, # Performing a spinjump on a immune enemy
0x0A93F, # Defeating an enemy via spinjump
0x0999E, # Thrown sprite hitting the ground from the side
0x192B8, # Creating/Eating block moving
0x195EC, # Rex stomped
0x134A7, # Bullet bill blaster shooting
0x13088, # Bullet bill generator #1
0x130DF, # Bullet bill generator #2
0x09631, # Bob-omb explosion
0x15918, # Popping a bubble
0x15D64, # Sumo bro stomping the ground
0x15ECC, # Sumo bro lightning spawning flames
0x1726B, # Bouncing off wiggler
0x08390, # Banzai bill spawn
0x0AF17, # Thwomp hitting the ground
0x0AFFC, # Thwimp hitting the ground
0x14707, # Chuck running
0x14381, # Chuck whistling
0x144F8, # Chuck clapping
0x14536, # Chuck jumping
0x145AE, # Chuck splitting
0x147D2, # Chuck bounce
0x147F6, # Chuck hurt
0x147B8, # Chuck defeated
0x19D55, # Dino torch shooting fire
0x19FFA, # Blargg attacking
0x188FF, # Swooper bat swooping
0x08584, # Bowser statue flame spawn
0x18ADA, # Bowser statue shooting a flame
0x13043, # Bowser statue flame from generator
0x0BF28, # Magikoopa shooting a magic spell
0x0BC5F, # Magikoopa's magic spell hitting the ground
0x0D745, # Line guided sprites' motor
0x0DB70, # Grinder sound
0x0E0A1, # Podoboo jumping
0x0E5F2, # Dry bones/Bony beetle collapsing
0x15474, # Giant wooden pillar hitting the ground
0x2C9C1, # Spiked columns hitting the ground
0x19B03, # Reznor shooting a fireball
0x19A66, # Reznor: Hitting a platform
0x1D752, # Reznor: Bridge collapsing
0x19ABB, # Reznor: Defeated
0x180E9, # Big Boo: Reappearing
0x18233, # Big Boo: Hurt
0x181DE, # Big Boo: Defeated
0x1CEC1, # Wendy/Lemmy: Hitting a dummy
0x1CECB, # Wendy/Lemmy: Hurt
0x1CE33, # Wendy/Lemmy: Hurt (correct)
0x1CE46, # Wendy/Lemmy: Hurt (incorrect)
0x1CE24, # Wendy/Lemmy: Defeated
0x1CE7E, # Wendy/Lemmy: Falling into lava
0x0CF0A, # Ludwig: Jumping
0x0D059, # Ludwig: Shooting a fireball
0x10414, # Morton/Roy: Pillar drop
0x0D299, # Morton/Roy: Ground smash
0x0D3AB, # Morton/Roy/Ludwig: Hit by a fireball
0x0D2FD, # Morton/Roy/Ludwig: Bouncing off
0x0D31E, # Morton/Roy/Ludwig: Bouncing off (immune)
0x0D334, # Morton/Roy/Ludwig: Bouncing off (immune, going up a wall)
0x0CFD0, # Morton/Roy/Ludwig: Defeated
0x0FCCE, # Iggy/Larry: Being hit
0x0FD40, # Iggy/Larry: Being hit by a fireball
0x0FB60, # Iggy/Larry: Falling in lava
0x1A8B2, # Peach emerging from Clown Car
0x1A8E3, # Peach throwing an item
0x1B0B8, # Bumping into Clown Car
0x1B129, # Bowser: Hurt
0x1AB8C, # Bowser: Slamming the ground (third phase)
0x1A5D0, # Bowser: Throwing a Mechakoopa
0x1A603, # Bowser: Dropping a ball
0x1A7F6, # Bowser: Spawning a flame
0x1B1A3, # Bowser's ball slam #1
0x1B1B1, # Bowser's ball slam #2
0x1E016, # Bowser's arena lightning effect
0x26CAA, # Map: Level tile reveal
0x26763, # Map: Terrain reveal
0x21170, # Map: Using a star
0x2666F, # Map: Castle destruction
0x272A4, # Map: Switch palace blocks spawning
0x203CC, # Map: Earthquake
0x27A78, # Map: Fish jumping
0x27736, # Map: Valley of bowser thunder
0x013C0, # Menu: Nintendo presents
0x01AE3, # Menu: File menu option select
0x01AF9, # Menu: File menu option change
0x01BBB, # Menu: Saving game
0x273FF, # Menu: Map misc menu appearing
0x27567, # Menu: Something during the map
0x1767A, # Cutscene: Castle door opening
0x17683, # Cutscene: Castle door closing
0x17765, # Cutscene: Ghost house door opening
0x1776E, # Cutscene: Ghost house door closing
0x04720, # Cutscene: Detonator fuse
0x04732, # Cutscene: Bouncing off something
0x0475F, # Cutscene: Tossing the castle
0x04798, # Cutscene: Picking up the castle
0x047AC, # Cutscene: Huff
0x047D1, # Cutscene: Hitting a castle
0x1C830, # Cutscene: Shooting a firework
0x625AF, # Cutscene: Egg shattering
0x64F2C, # Cutscene: Hitting a hill
0x6512A, # Cutscene: Castle crashing
0x65295, # Cutscene: Explosion
0x652B2, # Cutscene: Castle sinking
0x652BD, # Cutscene: Castle flying
0x652D8, # Cutscene: Fake explosion
0x653E7, # Cutscene: Castle being hit by a hammer
0x657D8 # Cutscene: Castle being mopped away
]
def generate_shuffled_sfx(rom, world: World):
# Adjust "hitting sprites in succession" codes
rom.write_bytes(0x0A60B, bytearray([0x22, 0x00, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE00 : nop #2 # Thrown sprites combo #1
rom.write_bytes(0x0A659, bytearray([0x22, 0x47, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE47 : nop #2 # Thrown sprites combo #2
rom.write_bytes(0x0A865, bytearray([0x22, 0x47, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE47 : nop #2 # Star combo
rom.write_bytes(0x0AB57, bytearray([0x22, 0x00, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE00 : nop #2 # Bouncing off enemies
rom.write_bytes(0x172C0, bytearray([0x22, 0x00, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE00 : nop #2 # Star combo (wigglers)
rom.write_bytes(0x1961D, bytearray([0x22, 0x00, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE00 : nop #2 # Star combo (rexes)
rom.write_bytes(0x19639, bytearray([0x22, 0x00, 0xFE, 0x0F, 0xEA, 0xEA])) # jsl $0FFE00 : nop #2 # Bouncing off rexes
COMBO_SFX_ADDR = 0x7FE00
rom.write_bytes(COMBO_SFX_ADDR + 0x0000, bytearray([0xC0, 0x01])) # COMBO_Y: CPY #$01
rom.write_bytes(COMBO_SFX_ADDR + 0x0002, bytearray([0xD0, 0x06])) # BNE label_0FFE0A
rom.write_bytes(COMBO_SFX_ADDR + 0x0004, bytearray([0xA9, 0x13])) # LDA #$13
rom.write_bytes(COMBO_SFX_ADDR + 0x0006, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0009, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x000A, bytearray([0xC0, 0x02])) # label_0FFE0A: CPY #$02
rom.write_bytes(COMBO_SFX_ADDR + 0x000C, bytearray([0xD0, 0x06])) # BNE label_0FFE14
rom.write_bytes(COMBO_SFX_ADDR + 0x000E, bytearray([0xA9, 0x14])) # LDA #$14
rom.write_bytes(COMBO_SFX_ADDR + 0x0010, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0013, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0014, bytearray([0xC0, 0x03])) # label_0FFE14: CPY #$03
rom.write_bytes(COMBO_SFX_ADDR + 0x0016, bytearray([0xD0, 0x06])) # BNE label_0FFE1E
rom.write_bytes(COMBO_SFX_ADDR + 0x0018, bytearray([0xA9, 0x15])) # LDA #$15
rom.write_bytes(COMBO_SFX_ADDR + 0x001A, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x001D, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x001E, bytearray([0xC0, 0x04])) # label_0FFE1E: CPY #$04
rom.write_bytes(COMBO_SFX_ADDR + 0x0020, bytearray([0xD0, 0x06])) # BNE label_0FFE28
rom.write_bytes(COMBO_SFX_ADDR + 0x0022, bytearray([0xA9, 0x16])) # LDA #$16
rom.write_bytes(COMBO_SFX_ADDR + 0x0024, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0027, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0028, bytearray([0xC0, 0x05])) # label_0FFE28: CPY #$05
rom.write_bytes(COMBO_SFX_ADDR + 0x002A, bytearray([0xD0, 0x06])) # BNE label_0FFE32
rom.write_bytes(COMBO_SFX_ADDR + 0x002C, bytearray([0xA9, 0x17])) # LDA #$17
rom.write_bytes(COMBO_SFX_ADDR + 0x002E, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0031, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0032, bytearray([0xC0, 0x06])) # label_0FFE32: CPY #$06
rom.write_bytes(COMBO_SFX_ADDR + 0x0034, bytearray([0xD0, 0x06])) # BNE label_0FFE3C
rom.write_bytes(COMBO_SFX_ADDR + 0x0036, bytearray([0xA9, 0x18])) # LDA #$18
rom.write_bytes(COMBO_SFX_ADDR + 0x0038, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x003B, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x003C, bytearray([0xC0, 0x07])) # label_0FFE3C: CPY #$07
rom.write_bytes(COMBO_SFX_ADDR + 0x003E, bytearray([0xD0, 0x06])) # BNE label_0FFE46
rom.write_bytes(COMBO_SFX_ADDR + 0x0040, bytearray([0xA9, 0x19])) # LDA #$19
rom.write_bytes(COMBO_SFX_ADDR + 0x0042, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0045, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0046, bytearray([0x6B])) # label_0FFE46: RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0047, bytearray([0xE0, 0x01])) # COMBO_X: CPX #$01
rom.write_bytes(COMBO_SFX_ADDR + 0x0049, bytearray([0xD0, 0x06])) # BNE label_0FFE51
rom.write_bytes(COMBO_SFX_ADDR + 0x004B, bytearray([0xA9, 0x13])) # LDA #$13
rom.write_bytes(COMBO_SFX_ADDR + 0x004D, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0050, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0051, bytearray([0xE0, 0x02])) # label_0FFE51: CPX #$02
rom.write_bytes(COMBO_SFX_ADDR + 0x0053, bytearray([0xD0, 0x06])) # BNE label_0FFE5B
rom.write_bytes(COMBO_SFX_ADDR + 0x0055, bytearray([0xA9, 0x14])) # LDA #$14
rom.write_bytes(COMBO_SFX_ADDR + 0x0057, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x005A, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x005B, bytearray([0xE0, 0x03])) # label_0FFE5B: CPX #$03
rom.write_bytes(COMBO_SFX_ADDR + 0x005D, bytearray([0xD0, 0x06])) # BNE label_0FFE65
rom.write_bytes(COMBO_SFX_ADDR + 0x005F, bytearray([0xA9, 0x15])) # LDA #$15
rom.write_bytes(COMBO_SFX_ADDR + 0x0061, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0064, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0065, bytearray([0xE0, 0x04])) # label_0FFE65: CPX #$04
rom.write_bytes(COMBO_SFX_ADDR + 0x0067, bytearray([0xD0, 0x06])) # BNE label_0FFE6F
rom.write_bytes(COMBO_SFX_ADDR + 0x0069, bytearray([0xA9, 0x16])) # LDA #$16
rom.write_bytes(COMBO_SFX_ADDR + 0x006B, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x006E, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x006F, bytearray([0xE0, 0x05])) # label_0FFE6F: CPX #$05
rom.write_bytes(COMBO_SFX_ADDR + 0x0071, bytearray([0xD0, 0x06])) # BNE label_0FFE79
rom.write_bytes(COMBO_SFX_ADDR + 0x0073, bytearray([0xA9, 0x17])) # LDA #$17
rom.write_bytes(COMBO_SFX_ADDR + 0x0075, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0078, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0079, bytearray([0xE0, 0x06])) # label_0FFE79: CPX #$06
rom.write_bytes(COMBO_SFX_ADDR + 0x007B, bytearray([0xD0, 0x06])) # BNE label_0FFE83
rom.write_bytes(COMBO_SFX_ADDR + 0x007D, bytearray([0xA9, 0x18])) # LDA #$18
rom.write_bytes(COMBO_SFX_ADDR + 0x007F, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x0082, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x0083, bytearray([0xE0, 0x07])) # label_0FFE83: CPX #$07
rom.write_bytes(COMBO_SFX_ADDR + 0x0085, bytearray([0xD0, 0x06])) # BNE label_0FFE8D
rom.write_bytes(COMBO_SFX_ADDR + 0x0087, bytearray([0xA9, 0x19])) # LDA #$19
rom.write_bytes(COMBO_SFX_ADDR + 0x0089, bytearray([0x8D, 0xF9, 0x1D])) # STA $1DF9
rom.write_bytes(COMBO_SFX_ADDR + 0x008C, bytearray([0x6B])) # RTL
rom.write_bytes(COMBO_SFX_ADDR + 0x008D, bytearray([0x6B])) # label_0FFE8D: RTL
# Adjust "Hit head on ceiling" code
rom.write_bytes(0x06D41 + 0x00, bytearray([0xA9, 0x01])) # lda #$01
rom.write_bytes(0x06D41 + 0x02, bytearray([0x8D, 0xF9, 0x1D])) # sta $1DF9
rom.write_bytes(0x06D41 + 0x05, bytearray([0xEA, 0xEA, 0xEA, 0xEA])) # nop #4
# Manually add "Map: Stepping onto a level tile" random SFX
selected_sfx = world.random.choice(valid_sfxs)
rom.write_byte(0x2169F + 0x01, selected_sfx[0])
rom.write_byte(0x2169F + 0x04, selected_sfx[1] + 0xF9)
# Disable panning on Bowser's flames
rom.write_bytes(0x1A83D, bytearray([0xEA, 0xEA, 0xEA])) # nop #3
# Randomize SFX calls
for address in game_sfx_calls:
# Get random SFX
if world.options.sfx_shuffle != "singularity":
selected_sfx = world.random.choice(valid_sfxs)
# Write randomized SFX num
rom.write_byte(address + 0x01, selected_sfx[0])
# Write randomized SFX port
rom.write_byte(address + 0x03, selected_sfx[1] + 0xF9)
def generate_shuffled_level_music(world: World):
shuffled_level_music = level_music_value_data.copy()
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
if world.options.music_shuffle == "consistent":
world.random.shuffle(shuffled_level_music)
elif world.options.music_shuffle == "singularity":
single_song = world.random.choice(shuffled_level_music)
shuffled_level_music = [single_song for i in range(len(shuffled_level_music))]
return shuffled_level_music
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
def generate_shuffled_ow_music(world: World):
shuffled_ow_music = ow_music_value_data.copy()
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
if world.options.music_shuffle == "consistent" or world.options.music_shuffle == "full":
world.random.shuffle(shuffled_ow_music)
elif world.options.music_shuffle == "singularity":
single_song = world.random.choice(shuffled_ow_music)
shuffled_ow_music = [single_song for i in range(len(shuffled_ow_music))]
return shuffled_ow_music
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
def generate_shuffled_ow_palettes(rom, world: World):
if world.options.overworld_palette_shuffle != "on_legacy":
return
for address, valid_palettes in valid_ow_palettes.items():
chosen_palette = world.random.choice(valid_palettes)
rom.write_byte(address, chosen_palette)
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
def generate_shuffled_header_data(rom, world: World):
if world.options.music_shuffle != "full" and world.options.level_palette_shuffle != "on_legacy":
return
for level_id in range(0, 0x200):
layer1_ptr_list = list(rom.read_bytes(0x2E000 + level_id * 3, 3))
layer1_ptr = (layer1_ptr_list[2] << 16 | layer1_ptr_list[1] << 8 | layer1_ptr_list[0])
if layer1_ptr == 0x68000:
# Unused Levels
continue
if layer1_ptr >= 0x70000:
layer1_ptr -= 0x8000
layer1_ptr -= 0x38000
level_header = list(rom.read_bytes(layer1_ptr, 5))
tileset = level_header[4] & 0x0F
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
if world.options.music_shuffle == "full":
level_header[2] &= 0x8F
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
level_header[2] |= (world.random.randint(0, 7) << 5)
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
if world.options.level_palette_shuffle == "on_legacy":
if tileset in valid_foreground_palettes:
level_header[3] &= 0xF8
level_header[3] |= world.random.choice(valid_foreground_palettes[tileset])
layer2_ptr_list = list(rom.read_bytes(0x2E600 + level_id * 3, 3))
layer2_ptr = (layer2_ptr_list[2] << 16 | layer2_ptr_list[1] << 8 | layer2_ptr_list[0])
if layer2_ptr in valid_background_palettes:
level_header[0] &= 0x1F
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
level_header[0] |= (world.random.choice(valid_background_palettes[layer2_ptr]) << 5)
if layer2_ptr in valid_background_colors:
level_header[1] &= 0x1F
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
level_header[1] |= (world.random.choice(valid_background_colors[layer2_ptr]) << 5)
rom.write_bytes(layer1_ptr, bytes(level_header))
SMW: v2.0 Content Update (#2762) Changelog: Features: - New optional Location Checks - 3-Up Moons - Hidden 1-Ups - Bonus Blocks - Blocksanity - All blocks that contain coins or items are included, with the exception of: - Blocks in Top Secret Area & Front Door/Bowser Castle - Blocks that are unreachable without glitches/unreasonable movement - New Items - Special Zone Clear - New Filler Items - 1 Coin - 5 Coins - 10 Coins - 50 Coins - New Trap Items - Reverse Trap - Thwimp Trap - SFX Shuffle - Palette Shuffle Overhaul - New Curated Palette can now be used for the Overworld and Level Palette Shuffle options - Foreground and Background Shuffle options have been merged into a single setting - Max possible Yoshi Egg value is 255 - UI in-game is updated to handle 3-digits - New `Display Received Item Popups` option: `progression_minus_yoshi_eggs` Quality of Life: - In-Game Indicators are now displayed on the map screen for location checks and received items - In-level sprites are displayed upon receiving certain items - The Camera Scroll unlocking is now only enabled on levels where it needs to be - SMW can now handle receiving more than 255 items - Significant World Code cleanup - New Options API - Removal of `world: MultiWorld` across the world - The PopTracker pack now has tabs for every level/sublevel, and can automatically swap tabs while playing if connected to the server Bug Fixes: - Several logic tweaks/fixes "Major credit to @TheLX5 for being the driving force for almost all of this update. We've been collaborating on design and polish of the features for the last few months, but all of the heavy lifting was all @TheLX5."
2024-03-12 21:00:13 +00:00
def generate_curated_level_palette_data(rom, world: World):
PALETTE_LEVEL_CODE_ADDR = 0x88000
PALETTE_INDEX_ADDR = 0x8F000
PALETTE_LEVEL_TILESET_ADDR = 0x8F200
PALETTE_LEVEL_PTR_ADDR = 0x92000
PALETTE_LEVEL_DATA_ADDR = 0xA8000
addr = pc_to_snes(PALETTE_LEVEL_PTR_ADDR)
snes_level_palette_pointers_1 = bytearray([0xBF, (addr)&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF])
snes_level_palette_pointers_2 = bytearray([0xBF, (addr+2)&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF])
# Enable curated palette loader
rom.write_bytes(0x02BED, bytearray([0x5C, 0x00, 0x80, 0x11])) # org $00ABED : jml custom_palettes
rom.write_bytes(0x02330, bytearray([0x5C, 0x02, 0x80, 0x11])) # org $00A318 : jml custom_palettes_original
rom.write_bytes(0x013D7, bytearray([0x20, 0x30, 0xA3])) # org $0093D7 : jmp $A330
rom.write_bytes(0x014DA, bytearray([0x20, 0x30, 0xA3])) # org $0094DA : jmp $A330
rom.write_bytes(0x015EC, bytearray([0x20, 0x30, 0xA3])) # org $0095EC : jmp $A330
rom.write_bytes(0x0165B, bytearray([0x20, 0x30, 0xA3])) # org $00965B : jmp $A330
rom.write_bytes(0x02DD9, bytearray([0x20, 0x30, 0xA3])) # org $00ADD9 : jmp $A330
rom.write_bytes(0x02E1F, bytearray([0x20, 0x30, 0xA3])) # org $00AE1F : jmp $A330
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0000, bytearray([0x80, 0x09])) # bra custom_palettes
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0002, bytearray([0xC2, 0x30])) # .original rep #$30
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0004, bytearray([0xA9, 0xDD, 0x7F])) # lda #$7FDD
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0007, bytearray([0x5C, 0xF2, 0xAB, 0x00])) # jml $00ABF2
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x000B, bytearray([0xC2, 0x30])) # custom_palettes: rep #$30
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x000D, bytearray([0xA9, 0x70, 0xB1])) # lda #$B170
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0010, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0012, bytearray([0x64, 0x0C])) # stz !_ptr+$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0014, bytearray([0xA9, 0x10, 0x00])) # lda.w #$0010
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0017, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0019, bytearray([0xA9, 0x07, 0x00])) # lda #$0007
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x001C, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x001E, bytearray([0xA9, 0x01, 0x00])) # lda #$0001
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0021, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0023, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0026, bytearray([0xAE, 0x0B, 0x01])) # .get_index ldx $010B
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0029, bytearray([0xBF, 0x00, 0xF2, 0x11])) # lda.l level_tilesets,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x002D, bytearray([0x29, 0xFF, 0x00])) # and #$00FF
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0030, bytearray([0xEB])) # xba
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0031, bytearray([0x85, 0x00])) # sta !_tileset
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0033, bytearray([0xBF, 0x00, 0xF0, 0x11])) # lda.l level_index,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0037, bytearray([0x29, 0xFF, 0x00])) # and #$00FF
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x003A, bytearray([0x05, 0x00])) # ora !_tileset
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x003C, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x003E, bytearray([0x0A])) # asl
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x003F, bytearray([0x18])) # clc
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0040, bytearray([0x65, 0x0A])) # adc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0042, bytearray([0x85, 0x0E])) # sta !_num
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0044, bytearray([0xAA])) # tax
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0045, snes_level_palette_pointers_1) # .back_color lda.l palette_pointers,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0049, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x004B, snes_level_palette_pointers_2) # lda.l palette_pointers+$02,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x004F, bytearray([0x85, 0x0C])) # sta !_ptr+$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0051, bytearray([0xA7, 0x0A])) # lda [!_ptr]
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0053, bytearray([0x8D, 0x01, 0x07])) # sta $0701
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0056, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0058, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x005A, bytearray([0xA9, 0x02, 0x00])) # .background lda.w #$0001*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x005D, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x005F, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0062, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0064, bytearray([0xA9, 0x01, 0x00])) # lda #$0001
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0067, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0069, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x006C, bytearray([0xA9, 0x42, 0x00])) # .foreground lda.w #$0021*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x006F, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0071, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0074, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0076, bytearray([0xA9, 0x01, 0x00])) # lda #$0001
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0079, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x007B, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x007E, bytearray([0xA9, 0x52, 0x00])) # .berries lda.w #$0029*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0081, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0083, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0086, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0088, bytearray([0xA9, 0x02, 0x00])) # lda #$0002
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x008B, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x008D, bytearray([0xA5, 0x0A])) # lda !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x008F, bytearray([0x48])) # pha
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0090, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0093, bytearray([0x68])) # pla
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0094, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0096, bytearray([0xA9, 0x32, 0x01])) # lda.w #$0099*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0099, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x009B, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x009E, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00A0, bytearray([0xA9, 0x02, 0x00])) # lda #$0002
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00A3, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00A5, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00A8, bytearray([0xA9, 0x82, 0x00])) # .global lda.w #$0041*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00AB, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00AD, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00B0, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00B2, bytearray([0xA9, 0x0B, 0x00])) # lda #$000B
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00B5, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00B7, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00BA, bytearray([0xA5, 0x00])) # .sprite_specific lda !_tileset
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00BC, bytearray([0xC9, 0x00, 0x05])) # cmp #$0500
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00BF, bytearray([0xD0, 0x1D])) # bne .end
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00C1, bytearray([0xAD, 0x2E, 0x19])) # lda $192E
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00C4, bytearray([0x29, 0x0F, 0x00])) # and #$000F
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00C7, bytearray([0xC9, 0x02, 0x00])) # cmp #$0002
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00CA, bytearray([0xD0, 0x12])) # bne .end
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00CC, bytearray([0xA9, 0xC2, 0x01])) # lda.w #$00E1*$02
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00CF, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00D1, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00D4, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00D6, bytearray([0xA9, 0x01, 0x00])) # lda #$0001
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00D9, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00DB, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00DE, bytearray([0xE2, 0x30])) # .end sep #$30
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E0, bytearray([0x5C, 0xEC, 0xAC, 0x00])) # jml $00ACEC
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E4, bytearray([0xA6, 0x04])) # load_colors: ldx !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E6, bytearray([0xA4, 0x06])) # ldy !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E8, bytearray([0xA7, 0x0A])) # .x_loop lda [!_ptr]
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00EA, bytearray([0x9D, 0x03, 0x07])) # sta $0703,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00ED, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00EF, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F1, bytearray([0xE8])) # inx
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F2, bytearray([0xE8])) # inx
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F3, bytearray([0x88])) # dey
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F4, bytearray([0x10, 0xF2])) # bpl .x_loop
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F6, bytearray([0xA5, 0x04])) # lda !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F8, bytearray([0x18])) # clc
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F9, bytearray([0x69, 0x20, 0x00])) # adc #$0020
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00FC, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00FE, bytearray([0xC6, 0x08])) # dec !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0100, bytearray([0x10, 0xE2])) # bpl load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0102, bytearray([0x60])) # rts
# Load palette paths
data = pkgutil.get_data(__name__, f"data/palettes/level/palettes.json").decode("utf-8")
tilesets = json.loads(data)
# Writes the level tileset index to ROM
rom.write_bytes(PALETTE_LEVEL_TILESET_ADDR, bytearray(level_palette_index))
# Builds the table in ROM that holds the palette index for each level, including sublevels
for level_id in range(0x200):
tileset_num = level_palette_index[level_id]
if tileset_num != 0xFF:
tileset = tileset_names[tileset_num]
else:
tileset = tileset_names[0x19]
palette = world.random.randint(0, len(tilesets[tileset])-1)
rom.write_bytes(PALETTE_INDEX_ADDR + level_id, bytearray([palette]))
# Writes the actual level palette data and pointer to said data to the ROM
pal_offset = 0x0000
tileset_num = 0
bank_palette_count = 0
for tileset in tilesets.keys():
for palette in range(len(tilesets[tileset])):
# Handle bank crossing
if bank_palette_count == 110:
pal_offset = (pal_offset & 0xF8000) + 0x8000
bank_palette_count = 0
# Write pointer
data_ptr = pc_to_snes(PALETTE_LEVEL_DATA_ADDR + pal_offset)
rom.write_bytes(PALETTE_LEVEL_PTR_ADDR + ((tileset_num*3)<<8) + (palette*3), bytearray([data_ptr & 0xFF, (data_ptr>>8)&0xFF, (data_ptr>>16)&0xFF]))
# Write data
rom.write_bytes(PALETTE_LEVEL_DATA_ADDR + pal_offset, read_palette_file(tileset, tilesets[tileset][palette], "level"))
pal_offset += 0x128
bank_palette_count += 1
tileset_num += 1
# Fix eaten berry tiles
EATEN_BERRY_ADDR = 0x68248
rom.write_byte(EATEN_BERRY_ADDR + 0x01, 0x04)
rom.write_byte(EATEN_BERRY_ADDR + 0x03, 0x04)
rom.write_byte(EATEN_BERRY_ADDR + 0x05, 0x04)
rom.write_byte(EATEN_BERRY_ADDR + 0x07, 0x04)
# Fix title screen changing background colors
rom.write_bytes(0x1D30, bytearray([0xEA, 0xEA, 0xEA]))
# Skips level intros automatically
rom.write_byte(0x4896, 0x80)
def generate_curated_map_palette_data(rom, world: World):
PALETTE_MAP_CODE_ADDR = 0x88200
PALETTE_UPLOADER_EDIT = 0x88400
PALETTE_MAP_INDEX_ADDR = 0x8F400
PALETTE_MAP_PTR_ADDR = 0x90000
PALETTE_MAP_DATA_ADDR = 0x98000
addr = pc_to_snes(PALETTE_MAP_PTR_ADDR)
snes_map_palette_pointers_1 = bytearray([0xBF, (addr)&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF])
snes_map_palette_pointers_2 = bytearray([0xBF, (addr+2)&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF])
rom.write_bytes(0x02D25, bytearray([0x5C, 0x09, 0x82, 0x11])) # org $00AD25 : jml map_palettes
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0000, bytearray([0xC2, 0x30])) # map_og_palettes: rep #$30
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0002, bytearray([0xA0, 0xD8, 0xB3])) # ldy #$B3D8
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0005, bytearray([0x5C, 0x2A, 0xAD, 0x00])) # jml $00AD2A
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0009, bytearray([0xC2, 0x30])) # map_palettes: rep #$30
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x000B, bytearray([0xAD, 0x31, 0x19])) # .prepare_index lda $1931
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x000E, bytearray([0x29, 0x0F, 0x00])) # and #$000F
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0011, bytearray([0x3A])) # dec
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0012, bytearray([0xAA])) # tax
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0013, bytearray([0xEB])) # xba
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0014, bytearray([0x85, 0x0E])) # sta !_num
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0016, bytearray([0xBF, 0x00, 0xF4, 0x11])) # lda.l map_index,x
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x001A, bytearray([0x29, 0xFF, 0x00])) # and #$00FF
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x001D, bytearray([0x05, 0x0E])) # ora !_num
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x001F, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0021, bytearray([0x0A])) # asl
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0022, bytearray([0x18])) # clc
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0023, bytearray([0x65, 0x0A])) # adc !_ptr
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0025, bytearray([0xAA])) # tax
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0026, snes_map_palette_pointers_1) # lda.l map_palette_pointers,x
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x002A, bytearray([0x85, 0x0A])) # sta !_ptr
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x002C, snes_map_palette_pointers_2) # lda.l map_palette_pointers+$02,x
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0030, bytearray([0x85, 0x0C])) # sta !_ptr+$02
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0032, bytearray([0xA7, 0x0A])) # .load_back_color lda [!_ptr]
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0034, bytearray([0x8D, 0x01, 0x07])) # sta $0701
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0037, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0039, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x003B, bytearray([0xA9, 0x82, 0x00])) # .load_layer_2 lda.w #$0041*$02
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x003E, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0040, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0043, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0045, bytearray([0xA9, 0x03, 0x00])) # lda #$0003
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0048, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x004A, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x004D, bytearray([0xA9, 0x52, 0x00])) # .load_layer_1 lda.w #$0029*$02
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0050, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0052, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0055, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0057, bytearray([0xA9, 0x05, 0x00])) # lda #$0005
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x005A, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x005C, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x005F, bytearray([0xA9, 0x10, 0x00])) # .load_layer_3 lda.w #$0008*$02
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0062, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0064, bytearray([0xA9, 0x07, 0x00])) # lda #$0007
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0067, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0069, bytearray([0xA9, 0x01, 0x00])) # lda #$0001
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x006C, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x006E, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0071, bytearray([0xA9, 0x02, 0x01])) # .load_sprites lda.w #$0081*$02
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0074, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0076, bytearray([0xA9, 0x06, 0x00])) # lda #$0006
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0079, bytearray([0x85, 0x06])) # sta !_x_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x007B, bytearray([0xA9, 0x07, 0x00])) # lda #$0007
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x007E, bytearray([0x85, 0x08])) # sta !_y_span
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0080, bytearray([0x20, 0xE4, 0x80])) # jsr load_colors
rom.write_bytes(PALETTE_MAP_CODE_ADDR + 0x0083, bytearray([0x5C, 0xA3, 0xAD, 0x00])) # .return jml $00ADA3
rom.write_bytes(0x2488, bytearray([0x5C, 0x00, 0x84, 0x11])) # org $00A488 : jml palette_upload
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0000, bytearray([0xAD, 0x00, 0x01])) # palette_upload: lda $0100
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0003, bytearray([0xC9, 0x0E])) # cmp #$0E
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0005, bytearray([0xF0, 0x0A])) # beq .map
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0007, bytearray([0xAC, 0x80, 0x06])) # .regular ldy $0680
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x000A, bytearray([0xBE, 0x81, 0xA4])) # ldx.w $A47F+2,y
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x000D, bytearray([0x5C, 0x8E, 0xA4, 0x00])) # jml $00A48E
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0011, bytearray([0xAD, 0xD9, 0x13])) # .map lda $13D9
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0014, bytearray([0xC9, 0x0A])) # cmp #$0A
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0016, bytearray([0xD0, 0xEF])) # bne .regular
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0018, bytearray([0xAD, 0xE8, 0x1D])) # lda $1DE8
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x001B, bytearray([0xC9, 0x06])) # cmp #$06
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x001D, bytearray([0xD0, 0xE8])) # bne .regular
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x001F, bytearray([0x9C, 0x03, 0x07])) # stz $0703
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0022, bytearray([0x9C, 0x04, 0x07])) # stz $0704
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0025, bytearray([0x9C, 0x21, 0x21])) # stz $2121
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0028, bytearray([0xA2, 0x06])) # ldx #$06
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x002A, bytearray([0xBD, 0x49, 0x92])) # .loop lda.w $9249,x
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x002D, bytearray([0x9D, 0x20, 0x43])) # sta $4320,x
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0030, bytearray([0xCA])) # dex
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0031, bytearray([0x10, 0xF7])) # bpl .loop
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0033, bytearray([0xA9, 0x04])) # lda #$04
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0035, bytearray([0x8D, 0x0B, 0x42])) # sta $420B
rom.write_bytes(PALETTE_UPLOADER_EDIT + 0x0038, bytearray([0x5C, 0xCF, 0xA4, 0x00])) # jml $00A4CF
# Insert this piece of ASM again in case levels are disabled
PALETTE_LEVEL_CODE_ADDR = 0x88000
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E4, bytearray([0xA6, 0x04])) # load_colors: ldx !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E6, bytearray([0xA4, 0x06])) # ldy !_x_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00E8, bytearray([0xA7, 0x0A])) # .x_loop lda [!_ptr]
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00EA, bytearray([0x9D, 0x03, 0x07])) # sta $0703,x
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00ED, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00EF, bytearray([0xE6, 0x0A])) # inc !_ptr
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F1, bytearray([0xE8])) # inx
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F2, bytearray([0xE8])) # inx
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F3, bytearray([0x88])) # dey
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F4, bytearray([0x10, 0xF2])) # bpl .x_loop
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F6, bytearray([0xA5, 0x04])) # lda !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F8, bytearray([0x18])) # clc
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00F9, bytearray([0x69, 0x20, 0x00])) # adc #$0020
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00FC, bytearray([0x85, 0x04])) # sta !_index
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x00FE, bytearray([0xC6, 0x08])) # dec !_y_span
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0100, bytearray([0x10, 0xE2])) # bpl load_colors
rom.write_bytes(PALETTE_LEVEL_CODE_ADDR + 0x0102, bytearray([0x60])) # rts
# Load palette paths
data = pkgutil.get_data(__name__, f"data/palettes/map/palettes.json").decode("utf-8")
maps = json.loads(data)
for map_id in range(0x07):
current_map_name = map_names[map_id]
palette = world.random.randint(0, len(maps[current_map_name])-1)
rom.write_bytes(PALETTE_MAP_INDEX_ADDR + map_id, bytearray([palette]))
# Writes the actual map palette data and pointer to said data to the ROM
pal_offset = 0x0000
map_num = 0
bank_palette_count = 0
for current_map in maps.keys():
for palette in range(len(maps[current_map])):
# Handle bank crossing
if bank_palette_count == 113:
pal_offset = (pal_offset & 0xF8000) + 0x8000
bank_palette_count = 0
# Write pointer
data_ptr = pc_to_snes(PALETTE_MAP_DATA_ADDR + pal_offset)
rom.write_bytes(PALETTE_MAP_PTR_ADDR + ((map_num*3)<<8) + (palette*3), bytearray([data_ptr & 0xFF, (data_ptr>>8)&0xFF, (data_ptr>>16)&0xFF]))
# Write data
rom.write_bytes(PALETTE_MAP_DATA_ADDR + pal_offset, read_palette_file(current_map, maps[current_map][palette], "map"))
# Update map mario palette
chosen_palette = world.options.mario_palette.value
rom.write_bytes(PALETTE_MAP_DATA_ADDR + pal_offset + 206, bytes(ow_mario_palettes[chosen_palette]))
pal_offset += 0x11C
bank_palette_count += 1
map_num += 1
def pc_to_snes(address):
return ((address << 1) & 0x7F0000) | (address & 0x7FFF) | 0x8000
def read_palette_file(tileset, filename, type_):
palette_file = pkgutil.get_data(__name__, f"data/palettes/{type_}/{tileset}/{filename}")
colors = bytearray([])
# Copy back colors
colors += bytearray([palette_file[0x200], palette_file[0x201]])
if type_ == "level":
# Copy background colors
colors += bytearray([palette_file[(0x01*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x11*2)+(i)] for i in range(14)])
# Copy foreground colors
colors += bytearray([palette_file[(0x21*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x31*2)+(i)] for i in range(14)])
# Copy berry colors
colors += bytearray([palette_file[(0x29*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x39*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x49*2)+(i)] for i in range(14)])
# Copy global colors
colors += bytearray([palette_file[(0x41*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x51*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x61*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x71*2)+(i)] for i in range(14)])
# Copy sprite colors
colors += bytearray([palette_file[(0x81*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x91*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xA1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xB1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xC1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xD1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xE1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xF1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xE9*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xF9*2)+(i)] for i in range(14)])
elif type_ == "map":
# Copy layer 2 colors
colors += bytearray([palette_file[(0x41*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x51*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x61*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x71*2)+(i)] for i in range(14)])
# Copy layer 1 colors
colors += bytearray([palette_file[(0x29*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x39*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x49*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x59*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x69*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x79*2)+(i)] for i in range(14)])
# Copy layer 3 colors
colors += bytearray([palette_file[(0x08*2)+(i)] for i in range(16)])
colors += bytearray([palette_file[(0x18*2)+(i)] for i in range(16)])
# Copy sprite colors
colors += bytearray([palette_file[(0x81*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0x91*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xA1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xB1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xC1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xD1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xE1*2)+(i)] for i in range(14)])
colors += bytearray([palette_file[(0xF1*2)+(i)] for i in range(14)])
return colors