diff --git a/Makefile b/Makefile index 1929850be58..7ddf95c491d 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ TARGET := dolzel2 BUILD_PATH := build BUILD_DIR := $(BUILD_PATH)/$(TARGET) +TARGET_ISO := $(BUILD_DIR)/dolzel2.iso SRC_DIRS := $(shell find src/ libs/ -type f -name '*.cpp') ASM_DIRS := $(shell find asm/ -type f -name '*.s') @@ -129,6 +130,7 @@ clean: clean_game: rm -r -f -d $(TARGET)/game + rm -r -f -d $(TARGET_ISO) clean_assets: rm -r -f -d game @@ -173,7 +175,10 @@ shift: dirs $(DOL_SHIFT) game: shift $(MAKE) rels @mkdir -p game - @$(PYTHON) tools/package_game_assets.py game $(BUILD_DIR) + @$(PYTHON) tools/package_game_assets.py ./game $(BUILD_DIR) + +iso: game + @$(PYTHON) tools/packageISO.py $(BUILD_DIR)/game/ $(TARGET_ISO) rungame: game @echo If you are playing on a shifted game make sure Hyrule Field Speed hack is disabled in dolphin! @@ -206,4 +211,4 @@ include tools/elf2dol/Makefile ### Debug Print ### print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true -.PHONY: default all dirs clean tools docs shift game rungame print-% +.PHONY: default all dirs clean tools docs shift game rungame iso print-% diff --git a/tools/extract_game_assets.py b/tools/extract_game_assets.py index 44124d3d3cb..fc110081355 100644 --- a/tools/extract_game_assets.py +++ b/tools/extract_game_assets.py @@ -101,7 +101,7 @@ Write the current folder to disk and return it's name/last entry number def writeFolder(parsedFstBin, i): - folderPath = i["folderName"] + "/" + folderPath = i["folderName"] + "/" lastEntryNumber = i["lastEntryNumber"] if i["parentFolderEntryNumber"] == 0: @@ -133,8 +133,8 @@ def writeAssets(parsedFstBin, handler): j = 0 folderStack = [] if not os.path.exists("./files/"): - os.makedirs("./files/") - os.chdir('./files/') + os.makedirs("./files/") + os.chdir("./files/") folderStack.append({"folderName": "./", "lastEntryNumber": numFileEntries}) for i in parsedFstBin: j += 1 @@ -153,37 +153,38 @@ def writeAssets(parsedFstBin, handler): while folderStack[-1]["lastEntryNumber"] == j + 1: folderStack.pop() -def writeSys(boot,bi2,apploader,dol,fst): + +def writeSys(boot, bi2, apploader, dol, fst): if not os.path.exists("./sys/"): os.makedirs("./sys/") - open("./sys/boot.bin","wb").write(boot) - open("./sys/bi2.bin","wb").write(bi2) - open("./sys/apploader.img","wb").write(apploader) - open("./sys/main.dol","wb").write(dol) - open("./sys/fst.bin","wb").write(fst) + open("./sys/boot.bin", "wb").write(boot) + open("./sys/bi2.bin", "wb").write(bi2) + open("./sys/apploader.img", "wb").write(apploader) + open("./sys/main.dol", "wb").write(dol) + open("./sys/fst.bin", "wb").write(fst) + def getDolInfo(disc): disc.seek(dolInfoPosition) dolOffset = int.from_bytes(bytearray(disc.read(4)), byteorder="big") dolSize = 0 for i in range(7): - disc.seek(dolOffset+(i*4)) + disc.seek(dolOffset + (i * 4)) segmentOffset = int.from_bytes(bytearray(disc.read(4)), byteorder="big") - disc.seek(dolOffset+0x90+(i*4)) + disc.seek(dolOffset + 0x90 + (i * 4)) segmentSize = int.from_bytes(bytearray(disc.read(4)), byteorder="big") - if (segmentOffset+segmentSize)>dolSize: + if (segmentOffset + segmentSize) > dolSize: dolSize = segmentOffset + segmentSize - - for i in range(11): - disc.seek(dolOffset+0x1c+(i*4)) - dataOffset = int.from_bytes(bytearray(disc.read(4)), byteorder="big") - disc.seek(dolOffset+0xac+(i*4)) - dataSize = int.from_bytes(bytearray(disc.read(4)), byteorder="big") - if (dataOffset+dataSize)>dolSize: - dolSize = dataOffset + dataSize - - return dolOffset, dolSize + for i in range(11): + disc.seek(dolOffset + 0x1C + (i * 4)) + dataOffset = int.from_bytes(bytearray(disc.read(4)), byteorder="big") + disc.seek(dolOffset + 0xAC + (i * 4)) + dataSize = int.from_bytes(bytearray(disc.read(4)), byteorder="big") + if (dataOffset + dataSize) > dolSize: + dolSize = dataOffset + dataSize + + return dolOffset, dolSize def extract(path): @@ -198,9 +199,9 @@ def extract(path): f.seek(bi2Position) bi2Bytes = bytearray(f.read(bi2Size)) - f.seek(apploaderPosition+0x14) + f.seek(apploaderPosition + 0x14) apploaderSize = int.from_bytes(bytearray(f.read(4)), byteorder="big") - f.seek(apploaderPosition+0x18) + f.seek(apploaderPosition + 0x18) trailerSize = int.from_bytes(bytearray(f.read(4)), byteorder="big") apploaderMainSize = 0x20 + apploaderSize + trailerSize f.seek(apploaderPosition) @@ -208,13 +209,12 @@ def extract(path): dolOffset, dolSize = getDolInfo(f) f.seek(dolOffset) dolBytes = bytearray(f.read(dolSize)) - # Seek to fst.bin and retrieve it f.seek(fstOffset) fstBinBytes = bytearray(f.read(fstSize)) - writeSys(bootBytes,bi2Bytes,apploaderBytes,dolBytes,fstBinBytes) + writeSys(bootBytes, bi2Bytes, apploaderBytes, dolBytes, fstBinBytes) # Parse fst.bin parsedFstBin = parseFstBin(fstBinBytes) diff --git a/tools/packageISO.py b/tools/packageISO.py new file mode 100644 index 00000000000..a074318e330 --- /dev/null +++ b/tools/packageISO.py @@ -0,0 +1,141 @@ +import sys +import os +from pathlib import Path +import struct + + +def addPaddingToFile(file, padding): + file.write(bytearray(padding - (file.tell() % padding))) + + +def sortFileList(x): + l = [] + for c in x: + c = ord(c.lower()) + if c == ord("_"): + l.append(255) + else: + l.append(c) + return l + + +def parseDir(dir, stringTable, currentEntryNum, parent): + os.chdir(dir) + entries = sorted(os.listdir("./"), key=sortFileList) + table = [] + for entry in entries: + currentEntryNum = currentEntryNum + 1 + tableEntry = { + "name": entry, + "children": None, + "size": None, + "stringTableOffset": len(stringTable), + "entryNum": currentEntryNum, + "parent": parent, + "path": None, + } + stringTable = stringTable + entry + "\0" + if os.path.isdir(entry): + tableEntry["children"], stringTable, currentEntryNum = parseDir( + entry, stringTable, currentEntryNum, tableEntry + ) + else: + tableEntry["size"] = os.path.getsize(entry) + tableEntry["path"] = os.path.abspath(entry) + + table.append(tableEntry) + os.chdir("..") + return table, stringTable, currentEntryNum + + +def recurseWriteFst(files, fstBin, isoFile): + for currentFile in files: + if currentFile["children"]: # is a directory + nextDirEntryNum = 0 + testLastEntryFile = currentFile["children"][-1] + parentEntryNum = 0 + while True: + if testLastEntryFile["children"]: + testLastEntryFile = testLastEntryFile["children"][-1] + else: + nextDirEntryNum = testLastEntryFile["entryNum"] + 1 + break + if currentFile["parent"]: + parentEntryNum = currentFile["parent"]["entryNum"] + fstBin.append( + struct.pack( + ">BBHII", + 1, + (currentFile["stringTableOffset"] >> 16) & 0xFF, + currentFile["stringTableOffset"] & 0xFFFF, + parentEntryNum, + nextDirEntryNum, + ) + ) + recurseWriteFst(currentFile["children"], fstBin, isoFile) + else: # is a file + fstBin.append( + struct.pack( + ">BBHII", + 0, + (currentFile["stringTableOffset"] >> 16) & 0xFF, + currentFile["stringTableOffset"] & 0xFFFF, + isoFile.tell(), + currentFile["size"], + ) + ) + isoFile.write(open(currentFile["path"], "rb").read()) + addPaddingToFile(isoFile, 0x100) + + +def packageISO(sourcePath, destPath): + print("Converting filesystem into ISO") + + ISOfile = open(destPath, "wb") + # write sys files + ISOfile.write(open(sourcePath / "sys/boot.bin", "rb").read()) + ISOfile.write(open(sourcePath / "sys/bi2.bin", "rb").read()) + ISOfile.write(open(sourcePath / "sys/apploader.img", "rb").read()) + addPaddingToFile(ISOfile, 0x100) + + dolStartPos = ISOfile.tell() + ISOfile.seek(0x420) + ISOfile.write(struct.pack(">I", dolStartPos)) + ISOfile.seek(dolStartPos) + + ISOfile.write(open(sourcePath / "sys/main.dol", "rb").read()) + addPaddingToFile(ISOfile, 0x100) + + fstStartPos = ISOfile.tell() + + files, stringTable, entryLength = parseDir(sourcePath / "files", "", 0, None) + entryLength = entryLength + 1 + + ISOfile.seek(0x424) + ISOfile.write( + struct.pack(">II", fstStartPos, (entryLength * 12) + len(stringTable)) + ) + + # print(stringTable) + # print(files) + # print(hex(entryLength)) + # print(files[0]["entryNum"]) + + fstBin = [] + fstBin.append(struct.pack(">BBHII", 1, 0, 0, 0, entryLength)) + + ISOfile.seek(fstStartPos + (entryLength * 12) + len(stringTable)) + addPaddingToFile(ISOfile, 0x100) + recurseWriteFst(files, fstBin, ISOfile) + + ISOfile.write(bytearray(1459978240 - (ISOfile.tell()))) + + ISOfile.seek(fstStartPos) + for fileEntry in fstBin: + ISOfile.write(fileEntry) + ISOfile.seek((entryLength * 12) + fstStartPos) + ISOfile.write(bytearray(stringTable, "utf8")) + + +if __name__ == "__main__": + packageISO(Path(sys.argv[1]), Path(sys.argv[2])) diff --git a/tools/package_game_assets.py b/tools/package_game_assets.py index 0f88ca2ecec..ae1053e833c 100644 --- a/tools/package_game_assets.py +++ b/tools/package_game_assets.py @@ -6,25 +6,25 @@ from pathlib import Path import hashlib import struct import ctypes -import syaz0 +import oead -def copy(path,destPath): - for root,dirs,files in os.walk(str(path)): +def copy(path, destPath): + for root, dirs, files in os.walk(str(path)): for file in files: - outputDir = destPath/Path(str(root)) - #print(str(outputDir.absolute())+file) + outputDir = destPath / Path(str(root)) + # print(str(outputDir.absolute())+file) if not outputDir.absolute().exists(): os.makedirs(outputDir.absolute()) - outputFile = Path(str(outputDir.absolute())+"/"+str(file)) - inFile = Path(str(Path(root).absolute())+"/"+str(file)) + outputFile = Path(str(outputDir.absolute()) + "/" + str(file)) + inFile = Path(str(Path(root).absolute()) + "/" + str(file)) if not outputFile.exists(): - print(str(inFile)+" -> "+str(outputFile)) - shutil.copyfile(inFile,outputFile) + print(str(inFile) + " -> " + str(outputFile)) + shutil.copyfile(inFile, outputFile) else: - if os.path.getmtime(inFile)>os.path.getmtime(outputFile): - print(str(inFile)+" -> "+str(outputFile)) - shutil.copyfile(inFile,outputFile) + if os.path.getmtime(inFile) > os.path.getmtime(outputFile): + print(str(inFile) + " -> " + str(outputFile)) + shutil.copyfile(inFile, outputFile) aMemRels = """d_a_alldie.rel @@ -163,56 +163,62 @@ d_a_vrbox.rel d_a_vrbox2.rel f_pc_profile_lst.rel""" -#Because libarc is only geared toward reading from arcs I'm writing my own arc writer in this file +# Because libarc is only geared toward reading from arcs I'm writing my own arc writer in this file + class HEADER: - RARC : int - length : int - headerLength : int - fileDataOffset : int - fileDataLen : int - fileDataLen2 : int - unk1 : int - unk2 : int + RARC: int + length: int + headerLength: int + fileDataOffset: int + fileDataLen: int + fileDataLen2: int + unk1: int + unk2: int + class INFO: - numNodes : int - firstNodeOffset : int - totalDirNum : int - firstDirOffset : int - stringTableLen : int - stringTableOffset : int - numDirsThatAreFiles : int - unk1 : int - unk2 : int + numNodes: int + firstNodeOffset: int + totalDirNum: int + firstDirOffset: int + stringTableLen: int + stringTableOffset: int + numDirsThatAreFiles: int + unk1: int + unk2: int + class NODE: - NAME : int + NAME: int stringTableOffset: int - hash : int - numDirs : int - firstDirIndex : int + hash: int + numDirs: int + firstDirIndex: int + class DIRECTORY: - dirIndex : int - stringHash : int - type : int - stringOffset : int - fileOffset : int - fileLength : int - unk1 : int + dirIndex: int + stringHash: int + type: int + stringOffset: int + fileOffset: int + fileLength: int + unk1: int + def computeHash(string): hash = 0 for char in string: - hash = hash*3 + hash = hash * 3 hash = hash + ord(char) hash = ctypes.c_ushort(hash) hash = hash.value return hash -def addFile(index,sizeIndex,dirs,name,stringTable,paths,data): + +def addFile(index, sizeIndex, dirs, name, stringTable, paths, data): file = DIRECTORY() file.dirIndex = index file.stringHash = computeHash(name) @@ -220,12 +226,12 @@ def addFile(index,sizeIndex,dirs,name,stringTable,paths,data): file.stringOffset = stringTable.find(name) path = None for relPath in paths: - if str(relPath).find(name)!=-1: + if str(relPath).find(name) != -1: path = relPath file.unk1 = 0 - fileData = open(path,"rb") + fileData = open(path, "rb") compressedData = oead.yaz0.compress(fileData.read()) - padding = (0x20-(len(compressedData)%0x20)) + padding = 0x20 - (len(compressedData) % 0x20) file.fileLength = len(compressedData) file.fileOffset = sizeIndex sizeIndex = sizeIndex + file.fileLength + padding @@ -234,37 +240,41 @@ def addFile(index,sizeIndex,dirs,name,stringTable,paths,data): fileData.close() dirs.append(file) - return dirs,data,sizeIndex + return dirs, data, sizeIndex -def copyRelFiles(buildPath,aMemList,mMemList): +def copyRelFiles(buildPath, aMemList, mMemList): relArcPaths = [] - for root,dirs,files in os.walk(str(buildPath/"rel")): + for root, dirs, files in os.walk(str(buildPath / "rel")): for file in files: - if file.find(".rel")!=-1: + if file.find(".rel") != -1: relArcFound = False for rel in aMemList: - if rel==file: + if rel == file: relArcFound = True for rel in mMemList: - if rel==file: + if rel == file: relArcFound = True - fullPath = Path(root+"/"+file) - if relArcFound==False: - print(str(fullPath)+" -> "+str(buildPath/"game/files/rel/Final/Release"/file)) - relSource = open(fullPath,"rb") + fullPath = Path(root + "/" + file) + if relArcFound == False: + print( + str(fullPath) + + " -> " + + str(buildPath / "game/files/rel/Final/Release" / file) + ) + relSource = open(fullPath, "rb") data = relSource.read() relSource.close() data = oead.yaz0.compress(data) - relNew = open(buildPath/"game/files/rel/Final/Release"/file,"wb") + relNew = open( + buildPath / "game/files/rel/Final/Release" / file, "wb" + ) relNew.write(data) relNew.truncate() relNew.close() else: relArcPaths.append(fullPath) - - arcHeader = HEADER() arcHeader.RARC = 0x52415243 arcHeader.headerLength = 0x20 @@ -279,24 +289,24 @@ def copyRelFiles(buildPath,aMemList,mMemList): rootNode.firstDirIndex = 0 rootNode.hash = computeHash("rels") aMemNode = NODE() - aMemNode.NAME = 0x414d454d + aMemNode.NAME = 0x414D454D aMemNode.hash = computeHash("amem") aMemNode.numDirs = 79 aMemNode.firstDirIndex = 4 mMemNode = NODE() mMemNode.hash = computeHash("mmem") - mMemNode.NAME = 0x4d4d454d + mMemNode.NAME = 0x4D4D454D mMemNode.numDirs = 59 mMemNode.firstDirIndex = 83 stringTable = ".\0..\0rels\0amem\0" for rel in aMemList: - stringTable = stringTable+rel+'\0' - stringTable = stringTable+"mmem\0" + stringTable = stringTable + rel + "\0" + stringTable = stringTable + "mmem\0" for rel in mMemList: - stringTable = stringTable+rel+'\0' - stringTable = stringTable+"\0\0\0\0\0\0" - + stringTable = stringTable + rel + "\0" + stringTable = stringTable + "\0\0\0\0\0\0" + rootNode.stringTableOffset = stringTable.find("rels") aMemNode.stringTableOffset = stringTable.find("amem") mMemNode.stringTableOffset = stringTable.find("mmem") @@ -337,26 +347,30 @@ def copyRelFiles(buildPath,aMemList,mMemList): unkDir2.fileLength = 0x10 unkDir2.unk1 = 0 - dirs = [aMemDir,mMemDir,unkDir,unkDir2] + dirs = [aMemDir, mMemDir, unkDir, unkDir2] data = bytearray() dirIndex = 4 sizeIndex = 0 for rel in aMemList: - retdirs,retdata,retSize = addFile(dirIndex,sizeIndex,dirs,rel,stringTable,relArcPaths,data) - dirIndex = dirIndex+1 + retdirs, retdata, retSize = addFile( + dirIndex, sizeIndex, dirs, rel, stringTable, relArcPaths, data + ) + dirIndex = dirIndex + 1 sizeIndex = retSize dirs = retdirs data = retdata dirs.append(unkDir) dirs.append(unkDir2) - dirIndex = dirIndex+2 + dirIndex = dirIndex + 2 for rel in mMemList: - retdirs,retdata,retSize = addFile(dirIndex,sizeIndex,dirs,rel,stringTable,relArcPaths,data) - dirIndex = dirIndex+1 + retdirs, retdata, retSize = addFile( + dirIndex, sizeIndex, dirs, rel, stringTable, relArcPaths, data + ) + dirIndex = dirIndex + 1 sizeIndex = retSize - #print(hex(dirIndex)) + # print(hex(dirIndex)) dirs = retdirs data = retdata unkDir3 = DIRECTORY() @@ -378,12 +392,14 @@ def copyRelFiles(buildPath,aMemList,mMemList): unkDir4.unk1 = 0 dirs.append(unkDir3) dirs.append(unkDir4) - dirIndex = dirIndex+2 + dirIndex = dirIndex + 2 - arcHeader.length = len(stringTable)+0x20+0x20+0x30+(len(dirs)*0x14)+len(data) - arcHeader.fileDataOffset=0x14E0 - arcHeader.fileDataLen=len(data) - arcHeader.fileDataLen2=arcHeader.fileDataLen + arcHeader.length = ( + len(stringTable) + 0x20 + 0x20 + 0x30 + (len(dirs) * 0x14) + len(data) + ) + arcHeader.fileDataOffset = 0x14E0 + arcHeader.fileDataLen = len(data) + arcHeader.fileDataLen2 = arcHeader.fileDataLen infoBlock.firstNodeOffset = 0x20 infoBlock.firstDirOffset = 0x60 @@ -393,49 +409,100 @@ def copyRelFiles(buildPath,aMemList,mMemList): infoBlock.unk2 = 0 infoBlock.totalDirNum = 0x8E - - outputArcFile = open(buildPath/"game/files/RELS.arc","wb") + outputArcFile = open(buildPath / "game/files/RELS.arc", "wb") outputArcFile.seek(0) - outputArcFile.write(struct.pack(">IIIIIIII",arcHeader.RARC,arcHeader.length,arcHeader.headerLength,arcHeader.fileDataOffset,arcHeader.fileDataLen,arcHeader.unk1,arcHeader.fileDataLen2,arcHeader.unk2)) - outputArcFile.write(struct.pack(">IIIIIIHHI",infoBlock.numNodes,infoBlock.firstNodeOffset,infoBlock.totalDirNum,infoBlock.firstDirOffset,infoBlock.stringTableLen,infoBlock.stringTableOffset,infoBlock.numDirsThatAreFiles,infoBlock.unk1,infoBlock.unk2)) - outputArcFile.write(struct.pack(">IIHHI",rootNode.NAME,rootNode.stringTableOffset,rootNode.hash,rootNode.numDirs,rootNode.firstDirIndex)) - outputArcFile.write(struct.pack(">IIHHI",aMemNode.NAME,aMemNode.stringTableOffset,aMemNode.hash,aMemNode.numDirs,aMemNode.firstDirIndex)) - outputArcFile.write(struct.pack(">IIHHI",mMemNode.NAME,mMemNode.stringTableOffset,mMemNode.hash,mMemNode.numDirs,mMemNode.firstDirIndex)) + outputArcFile.write( + struct.pack( + ">IIIIIIII", + arcHeader.RARC, + arcHeader.length, + arcHeader.headerLength, + arcHeader.fileDataOffset, + arcHeader.fileDataLen, + arcHeader.unk1, + arcHeader.fileDataLen2, + arcHeader.unk2, + ) + ) + outputArcFile.write( + struct.pack( + ">IIIIIIHHI", + infoBlock.numNodes, + infoBlock.firstNodeOffset, + infoBlock.totalDirNum, + infoBlock.firstDirOffset, + infoBlock.stringTableLen, + infoBlock.stringTableOffset, + infoBlock.numDirsThatAreFiles, + infoBlock.unk1, + infoBlock.unk2, + ) + ) + outputArcFile.write( + struct.pack( + ">IIHHI", + rootNode.NAME, + rootNode.stringTableOffset, + rootNode.hash, + rootNode.numDirs, + rootNode.firstDirIndex, + ) + ) + outputArcFile.write( + struct.pack( + ">IIHHI", + aMemNode.NAME, + aMemNode.stringTableOffset, + aMemNode.hash, + aMemNode.numDirs, + aMemNode.firstDirIndex, + ) + ) + outputArcFile.write( + struct.pack( + ">IIHHI", + mMemNode.NAME, + mMemNode.stringTableOffset, + mMemNode.hash, + mMemNode.numDirs, + mMemNode.firstDirIndex, + ) + ) outputArcFile.write(bytearray(16)) for dir in dirs: - outputArcFile.write(struct.pack(">HHHHIII",dir.dirIndex,dir.stringHash,dir.type,dir.stringOffset,dir.fileOffset,dir.fileLength,dir.unk1)) + outputArcFile.write( + struct.pack( + ">HHHHIII", + dir.dirIndex, + dir.stringHash, + dir.type, + dir.stringOffset, + dir.fileOffset, + dir.fileLength, + dir.unk1, + ) + ) outputArcFile.write(bytearray(8)) strBytearray = bytearray() - strBytearray.extend(map(ord,stringTable)) + strBytearray.extend(map(ord, stringTable)) outputArcFile.write(strBytearray) outputArcFile.write(data) outputArcFile.truncate() outputArcFile.close() - - - - - - - - - - - -def main(gamePath,buildPath): +def main(gamePath, buildPath): if not gamePath.exists(): gamePath.mkdir(parents=True, exist_ok=True) - + iso = Path("gz2e01.iso") if not iso.exists() or not iso.is_file(): print("gz2e01.iso doesn't exist in project directory!") sys.exit(1) - - if not (gamePath/"files").exists() or not (gamePath/"sys").exists(): + + if not (gamePath / "files").exists() or not (gamePath / "sys").exists(): print("ISO is not extracted; extracting...") previousDir = os.getcwd() os.chdir(str(gamePath.absolute())) @@ -443,15 +510,17 @@ def main(gamePath,buildPath): os.chdir(previousDir) print("Copying game files...") - copy(gamePath,buildPath.absolute()) + copy(gamePath, buildPath.absolute()) - print(str(buildPath/"main_shift.dol")+" -> "+str(buildPath/"game/sys/main.dol")) - shutil.copyfile(buildPath/"main_shift.dol",buildPath/"game/sys/main.dol") - - copyRelFiles(buildPath,aMemRels.splitlines(),mMemRels.splitlines()) + print( + str(buildPath / "main_shift.dol") + + " -> " + + str(buildPath / "game/sys/main.dol") + ) + shutil.copyfile(buildPath / "main_shift.dol", buildPath / "game/sys/main.dol") + copyRelFiles(buildPath, aMemRels.splitlines(), mMemRels.splitlines()) - if __name__ == "__main__": - main(Path(sys.argv[1]),Path(sys.argv[2])) \ No newline at end of file + main(Path(sys.argv[1]), Path(sys.argv[2]))