예제 #1
0
파일: cpk.py 프로젝트: Illidanz/hacktools
def extract(file, outfolder, guessextension=None):
    common.logDebug("Processing", file, "...")
    common.makeFolder(outfolder)
    cpk = readCPK(file)
    if cpk is None:
        common.logError("Error reading CPK")
        return
    if len(cpk.filetable) == 0:
        common.logError("No files in CPK filetable")
        return
    with common.Stream(file, "rb") as f:
        for entry in cpk.filetable:
            if entry.filetype != "FILE":
                continue
            folder, filename = entry.getFolderFile(outfolder)
            f.seek(entry.fileoffset)
            data = f.read(entry.filesize)
            f.seek(entry.fileoffset)
            checkcomp = f.readString(8)
            if checkcomp == "CRILAYLA":
                extractsize = entry.extractsize if entry.extractsize != 0 else entry.filesize
                if extractsize != 0:
                    data = compression.decompressCRILAYLA(f, entry.fileoffset)
            if guessextension is not None:
                filename = guessextension(data, entry, filename)
            if not os.path.isdir(folder):
                common.makeFolders(folder)
            with common.Stream(folder + filename, "wb") as fout:
                fout.write(data)
예제 #2
0
파일: wii.py 프로젝트: Illidanz/hacktools
def extractIso(isofile, extractfolder, workfolder=""):
    common.logMessage("Extracting ISO", isofile, "...")
    common.makeFolder(extractfolder)
    common.execute(
        "wit EXTRACT -o {iso} {folder}".format(iso=isofile,
                                               folder=extractfolder), False)
    if workfolder != "":
        common.copyFolder(extractfolder, workfolder)
    common.logMessage("Done!")
예제 #3
0
파일: wii.py 프로젝트: Illidanz/hacktools
def extractARC(infolder, outfolder):
    common.makeFolder(outfolder)
    common.logMessage("Extracting ARC to", outfolder, "...")
    files = common.getFiles(infolder, ".arc")
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        common.execute(
            "wszst EXTRACT " + infolder + file + " -D " + outfolder + file,
            False)
    common.logMessage("Done! Extracted", len(files), "files")
예제 #4
0
파일: wii.py 프로젝트: Illidanz/hacktools
def extractTPL(infolder, outfolder, splitName=True):
    common.makeFolder(outfolder)
    common.logMessage("Extracting TPL to", outfolder, "...")
    files = common.getFiles(infolder, ".tpl")
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        filename = file.split("/")[0] if splitName else file
        common.execute(
            "wimgt DECODE " + infolder + file + " -D " + outfolder + filename +
            "/" + os.path.basename(file).replace(".tpl", ".png"), False)
    common.logMessage("Done! Extracted", len(files), "files")
예제 #5
0
파일: nds.py 프로젝트: Illidanz/hacktools
def extractRom(romfile, extractfolder, workfolder=""):
    common.logMessage("Extracting ROM", romfile, "...")
    ndstool = common.bundledExecutable("ndstool.exe")
    if not os.path.isfile(ndstool):
        common.logError("ndstool not found")
        return
    common.makeFolder(extractfolder)
    common.execute(ndstool + " -x {rom} -9 {folder}arm9.bin -7 {folder}arm7.bin -y9 {folder}y9.bin -y7 {folder}y7.bin -t {folder}banner.bin -h {folder}header.bin -d {folder}data -y {folder}overlay".
                   format(rom=romfile, folder=extractfolder), False)
    if workfolder != "":
        common.copyFolder(extractfolder, workfolder)
    common.logMessage("Done!")
예제 #6
0
def extractIso(isofile, extractfolder, workfolder=""):
    common.logMessage("Extracting ISO", isofile, "...")
    common.makeFolder(extractfolder)
    iso = pycdlib.PyCdlib()
    iso.open(isofile)
    for dirname, dirlist, filelist in iso.walk(iso_path="/"):
        common.makeFolders(extractfolder + dirname[1:])
        for file in filelist:
            with open(extractfolder + dirname[1:] + "/" + file, "wb") as f:
                iso.get_file_from_iso_fp(f, iso_path=dirname + "/" + file)
    iso.close()
    if workfolder != "":
        common.copyFolder(extractfolder, workfolder)
    common.logMessage("Done!")
예제 #7
0
파일: wii.py 프로젝트: Illidanz/hacktools
def extractBREFT(infolder, tempfolder, outfolder):
    common.makeFolder(tempfolder)
    common.makeFolder(outfolder)
    common.logMessage("Extracting BREFT to", outfolder, "...")
    files = common.getFiles(infolder, ".breft")
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        outfile = file.split("/")
        outfile = "/" + outfile[1] + "/" + outfile[3]
        common.execute(
            "wszst EXTRACT " + infolder + file + " -D " + tempfolder + outfile,
            False)
        for imgfile in os.listdir(tempfolder + outfile + "/files"):
            common.execute(
                "wimgt DECODE " + tempfolder + outfile + "/files/" + imgfile +
                " -D " + outfolder + outfile + "/" + imgfile + ".png", False)
    common.logMessage("Done! Extracted", len(files), "files")
예제 #8
0
def extractRom(romfile, extractfolder, workfolder="", banksize=0x4000):
    common.logMessage("Extracting ROM", romfile, "...")
    common.makeFolder(extractfolder)
    filesize = os.path.getsize(romfile)
    banknum = filesize // banksize
    common.logMessage("Extracting", banknum, "banks ...")
    with common.Stream(romfile, "rb") as f:
        for i in range(banknum):
            bankname = "bank_"
            if i < 0x10:
                bankname += "0"
            bankname += format(i, 'x')
            with common.Stream(extractfolder + bankname + ".bin",
                               "wb") as fout:
                fout.write(f.read(banksize))
    if workfolder != "":
        common.copyFolder(extractfolder, workfolder)
    common.logMessage("Done!")
예제 #9
0
def run():
    infolder = "data/extract_NFP/NFP2D.NFP/"
    outfolder = "data/out_VSC/"
    common.makeFolder(outfolder)

    common.logMessage("Extracting VSC to", outfolder, "...")
    files = common.getFiles(infolder, ".VSC")
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        with common.Stream(infolder + file, "rb") as f:
            # Read header
            f.seek(4)
            unk1 = f.readUShort()
            unk2 = f.readUShort()
            size = f.readUInt()
            unk3 = f.readUInt()
            bpp = 4 if f.readUInt() == 1 else 8
            width = f.readUInt()
            height = f.readUInt()
            unk4 = f.readUInt()
            mapsize = f.readUInt()
            unk5 = f.readUInt()
            tilesize = f.readUInt()
            common.logDebug("size:", size, "width:", width, "height:", height, "mapsize:", mapsize, "tilesize:", tilesize, "bpp:", bpp)
            common.logDebug("unk1:", unk1, "unk2:", unk2, "unk3:", unk3, "unk4:", unk4, "unk5:", unk5)
            # Read data
            common.logDebug("mapoffset:", f.tell())
            mapdata = f.read(mapsize)
            common.logDebug("tileoffset:", f.tell())
            tiledata = f.read(tilesize)
            common.logDebug("paloffset:", f.tell())
            cpal = f.readString(4)
            if cpal != "CPAL":
                common.logError("Palette header", cpal)
                continue
            f.seek(20, 1)
            palnum = f.readUShort()
            f.seek(4, 1)
            paldata = f.read(palnum * 32)
            # Draw the image
            img = game.drawMappedImage(width, height, mapdata, tiledata, paldata, 8, bpp)
            img.save(outfolder + file.replace(".VSC", ".png"), "PNG")
    common.logMessage("Done! Extracted", len(files), "files")
예제 #10
0
파일: psx.py 프로젝트: Illidanz/hacktools
def extractTIM(infolder, outfolder, extensions=".tim", readfunc=None):
    common.makeFolder(outfolder)
    common.logMessage("Extracting TIM to", outfolder, "...")
    files = common.getFiles(infolder, extensions)
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        extension = os.path.splitext(file)[1]
        if readfunc is not None:
            tim, transp, forcepal = readfunc(infolder + file)
        else:
            transp = False
            forcepal = -1
            with common.Stream(infolder + file, "rb") as f:
                tim = readTIM(f)
        if tim is None:
            continue
        # Export img
        common.makeFolders(outfolder + os.path.dirname(file))
        outfile = outfolder + file.replace(extension, ".png")
        drawTIM(outfile, tim, transp, forcepal)
    common.logMessage("Done! Extracted", len(files), "files")
예제 #11
0
def run(data):
    infolder = data + "extract/"
    outfolder = data + "out_IMG/"

    common.logMessage("Extracting images to", outfolder, "...")
    common.makeFolder(outfolder)

    files = common.getFiles(infolder)

    extracted = 0
    with codecs.open(common.bundledFile("images.txt"), "r", "utf-8") as imagef:
        for file in files:
            section = common.getSection(imagef, file)
            with common.Stream(infolder + file, "rb") as f:
                for imgname in section.keys():
                    imgdata = section[imgname][0].split(",")
                    mapstart = int(imgdata[1], 16)
                    imgnum = int(imgdata[2]) if len(imgdata) >= 3 else 1
                    readpal = len(imgdata) >= 4 and imgdata[3] == "1"
                    extracted += imgnum
                    if "-" in imgdata[0]:
                        tilestart = int(imgdata[0].split("-")[0], 16)
                        tileend = int(imgdata[0].split("-")[1], 16)
                        for i in common.showProgress(range(tilestart, tileend + 1, 1)):
                            ws.extractMappedImage(f, outfolder + imgname + "_" + hex(i) + ".png", i, mapstart, imgnum, readpal)
                    else:
                        tilestart = int(imgdata[0], 16)
                        ws.extractMappedImage(f, outfolder + imgname + ".png", tilestart, mapstart, imgnum, readpal)
                if file == "bank_09.bin":
                    map = game.getBerserkMap(outfolder)
                    ws.writeMappedImage(f, 0xf080, [map], ws.bwpalette)
                    extracted += 1
    # Extract ramen stand image
    with common.Stream(infolder + "bank_03.bin", "rb") as f:
        map = game.getRamenMap(outfolder)
        ws.writeMappedImage(f, 0x3748, [map], ws.bwpalette)
        map = game.getLanternMap(outfolder)
        ws.writeMappedImage(f, 0x3748, [map], ws.bwpalette)
    common.logMessage("Done! Extracted", extracted, "files")
예제 #12
0
def run():
    infolder = "data/extract_NFP/NFP2D.NFP/"
    outfolder = "data/out_KPC/"
    common.makeFolder(outfolder)

    common.logMessage("Extracting KPC to", outfolder, "...")
    files = common.getFiles(infolder, ".KPC")
    for file in common.showProgress(files):
        common.logDebug("Processing", file, "...")
        with common.Stream(infolder + file, "rb") as f:
            # Read header
            f.seek(4)
            bits = []
            for i in range(5):
                bits.append(f.readByte())
            palcompressed = f.readByte() == 1
            mapcompressed = f.readByte() == 1
            tilecompressed = f.readByte() == 1
            width = f.readUShort() * 8
            height = f.readUShort() * 8
            mapsize = f.readUInt()
            mapoffset = f.readUInt()
            f.seek(5, 1)
            bpp = 8 if f.readUShort() == 1 else 4
            f.seek(92)
            tilesize = f.readUInt()
            tileoffset = f.readUInt()
            f.seek(124)
            unk = f.readUInt()
            palsize = f.readUInt()
            paloffset = f.readUInt()
            common.logDebug("width:", width, "height:", height, "bpp:", bpp)
            common.logDebug("mapsize:", mapsize, "mapoffset:", mapoffset)
            common.logDebug("tilesize:", tilesize, "tileoffset:", tileoffset)
            common.logDebug("palsize:", palsize, "paloffset:", paloffset)
            common.logDebug("palcompressed:", palcompressed, "mapcompressed:",
                            mapcompressed, "tilecompressed:", tilecompressed)
            common.logDebug("bits:", bits, "unk:", unk)
            # Read palette
            f.seek(paloffset)
            if palcompressed:
                paldata = nds.decompress(f, palsize)
            else:
                paldata = f.read(palsize)
            # Read map data
            f.seek(mapoffset)
            if mapcompressed:
                mapdata = nds.decompress(f, mapsize)
            else:
                mapdata = f.read(mapsize)
            # Read tile data
            f.seek(tileoffset)
            if tilecompressed:
                tiledata = nds.decompress(f, tilesize)
            else:
                tiledata = f.read(tilesize)
            # Draw the image
            img = game.drawMappedImage(width, height, mapdata, tiledata,
                                       paldata, 8, bpp)
            img.save(outfolder + file.replace(".KPC", ".png"), "PNG")
    common.logMessage("Done! Extracted", len(files), "files")
예제 #13
0
def run():
    infolder = "data/extract_NFP/SPC.NFP/"
    outfolder = "data/work_NFP/SPC.NFP/"
    infile = "data/spc_input.txt"
    infixfile = "data/sprite_fix.txt"
    tablefile = "data/table.txt"
    chartot = transtot = 0

    if not os.path.isfile(infile):
        common.logError("Input file", infile, "not found.")
        return
    common.makeFolder(outfolder)

    common.logMessage("Repacking SPC from", infile, "...")
    common.loadTable(tablefile)
    spritefixf = codecs.open(infixfile, "r", "utf-8")
    with codecs.open(infile, "r", "utf-8") as spc:
        files = common.getFiles(infolder, [".SPC", ".SET"])
        for file in common.showProgress(files):
            section = common.getSection(spc, file, "#", game.fixchars)
            spritefix = common.getSection(spritefixf, file, "#")
            if len(section) == 0 and len(spritefix) == 0:
                common.copyFile(infolder + file, outfolder + file)
                continue
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            common.logDebug("Repacking", file, "...")
            codepointers = []
            pointerdiff = {}
            funcpointers = {"MswMess": [], "MswHit": []}
            nextstr = None
            addstr = ""
            last29 = []
            oldstrpos = 0
            f = open(outfolder + file, "wb")
            f.close()
            with common.Stream(outfolder + file, "r+b") as f:
                with common.Stream(infolder + file, "rb") as fin:
                    # Write the header
                    f.writeString("SCRP")
                    fin.seek(4)
                    f.writeUInt(fin.readUInt())
                    f.writeString("CODE")
                    fin.seek(4, 1)
                    codesize = fin.readUInt()
                    f.writeUInt(codesize)
                    f.write(fin.read(6))
                    # Loop the file and shift pointers
                    while fin.tell() < 16 + codesize - 2:
                        pos = fin.tell()
                        byte = fin.readByte()
                        f.writeByte(byte)
                        if byte == 0x10:
                            oldlen = fin.readUShort()
                            fin.seek(-2, 1)
                            strpos = fin.tell()
                            strposf = f.tell()
                            sjis = game.readShiftJIS(fin)
                            if (sjis != "" and sjis
                                    in section) or nextstr is not None:
                                common.logDebug("Found SJIS string at",
                                                strpos + 16)
                                # Check if we have a nextstr to inject instead of using the section
                                if nextstr is None:
                                    newsjis = section[sjis].pop(0)
                                    if len(section[sjis]) == 0:
                                        del section[sjis]
                                    if newsjis == "!":
                                        newsjis = ""
                                        # Center the line
                                        savestrpos = f.tell()
                                        f.seek(oldstrpos - 28)
                                        checkbyte = f.readByte()
                                        if checkbyte == 0x02:
                                            f.seek(-1, 1)
                                            f.writeByte(1)
                                        f.seek(savestrpos)
                                    elif newsjis == "":
                                        newsjis = sjis
                                else:
                                    newsjis = nextstr
                                    nextstr = None
                                # If the string starts with <<, pad it with spaces
                                if newsjis.startswith("<<"):
                                    newsjis = newsjis[2:]
                                    pad = " " * ((20 - len(newsjis)) // 2)
                                    newsjis = pad + newsjis + pad
                                # If the string starts with "[xx]", add mouth flapping
                                if newsjis.startswith(
                                        "[") and newsjis[3] == "]":
                                    flapbyte = newsjis[1:3]
                                    newsjis = newsjis[4:]
                                    flappos = f.tell()
                                    f.seek(strposf - 5)
                                    f.writeByte(int(flapbyte, 16))
                                    f.seek(flappos)
                                # If the string contains a >>, split it and save it for later
                                if newsjis.find(">>") > 0:
                                    splitstr = newsjis.split(">>", 1)
                                    newsjis = splitstr[0]
                                    addstr = splitstr[1]
                                # Check if we have a string after
                                savepos = fin.tell()
                                fin.seek(9, 1)
                                b1 = fin.readByte()
                                b2 = fin.readByte()
                                fin.seek(savepos)
                                if b1 == 0x10 and b2 == 0x01:
                                    nextstr = ""
                                # If the string contains a |, try to turn the string into a 2-lines message
                                if newsjis.find("|") > 0:
                                    splitstr = newsjis.split("|", 1)
                                    newsjis = splitstr[0]
                                    nextstr = splitstr[1]
                                    newsjis = newsjis.replace("|", "<0A>")
                                    # Change the byte 0x1C bytes before the string to 2 if it's 1
                                    checkpos = 28
                                    if newsjis.startswith("FIX("):
                                        splitstr = newsjis.split(")", 1)
                                        newsjis = splitstr[1]
                                        checkpos = int(splitstr[0].replace(
                                            "FIX(", ""))
                                    f.seek(-checkpos, 1)
                                    checkbyte = f.readByte()
                                    if checkbyte == 0x01:
                                        f.seek(-1, 1)
                                        f.writeByte(2)
                                    f.seek(checkpos - 1, 1)
                                # Write the SJIS string
                                newlen = game.writeShiftJIS(f, newsjis)
                                lendiff = newlen - oldlen
                                if lendiff != 0:
                                    common.logDebug("Adding", lendiff, "at",
                                                    strpos)
                                    pointerdiff[strpos - 16] = lendiff
                                fin.seek(1, 1)
                            else:
                                common.logDebug(
                                    "Found ASCII or unaltered string at",
                                    strpos + 16)
                                fixPos = pos - 16
                                # Patch RITT_02 to add Dayakka's missing text
                                if file == "RITT_02.SPC" and fixPos == 1775:
                                    fin.seek(strpos + oldlen + 2)
                                    f.writeUShort(0x09)
                                    f.writeString("APP_DAYA")
                                    f.writeByte(0x00)
                                    pointerdiff[strpos - 16] = 8
                                elif file == "RITT_02.SPC" and fixPos == 1810:
                                    fin.seek(strpos + oldlen + 2)
                                    f.writeUShort(0x09)
                                    f.writeString("DAYA_004")
                                    f.writeByte(0x00)
                                    pointerdiff[strpos - 16] = 8
                                elif file == "RITT_02.SPC" and fixPos == 1845:
                                    fin.seek(strpos + oldlen + 2)
                                    f.writeUShort(0x05)
                                    f.writeString("AWAY")
                                    f.writeByte(0x00)
                                    pointerdiff[strpos - 16] = 4
                                elif file == "SYS_054.SPC" and fixPos == 4233:
                                    fin.seek(strpos + oldlen + 2)
                                    f.writeUShort(0x09)
                                    f.writeString("MSW_C083")
                                    f.writeByte(0x00)
                                else:
                                    fin.seek(strpos + 2)
                                    asciistr = fin.readNullString()
                                    if asciistr in spritefix:
                                        fin.seek(strpos + oldlen + 2)
                                        f.writeUShort(0x08)
                                        f.writeString(spritefix[asciistr][0])
                                        f.writeByte(0x00)
                                    else:
                                        fin.seek(strpos)
                                        f.write(fin.read(oldlen + 2))
                            f.write(fin.read(2))
                            pointer = fin.readUInt()
                            f.writeUInt(
                                common.shiftPointer(pointer, pointerdiff))
                            # Check if we have an addstr
                            if addstr != "" and nextstr is None:
                                addstrsplit = addstr.split(">>")
                                for addstr in addstrsplit:
                                    strsplit = addstr.split("|")
                                    startpointer = f.tell()
                                    startpointeri = fin.tell()
                                    f.writeByte(0x28)
                                    f.writeByte(0x00)
                                    funcpointers["MswMess"].append(f.tell() -
                                                                   16)
                                    f.writeByte(0x29)
                                    f.writeUInt(0x03)
                                    f.writeByte(0x80)
                                    f.writeUInt(0x00)
                                    f.writeByte(0x2A)
                                    f.writeByte(0x00)
                                    f.writeByte(0x31)
                                    f.writeByte(0x0F)
                                    f.writeUInt(0x0C)
                                    f.writeByte(0x29)
                                    f.writeUInt(0x00)
                                    funcpointers["MswHit"].append(f.tell() -
                                                                  16)
                                    f.writeByte(0x29)
                                    f.writeUInt(0x01)
                                    f.writeByte(0x80)
                                    f.writeUInt(0x00)
                                    f.writeByte(0x2A)
                                    f.writeByte(0x00)
                                    f.writeByte(0x31)
                                    f.writeByte(0x0F)
                                    f.writeUInt(0x04)
                                    f.writeByte(0x29)
                                    f.writeUInt(last29[len(last29) - 1])
                                    f.writeByte(0x10)
                                    strpointer = f.tell()
                                    game.writeShiftJIS(f, strsplit[0])
                                    f.writeByte(0x22)
                                    f.writeByte(0x00)
                                    f.writeUInt(strpointer - 16 - 4)
                                    f.writeByte(0x28)
                                    f.writeByte(0x00)
                                    f.writeByte(0x10)
                                    strpointer2 = f.tell()
                                    game.writeShiftJIS(
                                        f, strsplit[1]
                                        if len(strsplit) == 2 else "")
                                    f.writeByte(0x22)
                                    f.writeByte(0x00)
                                    f.writeUInt(strpointer2 - 16 - 4)
                                    endpointer = f.tell()
                                    common.logDebug("Adding new str",
                                                    endpointer - startpointer,
                                                    "at", startpointeri)
                                    if startpointeri - 16 not in pointerdiff:
                                        pointerdiff[startpointeri - 16] = 0
                                    pointerdiff[
                                        startpointeri -
                                        16] += endpointer - startpointer
                                addstr = ""
                            oldstrpos = strposf
                        elif byte == 0x15:
                            f.write(fin.read(1))
                            bytelen = fin.readByte()
                            f.writeByte(bytelen)
                            for i in range(bytelen):
                                f.write(fin.read(4))
                                codepointers.append(f.tell())
                                f.write(fin.read(4))
                        elif byte in game.spccodes:
                            if byte == 0x11:
                                codepointers.append(f.tell())
                            elif byte == 0x12:
                                codepointers.append(f.tell() + 1)
                            elif byte == 0x29:
                                last29.append(fin.readUInt())
                                fin.seek(-4, 1)
                            # Patch SYS_046/7 and fix the disappearing cut-in sprites
                            fixPos = pos - 16
                            if (file == "SYS_046.SPC" and byte == 0x29
                                    and fixPos
                                    in [9660, 11356, 11915, 13108, 13646]) or (
                                        file == "SYS_047.SPC" and byte == 0x29
                                        and fixPos == 1607):
                                f.writeUInt(0x0A)
                                fin.seek(4, 1)
                            else:
                                f.write(fin.read(game.spccodes[byte]))
                        common.logDebug("Unknown byte", common.toHex(byte),
                                        "at", pos)
                    f.writeByte(0x8F)
                    f.writeByte(0x00)
                    f.writeByte(0x00)
                    endpos = f.tell()
                    # Shift the other code pointers
                    for codepointer in codepointers:
                        f.seek(codepointer)
                        pointer = f.readUInt()
                        f.seek(-4, 1)
                        f.writeUInt(common.shiftPointer(pointer, pointerdiff))
                    # Write the code section size in the header
                    f.seek(12)
                    f.writeUInt(endpos - 16)
                    f.seek(endpos)
                    # Function section
                    fin.seek(codesize + 16)
                    f.writeString("FUNC")
                    fin.seek(4, 1)
                    funcsize = fin.readUInt()
                    f.writeUInt(funcsize)
                    # Copy the function section while shifting pointers
                    common.logDebug(str(funcpointers))
                    while True:
                        # Read the function name
                        function = fin.readNullString()
                        if function == "":
                            break
                        f.writeString(function)
                        f.writeZero(1)
                        common.logDebug("Found function:", function)
                        # Read the pointers until we find 0
                        while True:
                            pointer = fin.readUInt()
                            if pointer == 0:
                                f.writeUInt(0)
                                break
                            else:
                                pointer = common.shiftPointer(
                                    pointer, pointerdiff)
                                if function in funcpointers and len(
                                        funcpointers[function]) > 0:
                                    for newpointer in funcpointers[function]:
                                        common.logDebug(
                                            function, "new:", newpointer,
                                            "poi:", pointer)
                                        if pointer > newpointer:
                                            f.writeUInt(newpointer)
                                            funcpointers[function].remove(
                                                newpointer)
                                f.writeUInt(pointer)
                    f.writeZero(1)
                    # Write the file size in the header
                    pos = f.tell()
                    f.seek(4)
                    f.writeUInt(pos - 4)
                    f.seek(pos)
                    # Write TERM and pad with 0s
                    f.writeString("TERM")
                    f.writeZero(16 - (f.tell() % 16))
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))
예제 #14
0
def run():
    infolder = "data/extract_NFP/NFP2D.NFP/"
    altinfolder = "data/work_YCE/"
    outfolder = "data/out_YCE/"
    outfile = "data/yce_data.txt"
    common.makeFolder(outfolder)

    common.logMessage("Extracting YCE to", outfolder, "...")
    with open(outfile, "w") as yce:
        files = common.getFiles(infolder, ".YCE")
        for file in common.showProgress(files):
            common.logDebug("Processing", file, "...")
            filepath = infolder + file
            if os.path.isfile(altinfolder + file):
                filepath = altinfolder + file
            with common.Stream(filepath, "rb") as f:
                # Read header
                f.seek(8)
                size = f.readUInt()  # size - header (7)
                f.seek(4, 1)  # Always 0
                f.seek(4, 1)  # Always 24
                f.readUInt()  # Animation data offset
                f.readUInt()  # ?
                num = f.readUInt()  # Number of images
                images = []
                for i in range(num):
                    img = game.YCETexture()
                    img.offset = f.readUInt() + 24  # Image data offset
                    images.append(img)
                for img in images:
                    common.logDebug("Reading image at offset", img.offset,
                                    "...")
                    f.seek(img.offset)
                    img.size = f.readUInt()  # Image data size
                    constant = f.readUInt()  # 0x1C
                    if constant != 0x1C:
                        common.logDebug("Constant is not 0x1C!",
                                        common.toHex(constant))
                    img.oamnum = f.readUInt()  # Number of OAMs
                    img.oamsize = f.readUInt()  # OAM data size
                    img.tilesize = f.readUInt()  # Tile data size
                    img.paloffset = f.readUInt(
                    ) + img.offset  # Palette data offset (relative to offset)
                    constant = f.readUInt()  # 0x01
                    if constant != 0x01:
                        common.logDebug("Constant 2 is not 0x01!",
                                        common.toHex(constant))
                    common.logDebug("size:", img.size, "oamnum:", img.oamnum,
                                    "oamsize:", img.oamsize)
                    common.logDebug("tilesize:", img.tilesize, "paloffset:",
                                    img.paloffset)
                    img.oams = []
                    for j in range(img.oamnum):
                        oam = game.OAM()
                        oam.x = f.readShort(
                        )  # X position of the cell (-128 to 127)
                        oam.y = f.readShort(
                        )  # Y position of the cell (-256 to 255)
                        for x in range(8):
                            unkbyte = f.readByte()
                            if unkbyte != 0x00:
                                common.logDebug("unkbyte", x, "is not 0x00!",
                                                common.toHex(unkbyte))
                        shape = f.readByte()  # NCER OBJ Shape
                        size = f.readByte()  # NCER OBJ Size
                        for x in range(2):
                            unkbyte = f.readByte()
                            if unkbyte != 0x00:
                                common.logDebug("unkbyte2", x, "is not 0x00!",
                                                common.toHex(unkbyte))
                        oam.offset = f.readUInt()
                        # Table from http://www.romhacking.net/documents/%5B469%5Dnds_formats.htm#NCER
                        if shape == 0:
                            if size == 0:
                                tilesize = (8, 8)
                            elif size == 1:
                                tilesize = (16, 16)
                            elif size == 2:
                                tilesize = (32, 32)
                            elif size == 3:
                                tilesize = (64, 64)
                        elif shape == 1:
                            if size == 0:
                                tilesize = (16, 8)
                            elif size == 1:
                                tilesize = (32, 8)
                            elif size == 2:
                                tilesize = (32, 16)
                            elif size == 3:
                                tilesize = (64, 32)
                        elif shape == 2:
                            if size == 0:
                                tilesize = (8, 16)
                            elif size == 1:
                                tilesize = (8, 32)
                            elif size == 2:
                                tilesize = (16, 32)
                            elif size == 3:
                                tilesize = (32, 64)
                        oam.width = tilesize[0]
                        oam.height = tilesize[1]
                        img.oams.append(oam)
                    # Calculate width and height
                    minx = miny = 512
                    maxx = maxy = -512
                    for oam in img.oams:
                        minx = min(minx, oam.x)
                        miny = min(miny, oam.y)
                        maxx = max(maxx, oam.x + oam.width)
                        maxy = max(maxy, oam.y + oam.height)
                    img.width = maxx - minx
                    img.height = maxy - miny
                    for oam in img.oams:
                        oam.x -= minx
                        oam.y -= miny
                    common.logDebug("width:", img.width, "height:", img.height)
                    common.logDebug("oams:", img.oams)
                # Create image
                width = height = 0
                for img in images:
                    width = max(width, img.width + 40)
                    height += max(img.height, 10)
                outimg = Image.new("RGBA", (width, height), (0, 0, 0, 0))
                pixels = outimg.load()
                # Read images
                currheight = 0
                for img in images:
                    # Load palette
                    palette = []
                    f.seek(img.paloffset)
                    paldata = f.read(32)
                    for i in range(0, 32, 2):
                        p = struct.unpack("<H", paldata[i:i + 2])[0]
                        palette.append(common.readPalette(p))
                    # Read tile data
                    f.seek(img.offset + img.oamsize)
                    tiledata = f.read(img.tilesize)
                    for oam in img.oams:
                        x = oam.offset * 64
                        for i in range(oam.height // 8):
                            for j in range(oam.width // 8):
                                for i2 in range(8):
                                    for j2 in range(8):
                                        index = (tiledata[x // 2] >>
                                                 ((x % 2) << 2)) & 0x0f
                                        pixels[oam.x + j * 8 + j2,
                                               currheight + oam.y + i * 8 +
                                               i2] = palette[index]
                                        x += 1
                    # Draw palette
                    pixels = common.drawPalette(pixels, palette, width - 40,
                                                currheight)
                    currheight += max(img.height, 10)
                outimg.save(outfolder + file.replace(".YCE", ".png"), "PNG")
            yce.write(
                file + "=" +
                base64.standard_b64encode(pickle.dumps(images)).decode() +
                "\n")
    common.logMessage("Done! Extracted", len(files), "files")
예제 #15
0
def run(firstgame, no_redirect):
    infolder = "data/extract/data/data/"
    outfolder = "data/repack/data/data/"
    infile = "data/dat_input.txt"
    redfile = "data/redirects.asm"
    fontfile = "data/replace/data/font/lcfont12.NFTR"
    if not os.path.isfile(infile):
        common.logError("Input file", infile, "not found")
        return
    common.makeFolder(outfolder)
    chartot = transtot = 0
    monthsection, skipsection = game.monthsection, game.skipsection
    game.monthsection = game.skipsection = None

    encoding = "shift_jis" if firstgame else "shift_jisx0213"
    common.logMessage("Repacking DAT from", infile, "...")
    # Read the glyph size from the font
    if not os.path.isfile(fontfile):
        fontfile = fontfile.replace("replace/", "extract/")
    glyphs = nitro.readNFTR(fontfile).glyphs
    fixchars = game.getFixChars()
    # Copy this txt file
    if not firstgame and os.path.isfile(infolder + "facilityhelp.txt"):
        common.copyFile(infolder + "facilityhelp.txt",
                        outfolder + "facilityhelp.txt")
    redirects = []
    with codecs.open(infile, "r", "utf-8") as dat:
        files = common.getFiles(infolder, ".dat")
        for file in common.showProgress(files):
            section = common.getSection(dat, file, fixchars=fixchars)
            # If there are no lines, just copy the file
            if len(section) == 0:
                common.copyFile(infolder + file, outfolder + file)
                # Part of the AP patch
                if not firstgame and file == "route.dat":
                    with common.Stream(outfolder + file, "rb+") as f:
                        f.seek(0x5ee8)
                        f.writeByte(0x0)
                continue
            i = 0
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            common.logDebug("Processing", file, "...")
            size = os.path.getsize(infolder + file)
            with common.Stream(infolder + file, "rb") as fin:
                with common.Stream(outfolder + file, "wb") as f:
                    f.write(fin.read())
                    fin.seek(0)
                    # Loop the file and replace strings as needed
                    while fin.tell() < size - 2:
                        pos = fin.tell()
                        check = game.detectShiftJIS(fin, encoding)
                        if check != "":
                            if file == "entrance_icon.dat":
                                # For entrance_icon, just write the string and update the pointer
                                if check in section:
                                    # For the first one, seek to the correct position in the output file
                                    if i == 0:
                                        f.seek(pos)
                                    # Write the string
                                    newsjis = check
                                    if check in section and section[check][
                                            0] != "":
                                        common.logDebug(
                                            "Replacing string at", pos)
                                        newsjis = section[check][0]
                                    startpos = f.tell()
                                    game.writeShiftJIS(f, newsjis, False, True,
                                                       0, encoding)
                                    endpos = f.tell()
                                    # Update the pointer
                                    f.seek(0x1c98 + 4 * i)
                                    f.writeUInt(startpos - 0x1c98)
                                    f.seek(endpos)
                                    i += 1
                            else:
                                # Found a SJIS string, check if we have to replace it
                                if check in section and section[check][0] != "":
                                    common.logDebug("Replacing string at", pos)
                                    f.seek(pos)
                                    newsjis = section[check][0]
                                    maxlen = 0
                                    if file == "goods.dat":
                                        newsjis = common.wordwrap(
                                            newsjis, glyphs, 170)
                                        maxlen = 60
                                    elif file == "gossip.dat":
                                        newsjis = common.wordwrap(
                                            newsjis, glyphs, 190)
                                        if newsjis.count("<<") > 0:
                                            newsjis = common.centerLines(
                                                newsjis,
                                                glyphs,
                                                190,
                                                centercode="<<")
                                        if fin.tell() - pos < 35:
                                            maxlen = 35
                                        else:
                                            maxlen = 160
                                    elif file == "scenarioguide.dat":
                                        newsjis = common.wordwrap(
                                            newsjis, glyphs, 165)
                                        maxlen = 60
                                        if newsjis.count("|") > 1:
                                            common.logError(
                                                "scenarioguide line", newsjis,
                                                "too long")
                                    newlen = game.writeShiftJIS(
                                        f, newsjis, False, True, maxlen,
                                        encoding)
                                    if newlen < 0:
                                        if file != "gossip.dat" or no_redirect or maxlen != 160:
                                            common.logError(
                                                "String {} is too long ({}/{})."
                                                .format(
                                                    newsjis, len(newsjis),
                                                    maxlen))
                                        else:
                                            common.logWarning(
                                                "String {} is too long ({}/{})."
                                                .format(
                                                    newsjis, len(newsjis),
                                                    maxlen))
                                            # Doesn't fit, write it shorter
                                            f.seek(pos)
                                            cutat = 155 if firstgame else 150
                                            while ord(newsjis[cutat]) > 127:
                                                cutat -= 1
                                            stringfit = newsjis[:cutat]
                                            stringrest = newsjis[cutat:]
                                            game.writeShiftJIS(
                                                f, stringfit, False, True,
                                                maxlen, encoding)
                                            f.seek(-1, 1)
                                            f.writeByte(0x1f)
                                            f.writeByte(len(redirects))
                                            redirects.append(stringrest)
                                    # Pad with 0s if the line is shorter
                                    while f.tell() < fin.tell():
                                        f.writeByte(0x00)
                            pos = fin.tell() - 1
                        fin.seek(pos + 1)
    with codecs.open(redfile, "w", "utf-8") as f:
        f.write(".ascii \"NDSC\"\n\n")
        f.write("REDIRECT_START:\n\n")
        for i in range(len(redirects)):
            f.write(".dh REDIRECT_{} - REDIRECT_START\n".format(i))
        for i in range(len(redirects)):
            f.write("\nREDIRECT_{}:\n".format(i))
            redirect = redirects[i].replace("\"", "\\\"")
            redirect = redirect.replace("|", "\" :: .db 0xa :: .ascii \"")
            redirectascii = ""
            for c in redirect:
                if ord(c) > 127:
                    sjisc = common.toHex(
                        int.from_bytes(c.encode(encoding), "big"))
                    redirectascii += "\" :: .db 0x" + sjisc[:2] + " :: .db 0x" + sjisc[
                        2:] + " :: .ascii \""
                else:
                    redirectascii += c
            f.write(".ascii \"{}\" :: .db 0\n".format(redirectascii))
    game.monthsection, game.skipsection = monthsection, skipsection
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))
예제 #16
0
def extract(rom, bin, tdg, kpc, spc, vsc, yce):
    all = not rom and not bin and not tdg and not kpc and not spc and not vsc and not yce
    if all or rom:
        nds.extractRom(romfile, infolder, outfolder)
        # Extract NFP archives
        nfpin = "data/extract/data/"
        nfpout = "data/extract_NFP/"
        nfpwork = "data/work_NFP/"
        common.logMessage("Extracting NFP ...")
        common.makeFolder(nfpout)
        files = common.getFiles(nfpin, ".NFP")
        for file in common.showProgress(files):
            common.logDebug("Processing", file, "...")
            common.makeFolder(nfpout + file)
            with common.Stream(nfpin + file, "rb") as f:
                f.seek(52)  # Header: NFP2.0 (c)NOBORI 1997-2006
                filenum = f.readInt()
                f.seek(4, 1)  # Always 0x50
                datastart = f.readInt()
                f.seek(16, 1)  # All 0
                common.logDebug("Found", filenum, "files, data starting at",
                                datastart)
                for i in range(filenum):
                    # Filenames are always 16 bytes long, padded with 0s
                    subname = f.readString(16)
                    # Read starting position and size (multiplied by 4)
                    startpos = f.readInt()
                    size = f.readInt() // 4
                    # Extract the file
                    common.logDebug("Extracting", subname, "starting at",
                                    startpos, "with size", size)
                    savepos = f.tell()
                    f.seek(startpos)
                    with common.Stream(nfpout + file + "/" + subname,
                                       "wb") as newf:
                        newf.write(f.read(size))
                    f.seek(savepos)
        # Copy everything to the work folder
        common.copyFolder(nfpout, nfpwork)
        common.logMessage("Done! Extracted", len(files), "archives")
    if all or bin:
        import extract_bin
        extract_bin.run()
    if all or tdg:
        nitro.extractNSBMD("data/extract_NFP/NFP3D.NFP/", "data/out_3DG/",
                           ".3DG")
    if all or kpc:
        import extract_kpc
        extract_kpc.run()
    if all or spc:
        import extract_spc
        extract_spc.run()
    if all or vsc:
        import extract_vsc
        extract_vsc.run()
    if all or yce:
        for i in range(1, 8):
            common.copyFile(
                "data/extract_NFP/NFP2D.NFP/AV01_0" + str(i) + ".YCE",
                "data/extract_NFP/NFP2D.NFP/AV00_0" + str(i) + ".YCE")
        import extract_yce
        extract_yce.run()