def run(filename, processed=False): infolder = "data/work_NFP/SPC.NFP/" if processed else "data/extract_NFP/SPC.NFP/" outfile = "data/analyze_spc.txt" tablefile = "data/table.txt" common.loadTable(tablefile) functions = {} inversetable = {} for bigram, code in common.table.items(): inversetable[code] = bigram common.logMessage("Analyzing", filename, "...") with codecs.open(outfile, "w", "utf-8") as out: out.write(filename + "\n") with common.Stream(infolder + filename, "rb") as f: f.seek(12) # "SCRP" + filesize + "CODE" codesize = f.readUInt() if codesize > 10: f.seek(16 + codesize + 8) while True: function = f.readNullString() if function == "": break # Read the pointers until we find 0 i = 0 while True: pointer = f.readUInt() if pointer == 0: break else: if pointer in functions: functions[pointer] += "," + function + "#" + str(i) else: functions[pointer] = function + "#" + str(i) i += 1 f.seek(16 + 6) while f.tell() < 16 + codesize - 2: pos = f.tell() byte = f.readByte() if byte == 0x10: line = f.readBytes(2) f.seek(-2, 1) convert = "" if processed: sjislen = f.readUShort() try: i = 0 while i < sjislen - 1: strbyte = f.readByte() if strbyte in game.codes: convert += "<" + common.toHex(strbyte) + ">" i += 1 else: f.seek(-1, 1) char = common.toHex(f.readByte()) + common.toHex(f.readByte()) convert += inversetable[char] i += 2 except KeyError: convert = "" if convert != "": line += "\"" + convert + "\" " else: f.seek(pos + 1) sjis = game.readShiftJIS(f) if sjis != "": line += "\"" + sjis + "\" " else: f.seek(pos + 1) asciilen = f.readUShort() asciistr = f.read(asciilen - 1) line += "\"" + asciistr.decode("ascii").replace("\r", "").replace("\n", "") + "\" " line += f.readBytes(9) writeLine(out, pos, byte, line, functions) elif byte == 0x15: line = f.readBytes(2) f.seek(-1, 1) bytelen = f.readByte() for i in range(bytelen): line += f.readBytes(8) writeLine(out, pos, byte, line, functions) elif byte in game.spccodes: writeLine(out, pos, byte, f.readBytes(game.spccodes[byte]), functions) else: writeLine(out, pos, byte, "Unknown!", functions) for k, v in functions.items(): out.write("Missing function pointer " + str(k) + ": " + str(v) + "\n") common.logMessage("Done! Open", outfile)
def repack(no_rom, bin, tdg, kpc, spc, vsc, yce, deb, force, analyze): all = not bin and not tdg and not kpc and not spc and not vsc and not yce if all or bin or spc: import repack_font repack_font.run() if all or bin: import repack_bin repack_bin.run() common.armipsPatch("bin_patch.asm") if all or tdg: common.copyFile("data/extract_NFP/NFP3D.NFP/MSW_C053.3DG", "data/extract_NFP/NFP3D.NFP/MSW_C083.3DG") nitro.repackNSBMD("data/work_3DG/", "data/extract_NFP/NFP3D.NFP/", "data/work_NFP/NFP3D.NFP/", ".3DG", game.write3DG) import patch_jnt patch_jnt.run() if all or kpc: import repack_kpc repack_kpc.run() if all or spc: import repack_spc repack_spc.run() if all or vsc: import repack_vsc repack_vsc.run() if all or yce: import repack_yce repack_yce.run() if not no_rom: debfolder = "data/extract_NFP/" nfpin = "data/extract/data/" nfpwork = "data/work_NFP/" nfpout = "data/repack/data/" # Debug map if deb: common.copyFile(debfolder + "SPC.NFP/S_DEBUG.SPC", nfpwork + "SPC.NFP/S_MAIN.SPC") else: common.copyFile(debfolder + "SPC.NFP/S_MAIN.SPC", nfpwork + "SPC.NFP/S_MAIN.SPC") if force != "": common.copyFile(nfpwork + "SPC.NFP/" + force + ".SPC", nfpwork + "SPC.NFP/SYS_000.SPC") # Repack NFP archives if os.path.isdir(replacefolder): common.mergeFolder(replacefolder, nfpwork) common.logMessage("Repacking NFP ...") files = common.getFiles(nfpin, ".NFP") for file in common.showProgress(files): subfiles = os.listdir(nfpwork + file) filenum = len(subfiles) # Data starts at header (80 bytes) + entries (24 bytes each) datapos = 80 + (24 * filenum) # The file list is padded with 0s if it doesn't start at a multiple of 16 datapos += datapos % 16 common.logDebug("Repacking", file, "with", filenum, "files ...") with common.Stream(nfpout + file, "wb") as f: f.writeString("NFP2.0 (c)NOBORI 1997-2006") f.writeZero(26) f.writeInt(filenum) f.writeInt(0x50) f.writeInt(datapos) for i in range(filenum): subfile = subfiles[i] subfilepath = nfpwork + file + "/" + subfile filesize = os.path.getsize(subfilepath) f.seek(80 + (24 * i)) f.writeString(subfile) if len(subfile) < 16: f.writeZero(16 - len(subfile)) f.writeInt(datapos) f.writeInt(filesize * 4) f.seek(datapos) with open(subfilepath, "rb") as newf: f.write(newf.read(filesize)) datapos += filesize # Edit banner and repack ROM nds.editBannerTitle( bannerfile, "Tengen Toppa\nGurren Lagann\nKonami Digital Entertainment") nds.repackRom(romfile, rompatch, outfolder, patchfile)
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()
def run(firstgame, analyzefile): infolder = "data/extract/data/script/" outfile = "data/wsb_output.txt" commonfile = "data/common.txt" analyzeout = "data/wsb_analysis.txt" commonstr = {} # Read common strings from another file if os.path.isfile(commonfile): with codecs.open(commonfile, "r", "utf-8") as commonf: commonstr = common.getSection(commonf, "COMMON") encoding = "shift_jis" if firstgame else "shift_jisx0213" common.logMessage("Extracting WSB to", outfile, "...") with codecs.open(analyzeout, "w", "utf-8") as a: with codecs.open(outfile, "w", "utf-8") as out: if len(commonstr) > 0: out.write("!FILE:COMMON\n") for s in commonstr: out.write(s + "=\n") files = common.getFiles(infolder, ".wsb") for file in common.showProgress(files): analyze = analyzefile != "" and file.endswith(analyzefile) if analyzefile != "" and not analyze: continue first = True common.logDebug("Processing", file, "...") with common.Stream(infolder + file, "rb") as f: f.seek(4) # 0x10 codeoffset = f.readUInt() f.seek(8, 1) # all 0xFF unk = f.readUInt() textoffset = f.readUInt() codeoffset2 = f.readUInt() common.logDebug("codeoffset:", codeoffset, "unk:", unk, "textoffset:", textoffset, "codeoffset2:", codeoffset2) f.seek(4, 1) # Parse the various code blocks while looking for strings while f.tell() < codeoffset: pos = f.tell() b1 = f.readByte() b2 = f.readByte() if (b1 == 0x55 and b2 == 0x08) or (b1 == 0x95 and b2 == 0x10): # Found a string pointer if analyze: lenline = f.readBytes(4 if b1 == 0x95 else 2) f.seek(-(4 if b1 == 0x95 else 2), 1) sjis, strlen = game.readShiftJIS( f, b1 == 0x95, False, encoding) if sjis != "" and sjis != ">>" and sjis != " ": sjissplit = sjis.split(">>") for sjisline in sjissplit: if sjisline != "" and sjisline != " " and sjisline not in commonstr: if first: out.write("!FILE:" + file + "\n") first = False out.write(sjisline + "=\n") if analyze: # Try to calculate the length to check if the calculation is correct addlen = "" with common.Stream() as test: game.writeShiftJIS(test, sjis, b1 == 0x95, False, 0, encoding, firstgame) testlen = test.tell() test.seek(0) addlen = test.readBytes(4 if b1 == 0x95 else 2) if lenline != addlen: test.seek(0) addlen += "\nDIFF\n" + test.readBytes( testlen) + "\n" fpos = f.tell() f.seek(pos + 2) addlen += f.readBytes(fpos - f.tell()) writeLine(a, pos, b1, b2, lenline + sjis + " " + addlen) elif (b1, b2) in game.wsbcodes: if analyze: ptrstr = "" if (b1, b2) in game.wsbpointers: ptrstr += "ptr" writeLine( a, pos, b1, b2, f.readBytes(game.wsbcodes[(b1, b2)]) + ptrstr) else: f.seek(game.wsbcodes[(b1, b2)], 1) else: if analyze: writeLine(a, pos, b1, b2, "Unknown!") if codeoffset > 0: codenum = f.readUInt() for i in range(codenum): f.seek(codeoffset + 4 + 4 * i) codepointer = f.readUInt() f.seek(codeoffset + codepointer) sjis, codelen = game.readShiftJIS( f, False, True, encoding) # Ignore ASCII strings and a particular debug line found in every file if not common.isAscii(sjis) and sjis.find( "%d, %d") < 0 and sjis not in commonstr: if first: out.write("!FILE:" + file + "\n") first = False out.write(sjis + "=\n") if analyze: writeLine(a, i, 0, 0, str(codepointer) + " " + sjis) common.logMessage("Done! Extracted", len(files), "files")
def run(): infolder = "data/extract_NFP/NFP2D.NFP/" workfolder = "data/work_KPC/" outfolder = "data/work_NFP/NFP2D.NFP/" common.copyFolder(infolder, outfolder) common.logMessage("Repacking KPC from", workfolder, "...") files = common.getFiles(infolder, ".KPC") for file in common.showProgress(files): pngname = file.replace(".KPC", ".png") if not os.path.isfile(workfolder + pngname): common.copyFile(infolder + file, outfolder + file) continue common.logDebug("Processing", file, "...") with common.Stream(infolder + file, "rb") as fin: with common.Stream(outfolder + file, "wb") as f: # Find palette offset fin.seek(9) palcompressed = fin.readByte() == 1 fin.seek(2, 1) width = fin.readUShort() * 8 height = fin.readUShort() * 8 fin.seek(128) palsize = fin.readUInt() paloffset = fin.readUInt() # Read palette fin.seek(paloffset) if palcompressed: paldata = common.decompress(fin, palsize) else: paldata = fin.read(palsize) # Fix transparency for EQ_M0* files since their palette colors 0 and 1 are the same. tiles, maps = game.readMappedImage(workfolder + pngname, width, height, paldata, file.startswith("EQ_M0")) # Copy the header fin.seek(0) f.write(fin.read(192)) # Write map data mapstart = f.tell() for map in maps: mapdata = (map[0] << 12) + (map[1] << 11) + ( map[2] << 10) + map[3] f.writeUShort(mapdata) mapend = f.tell() f.writeByte(0) # Write tile data tilestart = f.tell() for tile in tiles: for i in range(32): index2 = tile[i * 2] index1 = tile[i * 2 + 1] f.writeByte(((index1) << 4) | index2) tileend = f.tell() f.writeByte(0) # Write palette palstart = f.tell() f.write(paldata) palend = f.tell() f.writeByte(0) # Write header data f.seek(9) f.writeByte(0) f.writeByte(0) f.writeByte(0) f.seek(16) f.writeUInt(mapend - mapstart) f.writeUInt(mapstart) f.seek(92) f.writeUInt(tileend - tilestart) f.writeUInt(tilestart) f.seek(128) f.writeUInt(palend - palstart) f.writeUInt(palstart) common.logMessage("Done!")
def run(data, processed): infolder = data + ("extract/" if not processed else "repack/") files = ["bank_11.bin", "bank_12.bin"] outfile = data + "analyze_output.txt" with codecs.open(data + "table_input.txt", "r", "utf-8") as tablef: table = common.getSection(tablef, "") invtable = {} with codecs.open(data + "table.txt", "r", "utf-8") as tablef: convtable = common.getSection(tablef, "") for char in convtable: invtable[int(convtable[char][0], 16)] = char with codecs.open(outfile, "w", "utf-8") as out: for file in common.showProgress(files): common.logMessage("Processing", file, "...") out.write("!FILE:" + file + "\n") size = os.path.getsize(infolder + file) with common.Stream(infolder + file, "rb") as f: while f.tell() < size - 1: pos = f.tell() opcode = f.readByte() if opcode in game.opcodes and game.opcodes[opcode] != -1: addline = "" if opcode in game.ptropcodes: addline = " Pointer: " + repr( game.ptropcodes[opcode]) if opcode == 0x0a: if processed: common.logDebug("Failing at", common.toHex(pos)) writeLine( out, pos, opcode, game.readString(f, table, processed=invtable)) else: writeLine(out, pos, opcode, game.readString(f, table)) elif opcode in game.repopcodes: readbytes = "" replen = 0 while True: byte = f.readBytes(1) readbytes += byte replen += 1 if byte == "FF " and (opcode not in game.ptropcodes or replen > 2): break writeLine(out, pos, opcode, readbytes + addline) else: writeLine( out, pos, opcode, f.readBytes(game.opcodes[opcode]) + addline) if opcode == 0xff: out.write("\n") check = f.readUInt() check2 = f.readUInt() f.seek(-8, 1) if check == 0xffffffff and check2 == 0xffffffff: break else: common.logError("Uknown opcode", common.toHex(opcode), "at", common.toHex(pos)) writeLine(out, pos, opcode, "Unknown") out.write("\n\n") common.logMessage("Done! Extracted", len(files), "files")
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"))
def run(): xmlfile = "data/fontdump.xml" imgfile = "data/fontdump.png" fontfile = "font.png" fontconfigfile = "fontconfig.txt" outfile = "data/fontout.png" infont = "data/extract_NFP/ETC.NFP/GL_12FNT.NFT" tempfont = "data/GL_12FNT.NFTR" outfont = "data/work_NFP/ETC.NFP/GL_12FNT.NFT" binin = "data/bin_input.txt" spcin = "data/spc_input.txt" table = "data/table.txt" common.logMessage("Repacking font ...") fontexe = common.bundledFile("NerdFontTerminatoR.exe") if not os.path.isfile(fontexe): common.logError("NerdFontTerminatoR not found") return # List of characters with codecs.open(fontconfigfile, "r", "utf-8") as f: fontconfig = common.getSection(f, "") upperchars = fontconfig["upperchars"][0].split("|") lowerchars = fontconfig["lowerchars"][0].split("|") numbers = fontconfig["numbers"][0].split("|") punctuation = fontconfig["punctuation"][0].split("|") customs = fontconfig["customs"][0].split("|") all = upperchars + lowerchars + numbers + punctuation + customs # X Position in the font.png file positions = {} for i in range(len(upperchars)): positions[upperchars[i]] = i * 12 positions[lowerchars[i]] = (i * 12) + 6 for i in range(len(numbers)): positions[numbers[i]] = (len(upperchars) * 12) + (i * 6) for i in range(len(punctuation)): positions[punctuation[i]] = (len(upperchars) * 12) + (len(numbers) * 6) + (i * 6) for i in range(len(customs)): positions[customs[i]] = (len(upperchars) * 12) + (len(numbers) * 6) + (len(punctuation) * 6) + (i * 12) # Fix the font size before dumping it with common.Stream(infont, "rb") as font: with common.Stream(tempfont, "wb") as temp: font.seek(8) size = font.readUInt() font.seek(0) temp.write(font.read(size)) # Dump the font common.execute(fontexe + " -e " + tempfont + " " + xmlfile + " " + imgfile, False) # Generate the code range coderanges = [(0x89, 0x9F), (0xE0, 0xEA)] skipcodes = [0x7F] charrange = (0x40, 0xFC) codes = [] for coderange in coderanges: for i in range(coderange[0], coderange[1] + 1): first = charrange[0] if i == 0x88: first = 0x9F last = charrange[1] if i == 0xEA: last = 0xA4 for j in range(first, last + 1): if j in skipcodes: continue hexcode = i * 0x100 + j if hexcode > 0x9872 and hexcode < 0x989F: continue codes.append(hexcode) # Generate a basic bigrams list items = [" "] for char1 in upperchars: for char2 in lowerchars: items.append(char1 + char2) for char1 in upperchars: items.append(" " + char1) items.append(char1 + " ") for char2 in upperchars: if char1 + char2 not in items: items.append(char1 + char2) for char1 in lowerchars: items.append(" " + char1) items.append(char1 + " ") for char2 in lowerchars: if char1 + char2 not in items: items.append(char1 + char2) for custom in customs: items.append(custom) # And a complete one from all the bigrams with codecs.open(spcin, "r", "utf-8") as spc: inputs = common.getSection(spc, "", "#", game.fixchars) with codecs.open(binin, "r", "utf-8") as bin: inputs.update(common.getSection(bin, "", "#", game.fixchars)) for k, input in inputs.items(): for str in input: str = "<0A>".join(str.replace("|", "<0A>").split(">>")) if str.startswith("<<"): str = str[2:] pad = " " * ((20 - len(str)) // 2) str = pad + str + pad if str.startswith("[") and str[3] == "]": str = str[4:] i = 0 while i < len(str): if i < len(str) - 1 and str[i+1] == "<": str = str[:i+1] + " " + str[i+1:] elif i < len(str) - 4 and (str[i+1:i+5] == "UNK(" or str[i+1:i+5] == "CUS("): str = str[:i+1] + " " + str[i+1:] char = str[i] if char == "<" and i < len(str) - 3 and str[i+3] == ">": i += 4 elif char == "U" and i < len(str) - 4 and str[i:i+4] == "UNK(": i += 9 elif char == "C" and i < len(str) - 4 and str[i:i+4] == "CUS(": i += 9 else: if i + 1 == len(str): bigram = char + " " else: bigram = char + str[i+1] i += 2 if bigram not in items: if bigram[0] not in all or bigram[1] not in all: common.logError("Invalid bigram", bigram, "from phrase", str) else: items.append(bigram) # Open the images img = Image.open(imgfile) pixels = img.load() font = Image.open(fontfile) fontpixels = font.load() # Generate the image and table fontx = 106 fonty = 5644 x = len(codes) - 1 tablestr = "" for item in items: if item in customs: for i2 in range(11): for j2 in range(11): pixels[fontx + i2, fonty + j2] = fontpixels[positions[item] + i2, j2] else: for i2 in range(5): for j2 in range(11): pixels[fontx + i2, fonty + j2] = fontpixels[positions[item[0]] + i2, j2] for j2 in range(11): pixels[fontx + 5, fonty + j2] = fontpixels[positions[" "], j2] for i2 in range(5): for j2 in range(11): pixels[fontx + i2 + 6, fonty + j2] = fontpixels[positions[item[1]] + i2, j2] fontx -= 13 if fontx < 0: fontx = 197 fonty -= 13 tablestr = (item + "=" + common.toHex(codes[x]) + "\n") + tablestr x -= 1 with codecs.open(table, "w", "utf-8") as f: f.write(tablestr) img.save(outfile, "PNG") # Generate the new font common.execute(fontexe + " -i " + xmlfile + " " + outfile + " " + tempfont, False) common.copyFile(tempfont, outfont) # Clean up the temp files os.remove(xmlfile) os.remove(imgfile) os.remove(outfile) os.remove(tempfont) if x < len(items): common.logMessage("Done! Couldn't fit", len(items) - x, "bigrams") else: common.logMessage("Done! Room for", x - len(items), "more bigrams")