Beispiel #1
0
    def ncsd_header(self, slot):
        """Retrieve NCSD header from rom on sdcard.

        This function retrieves the ncsd header from the specified rom on sdcard."""

        self.fail_on_non_sky3ds()

        self.diskfp.seek(self.rom_list[slot][1])
        return gamecard.ncsd_header(self.diskfp.read(0x1200))
Beispiel #2
0
    def ncsd_header(self, slot):
        """Retrieve NCSD header from rom on sdcard.

        This function retrieves the ncsd header from the specified rom on sdcard."""

        self.fail_on_non_sky3ds()

        self.diskfp.seek(self.rom_list[slot][1])
        return gamecard.ncsd_header(self.diskfp.read(0x1200))
Beispiel #3
0
    def find_game(self, product_code):
        """Find a game on sdcard by product-code

        This function is used to automatically restore savegames to the right game.
        It basically gets the product-codes of all roms on sdcard and compares it
        to the given argument.

        Keyword Arguments:
        product_code -- product-code to look for on sdcard"""

        self.fail_on_non_sky3ds()

        slot = -1
        rom_count = 0
        for rom in self.rom_list:
            self.diskfp.seek(rom[1])
            ncsd_header = gamecard.ncsd_header(self.diskfp.read(0x1200))
            if ncsd_header['product_code'] == product_code:
                return (rom_count, ncsd_header)
            rom_count += 1
        return (None, None)
Beispiel #4
0
    def find_game(self, product_code):
        """Find a game on sdcard by product-code

        This function is used to automatically restore savegames to the right game.
        It basically gets the product-codes of all roms on sdcard and compares it
        to the given argument.

        Keyword Arguments:
        product_code -- product-code to look for on sdcard"""

        self.fail_on_non_sky3ds()

        slot = -1
        rom_count = 0
        for rom in self.rom_list:
            self.diskfp.seek(rom[1])
            ncsd_header = gamecard.ncsd_header(self.diskfp.read(0x1200))
            if ncsd_header['product_code'] == product_code:
                return (rom_count, ncsd_header)
            rom_count+=1
        return (None, None)
Beispiel #5
0
    def dump_savegame(self, slot, output):
        """Dump savegame from sdcard to file

        This code first looks at the actual game header of the rom in the
        specified slot to figure out if this is a Card1 or Card2 savegame based
        game.

        For Card1 savegames it just dumps the savegame from the preallocated
        region of Card1 savegames (0x100000 - 0x2000000, 31 each 0x100000 / 1MB).
        The savegame file has 'CTR_SAVE', the product code of the game, a mark
        that this is a Card1 savegame and some padding in front of the actual
        savegame data.

        For Card2 savegames it reads the writable_address from the games
        ncsd-header, and dumps 10MB from that location to a file.
        The savegame file also has 'CTR_SAVE', the product-code and a (different)
        mark in front of the actual savegame as well as the type and size of
        (emulated) game chip.

        Keyword Arguments:
        slot -- rom slot
        output -- output savegame file"""

        self.fail_on_non_sky3ds()

        if slot >= len(self.rom_list):
            raise Exception("Slot not found")

        self.diskfp.seek(0)

        self.diskfp.seek(self.rom_list[slot][1])
        ncsd_header = gamecard.ncsd_header(self.diskfp.read(0x1200))

        savegamefp = open(output, "wb")

        # 0x00 CTR_SAVE
        savegamefp.write(b'CTR_SAVE')

        # 0x08 Product Code
        savegamefp.write(bytearray(
            ncsd_header['product_code'].encode('ascii')))

        # Zero-Padding + Save Type (0x00 = Card1, 0x01 = Card2)
        if ncsd_header['card_type'] == 'Card1':
            savegamefp.write(bytearray([0x00, 0x00]))
        else:
            savegamefp.write(bytearray([0x00, 0x01]))

        # Nand save offset / Writable Address
        self.diskfp.seek(self.rom_list[slot][1] + 0x200)
        savegamefp.write(self.diskfp.read(0x4))

        # Unique ID (0x40 bytes but only 0x10 really used)
        self.diskfp.seek(self.rom_list[slot][1] + 0x1440)
        savegamefp.write(self.diskfp.read(0x40))

        # Savegame Data
        if ncsd_header['card_type'] == 'Card1':
            # from card1 region (byte 1M - 32M on disk)
            self.diskfp.seek(0x100000 * (slot + 1))
            savegamefp.write(self.diskfp.read(0x100000))
        else:
            # from writable region in rom
            self.diskfp.seek(self.rom_list[slot][1] +
                             ncsd_header['writable_address'])
            for i in range(0, 10):
                savegamefp.write(self.diskfp.read(0x100000))

        savegamefp.close()
Beispiel #6
0
    def dump_savegame(self, slot, output):
        """Dump savegame from sdcard to file

        This code first looks at the actual game header of the rom in the
        specified slot to figure out if this is a Card1 or Card2 savegame based
        game.

        For Card1 savegames it just dumps the savegame from the preallocated
        region of Card1 savegames (0x100000 - 0x2000000, 31 each 0x100000 / 1MB).
        The savegame file has 'CTR_SAVE', the product code of the game, a mark
        that this is a Card1 savegame and some padding in front of the actual
        savegame data.

        For Card2 savegames it reads the writable_address from the games
        ncsd-header, and dumps 10MB from that location to a file.
        The savegame file also has 'CTR_SAVE', the product-code and a (different)
        mark in front of the actual savegame as well as the type and size of
        (emulated) game chip.

        Keyword Arguments:
        slot -- rom slot
        output -- output savegame file"""

        self.fail_on_non_sky3ds()

        if slot >= len(self.rom_list):
            raise Exception("Slot not found")

        self.diskfp.seek(0)

        self.diskfp.seek(self.rom_list[slot][1])
        ncsd_header = gamecard.ncsd_header(self.diskfp.read(0x1200))

        savegamefp = open(output, "wb")

        # 0x00 CTR_SAVE
        savegamefp.write(b'CTR_SAVE')

        # 0x08 Product Code
        savegamefp.write(bytearray(ncsd_header['product_code'].encode('ascii')))

        # Zero-Padding + Save Type (0x00 = Card1, 0x01 = Card2)
        if ncsd_header['card_type'] == 'Card1':
            savegamefp.write(bytearray([0x00, 0x00]))
        else:
            savegamefp.write(bytearray([0x00, 0x01]))

        # Nand save offset / Writable Address
        self.diskfp.seek(self.rom_list[slot][1] + 0x200)
        savegamefp.write(self.diskfp.read(0x4))

        # Unique ID (0x40 bytes but only 0x10 really used)
        self.diskfp.seek(self.rom_list[slot][1] + 0x1440)
        savegamefp.write(self.diskfp.read(0x40))

        # Savegame Data
        if ncsd_header['card_type'] == 'Card1':
            # from card1 region (byte 1M - 32M on disk)
            self.diskfp.seek(0x100000 * (slot + 1))
            savegamefp.write(self.diskfp.read(0x100000))
        else:
            # from writable region in rom
            self.diskfp.seek(self.rom_list[slot][1] + ncsd_header['writable_address'])
            for i in range(0, 10):
                savegamefp.write(self.diskfp.read(0x100000))

        savegamefp.close()