From f453841a5ce81e1790ccb130d7568f7908b703e2 Mon Sep 17 00:00:00 2001 From: jdflyer Date: Fri, 30 Dec 2022 17:45:12 -0700 Subject: [PATCH] ISO packaging script --- Makefile | 9 ++- tools/packageISO.py | 111 +++++++++++++++++++++++++++++++++++ tools/package_game_assets.py | 6 +- 3 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 tools/packageISO.py 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/packageISO.py b/tools/packageISO.py new file mode 100644 index 00000000000..ad2f222172a --- /dev/null +++ b/tools/packageISO.py @@ -0,0 +1,111 @@ +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])) \ No newline at end of file diff --git a/tools/package_game_assets.py b/tools/package_game_assets.py index 20bcf18f224..960ca1cc99b 100644 --- a/tools/package_game_assets.py +++ b/tools/package_game_assets.py @@ -6,7 +6,7 @@ from pathlib import Path import hashlib import struct import ctypes -import syaz0 +import oead def copy(path,destPath): @@ -224,7 +224,7 @@ def addFile(index,sizeIndex,dirs,name,stringTable,paths,data): path = relPath file.unk1 = 0 fileData = open(path,"rb") - compressedData = syaz0.compress(fileData.read()) + compressedData = oead.yaz0.compress(fileData.read()) padding = (0x20-(len(compressedData)%0x20)) file.fileLength = len(compressedData) file.fileOffset = sizeIndex @@ -255,7 +255,7 @@ def copyRelFiles(buildPath,aMemList,mMemList): relSource = open(fullPath,"rb") data = relSource.read() relSource.close() - data = syaz0.compress(data) + data = oead.yaz0.compress(data) relNew = open(buildPath/"game/files/rel/Final/Release"/file,"wb") relNew.write(data) relNew.truncate()