Beispiel #1
0
def validate_rom():
    """Validate MD5 matches the expected value"""
    if os.path.exists(DKONG_ZIP):
        buffer = open(DKONG_ZIP, 'rb').read()
        md5 = hashlib.md5(buffer).hexdigest()
        if md5 == "a13e81d6ef342d763dc897fe03893392":
            # ZIP is verified
            return True
        elif md5 in FIX_ALTERNATIVE_MD5:
            # ZIP has a recognised MD5 and can be converted using patch file
            alt_zip = os.path.join(ROM_DIR, f"dkong_{md5}.zip")
            shutil.copy(DKONG_ZIP, alt_zip)
            if os.path.exists(alt_zip):
                # Read the alternative ZIP binary
                with open(alt_zip, 'rb') as f_in:
                    alt_binary = f_in.read()
                ips = os.path.join(PATCH_DIR, f"fix_{md5}.ips")
                if os.path.exists(ips):
                    # Apply patch and write the fixed DKONG.ZIP to roms
                    patch = Patch.load(ips)
                    with open(DKONG_ZIP, 'w+b') as f_out:
                        f_out.write(patch.apply(alt_binary))
                    return True
            return False
        else:
            return False
    else:
        # No rom file so a verification error not is returned
        return True
Beispiel #2
0
    def __save_reload_and_apply(patch, source):
        encoded_patch = patch.encode()
        decoded_patch = None

        with tempfile.NamedTemporaryFile(delete=False) as f:
            f.write(encoded_patch)
            f.close()

            decoded_patch = Patch.load(f.name)

            os.unlink(f.name)

        return decoded_patch.apply(source)
Beispiel #3
0
def cmd_apply(args):
    patch = Patch.load(args.ips_file)

    in_file = None
    with open(args.in_file, 'rb') as f:
        in_file = f.read()

    out_file = patch.apply(in_file)

    if 'out_file' in args:
        with open(args.out_file, 'w+b') as f:
            f.write(out_file)
    else:
        sys.stdout.buffer.write(out_file)
Beispiel #4
0
def apply_patches():
    applied_patches_list = []
    if os.path.exists(DKONG_ZIP):
        ips_files = glob(os.path.join(PATCH_DIR, "dkong*.ips"))
        if ips_files:
            # Read the original ZIP binary
            with open(DKONG_ZIP, 'rb') as f_in:
                dkong_binary = f_in.read()

            # Apply patch and write the resulting hack to a subfolder
            for ips in ips_files:
                name = os.path.splitext(os.path.basename(ips))[0]
                subfolder = os.path.join(ROM_DIR, name)
                if not os.path.exists(subfolder):
                    os.mkdir(subfolder)
                    patch = Patch.load(ips)
                    with open(os.path.join(subfolder, "dkong.zip"),
                              'w+b') as f_out:
                        f_out.write(patch.apply(dkong_binary))
                        applied_patches_list.append(name)
    return applied_patches_list
Beispiel #5
0
def randomize_rom(rom: Rom, flags: Flags, rom_seed: str) -> Rom:
    rng = random.Random()
    rng.seed(rom_seed)

    print(f"Randomize ROM: {flags.text()}, seed='{rom_seed}'")
    patches_to_load = BASE_PATCHES
    if flags.encounters is not None:
        patches_to_load.append("data/FF1EncounterToggle.ips")
    if flags.default_party is not None:
        patches_to_load.append("data/RandomDefault.ips")

    patched_rom_data = rom.rom_data

    for patch_path in patches_to_load:
        patch = Patch.load(patch_path)
        patched_rom_data = patch.apply(patched_rom_data)
    rom = Rom(data=bytearray(patched_rom_data))

    rom = init_free_airship(rom)
    rom = add_credits(rom)

    event_text_block = EventTextBlock(rom)
    event_text_block.shrink()
    rom = event_text_block.pack(rom)

    rom = update_xp_requirements(rom, flags.exp_mult)

    if flags.key_item_shuffle is not None:
        placement = KeyItemPlacement(rom, rng.randint(0, 0xffffffff))
    else:
        placement = KeyItemPlacement(rom)
    rom = placement.rom

    if flags.magic is not None:
        shuffle_magic = SpellShuffle(rom, rng)
        rom = shuffle_magic.write(rom)

    if flags.treasures is not None:
        if flags.treasures == "shuffle":
            rom = treasure_shuffle(rom, rng)
        else:
            rom = random_bucketed_treasures(rom, rng, flags.wealth)

    if flags.debug is not None:
        class_stats_stream = rom.open_bytestream(0x1E1354, 96)
        class_stats = []
        while not class_stats_stream.is_eos():
            class_stats.append(JobClass(class_stats_stream))

        class_out_stream = OutputStream()
        for job_class in class_stats:
            # Set the starting weapon and armor for all classes to something
            # very fair and balanced: Masamune + Diamond Armlet. :)
            job_class.weapon_id = 0x28
            job_class.armor_id = 0x0e

            # Write the (very balanced) new data out
            job_class.write(class_out_stream)

        rom = rom.apply_patch(0x1E1354, class_out_stream.get_buffer())

    if flags.shuffle_formations:
        formation = FormationRandomization(rom, rng)
        rom = rom.apply_patches(formation.patches())

    if True:
        enemy_data_stream = rom.open_bytestream(0x1DE044, 0x1860)
        enemies = []
        while not enemy_data_stream.is_eos():
            enemies.append(EnemyStats(enemy_data_stream))

        # Rebalance (Revisited) Fiend HP
        enemies[0x78].max_hp = enemies[0x77].max_hp * 2
        enemies[0x7a].max_hp = enemies[0x79].max_hp * 2
        enemies[0x7c].max_hp = enemies[0x7b].max_hp * 2
        enemies[0x7e].max_hp = enemies[0x7d].max_hp * 2

        # And Chaos
        enemies[0x7f].max_hp = enemies[0x7e].max_hp * 2

        # Finally, Piscodemons can suck it
        enemies[0x67].atk = int(enemies[0x67].atk / 2)

        # We'll also lower everyone's INT just to see how that works
        for index in range(0x80):
            enemies[index].intel = int(.666 * enemies[index].intel)
            # print(f"{hex(index)} HP: {enemies[index].max_hp}, INT: {enemies[index].intel}")

        out = OutputStream()
        for enemy in enemies:
            enemy.write(out)
        rom = rom.apply_patch(0x1DE044, out.get_buffer())

    # Add the seed + flags to the party creation screen.
    seed_str = TextBlock.encode_text(f"Seed:\n{rom_seed}\nFlags:\n{flags}\x00")
    pointer = OutputStream()
    pointer.put_u32(0x8227054)
    rom = rom.apply_patches({
        0x227054: seed_str,
        0x4d8d4: pointer.get_buffer()
    })

    return rom
Beispiel #6
0
def cmd_trace(args):
    patch = Patch.load(args.ips_file)
    patch.trace()