Example #1
0
def extract(file):
    """
    Extrct the given archive
    """
    with open(file, "rb") as inf:
        inb = inf.read()

    while libyaz0.IsYazCompressed(inb):
        inb = libyaz0.decompress(inb)

    name = os.path.splitext(file)[0]
    ext = SarcLib.guessFileExt(inb)

    if ext != ".sarc":
        with open(''.join([name, ext]), "wb") as out:
            out.write(inb)

    else:
        arc = SarcLib.SARC_Archive()
        arc.load(inb)

        root = os.path.join(os.path.dirname(file), name)
        if not os.path.isdir(root):
            os.mkdir(root)

        files = []

        def getAbsPath(folder, path):
            nonlocal root
            nonlocal files

            for checkObj in folder.contents:
                if isinstance(checkObj, SarcLib.File):
                    files.append(
                        ["/".join([path, checkObj.name]), checkObj.data])

                else:
                    path_ = os.path.join(root, "/".join([path, checkObj.name]))
                    if not os.path.isdir(path_):
                        os.mkdir(path_)

                    getAbsPath(checkObj, "/".join([path, checkObj.name]))

        for checkObj in arc.contents:
            if isinstance(checkObj, SarcLib.File):
                files.append([checkObj.name, checkObj.data])

            else:
                path = os.path.join(root, checkObj.name)
                if not os.path.isdir(path):
                    os.mkdir(path)

                getAbsPath(checkObj, checkObj.name)

        for file, fileData in files:
            print(file)
            with open(os.path.join(root, file), "wb") as out:
                out.write(fileData)
Example #2
0
def addFileToLayout(arc, folderName, name, data):
    fileAdded = False
    for folder in arc.contents:
        if isinstance(folder, SarcLib.Folder) and folder.name == "lyt_root":
            for lytFolder in folder.contents:
                if isinstance(lytFolder,
                              SarcLib.Folder) and lytFolder.name == folderName:
                    for file in lytFolder.contents:
                        if isinstance(file,
                                      SarcLib.File) and file.name == name:
                            lytFolder.removeFile(file)
                            break

                    file = SarcLib.File()
                    file.name = name
                    file.data = data

                    lytFolder.addFile(file)
                    fileAdded = True

                if fileAdded:
                    break

        if fileAdded:
            break

    if fileAdded:
        print("Added: %s" % name)

    else:
        print("Something went wrong while adding %s!" % name)

    return arc
Example #3
0
    def saveSarc(self):
        arcContents = self.editor.getDataFromWidgets()
        newArchive = SarcLib.SARC_Archive(endianness='<')

        for file in arcContents:
            newArchive.addFile(file)

        outFile = newArchive.save()[0]

        with open(self.currentFilePath, 'wb+') as f:
            f.write(outFile)
Example #4
0
    def save(self):
        arc = SarcLib.SARC_Archive()
        self.addSpriteFiles()

        # Look up every tileset used in each area
        tilesets_names = []
        for area_SARC in self.areas:
            if area_SARC.tileset0 not in ('', None):
                tilesets_names.append(area_SARC.tileset0)

            if area_SARC.tileset1 not in ('', None):
                tilesets_names.append(area_SARC.tileset1)

            if area_SARC.tileset2 not in ('', None):
                tilesets_names.append(area_SARC.tileset2)

            if area_SARC.tileset3 not in ('', None):
                tilesets_names.append(area_SARC.tileset3)

        tilesets_names = tuple(set(tilesets_names))

        # Add each tileset to our archive
        for tileset_name in tilesets_names:
            if tileset_name not in self.szsData:
                if os.path.isfile(
                        os.path.join(globals.mod_path,
                                     'Stage/Texture/%s.szs' % tileset_name)):
                    with open(
                            os.path.join(globals.mod_path,
                                         'Stage/Texture/%s.szs' %
                                         tileset_name), "rb") as inf:
                        self.szsData[tileset_name] = DecompYaz0(inf.read())

                else:
                    print("Tileset %s not found!" % tileset_name)

        for file in self.szsData:
            arc.addFile(SarcLib.File(file, self.szsData[file]))

        return arc.save()[0]
Example #5
0
    def saveSarc(self):
        if self.currentFileType == 'map':
            arcContents = self.editor.getDataFromWidgets()
            newArchive = SarcLib.SARC_Archive()

            for file in arcContents:
                newArchive.addFile(file)

            outFile = newArchive.save()[0]
            CompYaz0(outFile, self.currentFilePath)
        else:
            outFile = self.editor.getCamData()

            with open(self.currentFilePath, 'wb+') as f:
                f.write(outFile)
Example #6
0
    def saveSarcAs(self):
        arcContents = self.editor.getDataFromWidgets()
        newArchive = SarcLib.SARC_Archive(endianness='<')

        for file in arcContents:
            newArchive.addFile(file)

        outFile = newArchive.save()[0]

        fileName = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save file', '', 'SARC files (*.sarc)')[0]

        if fileName == '':
            return

        with open(fileName, 'wb+') as f:
            f.write(outFile)
Example #7
0
        def save(self):
            """
            Save the level back to a file
            """

            # Make a new archive
            newArchive = SarcLib.SARC_Archive()

            # Create a folder within the archive
            courseFolder = SarcLib.Folder('course')
            newArchive.addFolder(courseFolder)

            # Go through the areas, save them and add them back to the archive
            for areanum, area in enumerate(self.areas):
                course, L0, L1, L2 = area.save()

                if course is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d.bin' % (areanum + 1), course))
                if L0 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL0.bin' % (areanum + 1),
                                     L0))
                if L1 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL1.bin' % (areanum + 1),
                                     L1))
                if L2 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL2.bin' % (areanum + 1),
                                     L2))

            outerArchive = SarcLib.SARC_Archive()
            outerArchive.addFile(SarcLib.File('level', newArchive.save()[0]))
            outerArchive.addFile(SarcLib.File('levelname', b'level'))

            return outerArchive.save()[0]
Example #8
0
    def loadSarc(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Open file', '', 'SARC files (*.sarc)')[0]

        if fileName == '':
            return

        self.currentFilePath = fileName

        with open(fileName, 'rb') as fileObj:
            data = fileObj.read()

        archive = SarcLib.SARC_Archive(data)
        archive.load(data)

        self.editor.loadData(archive.contents)

        self.saveFile.setDisabled(False)
        self.saveAsFile.setDisabled(False)
        self.closeFile.setDisabled(False)
        self.editor.setDisabled(False)
Example #9
0
    def loadSarc(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Open file', settings.value("LastPath", ""),
            'All Files (*.szs *.bin);;Route Archives (*.szs);;Map Camera Settings (*.bin)'
        )[0]
        if fileName == '':
            return

        self.currentFilePath = fileName
        self.setWindowTitle('RouteEdit NSMBU - %s' % self.currentFilePath)

        settings.setValue("LastPath", self.currentFilePath)

        with open(fileName, 'rb') as fileObj:
            data = fileObj.read()

        if fileName.endswith('.bin'):
            if len(data) != 0x1500:
                return
            self.editor.loadCamData(data)
            self.currentFileType = 'cam'

        else:
            if data[:4] != b'Yaz0':
                return

            data = DecompYaz0(data)
            if data[:4] != b'SARC':
                return

            archive = SarcLib.SARC_Archive(data)
            archive.load(data)

            self.editor.loadRouteData(archive.contents)
            self.currentFileType = 'map'

        self.saveFile.setDisabled(False)
        self.saveAsFile.setDisabled(False)
        self.closeFile.setDisabled(False)
        self.editor.setDisabled(False)
Example #10
0
def pack(root, endianness, level, outname):
    """
    Pack the files and folders in the root folder.
    """

    if "\\" in root:
        root = "/".join(root.split("\\"))

    if root[-1] == "/":
        root = root[:-1]

    arc = SarcLib.SARC_Archive(endianness=endianness)
    lenroot = len(root.split("/"))

    for path, dirs, files in os.walk(root):
        if "\\" in path:
            path = "/".join(path.split("\\"))

        lenpath = len(path.split("/"))

        if lenpath == lenroot:
            path = ""

        else:
            path = "/".join(path.split("/")[lenroot - lenpath:])

        for file in files:
            if path:
                filename = ''.join([path, "/", file])

            else:
                filename = file

            print(filename)

            fullname = ''.join([root, "/", filename])

            i = 0
            for folder in filename.split("/")[:-1]:
                if not i:
                    exec(
                        "folder%i = SarcLib.Folder(folder + '/'); arc.addFolder(folder%i)"
                        .replace('%i', str(i)))

                else:
                    exec(
                        "folder%i = SarcLib.Folder(folder + '/'); folder%m.addFolder(folder%i)"
                        .replace('%i', str(i)).replace('%m', str(i - 1)))

                i += 1

            with open(fullname, "rb") as f:
                inb = f.read()

            hasFilename = True
            if file[:5] == "hash_":
                hasFilename = False

            if not i:
                arc.addFile(SarcLib.File(file, inb, hasFilename))

            else:
                exec("folder%m.addFile(SarcLib.File(file, inb, hasFilename))".
                     replace('%m', str(i - 1)))

    data, maxAlignment = arc.save()

    if level != -1:
        outData = libyaz0.compress(data, maxAlignment, level)
        del data

        if not outname:
            outname = ''.join([root, ".szs"])

    else:
        outData = data
        if not outname:
            outname = ''.join([root, ".sarc"])

    with open(outname, "wb+") as output:
        output.write(outData)
Example #11
0
    def load(self, data, areaNum, progress=None):
        """
        Loads a NSMBU level from bytes data.
        """
        super().load(data, areaNum, progress)

        arc = SarcLib.SARC_Archive()
        arc.load(data)

        try:
            courseFolder = arc['course']
        except:
            return False

        # Sort the area data
        areaData = {}
        for file in courseFolder.contents:
            name, val = file.name, file.data

            if val is None: continue

            if not name.startswith('course'): continue
            if not name.endswith('.bin'): continue
            if '_bgdatL' in name:
                # It's a layer file
                if len(name) != 19: continue
                try:
                    thisArea = int(name[6])
                    laynum = int(name[14])
                except ValueError:
                    continue
                if not (0 < thisArea < 5): continue

                if thisArea not in areaData: areaData[thisArea] = [None] * 4
                areaData[thisArea][laynum + 1] = val
            else:
                # It's the course file
                if len(name) != 11: continue
                try:
                    thisArea = int(name[6])
                except ValueError:
                    continue
                if not (0 < thisArea < 5): continue

                if thisArea not in areaData: areaData[thisArea] = [None] * 4
                areaData[thisArea][0] = val

        # Create area objects
        self.areas = []
        thisArea = 1
        while thisArea in areaData:
            course = areaData[thisArea][0]
            L0 = areaData[thisArea][1]
            L1 = areaData[thisArea][2]
            L2 = areaData[thisArea][3]

            import area
            if thisArea == areaNum:
                newarea = area.Area_NSMBU()
                globals.Area = newarea
                SLib.Area = globals.Area
            else:
                newarea = area.AbstractArea()

            newarea.areanum = thisArea
            newarea.load(course, L0, L1, L2, progress)
            self.areas.append(newarea)

            thisArea += 1

        return True
Example #12
0
    def saveNewArea(self, innerfilename, course_new, L0_new, L1_new, L2_new):
        """
        Save the level back to a file (when adding a new or deleting an existing Area)
        """

        # Make a new archive
        newArchive = SarcLib.SARC_Archive()

        # Create a folder within the archive
        courseFolder = SarcLib.Folder('course')
        newArchive.addFolder(courseFolder)

        # Go through the areas, save them and add them back to the archive
        for areanum, area in enumerate(self.areas):
            course, L0, L1, L2 = area.save(True)

            if course is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d.bin' % (areanum + 1), course))
            if L0 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL0.bin' % (areanum + 1), L0))
            if L1 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL1.bin' % (areanum + 1), L1))
            if L2 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL2.bin' % (areanum + 1), L2))

        if course_new is not None:
            courseFolder.addFile(
                SarcLib.File('course%d.bin' % (len(self.areas) + 1),
                             course_new))
        if L0_new is not None:
            courseFolder.addFile(
                SarcLib.File('course%d_bgdatL0.bin' % (len(self.areas) + 1),
                             L0_new))
        if L1_new is not None:
            courseFolder.addFile(
                SarcLib.File('course%d_bgdatL1.bin' % (len(self.areas) + 1),
                             L1_new))
        if L2_new is not None:
            courseFolder.addFile(
                SarcLib.File('course%d_bgdatL2.bin' % (len(self.areas) + 1),
                             L2_new))

        # Here we have the new inner-SARC savedata
        innersarc = newArchive.save()[0]

        # Now make an outer SARC
        outerArchive = SarcLib.SARC_Archive()

        # Add the innersarc to it
        outerArchive.addFile(SarcLib.File(innerfilename, innersarc))

        # Make it easy for future Miyamotos to pick out the innersarc level name
        outerArchive.addFile(
            SarcLib.File('levelname', innerfilename.encode('utf-8')))

        # Add all the other stuff, too
        for szsThingName in globals.szsData:
            if szsThingName in [globals.levelNameCache, 'levelname']: continue
            outerArchive.addFile(
                SarcLib.File(szsThingName, globals.szsData[szsThingName]))

        # Save the outer sarc and return it
        return outerArchive.save()[0]
Example #13
0
    def save(self, innerfilename):
        """
        Save the level back to a file
        """

        # Make a new archive
        newArchive = SarcLib.SARC_Archive()

        # Create a folder within the archive
        courseFolder = SarcLib.Folder('course')
        newArchive.addFolder(courseFolder)

        # Go through the areas, save them and add them back to the archive
        for areanum, area in enumerate(self.areas):
            course, L0, L1, L2 = area.save()

            if course is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d.bin' % (areanum + 1), course))
            if L0 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL0.bin' % (areanum + 1), L0))
            if L1 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL1.bin' % (areanum + 1), L1))
            if L2 is not None:
                courseFolder.addFile(
                    SarcLib.File('course%d_bgdatL2.bin' % (areanum + 1), L2))

        # Here we have the new inner-SARC savedata
        innersarc = newArchive.save()[0]
        globals.szsData[innerfilename] = innersarc

        # Now make an outer SARC
        outerArchive = SarcLib.SARC_Archive()

        # Add the innersarc to it
        outerArchive.addFile(SarcLib.File(innerfilename, innersarc))

        # Make it easy for future Miyamotos to pick out the innersarc level name
        outerArchive.addFile(
            SarcLib.File('levelname', innerfilename.encode('utf-8')))
        globals.szsData['levelname'] = innerfilename.encode('utf-8')

        # Save all the tilesets
        if globals.TilesetEdited or globals.OverrideTilesetSaving:
            if globals.Area.tileset1:
                tilesetData = SaveTileset(1)
                if tilesetData:
                    globals.szsData[globals.Area.tileset1] = tilesetData

            if globals.Area.tileset2:
                tilesetData = SaveTileset(2)
                if tilesetData:
                    globals.szsData[globals.Area.tileset2] = tilesetData

            if globals.Area.tileset3:
                tilesetData = SaveTileset(3)
                if tilesetData:
                    globals.szsData[globals.Area.tileset3] = tilesetData

        # Add all the other stuff, too
        if os.path.isdir(globals.miyamoto_path + '/data'):
            szsNewData = {}

            szsNewData[innerfilename] = innersarc
            szsNewData['levelname'] = innerfilename.encode('utf-8')

            paths = [
                globals.miyamoto_path + '/miyamotodata/spriteresources.xml'
            ]
            for path in globals.gamedef.recursiveFiles('spriteresources'):
                if path:
                    paths.append(
                        os.path.join(
                            globals.miyamoto_path,
                            path if isinstance(path, str) else path.path))

            sprites_xml = {}
            for path in paths:
                # Read the sprites resources xml
                tree = etree.parse(path)
                root = tree.getroot()

                # Get all sprites' filenames and add them to a list
                for sprite in root.iter('sprite'):
                    id = int(sprite.get('id'))

                    name = []
                    for id2 in sprite:
                        name.append(id2.get('name'))

                    sprites_xml[id] = list(name)

            # Look up every sprite and tileset used in each area
            sprites_SARC = []
            tilesets_names = []
            for area_SARC in globals.Level.areas:
                for sprite in area_SARC.sprites:
                    sprites_SARC.append(sprite.type)

                if area_SARC.tileset0 not in ('', None):
                    tilesets_names.append(area_SARC.tileset0)

                if area_SARC.tileset1 not in ('', None):
                    tilesets_names.append(area_SARC.tileset1)

                if area_SARC.tileset2 not in ('', None):
                    tilesets_names.append(area_SARC.tileset2)

                if area_SARC.tileset3 not in ('', None):
                    tilesets_names.append(area_SARC.tileset3)

            sprites_SARC = list(set(sprites_SARC))
            tilesets_names = list(set(tilesets_names))

            # Sort the filenames for each "used" sprite
            sprites_names = []
            for sprite in sprites_SARC:
                if sprite in sprites_xml:
                    for sprite_name in sprites_xml[sprite]:
                        sprites_names.append(sprite_name)

            sprites_names = list(set(sprites_names))

            # Look up each needed file and add it to our archive
            for sprite_name in sprites_names:
                # Get it from inside the original archive
                if not globals.OverwriteSprite and sprite_name in globals.szsData:
                    outerArchive.addFile(
                        SarcLib.File(sprite_name,
                                     globals.szsData[sprite_name]))
                    szsNewData[sprite_name] = globals.szsData[sprite_name]

                # Get it from the "custom" data folder
                elif os.path.isfile(globals.miyamoto_path + '/data/custom/' +
                                    sprite_name):
                    with open(
                            globals.miyamoto_path + '/data/custom/' +
                            sprite_name, 'rb') as f:
                        f1 = f.read()

                    outerArchive.addFile(SarcLib.File(sprite_name, f1))
                    szsNewData[sprite_name] = f1

                # Get it from the data folder
                elif os.path.isfile(globals.miyamoto_path + '/data/' +
                                    sprite_name):
                    with open(globals.miyamoto_path + '/data/' + sprite_name,
                              'rb') as f:
                        f1 = f.read()

                    outerArchive.addFile(SarcLib.File(sprite_name, f1))
                    szsNewData[sprite_name] = f1

                # Throw a warning because the file was not found...
                else:
                    print("WARNING: Could not find the file: %s" % sprite_name)
                    print("Expect the level to crash ingame...")

            # Add each tileset to our archive
            for tileset_name in tilesets_names:
                if tileset_name in globals.szsData:
                    outerArchive.addFile(
                        SarcLib.File(tileset_name,
                                     globals.szsData[tileset_name]))
                    szsNewData[tileset_name] = globals.szsData[tileset_name]

            globals.szsData = szsNewData

        else:
            # data folder not found, copy the files
            for szsThingName in globals.szsData:
                if szsThingName in [
                        globals.levelNameCache, innerfilename, 'levelname'
                ]:
                    continue
                outerArchive.addFile(
                    SarcLib.File(szsThingName, globals.szsData[szsThingName]))

        # Save the outer sarc and return it
        return outerArchive.save()[0]
Example #14
0
def patchLayouts():
    """
    Patch all the layouts
    """
    if not os.path.isdir(
            os.path.join(globals.patchpath, 'content/Common/layout')):
        os.mkdir(os.path.join(globals.patchpath, 'content/Common/layout'))

    for layout in globals.Layouts:
        if os.path.isdir(os.path.join(globals.mod_path, 'Layouts/' + layout)):
            if not os.path.isfile(
                    os.path.join(globals.mod_path,
                                 'Layouts/%s/settings.xml' % layout)):
                continue

            settings = XmlToDict(
                os.path.join(globals.mod_path,
                             'Layouts/%s/settings.xml' % layout))

            if not settings:
                continue

            imgsSettings = []
            lans = []
            lyts = []

            for setting in settings:
                if settings[setting]:
                    if setting[:3] == "Img":
                        imgsSettings.append(settings[setting])

                    elif setting[:3] == "Lan":
                        if "Name" not in settings[setting]:
                            continue

                        name = settings[setting]["Name"]

                        if not name.endswith(".bflan"):
                            continue

                        elif not os.path.isfile(
                                os.path.join(globals.mod_path,
                                             'Layouts/%s/%s' %
                                             (layout, name))):
                            continue

                        lans.append(name)

                    elif setting[:3] == "Lyt":
                        if "Name" not in settings[setting]:
                            continue

                        name = settings[setting]["Name"]

                        if not name.endswith(".bflyt"):
                            continue

                        elif not os.path.isfile(
                                os.path.join(globals.mod_path,
                                             'Layouts/%s/%s' %
                                             (layout, name))):
                            continue

                        lyts.append(name)

            if not (imgsSettings or lans or lyts):
                continue

            imgs = {}
            for imgSettings in imgsSettings:
                name = ""
                bflimname = ""
                tileMode = 4
                swizzle = 0
                SRGB = "False"

                for setting in imgSettings:
                    if setting == "Name":
                        name = imgSettings[setting]

                    elif setting == "BFLIMName":
                        bflimname = imgSettings[setting]

                    elif imgSettings[setting]:
                        if setting == "TileMode":
                            try:
                                tileMode = int(imgSettings[setting], 0)

                            except ValueError:
                                tileMode = 4

                            else:
                                if tileMode > 16 or tileMode < 0:
                                    tileMode = 4

                        elif setting == "Swizzle":
                            try:
                                swizzle = int(imgSettings[setting], 0)

                            except ValueError:
                                swizzle = 0

                            else:
                                if swizzle > 7 or swizzle < 0:
                                    swizzle = 0

                        elif setting == "SRGB":
                            SRGB = imgSettings[setting]
                            if SRGB not in ["True", "False"]:
                                SRGB = "False"

                if not name:
                    continue

                elif not name.endswith(".dds"):
                    continue

                elif not os.path.isfile(
                        os.path.join(globals.mod_path, 'Layouts/%s/%s' %
                                     (layout, name))):
                    continue

                if not bflimname:
                    bflimname = name[:-3] + "bflim"

                data = writeFLIM(
                    os.path.join(globals.mod_path,
                                 'Layouts/%s/%s' % (layout, name)),
                    tileMode,
                    swizzle,
                    SRGB == "True",
                )

                if not data:
                    print(
                        "Something went wrong while converting %s to BFLIM!" %
                        name)
                    continue

                imgs[name] = {
                    "BFLIMName": bflimname,
                    "Data": data,
                }

            print("\nPatching: %s.szs\n" % layout)

            szsname = os.path.join(globals.gamepath,
                                   'Common/layout/%s.szs' % layout)

            if not os.path.isfile(szsname):
                print('Something went wrong while reading %s.szs!' % layout)
                continue

            else:
                with open(szsname, 'rb') as inf:
                    inb = inf.read()

            arc = SarcLib.SARC_Archive(DecompYaz0(inb))
            for name in imgs:
                bflimname = imgs[name]["BFLIMName"]
                data = imgs[name]["Data"]

                arc = addFileToLayout(arc, "timg", bflimname, data)

            for name in lans:
                with open(
                        os.path.join(globals.mod_path,
                                     'Layouts/%s/%s' % (layout, name)),
                        "rb") as inf:
                    data = inf.read()

                arc = addFileToLayout(arc, "anim", name, data)

            for name in lyts:
                with open(
                        os.path.join(globals.mod_path,
                                     'Layouts/%s/%s' % (layout, name)),
                        "rb") as inf:
                    data = inf.read()

                arc = addFileToLayout(arc, "blyt", name, data)

            with open(
                    os.path.join(globals.patchpath,
                                 'content/Common/layout/%s.sarc' % layout),
                    "wb+") as out:
                out.write(arc.save()[0])

            print('\nCompressing: %s.szs' % layout)

            if not CompYaz0(
                    os.path.join(globals.patchpath,
                                 'content/Common/layout/%s.sarc' % layout),
                    os.path.join(globals.patchpath,
                                 'content/Common/layout/%s.szs' % layout),
            ):
                print('Something went wrong while compressing %s.szs!' %
                      layout)

            else:
                print('Patched: %s.szs' % layout)

            os.remove(
                os.path.join(globals.patchpath,
                             'content/Common/layout/%s.sarc' % layout))
Example #15
0
    def load(self, files):
        self.szsData = files
        self.szsData['levelname'] = self.name.encode('utf-8')

        arc = SarcLib.SARC_Archive()
        arc.load(self.szsData[self.name])

        try:
            courseFolder = arc['course']

        except:
            return False

        areaData = {}
        for file in courseFolder.contents:
            name, val = file.name, file.data

            if val is None:
                continue

            if not name.startswith('course'):
                continue

            if not name.endswith('.bin'):
                continue

            if '_bgdatL' in name:
                # It's a layer file
                if len(name) != 19:
                    continue

                try:
                    thisArea = int(name[6])
                    laynum = int(name[14])

                except ValueError:
                    continue

                if not (0 < thisArea < 5):
                    continue

                if thisArea not in areaData:
                    areaData[thisArea] = [None] * 4

                areaData[thisArea][laynum + 1] = val

            else:
                # It's the course file
                if len(name) != 11:
                    continue

                try:
                    thisArea = int(name[6])

                except ValueError:
                    continue

                if not (0 < thisArea < 5):
                    continue

                if thisArea not in areaData:
                    areaData[thisArea] = [None] * 4

                areaData[thisArea][0] = val

        # Create area objects
        self.areas = []
        thisArea = 1
        while thisArea in areaData:
            course = areaData[thisArea][0]
            L0 = areaData[thisArea][1]
            L1 = areaData[thisArea][2]
            L2 = areaData[thisArea][3]

            newarea = Area()
            newarea.areanum = thisArea
            newarea.load(course, L0, L1, L2)
            self.areas.append(newarea)

            thisArea += 1

        return True
Example #16
0
def _LoadTileset(idx, name):
    """
    Load in a tileset into a specific slot
    """

    # if this file's not found, return
    if name not in globals.szsData: return

    sarcdata = globals.szsData[name]
    sarc = SarcLib.SARC_Archive()
    sarc.load(sarcdata)

    tileoffset = idx * 256

    # Decompress the textures
    try:
        comptiledata = sarc['BG_tex/%s.gtx' % name].data
        nmldata = sarc['BG_tex/%s_nml.gtx' % name].data
        colldata = sarc['BG_chk/d_bgchk_%s.bin' % name].data

    except KeyError:
        QtWidgets.QMessageBox.warning(
            None, globals.trans.string('Err_CorruptedTilesetData', 0),
            globals.trans.string('Err_CorruptedTilesetData', 1, '[file]', name),
        )

        return False

    # load in the textures
    img = loadGTX(comptiledata)
    nml = loadGTX(nmldata)

    # Divide it into individual tiles and
    # add collisions at the same time
    def getTileFromImage(tilemap, xtilenum, ytilenum):
        return tilemap.copy((xtilenum * 64) + 2, (ytilenum * 64) + 2, 60, 60)

    dest = QtGui.QPixmap.fromImage(img)
    dest2 = QtGui.QPixmap.fromImage(nml)
    sourcex = 0
    sourcey = 0
    for i in range(tileoffset, tileoffset + 256):
        T = TilesetTile(getTileFromImage(dest, sourcex, sourcey), getTileFromImage(dest2, sourcex, sourcey))
        T.setCollisions(struct.unpack_from('<Q', colldata, (i - tileoffset) * 8)[0])
        globals.Tiles[i] = T
        sourcex += 1
        if sourcex >= 32:
            sourcex = 0
            sourcey += 1

    def exists(fn):
        nonlocal sarc

        try:
            sarc[fn]

        except KeyError:
            return False

        return True
    
    # Load the tileset animations, if there are any
    if idx == 0:
        tileoffset = idx * 256

        hatena_anime = None
        block_anime = None
        tuka_coin_anime = None
        belt_conveyor_anime = None

        fn = 'BG_tex/hatena_anime.gtx'
        found = exists(fn)

        if found:
            hatena_anime = loadGTX(sarc[fn].data)

        fn = 'BG_tex/block_anime.gtx'
        found = exists(fn)

        if found:
            block_anime = loadGTX(sarc[fn].data)

        fn = 'BG_tex/tuka_coin_anime.gtx'
        found = exists(fn)

        if found:
            tuka_coin_anime = loadGTX(sarc[fn].data)

        fn = 'BG_tex/belt_conveyor_anime.gtx'
        found = exists(fn)

        if found:
            belt_conveyor_anime = loadGTX(sarc[fn].data, True)

        for i in range(tileoffset, tileoffset + 256):
            if globals.Tiles[i].coreType == 7:
                if hatena_anime:
                    globals.Tiles[i].addAnimationData(hatena_anime)

            elif globals.Tiles[i].coreType == 6:
                if block_anime:
                    globals.Tiles[i].addAnimationData(block_anime)

            elif globals.Tiles[i].coreType == 2:
                if tuka_coin_anime:
                    globals.Tiles[i].addAnimationData(tuka_coin_anime)

            elif globals.Tiles[i].coreType == 17:
                if belt_conveyor_anime:
                    for x in range(2):
                        if i == 144 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 0, True)

                        elif i == 145 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 1, True)

                        elif i == 146 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 2, True)

                        elif i == 147 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 0)

                        elif i == 148 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 1)

                        elif i == 149 + x * 16:
                            globals.Tiles[i].addConveyorAnimationData(belt_conveyor_anime, 2)

        for tile in globals.Overrides:
            if tile.coreType == 7:
                if hatena_anime:
                    tile.addAnimationData(hatena_anime)

            elif tile.coreType == 6:
                if block_anime:
                    tile.addAnimationData(block_anime)

    # Load the object definitions
    defs = [None] * 256

    indexfile = sarc['BG_unt/%s_hd.bin' % name].data
    deffile = sarc['BG_unt/%s.bin' % name].data
    objcount = len(indexfile) // 6
    indexstruct = struct.Struct('>HBBH')

    for i in range(objcount):
        data = indexstruct.unpack_from(indexfile, i * 6)
        obj = ObjectDef()
        obj.width = data[1]
        obj.height = data[2]
        obj.randByte = data[3]
        obj.load(deffile, data[0])
        defs[i] = obj

    globals.ObjectDefinitions[idx] = defs

    ProcessOverrides(name)
Example #17
0
def SaveTileset(name, tilesetObj):
    """
    Saves a tileset from a specific slot
    """
    defs = tilesetObj.defs
    if defs is None:
        return False

    colldata = tilesetObj.colldata
    deffile = b''
    indexfile = b''

    for obj in defs:
        if obj is None:
            break

        indexfile += struct.pack('>HBBxB', len(deffile), obj.width, obj.height, obj.randByte)

        for row in obj.rows:
            for tile in row:
                if len(tile) == 3:
                    byte2 = tile[2] << 2
                    byte2 |= (tile[1] >> 8) & 3  # Slot

                    deffile += bytes([tile[0], tile[1] & 0xFF, byte2])

                else:
                    deffile += bytes(tile)

            deffile += b'\xFE'

        deffile += b'\xFF'

    arc = SarcLib.SARC_Archive()

    tex = SarcLib.Folder('BG_tex')
    arc.addFolder(tex)
    tex.addFile(SarcLib.File('%s.gtx' % name, writeGTX(*tilesetObj.img)))
    tex.addFile(SarcLib.File('%s_nml.gtx' % name, writeGTX(*tilesetObj.nml)))

    if tilesetObj.hatena_anime:
        tex.addFile(SarcLib.File('hatena_anime.gtx', writeGTX(*tilesetObj.hatena_anime)))

    if tilesetObj.block_anime:
        tex.addFile(SarcLib.File('block_anime.gtx', writeGTX(*tilesetObj.block_anime)))

    if tilesetObj.hatena_anime_L:
        tex.addFile(SarcLib.File('hatena_anime_L.gtx', writeGTX(*tilesetObj.hatena_anime_L)))

    if tilesetObj.block_anime_L:
        tex.addFile(SarcLib.File('block_anime_L.gtx', writeGTX(*tilesetObj.block_anime_L)))

    if tilesetObj.tuka_coin_anime:
        tex.addFile(SarcLib.File('tuka_coin_anime.gtx', writeGTX(*tilesetObj.tuka_coin_anime)))

    if tilesetObj.belt_conveyor_anime:
        tex.addFile(SarcLib.File('belt_conveyor_anime.gtx', writeGTX(*tilesetObj.belt_conveyor_anime)))

    chk = SarcLib.Folder('BG_chk')
    arc.addFolder(chk)
    chk.addFile(SarcLib.File('d_bgchk_%s.bin' % name, colldata))

    unt = SarcLib.Folder('BG_unt')
    arc.addFolder(unt)
    unt.addFile(SarcLib.File('%s.bin' % name, deffile))
    unt.addFile(SarcLib.File('%s_hd.bin' % name, indexfile))

    return arc.save()[0]
Example #18
0
def LoadTileset(idx, name):
    """
    Load in a tileset into a specific slot
    """

    if not name:
        return None

    global TilesetPath
    if not TilesetPath:
        TilesetPath = input('Enter the path to the "Unit" folder, e.g. "C:\\NSMBUDX\\romfs\\Unit": ')

    path = TilesetPath
    found = False

    if path:
        sarcname = os.path.join(os.path.dirname(path), 'Unit', name + '.szs')
        if os.path.isfile(sarcname):
            found = True

    if not found:
        raise RuntimeError("Tileset %s not found!" % name)

    # get the data
    with open(sarcname, 'rb') as fileobj:
        sarcdata = fileobj.read()

    if sarcdata[:4] != b'Yaz0':
        raise RuntimeError("Tileset is not Yaz0 compressed!")

    sarcdata = DecompYaz0(sarcdata)

    sarc = SarcLib.SARC_Archive()
    sarc.load(sarcdata)

    def exists(fn):
        nonlocal sarc

        try:
            sarc[fn]

        except KeyError:
            return False

        return True

    # Decompress the textures
    try:
        bfresdata = sarc['output.bfres'].data
        colldata = sarc['BG_chk/d_bgchk_%s.bin' % name].data

    except KeyError:
        raise RuntimeError("Looks like tileset is corrupted...")

    tileset = Tileset()

    # load in the textures
    bntx = loadBNTXFromBFRES(bfresdata)
    tileset.img = loadTexFromBNTX(bntx, name)
    tileset.nml = loadTexFromBNTX(bntx, name + "_nml")
    
    # Load the tileset animations, if there are any
    if idx == 0:
        tileoffset = idx * 256

        try:
            tileset.hatena_anime = loadTexFromBNTX(bntx, "hatena_anime")

        except:
            pass

        try:
            tileset.block_anime = loadTexFromBNTX(bntx, "block_anime")

        except:
            pass

        try:
            tileset.hatena_anime_L = loadTexFromBNTX(bntx, "hatena_anime_L")

        except:
            pass

        try:
            tileset.block_anime_L = loadTexFromBNTX(bntx, "block_anime_L")

        except:
            pass

        try:
            tileset.tuka_coin_anime = loadTexFromBNTX(bntx, "tuka_coin_anime")

        except:
            pass

        try:
            tileset.belt_conveyor_anime = loadTexFromBNTX(bntx, "belt_conveyor_anime")

        except:
            pass

    # Load the object definitions
    defs = [None] * 256

    indexfile = sarc['BG_unt/%s_hd.bin' % name].data
    deffile = sarc['BG_unt/%s.bin' % name].data
    objcount = len(indexfile) // 6
    indexstruct = struct.Struct('<HBBH')

    for i in range(objcount):
        data = indexstruct.unpack_from(indexfile, i * 6)
        obj = ObjectDef()
        obj.width = data[1]
        obj.height = data[2]
        obj.randByte = data[3]
        obj.load(deffile, data[0])
        defs[i] = obj

    tileset.defs = defs
    tileset.colldata = colldata

    return tileset
Example #19
0
        def save(self):
            """
            Save the level back to a file
            """

            # Make a new archive
            newArchive = SarcLib.SARC_Archive()

            # Create a folder within the archive
            courseFolder = SarcLib.Folder('course')
            newArchive.addFolder(courseFolder)

            outerArchive = SarcLib.SARC_Archive()

            # Go through the areas, save them and add them back to the archive
            for areanum, area in enumerate(self.areas):
                course, L0, L1, L2 = area.save()

                if course is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d.bin' % (areanum + 1), course))
                if L0 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL0.bin' % (areanum + 1),
                                     L0))
                if L1 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL1.bin' % (areanum + 1),
                                     L1))
                if L2 is not None:
                    courseFolder.addFile(
                        SarcLib.File('course%d_bgdatL2.bin' % (areanum + 1),
                                     L2))

                # I need to kick in tileset saving here
                if area.tileset0 and area.tileset0Obj and not exists(
                        outerArchive, area.tileset0):
                    outerArchive.addFile(
                        SarcLib.File(
                            area.tileset0,
                            SaveTileset(area.tileset0, area.tileset0Obj)))

                if area.tileset1 and area.tileset1Obj and not exists(
                        outerArchive, area.tileset1):
                    outerArchive.addFile(
                        SarcLib.File(
                            area.tileset1,
                            SaveTileset(area.tileset1, area.tileset1Obj)))

                if area.tileset2 and area.tileset2Obj and not exists(
                        outerArchive, area.tileset2):
                    outerArchive.addFile(
                        SarcLib.File(
                            area.tileset2,
                            SaveTileset(area.tileset2, area.tileset2Obj)))

                if area.tileset3 and area.tileset3Obj and not exists(
                        outerArchive, area.tileset3):
                    outerArchive.addFile(
                        SarcLib.File(
                            area.tileset3,
                            SaveTileset(area.tileset3, area.tileset3Obj)))

            outerArchive.addFile(SarcLib.File(self.name, newArchive.save()[0]))

            return outerArchive.save()[0]
def change_water(path, water_type=0):
    water_types = [
        'Normal Water', 'Hot Water', 'Poison', 'Lava', 'Ice Water', 'Mud',
        'Clear Water', 'Sea Water'
    ]

    for parent_dir, dirs, files in os.walk(path):
        for file in files:
            current_path = '{0}{1}'.format(parent_dir, file)

            if 'water.extm.sstera' not in current_path:
                continue

            with open(current_path, 'rb') as infile:
                infile_binary = infile.read()

                while libyaz0.IsYazCompressed(infile_binary):
                    infile_binary = libyaz0.decompress(infile_binary)

                path, extension = os.path.splitext(current_path)
                filename = os.path.basename(current_path)

                if infile_binary[0x00:0x04] != b'SARC':
                    print('Not a sarc. :(')

                sarc = SarcLib.SARC_Archive()
                sarc.load(infile_binary)

                with tempfile.TemporaryDirectory() as temp_dir:
                    for sarc_file in sarc.contents:
                        if isinstance(sarc_file, SarcLib.File):
                            pos = 0
                            data = bytearray(sarc_file.data)
                            while pos + 8 <= len(sarc_file.data):
                                height, x_axis_flow_rate, z_axis_flow_rate, mate_check, mate = \
                                    struct.unpack('<3H2B', data[pos:pos + 0x08])

                                # height = 0x24cc
                                # x_axis_flow_rate = 0x8125
                                # z_axis_flow_rate = 0x8125
                                mate = water_type
                                mate_check = mate + 3

                                data[pos:pos + 0x08] = struct.pack(
                                    '<3H2B', height, x_axis_flow_rate,
                                    z_axis_flow_rate, mate_check, mate)

                                pos += 0x08

                            with open(
                                    '{0}/{1}'.format(temp_dir, sarc_file.name),
                                    'wb+') as outfile:
                                outfile.write(data)

                    sarc = SarcLib.SARC_Archive(endianness='>')

                    for path, dirs, files in os.walk(temp_dir):
                        for file in files:
                            with open('{0}/{1}'.format(path, file),
                                      'rb') as infile:
                                sarc.addFile(
                                    SarcLib.File(file, infile.read(), True))

                    data, alignment = sarc.save()
                    data = libyaz0.compress(data, alignment, 5)

                    destination = '{0}/output/MainField - {1}'.format(
                        os.path.dirname(__file__), water_types[water_type])

                    if not os.path.exists('{0}/output/'.format(
                            os.path.dirname(__file__))):
                        os.makedirs('{0}/output/'.format(
                            os.path.dirname(__file__)))
                    if not os.path.exists('{0}/output/MainField - {1}'.format(
                            os.path.dirname(__file__),
                            water_types[water_type])):
                        os.makedirs('{0}/output/MainField - {1}'.format(
                            os.path.dirname(__file__),
                            water_types[water_type]))

                    with open('{0}/{1}'.format(destination, filename),
                              'wb+') as outfile:
                        print('saving {0}...'.format(filename))
                        outfile.write(data)