mirror of
https://github.com/zeldaret/tp
synced 2026-08-21 14:37:49 -04:00
Shiftable
This commit is contained in:
@@ -7,6 +7,13 @@ Usage: `python tools/extract_game_assets.py`
|
||||
"""
|
||||
|
||||
fstInfoPosition = 0x424
|
||||
bootPosition = 0x0
|
||||
bootSize = 0x440
|
||||
bi2Position = 0x440
|
||||
bi2Size = 0x2000
|
||||
apploaderPosition = 0x2440
|
||||
dolInfoPosition = 0x420
|
||||
|
||||
numFileEntries = 0
|
||||
|
||||
"""
|
||||
@@ -94,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:
|
||||
@@ -125,6 +132,9 @@ def writeAssets(parsedFstBin, handler):
|
||||
# Write the folder structure and files to disc
|
||||
j = 0
|
||||
folderStack = []
|
||||
if not os.path.exists("./files/"):
|
||||
os.makedirs("./files/")
|
||||
os.chdir('./files/')
|
||||
folderStack.append({"folderName": "./", "lastEntryNumber": numFileEntries})
|
||||
for i in parsedFstBin:
|
||||
j += 1
|
||||
@@ -143,6 +153,38 @@ def writeAssets(parsedFstBin, handler):
|
||||
while folderStack[-1]["lastEntryNumber"] == j + 1:
|
||||
folderStack.pop()
|
||||
|
||||
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)
|
||||
|
||||
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))
|
||||
segmentOffset = int.from_bytes(bytearray(disc.read(4)), byteorder="big")
|
||||
disc.seek(dolOffset+0x90+(i*4))
|
||||
segmentSize = int.from_bytes(bytearray(disc.read(4)), byteorder="big")
|
||||
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
|
||||
|
||||
|
||||
|
||||
def extract(path):
|
||||
with open(path, "rb") as f:
|
||||
@@ -150,10 +192,30 @@ def extract(path):
|
||||
f.seek(fstInfoPosition)
|
||||
fstOffset, fstSize = getFstInfo(f, fstInfoPosition)
|
||||
|
||||
f.seek(bootPosition)
|
||||
bootBytes = bytearray(f.read(bootSize))
|
||||
|
||||
f.seek(bi2Position)
|
||||
bi2Bytes = bytearray(f.read(bi2Size))
|
||||
|
||||
f.seek(apploaderPosition+0x14)
|
||||
apploaderSize = int.from_bytes(bytearray(f.read(4)), byteorder="big")
|
||||
f.seek(apploaderPosition+0x18)
|
||||
trailerSize = int.from_bytes(bytearray(f.read(4)), byteorder="big")
|
||||
apploaderMainSize = 0x20 + apploaderSize + trailerSize
|
||||
f.seek(apploaderPosition)
|
||||
apploaderBytes = bytearray(f.read(apploaderMainSize))
|
||||
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)
|
||||
|
||||
# Parse fst.bin
|
||||
parsedFstBin = parseFstBin(fstBinBytes)
|
||||
|
||||
@@ -162,7 +224,7 @@ def extract(path):
|
||||
|
||||
|
||||
def main():
|
||||
extract(sys.argv[1], "rb")
|
||||
extract(sys.argv[1])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import extract_game_assets
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import struct
|
||||
|
||||
|
||||
def sha1_from_data(data):
|
||||
sha1 = hashlib.sha1()
|
||||
sha1.update(data)
|
||||
|
||||
return sha1.hexdigest().upper()
|
||||
|
||||
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)
|
||||
if not outputDir.absolute().exists():
|
||||
os.makedirs(outputDir.absolute())
|
||||
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)
|
||||
else:
|
||||
inf = open(inFile,"rb")
|
||||
inSum = sha1_from_data(bytearray(inf.read()))
|
||||
outf = open(outputFile,"rb")
|
||||
outSum = sha1_from_data(bytearray(outf.read()))
|
||||
if inSum!=outSum:
|
||||
print(str(inFile)+" -> "+str(outputFile))
|
||||
shutil.copyfile(inFile,outputFile)
|
||||
|
||||
|
||||
aMemRels = """d_a_alldie.rel
|
||||
d_a_andsw2.rel
|
||||
d_a_bd.rel
|
||||
d_a_canoe.rel
|
||||
d_a_cstaf.rel
|
||||
d_a_demo_item.rel
|
||||
d_a_door_bossl1.rel
|
||||
d_a_econt.rel
|
||||
d_a_e_dn.rel
|
||||
d_a_e_fm.rel
|
||||
d_a_e_ga.rel
|
||||
d_a_e_hb.rel
|
||||
d_a_e_nest.rel
|
||||
d_a_e_rd.rel
|
||||
d_a_fr.rel
|
||||
d_a_grass.rel
|
||||
d_a_kytag05.rel
|
||||
d_a_kytag10.rel
|
||||
d_a_kytag11.rel
|
||||
d_a_kytag14.rel
|
||||
d_a_mg_fish.rel
|
||||
d_a_npc_besu.rel
|
||||
d_a_npc_fairy_seirei.rel
|
||||
d_a_npc_fish.rel
|
||||
d_a_npc_henna.rel
|
||||
d_a_npc_kakashi.rel
|
||||
d_a_npc_kkri.rel
|
||||
d_a_npc_kolin.rel
|
||||
d_a_npc_maro.rel
|
||||
d_a_npc_taro.rel
|
||||
d_a_npc_tkj.rel
|
||||
d_a_obj_bhashi.rel
|
||||
d_a_obj_bkdoor.rel
|
||||
d_a_obj_bosswarp.rel
|
||||
d_a_obj_cboard.rel
|
||||
d_a_obj_digplace.rel
|
||||
d_a_obj_eff.rel
|
||||
d_a_obj_fmobj.rel
|
||||
d_a_obj_gptaru.rel
|
||||
d_a_obj_hhashi.rel
|
||||
d_a_obj_kanban2.rel
|
||||
d_a_obj_kbacket.rel
|
||||
d_a_obj_kgate.rel
|
||||
d_a_obj_klift00.rel
|
||||
d_a_obj_ktonfire.rel
|
||||
d_a_obj_ladder.rel
|
||||
d_a_obj_lv2candle.rel
|
||||
d_a_obj_magne_arm.rel
|
||||
d_a_obj_metalbox.rel
|
||||
d_a_obj_mgate.rel
|
||||
d_a_obj_nameplate.rel
|
||||
d_a_obj_ornament_cloth.rel
|
||||
d_a_obj_rope_bridge.rel
|
||||
d_a_obj_stick.rel
|
||||
d_a_obj_stonemark.rel
|
||||
d_a_obj_swallshutter.rel
|
||||
d_a_obj_swpropeller.rel
|
||||
d_a_obj_swpush5.rel
|
||||
d_a_obj_yobikusa.rel
|
||||
d_a_scene_exit2.rel
|
||||
d_a_shop_item.rel
|
||||
d_a_sq.rel
|
||||
d_a_swc00.rel
|
||||
d_a_tag_ajnot.rel
|
||||
d_a_tag_attack_item.rel
|
||||
d_a_tag_cstasw.rel
|
||||
d_a_tag_gstart.rel
|
||||
d_a_tag_hinit.rel
|
||||
d_a_tag_hjump.rel
|
||||
d_a_tag_hstop.rel
|
||||
d_a_tag_lv2prchk.rel
|
||||
d_a_tag_magne.rel
|
||||
d_a_tag_mhint.rel
|
||||
d_a_tag_mstop.rel
|
||||
d_a_tag_spring.rel
|
||||
d_a_tag_statue_evt.rel
|
||||
d_a_ykgr.rel"""
|
||||
|
||||
mMemRels = """d_a_andsw.rel
|
||||
d_a_arrow.rel
|
||||
d_a_bg.rel
|
||||
d_a_bg_obj.rel
|
||||
d_a_boomerang.rel
|
||||
d_a_crod.rel
|
||||
d_a_demo00.rel
|
||||
d_a_disappear.rel
|
||||
d_a_dmidna.rel
|
||||
d_a_door_dbdoor00.rel
|
||||
d_a_door_knob00.rel
|
||||
d_a_door_shutter.rel
|
||||
d_a_door_spiral.rel
|
||||
d_a_dshutter.rel
|
||||
d_a_ep.rel
|
||||
d_a_hitobj.rel
|
||||
d_a_kytag00.rel
|
||||
d_a_kytag04.rel
|
||||
d_a_kytag17.rel
|
||||
d_a_mg_rod.rel
|
||||
d_a_midna.rel
|
||||
d_a_nbomb.rel
|
||||
d_a_obj_brakeeff.rel
|
||||
d_a_obj_burnbox.rel
|
||||
d_a_obj_carry.rel
|
||||
d_a_obj_ito.rel
|
||||
d_a_obj_life_container.rel
|
||||
d_a_obj_movebox.rel
|
||||
d_a_obj_swpush.rel
|
||||
d_a_obj_timer.rel
|
||||
d_a_obj_yousei.rel
|
||||
d_a_path_line.rel
|
||||
d_a_scene_exit.rel
|
||||
d_a_set_bgobj.rel
|
||||
d_a_spinner.rel
|
||||
d_a_suspend.rel
|
||||
d_a_swhit0.rel
|
||||
d_a_tag_allmato.rel
|
||||
d_a_tag_attention.rel
|
||||
d_a_tag_camera.rel
|
||||
d_a_tag_chkpoint.rel
|
||||
d_a_tag_event.rel
|
||||
d_a_tag_evt.rel
|
||||
d_a_tag_evtarea.rel
|
||||
d_a_tag_evtmsg.rel
|
||||
d_a_tag_howl.rel
|
||||
d_a_tag_kmsg.rel
|
||||
d_a_tag_lantern.rel
|
||||
d_a_tag_mist.rel
|
||||
d_a_tag_msg.rel
|
||||
d_a_tag_push.rel
|
||||
d_a_tag_telop.rel
|
||||
d_a_tbox.rel
|
||||
d_a_tbox2.rel
|
||||
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
|
||||
|
||||
class HEADER:
|
||||
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
|
||||
|
||||
class NODE:
|
||||
NAME : int
|
||||
stringTableOffset: int
|
||||
hash : int
|
||||
numDirs : int
|
||||
firstDirIndex : int
|
||||
|
||||
class DIRECTORY:
|
||||
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 + ord(char)
|
||||
|
||||
if hash>65535:
|
||||
hash=hash%65535
|
||||
return hash
|
||||
|
||||
def addFile(index,sizeIndex,dirs,name,stringTable,paths,data):
|
||||
file = DIRECTORY()
|
||||
file.dirIndex = index
|
||||
file.stringHash = computeHash(name)
|
||||
file.type = 0xA500
|
||||
file.stringOffset = stringTable.find(name)
|
||||
path = None
|
||||
for relPath in paths:
|
||||
if str(relPath).find(name)!=-1:
|
||||
path = relPath
|
||||
file.fileLength = os.path.getsize(path)
|
||||
file.fileOffset = sizeIndex
|
||||
sizeIndex = sizeIndex + file.fileLength + 1
|
||||
file.unk1 = 0
|
||||
fileData = open(path,"rb")
|
||||
data += fileData.read(file.fileLength)
|
||||
fileData.close()
|
||||
dirs.append(file)
|
||||
|
||||
return dirs,data,sizeIndex
|
||||
|
||||
|
||||
def copyRelFiles(buildPath,aMemList,mMemList):
|
||||
relArcPaths = []
|
||||
for root,dirs,files in os.walk(str(buildPath/"rel")):
|
||||
for file in files:
|
||||
if file.find(".rel")!=-1:
|
||||
relArcFound = False
|
||||
for rel in aMemList:
|
||||
if rel==file:
|
||||
relArcFound = True
|
||||
for rel in mMemList:
|
||||
if rel==file:
|
||||
relArcFound = True
|
||||
fullPath = Path(root+"/"+file)
|
||||
print(str(fullPath)+" -> "+str(buildPath/"game/files/rel/Final/Release"/file))
|
||||
shutil.copy(fullPath,buildPath/"game/files/rel/Final/Release/") #We're copying uncompressed rels here, we should compress in the future!
|
||||
if relArcFound==True:
|
||||
relArcPaths.append(fullPath)
|
||||
#print(relArcPaths)
|
||||
|
||||
#After writing this all I found out we don't actually need RELS.arc to load rels lol, keeping it here for the future in case we want to match RELS.arc
|
||||
|
||||
arcHeader = HEADER()
|
||||
arcHeader.RARC = 0x52415243
|
||||
arcHeader.headerLength = 0x20
|
||||
arcHeader.unk1 = 0
|
||||
arcHeader.unk2 = 0
|
||||
infoBlock = INFO()
|
||||
infoBlock.numNodes = 5
|
||||
infoBlock.numDirsThatAreFiles = 142
|
||||
rootNode = NODE()
|
||||
rootNode.NAME = 0x524F4F54
|
||||
rootNode.numDirs = 4
|
||||
rootNode.firstDirIndex = 0
|
||||
rootNode.hash = computeHash("rels")
|
||||
aMemNode = NODE()
|
||||
aMemNode.NAME = 0x414d454d
|
||||
aMemNode.hash = computeHash("amem")
|
||||
aMemNode.numDirs = 79
|
||||
aMemNode.firstDirIndex = 4
|
||||
mMemNode = NODE()
|
||||
mMemNode.hash = computeHash("mmem")
|
||||
mMemNode.NAME = 0x4d4d454d
|
||||
mMemNode.numDirs = 59
|
||||
mMemNode.firstDirIndex = 83
|
||||
|
||||
stringTable = "\x2E\0\x2E\x2E\0rels\0amem\0"
|
||||
for rel in aMemList:
|
||||
stringTable = stringTable+rel+'\0'
|
||||
stringTable = stringTable+"mmem\0"
|
||||
for rel in mMemList:
|
||||
stringTable = stringTable+rel+'\0'
|
||||
|
||||
rootNode.stringTableOffset = stringTable.find("rels")
|
||||
aMemNode.stringTableOffset = stringTable.find("amem")
|
||||
mMemNode.stringTableOffset = stringTable.find("mmem")
|
||||
|
||||
aMemDir = DIRECTORY()
|
||||
aMemDir.dirIndex = 0xFFFF
|
||||
aMemDir.type = 0x200
|
||||
aMemDir.stringOffset = stringTable.find("amem")
|
||||
aMemDir.stringHash = computeHash("amem")
|
||||
aMemDir.fileOffset = 1
|
||||
aMemDir.fileLength = 0x10
|
||||
aMemDir.unk1 = 0
|
||||
|
||||
mMemDir = DIRECTORY()
|
||||
mMemDir.dirIndex = 0xFFFF
|
||||
mMemDir.type = 0x200
|
||||
mMemDir.stringOffset = stringTable.find("mmem")
|
||||
mMemDir.stringHash = computeHash("mmem")
|
||||
mMemDir.fileOffset = 2
|
||||
mMemDir.fileLength = 0x10
|
||||
mMemDir.unk1 = 0
|
||||
|
||||
unkDir = DIRECTORY()
|
||||
unkDir.dirIndex = 0xFFFF
|
||||
unkDir.stringHash = 0x2E
|
||||
unkDir.type = 0x200
|
||||
unkDir.stringOffset = 0
|
||||
unkDir.fileOffset = 0
|
||||
unkDir.fileLength = 0x10
|
||||
unkDir.unk1 = 0
|
||||
|
||||
unkDir2 = DIRECTORY()
|
||||
unkDir2.dirIndex = 0xFFFF
|
||||
unkDir2.stringHash = 0xB8
|
||||
unkDir2.type = 0x200
|
||||
unkDir2.stringOffset = 2
|
||||
unkDir2.fileOffset = 0xFFFFFFFF
|
||||
unkDir2.fileLength = 0x10
|
||||
unkDir2.unk1 = 0
|
||||
|
||||
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
|
||||
sizeIndex = retSize
|
||||
dirs = retdirs
|
||||
data = retdata
|
||||
for rel in mMemList:
|
||||
retdirs,retdata,retSize = addFile(dirIndex,sizeIndex,dirs,rel,stringTable,relArcPaths,data)
|
||||
dirIndex = dirIndex+1
|
||||
sizeIndex = retSize
|
||||
#print(hex(dirIndex))
|
||||
dirs = retdirs
|
||||
data = retdata
|
||||
|
||||
arcHeader.length = sizeIndex+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
|
||||
infoBlock.stringTableLen = len(stringTable)
|
||||
infoBlock.stringTableOffset = 0xB80
|
||||
infoBlock.unk1 = 0x100
|
||||
infoBlock.unk2 = 0
|
||||
infoBlock.totalDirNum = len(dirs)
|
||||
|
||||
|
||||
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.fileDataLen2,arcHeader.unk1,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))
|
||||
unkData = [0x8A ,0xCF ,0x7F ,0xA5 ,0x00 ,0x09 ,0x36 ,0x00 ,0x0D ,0x08 ,0xA0 ,0x00 ,0x00 ,0x0C ,0xD8 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x8B ,0x9B ,0xF7 ,0xA5 ,0x00 ,0x09 ,0x45 ,0x00 ,0x0D ,0x15 ,0x80 ,0x00 ,0x00 ,0x21 ,0xED ,0x00 ,0x00 ,0x00 ,0x00 ,0xFF ,0xFF ,0x00 ,0x2E ,0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x02 ,0x00 ,0x00 ,0x00 ,0x10 ,0x00 ,0x00 ,0x00 ,0x00 ,0xFF ,0xFF ,0x00 ,0xB8 ,0x02 ,0x00 ,0x00 ,0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x10 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, 0x00]
|
||||
outputArcFile.write(bytearray(unkData))
|
||||
strBytearray = bytearray()
|
||||
strBytearray.extend(map(ord,stringTable))
|
||||
outputArcFile.write(strBytearray)
|
||||
outputArcFile.write(bytearray(6))
|
||||
outputArcFile.write(data)
|
||||
|
||||
outputArcFile.truncate()
|
||||
outputArcFile.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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():
|
||||
print("ISO is not extracted; extracting...")
|
||||
previousDir = os.getcwd()
|
||||
os.chdir(str(gamePath.absolute()))
|
||||
extract_game_assets.extract("../" + str(iso))
|
||||
os.chdir(previousDir)
|
||||
|
||||
print("Copying game files...")
|
||||
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())
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(Path(sys.argv[1]),Path(sys.argv[2]))
|
||||
+1
-1
@@ -351,7 +351,7 @@ def check(debug, rels, game_path, build_path):
|
||||
CONSOLE.print(text)
|
||||
|
||||
try:
|
||||
check_sha1(game_path, build_path, rels)
|
||||
check_sha1(game_path/"files", build_path, rels)
|
||||
text = Text(" OK")
|
||||
text.stylize("bold green")
|
||||
CONSOLE.print(text)
|
||||
|
||||
Reference in New Issue
Block a user