Пример #1
0
def run(firstgame):
    infolder = "data/extract/data/script/"
    outfolder = "data/repack/data/script/"
    infile = "data/wsb_input.txt"
    fontfile = "data/replace/data/font/lcfont12.NFTR"
    if not os.path.isfile(infile):
        common.logError("Input file", infile, "not found")
        return

    encoding = "shift_jis" if firstgame else "shift_jisx0213"
    common.logMessage("Repacking WSB 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
    wordwrap = game.wordwrap[0] if firstgame else game.wordwrap[1]
    fixchars = game.getFixChars()
    with codecs.open(infile, "r", "utf-8") as wsb:
        commonsection = common.getSection(wsb, "COMMON", fixchars=fixchars)
        chartot, transtot = common.getSectionPercentage(commonsection)
        files = common.getFiles(infolder, ".wsb")
        for file in common.showProgress(files):
            section = common.getSection(wsb, file, fixchars=fixchars)
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            # Repack the file
            pointerdiff = {}
            pointers = {}
            common.logDebug(" Processing", file, "...")
            insize = os.path.getsize(infolder + file)
            with common.Stream(infolder + file, "rb") as fin:
                with common.Stream(outfolder + file, "wb") as f:
                    # Copy header
                    fin.seek(4)  # 0x10
                    codeoffset = fin.readUInt()
                    if codeoffset == 0 and not firstgame:
                        fin.seek(0)
                        f.write(fin.read())
                        continue
                    fin.seek(8, 1)  # all 0xFF
                    unk = fin.readUInt()
                    textoffset = fin.readUInt()
                    codeoffset2 = fin.readUInt()
                    fin.seek(0)
                    f.write(fin.read(32))
                    # Write new strings
                    while fin.tell() < codeoffset:
                        pos = fin.tell()
                        fpos = f.tell()
                        b1 = fin.readByte()
                        b2 = fin.readByte()
                        f.writeByte(b1)
                        f.writeByte(b2)
                        if (b1 == 0x55 and b2 == 0x08) or (b1 == 0x95
                                                           and b2 == 0x10):
                            sjis, oldlen = game.readShiftJIS(
                                fin, b1 == 0x95, False, encoding)
                            # Fix a bugged line with wrong speaker code
                            if file == "event/ev_mou/mou_10.wsb" and sjis == "そうじゃな。|わっちの直感が申すには……>>":
                                f.seek(fpos - 12)
                                f.writeByte(0x53)
                                f.seek(fpos + 2)
                            strreplaced = False
                            if sjis != "" and sjis != ">>":
                                sjissplit = sjis.split(">>")
                                for i in range(len(sjissplit)):
                                    newsjis = sjisline = sjissplit[i]
                                    if sjisline in commonsection:
                                        newsjis = commonsection[sjisline][0]
                                    elif sjisline in section:
                                        newsjis = section[sjisline].pop(0)
                                        if len(section[sjisline]) == 0:
                                            del section[sjisline]
                                    if newsjis != "":
                                        # Disable wordwrap for strings that contain replace codes
                                        if newsjis.count("@<") > 0:
                                            sjissplit[i] = newsjis
                                        # Check for automatic centering
                                        elif newsjis.count("<<") > 0:
                                            sjissplit[i] = common.centerLines(
                                                newsjis,
                                                glyphs,
                                                wordwrap,
                                                centercode="<<")
                                        else:
                                            sjissplit[i] = common.wordwrap(
                                                newsjis, glyphs, wordwrap)
                                            if sjissplit[i].count("|") > 2:
                                                common.logError(
                                                    "Sub-line too long:",
                                                    sjissplit[i])
                                                cutsplit = sjissplit[i].split(
                                                    "|")
                                                sjissplit[i] = cutsplit[
                                                    0] + "|" + cutsplit[
                                                        1] + "|" + cutsplit[2]
                                newsjis = ">>".join(sjissplit)
                                if newsjis != sjis and newsjis != "" and newsjis != ">>":
                                    common.logDebug("Repacking", newsjis, "at",
                                                    common.toHex(pos))
                                    strreplaced = True
                                    if newsjis == "!":
                                        newsjis = ""
                                    newlen = game.writeShiftJIS(
                                        f, newsjis, b1 == 0x95, False, 0,
                                        encoding, firstgame)
                                    lendiff = newlen - oldlen
                                    if newlen > (0x80 if firstgame else
                                                 0x70) and b1 == 0x55:
                                        common.logDebug(
                                            "String is too long", newlen,
                                            "changing to 0x95")
                                        f.seek(fpos)
                                        f.writeByte(0x95)
                                        f.writeByte(0x10)
                                        game.writeShiftJIS(
                                            f, newsjis, True, False, 0,
                                            encoding, firstgame)
                                        lendiff += 2
                                    if lendiff != 0:
                                        common.logDebug(
                                            "Adding", lendiff, "at", pos)
                                        pointerdiff[pos - 16] = lendiff
                            if not strreplaced:
                                fin.seek(pos + 2)
                                f.write(
                                    fin.read(oldlen +
                                             (4 if b1 == 0x95 else 2)))
                        elif (b1, b2) in game.wsbcodes:
                            if (b1, b2) in game.wsbpointers:
                                if b1 == 0x81 and b2 == 0xB9:
                                    f.write(fin.read(2))
                                pointer = fin.readUInt()
                                pointers[f.tell()] = pointer
                                f.writeUInt(pointer)
                            else:
                                f.write(fin.read(game.wsbcodes[(b1, b2)]))
                    # Write code section
                    if codeoffset > 0:
                        newcodeoffset = f.tell()
                        codediff = 0
                        codenum = fin.readUInt()
                        f.writeUInt(codenum)
                        for i in range(codenum):
                            fin.seek(codeoffset + 4 + 4 * i)
                            f.seek(newcodeoffset + 4 + 4 * i)
                            codepointer = fin.readUInt()
                            f.writeUInt(codepointer + codediff)
                            fin.seek(codeoffset + codepointer)
                            f.seek(newcodeoffset + codepointer + codediff)
                            sjis, codelen = game.readShiftJIS(
                                fin, False, True, encoding)
                            strreplaced = False
                            if sjis in section or sjis in commonsection:
                                if sjis in commonsection:
                                    newsjis = commonsection[sjis][0]
                                else:
                                    newsjis = section[sjis].pop(0)
                                    if len(section[sjis]) == 0:
                                        del section[sjis]
                                if newsjis != "":
                                    strreplaced = True
                                    newcodelen = game.writeShiftJIS(
                                        f, newsjis, False, True, 0, encoding,
                                        firstgame)
                                    if codelen != newcodelen:
                                        codediff += newcodelen - codelen
                            if not strreplaced:
                                fin.seek(codeoffset + codepointer)
                                f.write(fin.read(codelen))
                    f.writeZero(insize - fin.tell())
                    # Write new header offsets
                    f.seek(4)
                    f.writeUInt(common.shiftPointer(codeoffset, pointerdiff))
                    f.seek(8, 1)
                    f.writeUInt(common.shiftPointer(unk, pointerdiff))
                    f.writeUInt(common.shiftPointer(textoffset, pointerdiff))
                    f.writeUInt(common.shiftPointer(codeoffset2, pointerdiff))
                    # Shift pointers
                    for k, v in pointers.items():
                        f.seek(k)
                        f.writeUInt(common.shiftPointer(v, pointerdiff))
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))
Пример #2
0
def gen(font, text, out, vert, fw, spacing, color, bg, width, height, center,
        wwrap, no_crop):
    """FONT is the font file, .NFTR extension can be omitted.

    TEXT is the text to write. "\\n" can be used for a line break. Can be the name of a UTF-8 file to read the text from."""
    if not os.path.isfile(font):
        if not font.lower().endswith(".nftr"):
            font = font + ".NFTR"
        if not os.path.isfile(font):
            common.logMessage("[ERROR] Font", font, "not found")
            return None
    if os.path.isfile(text):
        with codecs.open(text, "r", "utf-8") as f:
            text = f.read().replace("\r\n", "\\n").replace("\n", "\\n")
    text = text.replace("\\n", "\n")
    # Add an additional line break to center the last line
    if not text.endswith("\n"):
        text += "\n"
    # Read the font data
    nftr = nitro.readNFTR(font, True)
    if wwrap:
        # Extract the glyphs for wordwrapping
        glyphs = {}
        for char in nftr.glyphs:
            glyph = nftr.glyphs[char]
            glyphs[char] = common.FontGlyph(glyph.start, glyph.width,
                                            glyph.length, glyph.char,
                                            glyph.code, glyph.index)
            if fw > 0:
                glyphs[char].length = fw
            else:
                glyphs[char].length += spacing
        # Wordwrap the text
        text = common.wordwrap(text,
                               glyphs,
                               width,
                               default=nftr.width,
                               linebreak="\n",
                               sectionsep="")
    # Create the empty image
    img = Image.new("RGBA", (width, height), (0, 0, 0, 0))
    if center:
        clearline = Image.new("RGBA", (width, nftr.height + vert),
                              (0, 0, 0, 0))
    # Generate the text
    currentx = 0
    currenty = 0
    for i in range(len(text)):
        c = text[i]
        if c == "\n":
            # Center the line
            if center:
                line = img.crop(
                    (0, currenty, width, currenty + nftr.height + vert))
                bbox = line.getbbox()
                line = line.crop(bbox)
                img.paste(clearline, (0, currenty))
                img.paste(line, ((width - line.width) // 2, currenty))
            # Reset the x position and increase y
            currentx = 0
            currenty += nftr.height + vert
            continue
        if c not in nftr.glyphs:
            common.logMessage("[WARNING] Glyph", hex(ord(c)), "not found.")
            c = " "
        glyph = nftr.glyphs[c]
        glyphdata = nftr.plgc[glyph.index]
        img.paste(glyphdata, (currentx + glyph.start, currenty))
        if fw > 0:
            currentx += fw + spacing
        else:
            currentx += glyph.length + spacing
    # Tint the image
    if color != "black":
        alpha = img.getchannel("A")
        img = Image.new("RGBA", (img.width, img.height), color)
        img.putalpha(alpha)
    # Crop and save the image
    if not no_crop:
        bbox = img.getbbox()
        img = img.crop(bbox)
    if bg == "transparent":
        final = img
    else:
        final = Image.new("RGBA", (img.width, img.height),
                          bg if bg != "transparent" else (0, 0, 0, 0))
        final.paste(img, (0, 0), img)
    if out != "":
        final.save(out, "PNG")
    return final
Пример #3
0
def run(data):
    infolder = data + "extract/"
    outfolder = data + "repack/"
    files = ["bank_11.bin", "bank_12.bin"]
    binfile = outfolder + "bank_14.bin"
    debugfile = outfolder + "bank_1e.bin"
    infile = data + "script_input.txt"
    chartot = transtot = 0
    table, invtable, ccodes, glyphs = game.getFontData(data)

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

    pointers = {}
    pointerdiff = {}
    common.logMessage("Repacking script from", infile, "...")
    with codecs.open(infile, "r", "utf-8") as script:
        for file in common.showProgress(files):
            section = common.getSection(script, file)
            pointers[file] = []
            pointerdiff[file] = {}
            if len(section) == 0:
                continue
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            # Repack the file
            common.logMessage("Processing", file, "...")
            size = os.path.getsize(infolder + file)
            with common.Stream(infolder + file, "rb") as fin:
                with common.Stream(outfolder + file, "wb") as f:
                    while fin.tell() < size:
                        opcode = fin.readByte()
                        if opcode == 0x0a:
                            f.writeByte(opcode)
                            strpos2 = f.tell()
                            strpos = fin.tell()
                            readstr = game.readString(fin, table)
                            newstr = ""
                            if readstr != "":
                                addend = ""
                                if readstr[-2:] == ">>":
                                    addend = ">>"
                                    readstr = readstr[:-2]
                                if readstr in section:
                                    newstr = section[readstr].pop(0)
                                    if len(section[readstr]) == 0:
                                        del section[readstr]
                            strend = fin.tell()
                            if newstr != "":
                                newstr = common.wordwrap(
                                    newstr, glyphs, game.wordwrap,
                                    game.detectTextCode)
                                if newstr == "!":
                                    newstr = ""
                                newstr += addend
                                common.logDebug("Writing string at",
                                                common.toHex(strpos),
                                                common.toHex(strpos2), newstr)
                                game.writeString(f, newstr, invtable, ccodes)
                                f.writeUShort(0xffff)
                                strend2 = f.tell()
                                lendiff = (strend2 - strpos2) - (strend -
                                                                 strpos)
                                if lendiff != 0:
                                    common.logDebug("Adding", lendiff, "at",
                                                    common.toHex(strpos))
                                    pointerdiff[file][strpos + 1] = lendiff
                            else:
                                fin.seek(strpos)
                                f.write(fin.read(strend - strpos))
                        elif opcode in game.repopcodes:
                            if opcode in game.ptropcodes:
                                pointers[file].append(f.tell())
                            f.writeByte(opcode)
                            replen = 0
                            while True:
                                loopbyte = fin.readByte()
                                f.writeByte(loopbyte)
                                replen += 1
                                if loopbyte == 0xff and (opcode
                                                         not in game.ptropcodes
                                                         or replen > 2):
                                    break
                        else:
                            if opcode in game.ptropcodes:
                                pointers[file].append(f.tell())
                            f.writeByte(opcode)
                            f.write(fin.read(game.opcodes[opcode]))
                            if opcode == 0xff:
                                check = fin.readUInt()
                                check2 = fin.readUInt()
                                fin.seek(-8, 1)
                                if check == 0xffffffff and check2 == 0xffffffff:
                                    break
                    # Pad with 0xffff
                    f.writeBytes(0xff, 0xffff - f.tell() + 1)
    common.logMessage("Shifting script pointers ...")
    for file in common.showProgress(files):
        with common.Stream(outfolder + file, "rb+") as f:
            for pointerpos in pointers[file]:
                f.seek(pointerpos)
                opcode = f.readByte()
                for pointeroff in game.ptropcodes[opcode]:
                    pointerfile = file
                    if type(pointeroff) == tuple:
                        f.seek(pointerpos + 1 + pointeroff[1])
                        bankid = f.readUShort()
                        pointerfile = files[0] if bankid == 0x00f1 else files[1]
                        pointeroff = pointeroff[0]
                    f.seek(pointerpos + 1 + pointeroff)
                    pointer = f.readUShort()
                    if pointer != 0xffff:
                        newpointer = common.shiftPointer(
                            pointer, pointerdiff[pointerfile])
                    else:
                        newpointer = pointer
                    f.seek(-2, 1)
                    f.writeUShort(newpointer)
    common.logMessage("Shifting bin pointers ...")
    # Read pointer tables in the bin file
    with common.Stream(binfile.replace("/repack/", "/extract/"), "rb+") as f:
        f.seek(0x23b0)
        while f.tell() < 0x2740:
            pos1 = f.tell()
            ptr1 = f.readUShort()
            bank1 = f.readUShort()
            pos2 = f.tell()
            ptr2 = f.readUShort()
            bank2 = f.readUShort()
            game.binptrs.append((pos1, ptr1, bank1))
            game.binptrs.append((pos2, ptr2, bank2))
            f.seek(8, 1)
        for binrange in [(0x2ff7, 0x3027), (0x3063, 0x309b), (0x480f, 0x481f),
                         (0x496b, 0x499b), (0x4a01, 0x4a39)]:
            f.seek(binrange[0])
            while f.tell() < binrange[1]:
                pos = f.tell()
                ptr = f.readUShort()
                bank = f.readUShort()
                game.binptrs.append((pos, ptr, bank))
        f.seek(0x902e)
        while f.tell() < 0x9106:
            pos = f.tell()
            ptr = f.readUShort()
            game.binptrs.append((pos, ptr, 0xf2))
    game.binptrs.append((0x26b8, 0x3d7b, 0xf2))
    shiftPointers(binfile, game.binptrs, pointerdiff)
    # Shift debug pointers
    debugptrs = []
    with common.Stream(debugfile.replace("/repack/", "/extract/"), "rb+") as f:
        f.seek(0xcd92)
        while f.tell() < 0xd420:
            pos1 = f.tell()
            ptr1 = f.readUShort()
            bank1 = f.readUShort()
            debugptrs.append((pos1, ptr1, bank1))
            f.seek(12, 1)
    shiftPointers(debugfile, debugptrs, pointerdiff)
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))
Пример #4
0
def run():
    infolder = "data/extract/data/Rom/event/script/"
    outfolder = "data/repack/data/Rom/event/script/"
    infile = "data/cnut_input.txt"
    fontfile = "data/repack/data/Rom/font/font0.NFTR"
    replacefontfile = "data/replace/data/Rom/font/font0.NFTR"
    chartot = transtot = 0

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

    common.logMessage("Repacking CNUT from", infile, "...")
    if os.path.isfile(replacefontfile):
        glyphs = nitro.readNFTR(replacefontfile).glyphs
    else:
        glyphs = nitro.readNFTR(fontfile).glyphs
    with codecs.open(infile, "r", "utf-8") as cnut:
        files = common.getFiles(infolder, ".cnut")
        for file in common.showProgress(files):
            section = common.getSection(cnut, file, "//")
            if len(section) == 0:
                common.makeFolders(outfolder + file)
                common.copyFile(infolder + file, outfolder + file)
                continue
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            # Repack the file
            common.logDebug("Processing", file, "...")
            size = os.path.getsize(infolder + file)
            lastpos = 0
            with common.Stream(infolder + file, "rb") as fin:
                common.makeFolders(infolder + file)
                with common.Stream(outfolder + file, "wb") as f:
                    while fin.tell() < size - 4:
                        pos = fin.tell()
                        b1 = fin.readByte()
                        b2 = fin.readByte()
                        b3 = fin.readByte()
                        b4 = fin.readByte()
                        if b1 == 0x10 and b2 == 0x00 and b3 == 0x00 and b4 == 0x08:
                            # Found a string
                            check = game.readShiftJIS(fin)
                            pre = post = ""
                            # Add back some codes that are removed from extracted lines
                            if check.startswith("#CLR()"):
                                pre = "#CLR()"
                                check = check[6:]
                            if check.startswith("#ARW("):
                                pre += check[:7]
                                check = check[7:]
                            if check.endswith("#INP()"):
                                post = "#INP()"
                                check = check[:-6]
                            # Check if the line is translated and replace it
                            if check in section:
                                newsjis = section[check].pop(0)
                                if len(section[check]) == 0:
                                    del section[check]
                                if newsjis != "":
                                    newsjis = pre + newsjis + post
                                    if newsjis != check:
                                        newsjis = common.wordwrap(
                                            newsjis, glyphs, 205,
                                            game.detectTextCode)
                                        newsjis = newsjis.replace(
                                            ">>", "#INP()" + pre).replace(
                                                "|", "<0A>")
                                        # Copy data up to here
                                        endpos = fin.tell()
                                        fin.seek(lastpos)
                                        f.write(fin.read(pos + 4 - lastpos))
                                        lastpos = endpos
                                        common.logDebug("  Repacking at", pos)
                                        game.writeShiftJIS(f, newsjis)
                        else:
                            fin.seek(pos + 1)
                    fin.seek(lastpos)
                    f.write(fin.read(size - lastpos))
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))
Пример #5
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))
Пример #6
0
def run(data, allfile=False):
    infolder = data + "extract/"
    outfolder = data + "repack/"
    infile = data + "bin_input.txt"
    infilename = data + "name_input.txt"
    chartot = transtot = 0
    table, invtable, ccodes, glyphs = game.getFontData(data)

    with codecs.open(infile, "r", "utf-8") as bin:
        common.logMessage("Repacking bin from", infile, "...")
        for file in common.showProgress(game.fileranges):
            section = common.getSection(bin, file)
            if len(section) == 0:
                continue
            chartot, transtot = common.getSectionPercentage(
                section, chartot, transtot)
            # Repack the file
            common.logMessage("Processing", file, "...")
            common.copyFile(infolder + file, outfolder + file)
            with common.Stream(outfolder + file, "rb+") as f:
                if file != "bank_1d.bin":
                    for binrange in game.fileranges[file]:
                        f.seek(binrange[0])
                        while f.tell() < binrange[1]:
                            if (len(binrange) >= 3):
                                f.seek(binrange[2], 1)
                            strpos = f.tell()
                            readstr = game.readString(f, table, True)
                            if allfile and len(readstr) > 50:
                                f.seek(strpos + 2)
                                continue
                            if readstr.startswith("|"):
                                f.seek(strpos + 2)
                                continue
                            if readstr != "":
                                newstr = ""
                                if readstr in section:
                                    newstr = section[readstr].pop(0)
                                    if len(section[readstr]) == 0:
                                        del section[readstr]
                                strend = f.tell()
                                if newstr != "":
                                    if newstr == "!":
                                        newstr = ""
                                    common.logDebug("Repacking", newstr, "at",
                                                    common.toHex(strpos))
                                    f.seek(strpos)
                                    game.writeString(f, newstr, invtable,
                                                     ccodes,
                                                     strend - strpos - 2, True)
                                    while f.tell() < strend:
                                        f.writeByte(int(ccodes[" "][0], 16))
                                    f.seek(strend - 2)
                                    f.writeUShort(0xffff)
                else:
                    # String pointers are stored starting at 0xcd00
                    f.seek(0xcd00)
                    ptrs = []
                    for i in range(23):
                        ptrs.append(f.readUShort())
                        f.seek(14, 1)
                    strings = []
                    for ptr in ptrs:
                        f.seek(ptr)
                        strings.append(game.readString(f, table, True))
                    newptrs = []
                    f.seek(0xce70)
                    for i in range(len(strings)):
                        if strings[i] in section:
                            newstr = section[strings[i]].pop(0)
                        else:
                            newstr = strings[i]
                        newstr = common.wordwrap(newstr, glyphs,
                                                 game.wordwrap_angel,
                                                 game.detectTextCode)
                        common.logDebug("Repacking", newstr, "at",
                                        common.toHex(f.tell()))
                        newstr = newstr.split("|")
                        if len(newstr) > 8:
                            common.logError("Line too long",
                                            str(len(newstr)) + "/8", newstr[0])
                            newstr = newstr[:8]
                        while len(newstr) < 8:
                            newstr.append("")
                        for binstr in newstr:
                            if not binstr.startswith("▼"):
                                binstr = " " + binstr
                            newptrs.append(f.tell())
                            game.writeString(f, binstr, invtable, ccodes, -1,
                                             True)
                            f.writeUShort(0xffff)
                    f.seek(0xcd00)
                    for newptr in newptrs:
                        f.writeUShort(newptr)
    # Set the name input selection glyphs in bank 14
    newglyphs = {}
    with codecs.open(infilename, "r", "utf-8") as name:
        nameglyphs = name.read().replace("\r",
                                         "").replace("\n",
                                                     "").replace("#", "")
    with common.Stream(outfolder + "bank_14.bin", "rb+") as f:
        # Write the new name input values
        f.seek(0xc250)
        for nameglyph in nameglyphs:
            if nameglyph in invtable and invtable[nameglyph][:2] != 'ff':
                f.writeUShort(int(invtable[nameglyph], 16))
            else:
                glyphcode = int(ccodes[nameglyph][0], 16) - 0x20
                glyphcode <<= 6
                glyphcode += 0xa300
                newglyphs[nameglyph] = glyphcode
                f.writeUShort(glyphcode)
        # Write "Adam", but using the long glyphs
        f.seek(0x296c + 3)
        f.writeUShort(int(invtable["A"], 16))
        f.seek(3, 1)
        f.writeUShort(newglyphs["d"])
        f.seek(3, 1)
        f.writeUShort(newglyphs["a"])
        f.seek(3, 1)
        f.writeUShort(newglyphs["m"])
    common.logMessage("Done! Translation is at {0:.2f}%".format(
        (100 * transtot) / chartot))

    nasm.run(common.bundledFile("bin_patch.asm"))