2023-03-20 16:26:03 +00:00
import binascii
import importlib . util
import importlib . machinery
import os
2023-04-11 07:18:33 +00:00
import pkgutil
2023-11-22 14:29:33 +00:00
from collections import defaultdict
2024-06-18 02:48:15 +00:00
from typing import TYPE_CHECKING
2023-03-20 16:26:03 +00:00
from . romTables import ROMWithTables
from . import assembler
from . import mapgen
from . import patches
from . patches import overworld as _
from . patches import dungeon as _
from . patches import entrances as _
from . patches import enemies as _
from . patches import titleScreen as _
from . patches import aesthetics as _
from . patches import music as _
from . patches import core as _
from . patches import phone as _
from . patches import photographer as _
from . patches import owl as _
from . patches import bank3e as _
from . patches import bank3f as _
from . patches import inventory as _
from . patches import witch as _
from . patches import tarin as _
from . patches import fishingMinigame as _
from . patches import softlock as _
from . patches import maptweaks as _
from . patches import chest as _
from . patches import bomb as _
from . patches import rooster as _
from . patches import shop as _
from . patches import trendy as _
from . patches import goal as _
from . patches import hardMode as _
from . patches import weapons as _
from . patches import health as _
from . patches import heartPiece as _
from . patches import droppedKey as _
from . patches import goldenLeaf as _
from . patches import songs as _
from . patches import bowwow as _
from . patches import desert as _
from . patches import reduceRNG as _
from . patches import madBatter as _
from . patches import tunicFairy as _
from . patches import seashell as _
from . patches import instrument as _
from . patches import endscreen as _
from . patches import save as _
from . patches import bingo as _
from . patches import multiworld as _
from . patches import tradeSequence as _
from . import hints
from . patches import bank34
2023-10-01 23:16:25 +00:00
from . utils import formatText
2024-12-03 05:59:55 +00:00
from . . Options import TrendyGame , Palette , Warps
2023-10-01 23:16:25 +00:00
from . roomEditor import RoomEditor , Object
2023-04-26 08:49:38 +00:00
from . patches . aesthetics import rgb_to_bin , bin_to_rgb
from . locations . keyLocation import KeyLocation
2023-03-20 16:26:03 +00:00
2023-07-14 01:14:04 +00:00
from BaseClasses import ItemClassification
from . . Locations import LinksAwakeningLocation
2024-04-14 01:21:55 +00:00
from . . Options import TrendyGame , Palette , MusicChangeCondition , BootsControls
2023-03-20 16:26:03 +00:00
2024-06-18 02:48:15 +00:00
if TYPE_CHECKING :
from . . import LinksAwakeningWorld
2023-03-20 16:26:03 +00:00
# Function to generate a final rom, this patches the rom with all required patches
2024-06-18 02:48:15 +00:00
def generateRom ( args , world : " LinksAwakeningWorld " ) :
2023-04-11 07:18:33 +00:00
rom_patches = [ ]
2024-06-18 02:48:15 +00:00
player_names = list ( world . multiworld . player_name . values ( ) )
2023-04-11 07:18:33 +00:00
rom = ROMWithTables ( args . input_filename , rom_patches )
2023-03-20 16:26:03 +00:00
rom . player_names = player_names
pymods = [ ]
if args . pymod :
for pymod in args . pymod :
spec = importlib . util . spec_from_loader ( pymod , importlib . machinery . SourceFileLoader ( pymod , pymod ) )
module = importlib . util . module_from_spec ( spec )
spec . loader . exec_module ( module )
pymods . append ( module )
for pymod in pymods :
pymod . prePatch ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . gfxmod :
patches . aesthetics . gfxMod ( rom , os . path . join ( " data " , " sprites " , " ladx " , world . ladxr_settings . gfxmod ) )
2023-03-20 16:26:03 +00:00
2024-06-18 02:48:15 +00:00
item_list = [ item for item in world . ladxr_logic . iteminfo_list if not isinstance ( item , KeyLocation ) ]
2023-03-20 16:26:03 +00:00
assembler . resetConsts ( )
assembler . const ( " INV_SIZE " , 16 )
assembler . const ( " wHasFlippers " , 0xDB3E )
assembler . const ( " wHasMedicine " , 0xDB3F )
assembler . const ( " wTradeSequenceItem " , 0xDB40 ) # we use it to store flags of which trade items we have
assembler . const ( " wTradeSequenceItem2 " , 0xDB7F ) # Normally used to store that we have exchanged the trade item, we use it to store flags of which trade items we have
assembler . const ( " wSeashellsCount " , 0xDB41 )
assembler . const ( " wGoldenLeaves " , 0xDB42 ) # New memory location where to store the golden leaf counter
2024-04-14 01:21:55 +00:00
assembler . const ( " wCollectedTunics " , 0xDB6D ) # Memory location where to store which tunic options are available (and boots)
2023-03-20 16:26:03 +00:00
assembler . const ( " wCustomMessage " , 0xC0A0 )
# We store the link info in unused color dungeon flags, so it gets preserved in the savegame.
assembler . const ( " wLinkSyncSequenceNumber " , 0xDDF6 )
assembler . const ( " wLinkStatusBits " , 0xDDF7 )
assembler . const ( " wLinkGiveItem " , 0xDDF8 )
assembler . const ( " wLinkGiveItemFrom " , 0xDDF9 )
assembler . const ( " wLinkSendItemRoomHigh " , 0xDDFA )
assembler . const ( " wLinkSendItemRoomLow " , 0xDDFB )
assembler . const ( " wLinkSendItemTarget " , 0xDDFC )
assembler . const ( " wLinkSendItemItem " , 0xDDFD )
assembler . const ( " wZolSpawnCount " , 0xDE10 )
assembler . const ( " wCuccoSpawnCount " , 0xDE11 )
assembler . const ( " wDropBombSpawnCount " , 0xDE12 )
assembler . const ( " wLinkSpawnDelay " , 0xDE13 )
#assembler.const("HARDWARE_LINK", 1)
2024-06-18 02:48:15 +00:00
assembler . const ( " HARD_MODE " , 1 if world . ladxr_settings . hardmode != " none " else 0 )
2023-03-20 16:26:03 +00:00
patches . core . cleanup ( rom )
patches . save . singleSaveSlot ( rom )
patches . phone . patchPhone ( rom )
patches . photographer . fixPhotographer ( rom )
patches . core . bugfixWrittingWrongRoomStatus ( rom )
patches . core . bugfixBossroomTopPush ( rom )
patches . core . bugfixPowderBagSprite ( rom )
patches . core . fixEggDeathClearingItems ( rom )
patches . core . disablePhotoPrint ( rom )
patches . core . easyColorDungeonAccess ( rom )
patches . owl . removeOwlEvents ( rom )
patches . enemies . fixArmosKnightAsMiniboss ( rom )
2024-06-18 02:48:15 +00:00
patches . bank3e . addBank3E ( rom , world . multi_key , world . player , player_names )
2023-03-20 16:26:03 +00:00
patches . bank3f . addBank3F ( rom )
patches . bank34 . addBank34 ( rom , item_list )
patches . core . removeGhost ( rom )
patches . core . fixMarinFollower ( rom )
patches . core . fixWrongWarp ( rom )
patches . core . alwaysAllowSecretBook ( rom )
patches . core . injectMainLoop ( rom )
2023-10-01 23:16:25 +00:00
2023-03-20 16:26:03 +00:00
from . . Options import ShuffleSmallKeys , ShuffleNightmareKeys
2024-06-18 02:48:15 +00:00
if world . options . shuffle_small_keys != ShuffleSmallKeys . option_original_dungeon or \
world . options . shuffle_nightmare_keys != ShuffleNightmareKeys . option_original_dungeon :
2023-03-20 16:26:03 +00:00
patches . inventory . advancedInventorySubscreen ( rom )
patches . inventory . moreSlots ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . witch :
2023-03-20 16:26:03 +00:00
patches . witch . updateWitch ( rom )
patches . softlock . fixAll ( rom )
2024-12-01 03:58:10 +00:00
if not world . ladxr_settings . rooster :
patches . maptweaks . tweakMap ( rom )
patches . maptweaks . tweakBirdKeyRoom ( rom )
2023-03-20 16:26:03 +00:00
patches . chest . fixChests ( rom )
patches . shop . fixShop ( rom )
patches . rooster . patchRooster ( rom )
patches . trendy . fixTrendy ( rom )
patches . droppedKey . fixDroppedKey ( rom )
patches . madBatter . upgradeMadBatter ( rom )
patches . tunicFairy . upgradeTunicFairy ( rom )
patches . tarin . updateTarin ( rom )
patches . fishingMinigame . updateFinishingMinigame ( rom )
patches . health . upgradeHealthContainers ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . owlstatues in ( " dungeon " , " both " ) :
2023-03-20 16:26:03 +00:00
patches . owl . upgradeDungeonOwlStatues ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . owlstatues in ( " overworld " , " both " ) :
2023-03-20 16:26:03 +00:00
patches . owl . upgradeOverworldOwlStatues ( rom )
patches . goldenLeaf . fixGoldenLeaf ( rom )
patches . heartPiece . fixHeartPiece ( rom )
patches . seashell . fixSeashell ( rom )
patches . instrument . fixInstruments ( rom )
patches . seashell . upgradeMansion ( rom )
patches . songs . upgradeMarin ( rom )
patches . songs . upgradeManbo ( rom )
patches . songs . upgradeMamu ( rom )
2024-12-01 03:58:10 +00:00
patches . tradeSequence . patchTradeSequence ( rom , world . ladxr_settings )
2024-06-18 02:48:15 +00:00
patches . bowwow . fixBowwow ( rom , everywhere = world . ladxr_settings . bowwow != ' normal ' )
if world . ladxr_settings . bowwow != ' normal ' :
2023-03-20 16:26:03 +00:00
patches . bowwow . bowwowMapPatches ( rom )
patches . desert . desertAccess ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . overworld == ' dungeondive ' :
2023-03-20 16:26:03 +00:00
patches . overworld . patchOverworldTilesets ( rom )
patches . overworld . createDungeonOnlyOverworld ( rom )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . overworld == ' nodungeons ' :
2023-03-20 16:26:03 +00:00
patches . dungeon . patchNoDungeons ( rom )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . overworld == ' random ' :
2023-03-20 16:26:03 +00:00
patches . overworld . patchOverworldTilesets ( rom )
2024-06-18 02:48:15 +00:00
mapgen . store_map ( rom , world . ladxr_logic . world . map )
2023-03-20 16:26:03 +00:00
#if settings.dungeon_items == 'keysy':
# patches.dungeon.removeKeyDoors(rom)
# patches.reduceRNG.slowdownThreeOfAKind(rom)
patches . reduceRNG . fixHorseHeads ( rom )
patches . bomb . onlyDropBombsWhenHaveBombs ( rom )
2024-06-18 02:48:15 +00:00
if world . options . music_change_condition == MusicChangeCondition . option_always :
2023-03-29 12:48:10 +00:00
patches . aesthetics . noSwordMusic ( rom )
2024-06-18 02:48:15 +00:00
patches . aesthetics . reduceMessageLengths ( rom , world . random )
2023-03-20 16:26:03 +00:00
patches . aesthetics . allowColorDungeonSpritesEverywhere ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . music == ' random ' :
patches . music . randomizeMusic ( rom , world . random )
elif world . ladxr_settings . music == ' off ' :
2023-03-20 16:26:03 +00:00
patches . music . noMusic ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . noflash :
2023-03-20 16:26:03 +00:00
patches . aesthetics . removeFlashingLights ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . hardmode == " oracle " :
2023-03-20 16:26:03 +00:00
patches . hardMode . oracleMode ( rom )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . hardmode == " hero " :
2023-03-20 16:26:03 +00:00
patches . hardMode . heroMode ( rom )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . hardmode == " ohko " :
2023-03-20 16:26:03 +00:00
patches . hardMode . oneHitKO ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . superweapons :
2023-03-20 16:26:03 +00:00
patches . weapons . patchSuperWeapons ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . textmode == ' fast ' :
2023-03-20 16:26:03 +00:00
patches . aesthetics . fastText ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . textmode == ' none ' :
2023-03-20 16:26:03 +00:00
patches . aesthetics . fastText ( rom )
patches . aesthetics . noText ( rom )
2024-06-18 02:48:15 +00:00
if not world . ladxr_settings . nagmessages :
2023-03-20 16:26:03 +00:00
patches . aesthetics . removeNagMessages ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . lowhpbeep == ' slow ' :
2023-03-20 16:26:03 +00:00
patches . aesthetics . slowLowHPBeep ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . lowhpbeep == ' none ' :
2023-03-20 16:26:03 +00:00
patches . aesthetics . removeLowHPBeep ( rom )
2024-06-18 02:48:15 +00:00
if 0 < = int ( world . ladxr_settings . linkspalette ) :
patches . aesthetics . forceLinksPalette ( rom , int ( world . ladxr_settings . linkspalette ) )
2023-03-20 16:26:03 +00:00
if args . romdebugmode :
# The default rom has this build in, just need to set a flag and we get this save.
rom . patch ( 0 , 0x0003 , " 00 " , " 01 " )
# Patch the sword check on the shopkeeper turning around.
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . steal == ' never ' :
2023-03-20 16:26:03 +00:00
rom . patch ( 4 , 0x36F9 , " FA4EDB " , " 3E0000 " )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . steal == ' always ' :
2023-03-20 16:26:03 +00:00
rom . patch ( 4 , 0x36F9 , " FA4EDB " , " 3E0100 " )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . hpmode == ' inverted ' :
2023-03-20 16:26:03 +00:00
patches . health . setStartHealth ( rom , 9 )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . hpmode == ' 1 ' :
2023-03-20 16:26:03 +00:00
patches . health . setStartHealth ( rom , 1 )
patches . inventory . songSelectAfterOcarinaSelect ( rom )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . quickswap == ' a ' :
2023-03-20 16:26:03 +00:00
patches . core . quickswap ( rom , 1 )
2024-06-18 02:48:15 +00:00
elif world . ladxr_settings . quickswap == ' b ' :
2023-03-20 16:26:03 +00:00
patches . core . quickswap ( rom , 0 )
2024-04-14 01:21:55 +00:00
2024-06-18 02:48:15 +00:00
patches . core . addBootsControls ( rom , world . options . boots_controls )
2024-04-14 01:21:55 +00:00
2023-10-01 23:16:25 +00:00
2024-06-18 02:48:15 +00:00
world_setup = world . ladxr_logic . world_setup
2023-03-20 16:26:03 +00:00
2023-07-14 01:14:04 +00:00
JUNK_HINT = 0.33
RANDOM_HINT = 0.66
# USEFUL_HINT = 1.0
# TODO: filter events, filter unshuffled keys
2024-06-18 02:48:15 +00:00
all_items = world . multiworld . get_items ( )
our_items = [ item for item in all_items
if item . player == world . player
and item . location
and item . code is not None
and item . location . show_in_spoiler ]
2023-07-14 01:14:04 +00:00
our_useful_items = [ item for item in our_items if ItemClassification . progression in item . classification ]
2023-08-11 08:56:36 +00:00
2023-07-14 01:14:04 +00:00
def gen_hint ( ) :
2024-06-18 02:48:15 +00:00
chance = world . random . uniform ( 0 , 1 )
2023-07-14 01:14:04 +00:00
if chance < JUNK_HINT :
return None
elif chance < RANDOM_HINT :
2024-06-18 02:48:15 +00:00
location = world . random . choice ( our_items ) . location
2023-07-14 01:14:04 +00:00
else : # USEFUL_HINT
2024-06-18 02:48:15 +00:00
location = world . random . choice ( our_useful_items ) . location
2023-07-14 01:14:04 +00:00
2024-06-18 02:48:15 +00:00
if location . item . player == world . player :
2023-07-14 01:14:04 +00:00
name = " Your "
else :
2024-06-18 02:48:15 +00:00
name = f " { world . multiworld . player_name [ location . item . player ] } ' s "
2024-08-29 06:15:49 +00:00
# filter out { and } since they cause issues with string.format later on
name = name . replace ( " { " , " " ) . replace ( " } " , " " )
2023-10-01 23:16:25 +00:00
2023-07-14 01:14:04 +00:00
if isinstance ( location , LinksAwakeningLocation ) :
location_name = location . ladxr_item . metadata . name
else :
location_name = location . name
2023-08-11 08:56:36 +00:00
2023-07-14 01:14:04 +00:00
hint = f " { name } { location . item } is at { location_name } "
2024-06-18 02:48:15 +00:00
if location . player != world . player :
2024-08-29 06:15:49 +00:00
# filter out { and } since they cause issues with string.format later on
player_name = world . multiworld . player_name [ location . player ] . replace ( " { " , " " ) . replace ( " } " , " " )
hint + = f " in { player_name } ' s world "
2023-07-14 01:14:04 +00:00
2023-08-11 08:56:36 +00:00
# Cap hint size at 85
# Realistically we could go bigger but let's be safe instead
hint = hint [ : 85 ]
2023-07-14 01:14:04 +00:00
return hint
2023-03-20 16:26:03 +00:00
2024-06-18 02:48:15 +00:00
hints . addHints ( rom , world . random , gen_hint )
2023-03-20 16:26:03 +00:00
if world_setup . goal == " raft " :
patches . goal . setRaftGoal ( rom )
elif world_setup . goal in ( " bingo " , " bingo-full " ) :
patches . bingo . setBingoGoal ( rom , world_setup . bingo_goals , world_setup . goal )
elif world_setup . goal == " seashells " :
patches . goal . setSeashellGoal ( rom , 20 )
else :
patches . goal . setRequiredInstrumentCount ( rom , world_setup . goal )
# Patch the generated logic into the rom
patches . chest . setMultiChest ( rom , world_setup . multichest )
2024-06-18 02:48:15 +00:00
if world . ladxr_settings . overworld not in { " dungeondive " , " random " } :
2023-03-20 16:26:03 +00:00
patches . entrances . changeEntrances ( rom , world_setup . entrance_mapping )
for spot in item_list :
if spot . item and spot . item . startswith ( " * " ) :
spot . item = spot . item [ 1 : ]
mw = None
if spot . item_owner != spot . location_owner :
mw = spot . item_owner
2023-04-04 00:23:39 +00:00
if mw > 100 :
# There are only 101 player name slots (99 + "The Server" + "another world"), so don't use more than that
mw = 100
2023-03-20 16:26:03 +00:00
spot . patch ( rom , spot . item , multiworld = mw )
patches . enemies . changeBosses ( rom , world_setup . boss_mapping )
patches . enemies . changeMiniBosses ( rom , world_setup . miniboss_mapping )
if not args . romdebugmode :
patches . core . addFrameCounter ( rom , len ( item_list ) )
patches . core . warpHome ( rom ) # Needs to be done after setting the start location.
2024-06-18 02:48:15 +00:00
patches . titleScreen . setRomInfo ( rom , world . multi_key , world . multiworld . seed_name , world . ladxr_settings ,
world . player_name , world . player )
if world . options . ap_title_screen :
2023-04-11 07:18:33 +00:00
patches . titleScreen . setTitleGraphics ( rom )
2023-03-20 16:26:03 +00:00
patches . endscreen . updateEndScreen ( rom )
patches . aesthetics . updateSpriteData ( rom )
if args . doubletrouble :
patches . enemies . doubleTrouble ( rom )
2024-06-18 02:48:15 +00:00
if world . options . text_shuffle :
2023-11-22 14:29:33 +00:00
buckets = defaultdict ( list )
# For each ROM bank, shuffle text within the bank
for n , data in enumerate ( rom . texts . _PointerTable__data ) :
# Don't muck up which text boxes are questions and which are statements
if type ( data ) != int and data and data != b ' \xFF ' :
buckets [ ( rom . texts . _PointerTable__banks [ n ] , data [ len ( data ) - 1 ] == 0xfe ) ] . append ( ( n , data ) )
for bucket in buckets . values ( ) :
# For each bucket, make a copy and shuffle
shuffled = bucket . copy ( )
2024-06-18 02:48:15 +00:00
world . random . shuffle ( shuffled )
2023-11-22 14:29:33 +00:00
# Then put new text in
for bucket_idx , ( orig_idx , data ) in enumerate ( bucket ) :
rom . texts [ shuffled [ bucket_idx ] [ 0 ] ] = data
2024-06-18 02:48:15 +00:00
if world . options . trendy_game != TrendyGame . option_normal :
2023-03-20 16:26:03 +00:00
# TODO: if 0 or 4, 5, remove inaccurate conveyor tiles
2023-10-01 23:16:25 +00:00
2023-03-20 16:26:03 +00:00
room_editor = RoomEditor ( rom , 0x2A0 )
2024-06-18 02:48:15 +00:00
if world . options . trendy_game == TrendyGame . option_easy :
2023-03-20 16:26:03 +00:00
# Set physics flag on all objects
for i in range ( 0 , 6 ) :
rom . banks [ 0x4 ] [ 0x6F1E + i - 0x4000 ] = 0x4
else :
# All levels
# Set physics flag on yoshi
rom . banks [ 0x4 ] [ 0x6F21 - 0x4000 ] = 0x3
# Add new conveyor to "push" yoshi (it's only a visual)
room_editor . objects . append ( Object ( 5 , 3 , 0xD0 ) )
2024-06-18 02:48:15 +00:00
if world . options . trendy_game > = TrendyGame . option_harder :
2023-03-20 16:26:03 +00:00
"""
Data_004_76A0 : :
db $ FC , $ 00 , $ 04 , $ 00 , $ 00
Data_004_76A5 : :
db $ 00 , $ 04 , $ 00 , $ FC , $ 00
"""
speeds = {
TrendyGame . option_harder : ( 3 , 8 ) ,
TrendyGame . option_hardest : ( 3 , 8 ) ,
TrendyGame . option_impossible : ( 3 , 16 ) ,
}
def speed ( ) :
2024-06-18 02:48:15 +00:00
return world . random . randint ( * speeds [ world . options . trendy_game ] )
2023-10-01 23:16:25 +00:00
rom . banks [ 0x4 ] [ 0x76A0 - 0x4000 ] = 0xFF - speed ( )
2023-03-20 16:26:03 +00:00
rom . banks [ 0x4 ] [ 0x76A2 - 0x4000 ] = speed ( )
rom . banks [ 0x4 ] [ 0x76A6 - 0x4000 ] = speed ( )
rom . banks [ 0x4 ] [ 0x76A8 - 0x4000 ] = 0xFF - speed ( )
2024-06-18 02:48:15 +00:00
if world . options . trendy_game > = TrendyGame . option_hardest :
2023-10-01 23:16:25 +00:00
rom . banks [ 0x4 ] [ 0x76A1 - 0x4000 ] = 0xFF - speed ( )
2023-03-20 16:26:03 +00:00
rom . banks [ 0x4 ] [ 0x76A3 - 0x4000 ] = speed ( )
rom . banks [ 0x4 ] [ 0x76A5 - 0x4000 ] = speed ( )
rom . banks [ 0x4 ] [ 0x76A7 - 0x4000 ] = 0xFF - speed ( )
room_editor . store ( rom )
# This doesn't work, you can set random conveyors, but they aren't used
# for x in range(3, 9):
# for y in range(1, 5):
# room_editor.objects.append(Object(x, y, 0xCF + rnd.randint(0, 3)))
# Attempt at imitating gb palette, fails
if False :
gb_colors = [
[ 0x0f , 0x38 , 0x0f ] ,
[ 0x30 , 0x62 , 0x30 ] ,
[ 0x8b , 0xac , 0x0f ] ,
2023-10-01 23:16:25 +00:00
[ 0x9b , 0xbc , 0x0f ] ,
2023-03-20 16:26:03 +00:00
]
for color in gb_colors :
for channel in range ( 3 ) :
color [ channel ] = color [ channel ] * 31 / / 0xbc
2023-10-01 23:16:25 +00:00
2024-12-03 05:59:55 +00:00
if world . options . warps != Warps . option_vanilla :
patches . core . addWarpImprovements ( rom , world . options . warps == Warps . option_improved_additional )
2023-03-20 16:26:03 +00:00
2024-06-18 02:48:15 +00:00
palette = world . options . palette
2023-03-20 16:26:03 +00:00
if palette != Palette . option_normal :
ranges = {
# Object palettes
# Overworld palettes
# Dungeon palettes
# Interior palettes
" code/palettes.asm 1 " : ( 0x21 , 0x1518 , 0x34A0 ) ,
# Intro/outro(?)
# File select
# S+Q
# Map
" code/palettes.asm 2 " : ( 0x21 , 0x3536 , 0x3FFE ) ,
# Used for transitioning in and out of forest
" backgrounds/palettes.asm " : ( 0x24 , 0x3478 , 0x3578 ) ,
# Haven't yet found menu palette
}
for name , ( bank , start , end ) in ranges . items ( ) :
def clamp ( x , min , max ) :
if x < min :
return min
if x > max :
return max
return x
for address in range ( start , end , 2 ) :
packed = ( rom . banks [ bank ] [ address + 1 ] << 8 ) | rom . banks [ bank ] [ address ]
r , g , b = bin_to_rgb ( packed )
2023-10-01 23:16:25 +00:00
2023-03-20 16:26:03 +00:00
# 1 bit
if palette == Palette . option_1bit :
r & = 0b10000
g & = 0b10000
b & = 0b10000
# 2 bit
elif palette == Palette . option_1bit :
r & = 0b11000
g & = 0b11000
b & = 0b11000
# Invert
elif palette == Palette . option_inverted :
r = 31 - r
g = 31 - g
b = 31 - b
# Pink
elif palette == Palette . option_pink :
r = r / / 2
r + = 16
r = int ( r )
r = clamp ( r , 0 , 0x1F )
b = b / / 2
b + = 16
b = int ( b )
b = clamp ( b , 0 , 0x1F )
elif palette == Palette . option_greyscale :
# gray=int(0.299*r+0.587*g+0.114*b)
gray = ( r + g + b ) / / 3
r = g = b = gray
packed = rgb_to_bin ( r , g , b )
rom . banks [ bank ] [ address ] = packed & 0xFF
rom . banks [ bank ] [ address + 1 ] = packed >> 8
SEED_LOCATION = 0x0134
# Patch over the title
2024-06-18 02:48:15 +00:00
assert ( len ( world . multi_key ) == 12 )
rom . patch ( 0x00 , SEED_LOCATION , None , binascii . hexlify ( world . multi_key ) )
2023-03-20 16:26:03 +00:00
for pymod in pymods :
pymod . postPatch ( rom )
return rom