def repackIso(isofile, isopatch, workfolder, patchfile=""): common.logMessage("Repacking ISO", isopatch, "...") if os.path.isfile(isopatch): os.remove(isopatch) common.execute( "wit COPY {folder} {iso}".format(folder=workfolder, iso=isopatch), False) common.logMessage("Done!")
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!")
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")
def extractBRFNT(infile, outfile): brfnt2tpl = common.bundledExecutable("brfnt2tpl.exe") if not os.path.isfile(brfnt2tpl): common.logError("brfnt2tpl not found") return common.execute(brfnt2tpl + " {file}".format(file=infile), False) common.execute( "wimgt DECODE " + infile.replace(".brfnt", ".tpl") + " -D " + outfile, False) os.remove(infile.replace(".brfnt", ".tpl")) os.remove(infile.replace(".brfnt", ".vbfta"))
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")
def signBIN(binout, ebinout, tag): common.logMessage("Signing BIN ...") sign_np = common.bundledExecutable("sign_np.exe") if not os.path.isfile(sign_np): common.logMessage("sign_np not found, copying BOOT to EBOOT...") common.copyFile(binout, ebinout) else: common.execute( sign_np + " -elf {binout} {ebinout} {tag}".format( binout=binout, ebinout=ebinout, tag=str(tag)), False) common.logMessage("Done!")
def repackRom(romfile, rompatch, workfolder, patchfile=""): common.logMessage("Repacking ROM", rompatch, "...") ndstool = common.bundledExecutable("ndstool.exe") if not os.path.isfile(ndstool): common.logError("ndstool not found") return common.execute(ndstool + " -c {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=rompatch, folder=workfolder), False) common.logMessage("Done!") # Create xdelta patch if patchfile != "": common.xdeltaPatch(patchfile, romfile, rompatch)
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!")
def patchdump(): patchfile = "data/bad_to_good.xdelta" common.logMessage("Creating xdelta patch", patchfile, "...") xdelta = common.bundledFile("xdelta.exe") if not os.path.isfile(xdelta): common.logError("xdelta not found") return common.execute( xdelta + " -f -e -s {rom} {rompatch} {patch}".format( rom=romfile.replace(".nds", "_bad.nds"), rompatch=romfile, patch=patchfile), False) common.logMessage("Done!")
def repackBRFNT(outfile, workfile): brfnt2tpl = common.bundledExecutable("brfnt2tpl.exe") if not os.path.isfile(brfnt2tpl): common.logError("brfnt2tpl not found") return common.execute(brfnt2tpl + " {file}".format(file=outfile), False) tplfile = outfile.replace(".brfnt", ".tpl") tpl = readTPL(tplfile) writeTPL(tplfile, tpl, workfile) common.execute( brfnt2tpl + " {file}".format(file=outfile.replace(".brfnt", ".tpl")), False) os.remove(outfile.replace(".brfnt", ".tpl")) os.remove(outfile.replace(".brfnt", ".vbfta"))
def extractBIN(infolder, outfolder, cuefile, data="data/"): common.logMessage("Extracting BIN", cuefile, "...") if not os.path.isfile("psximager\\psxrip.exe"): common.logError("psximager not found") return common.clearFolder(infolder) common.execute( "psximager\\psxrip.exe \"{iso}\" \"{folder}\"".format( iso=cuefile, folder=infolder[:-1]), False) common.copyFile(data + "extract.sys", data + "repack.sys") with open(data + "extract.cat", "r") as fin: with open(data + "repack.cat", "w") as fout: fout.write(fin.read().replace(data + "extract", data + "repack")) common.copyFolder(infolder, outfolder) common.logMessage("Done!")
def repackBIN(binfile, binpatch, cuefile, patchfile="", data="data/"): common.logMessage("Repacking BIN", binpatch, "...") if not os.path.isfile("psximager\\psxbuild.exe"): common.logError("psximager not found") return common.execute( "psximager\\psxbuild.exe \"{cat}\" \"{bin}\"".format( cat=data + "repack.cat", bin=binpatch), False) with open(cuefile, "w") as fout: fout.write("FILE \"" + binpatch.replace(data, "") + "\" BINARY\r\n") fout.write(" TRACK 01 MODE2/2352\r\n") fout.write(" INDEX 01 00:00:00\r\n") common.logMessage("Done!") # Create xdelta patch if patchfile != "": common.xdeltaPatch(patchfile, binfile, binpatch)
def asmPatch(file, workfolder, banks=[0x0], banksize=0x4000): common.logMessage("Applying ASM patch ...") wlagb = common.bundledExecutable("wla-gb.exe") if not os.path.isfile(wlagb): common.logError("wla-gb not found") return wlalink = common.bundledExecutable("wlalink.exe") if not os.path.isfile(wlalink): common.logError("wlalink not found") return # Create the output file ofile = file.replace(".asm", ".o") if os.path.isfile(ofile): os.remove(ofile) common.execute( wlagb + " -o {ofile} {binpatch}".format(binpatch=file, ofile=ofile), False) if not os.path.isfile(ofile): return # Run the linker and create a temporary patched ROM tempfile = file.replace(".asm", ".txt") deletetemp = False if not os.path.isfile(tempfile): deletetemp = True with open(tempfile, "w") as f: f.write("[objects]\n") f.write(ofile + "\n") temprom = "temprom.gb" common.execute( wlalink + " -r {tempfile} {temprom}".format(tempfile=tempfile, temprom=temprom), False) if deletetemp: os.remove(tempfile) os.remove(ofile) # Extract the banks we're interested in from the temp ROM with common.Stream(temprom, "rb") as f: for i in banks: bankname = "bank_" if i < 0x10: bankname += "0" bankname += format(i, 'x') f.seek(i * banksize) with common.Stream(workfolder + bankname + ".bin", "wb") as fout: fout.write(f.read(banksize)) os.remove(temprom) common.logMessage("Done!")
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")
def repackUMD(isofile, isopatch, workfolder, patchfile=""): common.logMessage("Repacking ISO", isopatch, "...") common.copyFile(isofile, isopatch) umdreplace = common.bundledExecutable("UMD-replace.exe") if not os.path.isfile(umdreplace): common.logError("UMD-replace not found") return files = common.getFiles(workfolder) for file in common.showProgress(files): common.execute( umdreplace + " \"{imagename}\" \"/{filename}\" \"{newfile}\"".format( imagename=isopatch, filename=file, newfile=workfolder + file), False) common.logMessage("Done!") # Create xdelta patch if patchfile != "": common.xdeltaPatch(patchfile, isofile, isopatch)
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")
def run(asmfile): # Support a syntax similar to armips, but simplified: # .open file: opens a file # .org 0x100: seek opened file to 0x100 # Everything between this and the next .org/.close # is compiled and wrote to the file with nasm # .import 0x200 file: imports the specified file and writes it to the address # .close: close the opened file (required) tempfile = "asm.tmp" tempout = "asm.bin" with codecs.open(asmfile, "r", "utf-8") as asmf: lines = asmf.readlines() currf = None i = 0 while i < len(lines): line = lines[i].strip() if line == ".close": common.logDebug("Closing file") if currf is not None: currf.close() currf = None elif line.startswith(".open"): parameters = shlex.split(line[5:].strip()) filename = parameters[0] common.logDebug("Opening file", filename) if not os.path.isfile(filename): common.logError("File", filename, "not found.") break currf = common.Stream(filename, "rb+").__enter__() elif line.startswith(".import"): filename = line[7:].strip() parameters = shlex.split(line[7:].strip()) filename = parameters[1] if not os.path.isfile(filename): common.logError("File", filename, "not found.") break importpos = parameters[0] if importpos.startswith("0x"): importpos = int(importpos.replace("0x", ""), 16) else: importpos = int(importpos) currf.seek(importpos) with common.Stream(filename, "rb") as importfile: currf.write(importfile.read()) elif line.startswith(".org"): orgpos = line[4:].strip() if orgpos.startswith("0x"): orgpos = int(orgpos.replace("0x", ""), 16) else: orgpos = int(orgpos) common.logDebug("Seeking to", orgpos) currf.seek(orgpos) # Read up until the next .org or .close and send to nasm j = i + 1 nasmlines = "[BITS 16]\ncpu 186\norg " + str(orgpos) + "\n" while j < len(lines): nasmline = lines[j].strip() if nasmline.startswith(".org") or nasmline.startswith( ".close") or nasmline.startswith(".import"): i = j - 1 break else: if nasmline != "" and not nasmline.startswith(";"): nasmlines += nasmline + "\n" j += 1 common.logDebug("NASM lines:", nasmlines.strip().replace("\n", " | ")) # Write the nasm lines to a file and compile them with codecs.open(tempfile, "w", "utf-8") as tempf: tempf.write(nasmlines) nasm = common.bundledExecutable("nasm.exe") common.execute(nasm + " -O1 -o " + tempout + " -f bin " + tempfile, False) # Read the temp file and write it to the opened one with common.Stream(tempout, "rb") as tempf: currf.write(tempf.read()) os.remove(tempfile) os.remove(tempout) i += 1 if currf is not None: currf.close()