From ce30913121bb5c69011cd06634f0b31d41955b62 Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Sun, 17 Dec 2017 17:30:50 -0500 Subject: [PATCH] Get sprite json from vt.alttp.run Fix plando's sprite support Always write both sprite and pallet (using the default if a sprite does not include a pallet) so that the adjuster still works. --- Gui.py | 8 ++++---- Plando.py | 4 ++-- Rom.py | 16 +++++++--------- Zelda.sprite | Bin 28672 -> 0 bytes 4 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 Zelda.sprite diff --git a/Gui.py b/Gui.py index 39ce2292..e197100d 100644 --- a/Gui.py +++ b/Gui.py @@ -456,7 +456,8 @@ class SpriteSelector(object): try: task.update_status("Downloading official sprites list") - sprites_arr = json.loads(temp_sprites_json) + with urlopen('http://vt.alttp.run/sprites') as response: + sprites_arr = json.load(response) except Exception as e: resultmessage = "Error getting list of official sprites. Sprites not updated.\n\n%s: %s" % (type(e).__name__, e) successful = False @@ -468,7 +469,8 @@ class SpriteSelector(object): current_sprites = [os.path.basename(file) for file in glob(self.official_sprite_dir+'/*')] official_sprites = [(sprite['file'], os.path.basename(urlparse(sprite['file']).path)) for sprite in sprites_arr] needed_sprites = [(sprite_url, filename) for (sprite_url, filename) in official_sprites if filename not in current_sprites] - bundled_sprites = [] + bundled_sprites = [os.path.basename(file) for file in glob(self.local_official_sprite_dir+'/*')] + # todo: eventually use the above list to avoid downloading any sprites that we already have cached in the bundle. official_filenames = [filename for (_, filename) in official_sprites] obsolete_sprites = [sprite for sprite in current_sprites if sprite not in official_filenames] @@ -653,7 +655,5 @@ def get_image_for_sprite(sprite): return image.zoom(2) -temp_sprites_json = '''[{"name":"Link","file":"http:\/\/spr.beegunslingers.com\/link.1.spr"},{"name":"Four Swords Link","file":"http:\/\/spr.beegunslingers.com\/4slink-armors.1.spr"},{"name":"Boo","file":"http:\/\/spr.beegunslingers.com\/boo.2.spr"},{"name":"Boy","file":"http:\/\/spr.beegunslingers.com\/boy.2.spr"},{"name":"Cactuar","file":"http:\/\/spr.beegunslingers.com\/cactuar.1.spr"},{"name":"Cat","file":"http:\/\/spr.beegunslingers.com\/cat.1.spr"},{"name":"Cat Boo","file":"http:\/\/spr.beegunslingers.com\/catboo.1.spr"},{"name":"Cirno","file":"http:\/\/spr.beegunslingers.com\/cirno.1.spr"},{"name":"Dark Boy","file":"http:\/\/spr.beegunslingers.com\/darkboy.2.spr"},{"name":"Dark Girl","file":"http:\/\/spr.beegunslingers.com\/darkgirl.1.spr"},{"name":"Dark Link","file":"http:\/\/spr.beegunslingers.com\/darklink.1.spr"},{"name":"Dark Maple Queen","file":"http:\/\/spr.beegunslingers.com\/shadowsaku.1.spr"},{"name":"Dark Swatchy","file":"http:\/\/spr.beegunslingers.com\/darkswatchy.1.spr"},{"name":"Dark Zelda","file":"http:\/\/spr.beegunslingers.com\/darkzelda.1.spr"},{"name":"Dark Zora","file":"http:\/\/spr.beegunslingers.com\/darkzora.2.spr"},{"name":"Decidueye","file":"http:\/\/spr.beegunslingers.com\/decidueye.1.spr"},{"name":"Demon Link","file":"http:\/\/spr.beegunslingers.com\/demonlink.1.spr"},{"name":"Frog","file":"http:\/\/spr.beegunslingers.com\/froglink.2.spr"},{"name":"Ganondorf","file":"http:\/\/spr.beegunslingers.com\/ganondorf.1.spr"},{"name":"Garfield","file":"http:\/\/spr.beegunslingers.com\/garfield.1.spr"},{"name":"Girl","file":"http:\/\/spr.beegunslingers.com\/girl.2.spr"},{"name":"Headless Link","file":"http:\/\/spr.beegunslingers.com\/headlesslink.1.spr"},{"name":"Invisible Man","file":"http:\/\/spr.beegunslingers.com\/invisibleman.1.spr"},{"name":"Inkling","file":"http:\/\/spr.beegunslingers.com\/inkling.1.spr"},{"name":"Kirby","file":"http:\/\/spr.beegunslingers.com\/kirby-meta.2.spr"},{"name":"Kore8","file":"http:\/\/spr.beegunslingers.com\/kore8.1.spr"},{"name":"Pony","file":"http:\/\/spr.beegunslingers.com\/littlepony.1.spr"},{"name":"Luigi","file":"http:\/\/spr.beegunslingers.com\/luigi.1.spr"},{"name":"Maiden","file":"http:\/\/spr.beegunslingers.com\/maiden.2.spr"},{"name":"Maple Queen","file":"http:\/\/spr.beegunslingers.com\/maplequeen.1.spr"},{"name":"Mario","file":"http:\/\/spr.beegunslingers.com\/mario-classic.1.spr"},{"name":"Marisa","file":"http:\/\/spr.beegunslingers.com\/marisa.1.spr"},{"name":"Mike Jones","file":"http:\/\/spr.beegunslingers.com\/mikejones.2.spr"},{"name":"Minish Cap Link","file":"http:\/\/spr.beegunslingers.com\/minishcaplink.3.spr"},{"name":"Modern Link","file":"http:\/\/spr.beegunslingers.com\/modernlink.1.spr"},{"name":"Mog","file":"http:\/\/spr.beegunslingers.com\/mog.1.spr"},{"name":"Mouse","file":"http:\/\/spr.beegunslingers.com\/mouse.1.spr"},{"name":"Nature Link","file":"http:\/\/spr.beegunslingers.com\/naturelink.1.spr"},{"name":"Negative Link","file":"http:\/\/spr.beegunslingers.com\/negativelink.1.spr"},{"name":"Neon Link","file":"http:\/\/spr.beegunslingers.com\/neonlink.1.spr"},{"name":"Old Man","file":"http:\/\/spr.beegunslingers.com\/oldman.1.spr"},{"name":"Pink Ribbon Link","file":"http:\/\/spr.beegunslingers.com\/pinkribbonlink.1.spr"},{"name":"Popoi","file":"http:\/\/spr.beegunslingers.com\/popoi.1.spr"},{"name":"Pug","file":"http:\/\/spr.beegunslingers.com\/pug.2.spr"},{"name":"Purple Chest","file":"http:\/\/spr.beegunslingers.com\/purplechest-bottle.2.spr"},{"name":"Roy Koopa","file":"http:\/\/spr.beegunslingers.com\/roykoopa.1.spr"},{"name":"Rumia","file":"http:\/\/spr.beegunslingers.com\/rumia.1.spr"},{"name":"Samus","file":"http:\/\/spr.beegunslingers.com\/samus.4.spr"},{"name":"Soda Can","file":"http:\/\/spr.beegunslingers.com\/sodacan.1.spr"},{"name":"Static Link","file":"http:\/\/spr.beegunslingers.com\/staticlink.1.spr"},{"name":"Santa Link","file":"http:\/\/spr.beegunslingers.com\/santalink.1.spr"},{"name":"Super Bunny","file":"http:\/\/spr.beegunslingers.com\/superbunny.1.spr"},{"name":"Swatchy","file":"http:\/\/spr.beegunslingers.com\/swatchy.1.spr"},{"name":"Tingle","file":"http:\/\/spr.beegunslingers.com\/tingle.1.spr"},{"name":"Toad","file":"http:\/\/spr.beegunslingers.com\/toad.1.spr"},{"name":"Valeera","file":"http:\/\/spr.beegunslingers.com\/valeera.1.spr"},{"name":"Vitreous","file":"http:\/\/spr.beegunslingers.com\/vitreous.1.spr"},{"name":"Vivi","file":"http:\/\/spr.beegunslingers.com\/vivi.1.spr"},{"name":"Will","file":"http:\/\/spr.beegunslingers.com\/will.1.spr"},{"name":"Wizzrobe","file":"http:\/\/spr.beegunslingers.com\/wizzrobe.4.spr"},{"name":"Yunica","file":"http:\/\/spr.beegunslingers.com\/yunica.1.spr"},{"name":"Zelda","file":"http:\/\/spr.beegunslingers.com\/zelda.2.spr"},{"name":"Zero Suit Samus","file":"http:\/\/spr.beegunslingers.com\/zerosuitsamus.1.spr"},{"name":"Zora","file":"http:\/\/spr.beegunslingers.com\/zora.1.spr"}]''' - if __name__ == '__main__': guiMain() diff --git a/Plando.py b/Plando.py index 3908c06c..64a72afd 100644 --- a/Plando.py +++ b/Plando.py @@ -9,7 +9,7 @@ import sys from BaseClasses import World from Regions import create_regions from EntranceShuffle import link_entrances, connect_entrance, connect_two_way, connect_exit -from Rom import patch_rom, LocalRom, write_string_to_rom +from Rom import patch_rom, LocalRom, Sprite, write_string_to_rom from Rules import set_rules from Dungeons import create_dungeons from Items import ItemFactory @@ -75,7 +75,7 @@ def main(args): logger.info('Patching ROM.') if args.sprite is not None: - sprite = bytearray(open(args.sprite, 'rb').read()) + sprite = Sprite(args.sprite) else: sprite = None diff --git a/Rom.py b/Rom.py index eb860b55..ffe1b593 100644 --- a/Rom.py +++ b/Rom.py @@ -114,8 +114,8 @@ class Sprite(object): if len(filedata) == 0x7000: # sprite file with graphics and without palette data self.sprite = filedata[:0x7000] - self.palette = None - self.glove_palette = None + self.palette = list(self.default_palette) + self.glove_palette = list(self.default_glove_palette) elif len(filedata) == 0x7078: # sprite file with graphics and palette data self.sprite = filedata[:0x7000] @@ -142,11 +142,11 @@ class Sprite(object): return self.sprite = sprite if len(palette) == 0: - self.palette = None - self.glove_palette = None + self.palette = list(self.default_palette) + self.glove_palette = list(self.default_glove_palette) elif len(palette) == 0x78: self.palette = palette - self.glove_palette = None + self.glove_palette = list(self.default_glove_palette) elif len(palette) == 0x7C: self.palette = palette[:0x78] self.glove_palette = palette[0x78:] @@ -849,10 +849,8 @@ def write_sprite(rom, sprite): if not sprite.valid: return rom.write_bytes(0x80000, sprite.sprite) - if sprite.palette is not None: - rom.write_bytes(0xDD308, sprite.palette) - if sprite.glove_palette is not None: - rom.write_bytes(0xDEDF5, sprite.glove_palette) + rom.write_bytes(0xDD308, sprite.palette) + rom.write_bytes(0xDEDF5, sprite.glove_palette) def write_string_to_rom(rom, target, string): diff --git a/Zelda.sprite b/Zelda.sprite deleted file mode 100644 index 201e4c0e711eb9ae60f12414549d3cd62eb49187..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 xVqbc;v)lK>mK*zS=~#4X