mirror of
				https://github.com/Virtual-World-RE/NeoGF.git
				synced 2025-11-04 01:40:30 +01:00 
			
		
		
		
	Update gcmtool.py
This commit is contained in:
		@@ -5,7 +5,7 @@ from pathlib import Path
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = "0.1.4"
 | 
					__version__ = "0.2.0"
 | 
				
			||||||
__author__ = "rigodron, algoflash, GGLinnk"
 | 
					__author__ = "rigodron, algoflash, GGLinnk"
 | 
				
			||||||
__license__ = "MIT"
 | 
					__license__ = "MIT"
 | 
				
			||||||
__status__ = "developpement"
 | 
					__status__ = "developpement"
 | 
				
			||||||
@@ -39,15 +39,15 @@ class InvalidConfValueError(Exception): pass
 | 
				
			|||||||
class ApploaderOverflowError(Exception): pass
 | 
					class ApploaderOverflowError(Exception): pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def align_top(address:int, align:int):
 | 
					def align_top(offset:int, align:int):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Give the upper rounded address aligned using the align value.
 | 
					    Give the upper rounded offset aligned using the align value.
 | 
				
			||||||
    input: address = int
 | 
					    input: offset = int
 | 
				
			||||||
    input: align = int
 | 
					    input: align = int
 | 
				
			||||||
    return address = int
 | 
					    return offset = int
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    if address % align == 0: return address
 | 
					    if offset % align == 0: return offset
 | 
				
			||||||
    return address + align - (address % align)
 | 
					    return offset + align - (offset % align)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Fst:
 | 
					class Fst:
 | 
				
			||||||
@@ -150,6 +150,7 @@ class FstTree(Fst):
 | 
				
			|||||||
    * root_path = Path (the part with folder that are out of the tree)
 | 
					    * root_path = Path (the part with folder that are out of the tree)
 | 
				
			||||||
    * fst_offset = int (to know where is the current min offset before 
 | 
					    * fst_offset = int (to know where is the current min offset before 
 | 
				
			||||||
        adding the fst and name_block length)
 | 
					        adding the fst and name_block length)
 | 
				
			||||||
 | 
					        has to be aligned
 | 
				
			||||||
    * align = int (It could change in some GCM)
 | 
					    * align = int (It could change in some GCM)
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    # When we walk recursivly in a path we don't wan't to add theirs out parents so it allow to stop at the folder we choose as root
 | 
					    # When we walk recursivly in a path we don't wan't to add theirs out parents so it allow to stop at the folder we choose as root
 | 
				
			||||||
@@ -164,7 +165,11 @@ class FstTree(Fst):
 | 
				
			|||||||
    __name_block = None
 | 
					    __name_block = None
 | 
				
			||||||
    # Used to find min file_offset when fst is at the end of the iso beginning (otherweise we can't know the first available offset)
 | 
					    # Used to find min file_offset when fst is at the end of the iso beginning (otherweise we can't know the first available offset)
 | 
				
			||||||
    __nameblock_length = None
 | 
					    __nameblock_length = None
 | 
				
			||||||
    def __init__(self, root_path:Path, fstbin_offset:int, align:int = 4):
 | 
					    __user_position = None
 | 
				
			||||||
 | 
					    __user_length = None
 | 
				
			||||||
 | 
					    # FST high tell if fst is after dol
 | 
				
			||||||
 | 
					    __is_fst_last = None
 | 
				
			||||||
 | 
					    def __init__(self, root_path:Path, offset:int, is_fst_last:bool, align:int = 4):
 | 
				
			||||||
        # as said before we don't want to add parents folder that don't are used in the folder we are packing.
 | 
					        # as said before we don't want to add parents folder that don't are used in the folder we are packing.
 | 
				
			||||||
        self.__root_path_length = len(root_path.parts)
 | 
					        self.__root_path_length = len(root_path.parts)
 | 
				
			||||||
        self.__root_node = Folder(root_path.name, None)
 | 
					        self.__root_node = Folder(root_path.name, None)
 | 
				
			||||||
@@ -172,7 +177,8 @@ class FstTree(Fst):
 | 
				
			|||||||
        self.__name_block = b""
 | 
					        self.__name_block = b""
 | 
				
			||||||
        self.__fst_block = b""
 | 
					        self.__fst_block = b""
 | 
				
			||||||
        self.__nameblock_length = 0
 | 
					        self.__nameblock_length = 0
 | 
				
			||||||
        self.__current_file_offset = fstbin_offset
 | 
					        self.__current_file_offset = offset
 | 
				
			||||||
 | 
					        self.__is_fst_last = is_fst_last
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.__to_str(self.__root_node)
 | 
					        return self.__to_str(self.__root_node)
 | 
				
			||||||
    def __to_str(self, node:Node, depth=0):
 | 
					    def __to_str(self, node:Node, depth=0):
 | 
				
			||||||
@@ -275,9 +281,14 @@ class FstTree(Fst):
 | 
				
			|||||||
        The hard part Here is that we have to know the result before
 | 
					        The hard part Here is that we have to know the result before
 | 
				
			||||||
        knowing where we can begin to add files.
 | 
					        knowing where we can begin to add files.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.__current_file_offset += self.__get_fst_length()
 | 
					        if self.__is_fst_last:
 | 
				
			||||||
 | 
					            self.__current_file_offset += self.__get_fst_length() # aligned + aligned = aligned
 | 
				
			||||||
 | 
					        self.__user_position = self.__current_file_offset
 | 
				
			||||||
        self.__prepare()
 | 
					        self.__prepare()
 | 
				
			||||||
 | 
					        self.__user_length = self.__current_file_offset - self.__user_position
 | 
				
			||||||
        return self.__fst_block + self.__name_block
 | 
					        return self.__fst_block + self.__name_block
 | 
				
			||||||
 | 
					    def user_position(self): return self.__user_position
 | 
				
			||||||
 | 
					    def user_length(self):   return self.__user_length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BootBin:
 | 
					class BootBin:
 | 
				
			||||||
@@ -310,6 +321,8 @@ class BootBin:
 | 
				
			|||||||
    def fst_offset(self):         return int.from_bytes(self.__data[BootBin.FSTOFFSET_OFFSET:BootBin.FSTOFFSET_OFFSET+4],"big")
 | 
					    def fst_offset(self):         return int.from_bytes(self.__data[BootBin.FSTOFFSET_OFFSET:BootBin.FSTOFFSET_OFFSET+4],"big")
 | 
				
			||||||
    def fst_len(self):            return int.from_bytes(self.__data[BootBin.FSTLEN_OFFSET:BootBin.FSTLEN_OFFSET+4],"big")
 | 
					    def fst_len(self):            return int.from_bytes(self.__data[BootBin.FSTLEN_OFFSET:BootBin.FSTLEN_OFFSET+4],"big")
 | 
				
			||||||
    def fst_max_len(self):        return int.from_bytes(self.__data[BootBin.FSTMAXLEN_OFFSET:BootBin.FSTMAXLEN_OFFSET+4],"big")
 | 
					    def fst_max_len(self):        return int.from_bytes(self.__data[BootBin.FSTMAXLEN_OFFSET:BootBin.FSTMAXLEN_OFFSET+4],"big")
 | 
				
			||||||
 | 
					    def user_position(self):      return int.from_bytes(self.__data[0x434:0x438],"big")
 | 
				
			||||||
 | 
					    def user_length(self):        return int.from_bytes(self.__data[0x438:0x43c],"big")
 | 
				
			||||||
    def set_game_code(self, game_code:str):
 | 
					    def set_game_code(self, game_code:str):
 | 
				
			||||||
        self.__data[:4] = bytes(game_code, "ascii")
 | 
					        self.__data[:4] = bytes(game_code, "ascii")
 | 
				
			||||||
    def set_maker_code(self, maker_code:str):
 | 
					    def set_maker_code(self, maker_code:str):
 | 
				
			||||||
@@ -330,10 +343,14 @@ class BootBin:
 | 
				
			|||||||
        self.__data[BootBin.DOLOFFSET_OFFSET:BootBin.DOLOFFSET_OFFSET+4] = offset.to_bytes(4, "big")
 | 
					        self.__data[BootBin.DOLOFFSET_OFFSET:BootBin.DOLOFFSET_OFFSET+4] = offset.to_bytes(4, "big")
 | 
				
			||||||
    def set_fst_offset(self, offset:int):
 | 
					    def set_fst_offset(self, offset:int):
 | 
				
			||||||
        self.__data[BootBin.FSTOFFSET_OFFSET:BootBin.FSTOFFSET_OFFSET+4] = offset.to_bytes(4, "big")
 | 
					        self.__data[BootBin.FSTOFFSET_OFFSET:BootBin.FSTOFFSET_OFFSET+4] = offset.to_bytes(4, "big")
 | 
				
			||||||
    def set_fst_len(self, size:int):
 | 
					    def set_fst_len(self, length:int):
 | 
				
			||||||
        self.__data[BootBin.FSTLEN_OFFSET:BootBin.FSTLEN_OFFSET+4] = size.to_bytes(4, "big")
 | 
					        self.__data[BootBin.FSTLEN_OFFSET:BootBin.FSTLEN_OFFSET+4] = length.to_bytes(4, "big")
 | 
				
			||||||
    def set_fst_max_len(self, size:int):
 | 
					    def set_fst_max_len(self, length:int):
 | 
				
			||||||
        self.__data[BootBin.FSTMAXLEN_OFFSET:BootBin.FSTMAXLEN_OFFSET+4] = size.to_bytes(4, "big")
 | 
					        self.__data[BootBin.FSTMAXLEN_OFFSET:BootBin.FSTMAXLEN_OFFSET+4] = length.to_bytes(4, "big")
 | 
				
			||||||
 | 
					    def set_user_position(self, user_position:int):
 | 
				
			||||||
 | 
					        self.__data[0x434:0x438] = user_position.to_bytes(4, "big")
 | 
				
			||||||
 | 
					    def set_user_length(self, user_length:int):
 | 
				
			||||||
 | 
					        self.__data[0x438:0x43c] = user_length.to_bytes(4, "big")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Bi2Bin:
 | 
					class Bi2Bin:
 | 
				
			||||||
@@ -360,6 +377,7 @@ class Bi2Bin:
 | 
				
			|||||||
    def country_code(self):           return int.from_bytes(self.__data[24:28], "big")
 | 
					    def country_code(self):           return int.from_bytes(self.__data[24:28], "big")
 | 
				
			||||||
    def total_disk(self):             return int.from_bytes(self.__data[28:32], "big")
 | 
					    def total_disk(self):             return int.from_bytes(self.__data[28:32], "big")
 | 
				
			||||||
    def long_file_name_support(self): return int.from_bytes(self.__data[32:36], "big")
 | 
					    def long_file_name_support(self): return int.from_bytes(self.__data[32:36], "big")
 | 
				
			||||||
 | 
					    def dol_limit(self):              return int.from_bytes(self.__data[40:44], "big")
 | 
				
			||||||
    def set_debug_monitor_size(self, debug_monitor_size:int):
 | 
					    def set_debug_monitor_size(self, debug_monitor_size:int):
 | 
				
			||||||
        self.__data[:4] = debug_monitor_size.to_bytes(4, "big")
 | 
					        self.__data[:4] = debug_monitor_size.to_bytes(4, "big")
 | 
				
			||||||
    def set_simulated_memory_size(self, simulated_memory_size:int):
 | 
					    def set_simulated_memory_size(self, simulated_memory_size:int):
 | 
				
			||||||
@@ -378,6 +396,8 @@ class Bi2Bin:
 | 
				
			|||||||
        self.__data[28:32] = total_disk.to_bytes(4, "big")
 | 
					        self.__data[28:32] = total_disk.to_bytes(4, "big")
 | 
				
			||||||
    def set_long_file_name_support(self, long_file_name_support:int):
 | 
					    def set_long_file_name_support(self, long_file_name_support:int):
 | 
				
			||||||
        self.__data[32:36] = long_file_name_support.to_bytes(4, "big")
 | 
					        self.__data[32:36] = long_file_name_support.to_bytes(4, "big")
 | 
				
			||||||
 | 
					    def set_dol_limit(self, dol_limit:int):
 | 
				
			||||||
 | 
					        self.__data[40:44] = dol_limit.to_bytes(4, "big")
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApploaderImg:
 | 
					class ApploaderImg:
 | 
				
			||||||
@@ -431,7 +451,7 @@ class Gcm:
 | 
				
			|||||||
        config = ConfigParser(allow_no_value=True) # allow_no_value to allow adding comments
 | 
					        config = ConfigParser(allow_no_value=True) # allow_no_value to allow adding comments
 | 
				
			||||||
        config.optionxform = str # makes options case sensitive
 | 
					        config.optionxform = str # makes options case sensitive
 | 
				
			||||||
        config.add_section("Default")
 | 
					        config.add_section("Default")
 | 
				
			||||||
        config.set("Default", "# Documentation available here: https://github.com/Virtual-World-RE/NeoGF/tree/main/gcmtool#system_conf")
 | 
					        config.set("Default", "# Documentation available here: https://github.com/Virtual-World-RE/NeoGF/blob/main/gcmtool/README.md#syssytemconf")
 | 
				
			||||||
        config.set("Default", "boot.bin_section", "disabled")
 | 
					        config.set("Default", "boot.bin_section", "disabled")
 | 
				
			||||||
        config.set("Default", "bi2.bin_section", "disabled")
 | 
					        config.set("Default", "bi2.bin_section", "disabled")
 | 
				
			||||||
        config.set("Default", "apploader.img_section", "disabled")
 | 
					        config.set("Default", "apploader.img_section", "disabled")
 | 
				
			||||||
@@ -449,6 +469,9 @@ class Gcm:
 | 
				
			|||||||
        config.set("boot.bin", "FstOffset",        f"auto")
 | 
					        config.set("boot.bin", "FstOffset",        f"auto")
 | 
				
			||||||
        config.set("boot.bin", "FstLen",           f"auto")
 | 
					        config.set("boot.bin", "FstLen",           f"auto")
 | 
				
			||||||
        config.set("boot.bin", "FstMaxLen",        f"auto")
 | 
					        config.set("boot.bin", "FstMaxLen",        f"auto")
 | 
				
			||||||
 | 
					        config.set("boot.bin", "UserPosition",     f"auto")
 | 
				
			||||||
 | 
					        config.set("boot.bin", "UserLength",       f"auto")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        config.add_section("bi2.bin")
 | 
					        config.add_section("bi2.bin")
 | 
				
			||||||
        config.set("bi2.bin", "DebugMonitorSize",    f"0x{self.__bi2bin.debug_monitor_size():x}")
 | 
					        config.set("bi2.bin", "DebugMonitorSize",    f"0x{self.__bi2bin.debug_monitor_size():x}")
 | 
				
			||||||
@@ -460,6 +483,7 @@ class Gcm:
 | 
				
			|||||||
        config.set("bi2.bin", "CountryCode",         str(self.__bi2bin.country_code())) # 0, 1, 2, 4
 | 
					        config.set("bi2.bin", "CountryCode",         str(self.__bi2bin.country_code())) # 0, 1, 2, 4
 | 
				
			||||||
        config.set("bi2.bin", "TotalDisk",           str(self.__bi2bin.total_disk())) # 1-99
 | 
					        config.set("bi2.bin", "TotalDisk",           str(self.__bi2bin.total_disk())) # 1-99
 | 
				
			||||||
        config.set("bi2.bin", "LongFileNameSupport", str(self.__bi2bin.long_file_name_support())) # 0, 1
 | 
					        config.set("bi2.bin", "LongFileNameSupport", str(self.__bi2bin.long_file_name_support())) # 0, 1
 | 
				
			||||||
 | 
					        config.set("bi2.bin", "DolLimit",            f"0x{self.__bi2bin.dol_limit():x}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        config.add_section("apploader.img")
 | 
					        config.add_section("apploader.img")
 | 
				
			||||||
        config.set("apploader.img", "Version",     self.__apploaderimg.version())
 | 
					        config.set("apploader.img", "Version",     self.__apploaderimg.version())
 | 
				
			||||||
@@ -469,7 +493,8 @@ class Gcm:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        with (sys_path / "system.conf").open("w") as conf_file:
 | 
					        with (sys_path / "system.conf").open("w") as conf_file:
 | 
				
			||||||
            config.write(conf_file)
 | 
					            config.write(conf_file)
 | 
				
			||||||
    def __load_conf(self, sys_path:Path):
 | 
					        logging.info("sys/sytem.conf saved.")
 | 
				
			||||||
 | 
					    def __load_conf(self, sys_path:Path, get_conf_values:bool = False):
 | 
				
			||||||
        "Patch boot.bin, bi2.bin and apploader.img with the conf in sys/system.conf if Default section status is enabled."
 | 
					        "Patch boot.bin, bi2.bin and apploader.img with the conf in sys/system.conf if Default section status is enabled."
 | 
				
			||||||
        config = ConfigParser(allow_no_value=True) # allow_no_value to allow adding comments
 | 
					        config = ConfigParser(allow_no_value=True) # allow_no_value to allow adding comments
 | 
				
			||||||
        config.optionxform = str # makes options case sensitive
 | 
					        config.optionxform = str # makes options case sensitive
 | 
				
			||||||
@@ -506,11 +531,14 @@ class Gcm:
 | 
				
			|||||||
            ("boot.bin", "FstOffset",          True),
 | 
					            ("boot.bin", "FstOffset",          True),
 | 
				
			||||||
            ("boot.bin", "FstLen",             True),
 | 
					            ("boot.bin", "FstLen",             True),
 | 
				
			||||||
            ("boot.bin", "FstMaxLen",          True),
 | 
					            ("boot.bin", "FstMaxLen",          True),
 | 
				
			||||||
 | 
					            ("boot.bin", "UserPosition",       True),
 | 
				
			||||||
 | 
					            ("boot.bin", "UserLength",         True),
 | 
				
			||||||
            ("bi2.bin", "DebugMonitorSize",    False),
 | 
					            ("bi2.bin", "DebugMonitorSize",    False),
 | 
				
			||||||
            ("bi2.bin", "SimulatedMemorySize", False),
 | 
					            ("bi2.bin", "SimulatedMemorySize", False),
 | 
				
			||||||
            ("bi2.bin", "ArgumentOffset",      False),
 | 
					            ("bi2.bin", "ArgumentOffset",      False),
 | 
				
			||||||
            ("bi2.bin", "TrackLocation",       False),
 | 
					            ("bi2.bin", "TrackLocation",       False),
 | 
				
			||||||
            ("bi2.bin", "TrackSize",           False),
 | 
					            ("bi2.bin", "TrackSize",           False),
 | 
				
			||||||
 | 
					            ("bi2.bin", "DolLimit",            False),
 | 
				
			||||||
            ("apploader.img", "EntryPoint",    False),
 | 
					            ("apploader.img", "EntryPoint",    False),
 | 
				
			||||||
            ("apploader.img", "Size",          False),
 | 
					            ("apploader.img", "Size",          False),
 | 
				
			||||||
            ("apploader.img", "TrailerSize",   False)])
 | 
					            ("apploader.img", "TrailerSize",   False)])
 | 
				
			||||||
@@ -519,6 +547,13 @@ class Gcm:
 | 
				
			|||||||
        self.__bi2bin.make_mut()
 | 
					        self.__bi2bin.make_mut()
 | 
				
			||||||
        self.__apploaderimg.make_mut()
 | 
					        self.__apploaderimg.make_mut()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        conf_value_dol_offset = None
 | 
				
			||||||
 | 
					        conf_value_fst_offset = None
 | 
				
			||||||
 | 
					        conf_value_fst_len = 0
 | 
				
			||||||
 | 
					        conf_value_fst_max_len = None
 | 
				
			||||||
 | 
					        conf_value_user_position = None
 | 
				
			||||||
 | 
					        conf_value_user_length = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if config["Default"]["boot.bin_section"].lower() == "enabled":
 | 
					        if config["Default"]["boot.bin_section"].lower() == "enabled":
 | 
				
			||||||
            if len(config["boot.bin"]["GameCode"]) != 4:
 | 
					            if len(config["boot.bin"]["GameCode"]) != 4:
 | 
				
			||||||
                raise InvalidConfValueError("Error - Invalid [boot.bin][GameCode]: must be str with length = 4.")
 | 
					                raise InvalidConfValueError("Error - Invalid [boot.bin][GameCode]: must be str with length = 4.")
 | 
				
			||||||
@@ -560,24 +595,42 @@ class Gcm:
 | 
				
			|||||||
                if dol_offset > 0xffffffff:
 | 
					                if dol_offset > 0xffffffff:
 | 
				
			||||||
                    raise InvalidConfValueError("Error - Invalid [boot.bin][DolOffset]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][DolOffset]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
                self.__bootbin.set_dol_offset( dol_offset )
 | 
					                self.__bootbin.set_dol_offset( dol_offset )
 | 
				
			||||||
 | 
					                conf_value_dol_offset = dol_offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if config["boot.bin"]["FstOffset"] != "auto":
 | 
					            if config["boot.bin"]["FstOffset"] != "auto":
 | 
				
			||||||
                fst_offset = int(config["boot.bin"]["FstOffset"], 16)
 | 
					                fst_offset = int(config["boot.bin"]["FstOffset"], 16)
 | 
				
			||||||
                if fst_offset > 0xffffffff:
 | 
					                if fst_offset > 0xffffffff:
 | 
				
			||||||
                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstOffset]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstOffset]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
                self.__bootbin.set_fst_offset( fst_offset )
 | 
					                self.__bootbin.set_fst_offset( fst_offset )
 | 
				
			||||||
 | 
					                conf_value_fst_offset = fst_offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if config["boot.bin"]["FstLen"] != "auto":
 | 
					            if config["boot.bin"]["FstLen"] != "auto":
 | 
				
			||||||
                fst_len = int(config["boot.bin"]["FstLen"], 16)
 | 
					                fst_len = int(config["boot.bin"]["FstLen"], 16)
 | 
				
			||||||
                if fst_len > 0xffffffff:
 | 
					                if fst_len > 0xffffffff:
 | 
				
			||||||
                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstLen]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstLen]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
                self.__bootbin.set_fst_len( fst_len )
 | 
					                self.__bootbin.set_fst_len( fst_len )
 | 
				
			||||||
 | 
					                conf_value_fst_len = fst_len
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if config["boot.bin"]["FstMaxLen"] != "auto":
 | 
					            if config["boot.bin"]["FstMaxLen"] != "auto":
 | 
				
			||||||
                fst_max_len = int(config["boot.bin"]["FstMaxLen"], 16)
 | 
					                fst_max_len = int(config["boot.bin"]["FstMaxLen"], 16)
 | 
				
			||||||
                if fst_max_len > 0xffffffff:
 | 
					                if fst_max_len > 0xffffffff:
 | 
				
			||||||
                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstMaxLen]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][FstMaxLen]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
                self.__bootbin.set_fst_max_len( fst_max_len )
 | 
					                self.__bootbin.set_fst_max_len( fst_max_len )
 | 
				
			||||||
 | 
					                conf_value_fst_max_len = fst_max_len
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            if config["boot.bin"]["UserPosition"] != "auto":
 | 
				
			||||||
 | 
					                user_position = int(config["boot.bin"]["UserPosition"], 16)
 | 
				
			||||||
 | 
					                if user_position > 0xffffffff:
 | 
				
			||||||
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][UserPosition]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
 | 
					                self.__bootbin.set_user_position( user_position )
 | 
				
			||||||
 | 
					                conf_value_user_position = user_position
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if config["boot.bin"]["UserLength"] != "auto":
 | 
				
			||||||
 | 
					                user_length = int(config["boot.bin"]["UserLength"], 16)
 | 
				
			||||||
 | 
					                if user_length > 0xffffffff:
 | 
				
			||||||
 | 
					                    raise InvalidConfValueError("Error - Invalid [boot.bin][UserLength]: must be auto or unsigned hex value with length < 5 bytes.")
 | 
				
			||||||
 | 
					                self.__bootbin.set_user_length( user_length )
 | 
				
			||||||
 | 
					                conf_value_user_length = user_length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if config["Default"]["bi2.bin_section"].lower() == "enabled":
 | 
					        if config["Default"]["bi2.bin_section"].lower() == "enabled":
 | 
				
			||||||
            debug_monitor_size = int(config["bi2.bin"]["DebugMonitorSize"], 16)
 | 
					            debug_monitor_size = int(config["bi2.bin"]["DebugMonitorSize"], 16)
 | 
				
			||||||
@@ -622,6 +675,11 @@ class Gcm:
 | 
				
			|||||||
                raise InvalidConfValueError("Error - Invalid [bi2.bin][LongFileNameSupport]: must be 0 or 1.")
 | 
					                raise InvalidConfValueError("Error - Invalid [bi2.bin][LongFileNameSupport]: must be 0 or 1.")
 | 
				
			||||||
            self.__bi2bin.set_long_file_name_support( int(config["bi2.bin"]["LongFileNameSupport"]) )
 | 
					            self.__bi2bin.set_long_file_name_support( int(config["bi2.bin"]["LongFileNameSupport"]) )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            dol_limit = int(config["bi2.bin"]["DolLimit"], 16)
 | 
				
			||||||
 | 
					            if dol_limit > 0xffffffff:
 | 
				
			||||||
 | 
					                raise InvalidConfValueError("Error - Invalid [bi2.bin][DolLimit]: must be hex value with length < 5 bytes.")
 | 
				
			||||||
 | 
					            self.__bi2bin.set_dol_limit( dol_limit )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if config["Default"]["apploader.img_section"].lower() == "enabled":
 | 
					        if config["Default"]["apploader.img_section"].lower() == "enabled":
 | 
				
			||||||
            version = config["apploader.img"]["Version"]
 | 
					            version = config["apploader.img"]["Version"]
 | 
				
			||||||
            if len(version) > 10:
 | 
					            if len(version) > 10:
 | 
				
			||||||
@@ -646,6 +704,18 @@ class Gcm:
 | 
				
			|||||||
        (sys_path / "boot.bin").write_bytes(self.__bootbin.data())
 | 
					        (sys_path / "boot.bin").write_bytes(self.__bootbin.data())
 | 
				
			||||||
        (sys_path / "bi2.bin").write_bytes(self.__bi2bin.data())
 | 
					        (sys_path / "bi2.bin").write_bytes(self.__bi2bin.data())
 | 
				
			||||||
        (sys_path / "apploader.img").write_bytes(self.__apploaderimg.data())
 | 
					        (sys_path / "apploader.img").write_bytes(self.__apploaderimg.data())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        logging.info("sys/sytem.conf loaded.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if get_conf_values:
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                conf_value_dol_offset,
 | 
				
			||||||
 | 
					                conf_value_fst_offset,
 | 
				
			||||||
 | 
					                conf_value_fst_len,
 | 
				
			||||||
 | 
					                conf_value_fst_max_len,
 | 
				
			||||||
 | 
					                conf_value_user_position,
 | 
				
			||||||
 | 
					                conf_value_user_length
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
    def __get_min_file_offset(self, fstbin_data:bytes):
 | 
					    def __get_min_file_offset(self, fstbin_data:bytes):
 | 
				
			||||||
        "Get the min file offset to check if there is an overflow."
 | 
					        "Get the min file offset to check if there is an overflow."
 | 
				
			||||||
        min_offset = None
 | 
					        min_offset = None
 | 
				
			||||||
@@ -752,7 +822,7 @@ class Gcm:
 | 
				
			|||||||
                    (currentdir_path / name).write_bytes( iso_file.read(filesize) )
 | 
					                    (currentdir_path / name).write_bytes( iso_file.read(filesize) )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    logging.debug(f"{iso_path}(0x{fileoffset:x}:0x{fileoffset + filesize:x}) -> {currentdir_path / name}")
 | 
					                    logging.debug(f"{iso_path}(0x{fileoffset:x}:0x{fileoffset + filesize:x}) -> {currentdir_path / name}")
 | 
				
			||||||
    def pack(self, folder_path:Path, iso_path:Path = None, disable_ignore:bool = False):
 | 
					    def pack(self, folder_path:Path, iso_path:Path = None, disable_ignore:bool = False, skip_conf:bool = False):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Pack takes a folder unpacked by the pack command and pack it in a GCM/iso file.
 | 
					        Pack takes a folder unpacked by the pack command and pack it in a GCM/iso file.
 | 
				
			||||||
        input: folder_path = Path
 | 
					        input: folder_path = Path
 | 
				
			||||||
@@ -771,8 +841,11 @@ class Gcm:
 | 
				
			|||||||
                self.__bi2bin = Bi2Bin((sys_path / "bi2.bin").read_bytes())
 | 
					                self.__bi2bin = Bi2Bin((sys_path / "bi2.bin").read_bytes())
 | 
				
			||||||
                self.__apploaderimg = ApploaderImg((sys_path / "apploader.img").read_bytes())
 | 
					                self.__apploaderimg = ApploaderImg((sys_path / "apploader.img").read_bytes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Patch boot.bin and bi2.bin if system.conf is enabled
 | 
					                # Patch boot.bin bi2.bin and apploader.img if system.conf is enabled
 | 
				
			||||||
                self.__load_conf(sys_path)
 | 
					                if not skip_conf:
 | 
				
			||||||
 | 
					                    self.__load_conf(sys_path)
 | 
				
			||||||
 | 
					                if self.__bootbin.fst_len() > self.__bootbin.fst_max_len():
 | 
				
			||||||
 | 
					                    raise InvalidFSTSizeError(f"Error - fst.bin max length < fst.bin length in boot.bin offset 0x{BootBin.FSTMAXLEN_OFFSET:x}:0x{BootBin.FSTMAXLEN_OFFSET+4:x}.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                logging.debug(f"{sys_path / 'boot.bin'}      -> {iso_path}(0x0:0x{BootBin.LEN:x})")
 | 
					                logging.debug(f"{sys_path / 'boot.bin'}      -> {iso_path}(0x0:0x{BootBin.LEN:x})")
 | 
				
			||||||
                iso_file.write(self.__bootbin.data())
 | 
					                iso_file.write(self.__bootbin.data())
 | 
				
			||||||
@@ -787,7 +860,7 @@ class Gcm:
 | 
				
			|||||||
                fstbin_len = self.__bootbin.fst_len()
 | 
					                fstbin_len = self.__bootbin.fst_len()
 | 
				
			||||||
                fstbin_end_offset = fstbin_offset + fstbin_len
 | 
					                fstbin_end_offset = fstbin_offset + fstbin_len
 | 
				
			||||||
                if (sys_path / "fst.bin").stat().st_size != fstbin_len:
 | 
					                if (sys_path / "fst.bin").stat().st_size != fstbin_len:
 | 
				
			||||||
                    raise InvalidFSTSizeError(f"Error - Invalid fst.bin size in boot.bin offset 0x{BootBin.FSTLEN_OFFSET:x}:0x{BootBin.FSTLEN_OFFSET+4:x}.")
 | 
					                    raise InvalidFSTSizeError(f"Error - Invalid fst.bin length in boot.bin offset 0x{BootBin.FSTLEN_OFFSET:x}:0x{BootBin.FSTLEN_OFFSET+4:x}.")
 | 
				
			||||||
                logging.debug(f"{sys_path / 'fst.bin'}       -> {iso_path}(0x{fstbin_offset:x}:0x{fstbin_offset + fstbin_len:x})")
 | 
					                logging.debug(f"{sys_path / 'fst.bin'}       -> {iso_path}(0x{fstbin_offset:x}:0x{fstbin_offset + fstbin_len:x})")
 | 
				
			||||||
                iso_file.seek( fstbin_offset )
 | 
					                iso_file.seek( fstbin_offset )
 | 
				
			||||||
                fstbin_data = (sys_path / "fst.bin").read_bytes()
 | 
					                fstbin_data = (sys_path / "fst.bin").read_bytes()
 | 
				
			||||||
@@ -803,15 +876,15 @@ class Gcm:
 | 
				
			|||||||
                if not disable_ignore:
 | 
					                if not disable_ignore:
 | 
				
			||||||
                    if not Gcm.APPLOADER_OFFSET < dol_offset < dol_end_offset <= fstbin_offset and not \
 | 
					                    if not Gcm.APPLOADER_OFFSET < dol_offset < dol_end_offset <= fstbin_offset and not \
 | 
				
			||||||
                        fstbin_offset < dol_offset < dol_end_offset <= min_file_offset:
 | 
					                        fstbin_offset < dol_offset < dol_end_offset <= min_file_offset:
 | 
				
			||||||
                        raise DolSizeOverflowError("Error - The dol size has been increased and overflow on next file or on FST. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
					                        raise DolSizeOverflowError("Error - The dol length has been increased and overflow on next file or on FST. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if not Gcm.APPLOADER_OFFSET < fstbin_offset < fstbin_end_offset <= dol_offset and not \
 | 
					                if not Gcm.APPLOADER_OFFSET < fstbin_offset < fstbin_end_offset <= dol_offset and not \
 | 
				
			||||||
                    dol_end_offset <= fstbin_offset < fstbin_end_offset <= min_file_offset:
 | 
					                    dol_end_offset <= fstbin_offset < fstbin_end_offset <= min_file_offset:
 | 
				
			||||||
                    raise FstSizeOverflowError("Error - The FST size has been increased and overflow on next file or on FST. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
					                    raise FstSizeOverflowError("Error - The FST length has been increased and overflow on next file or on dol. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if Gcm.APPLOADER_OFFSET < dol_offset < apploader_end_offset or \
 | 
					                if Gcm.APPLOADER_OFFSET < dol_offset < apploader_end_offset or \
 | 
				
			||||||
                    Gcm.APPLOADER_OFFSET < fstbin_offset < apploader_end_offset:
 | 
					                    Gcm.APPLOADER_OFFSET < fstbin_offset < apploader_end_offset:
 | 
				
			||||||
                    raise ApploaderOverflowError("Error - The apploader size has been increased and overflow on dol or on FST. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
					                    raise ApploaderOverflowError("Error - The apploader length has been increased and overflow on dol or on FST. To solve this check the sys/system.conf file if used or use --rebuild-fst.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                logging.debug(f"{sys_path / 'boot.dol'}      -> {iso_path}(0x{dol_offset:x}:0x{dol_end_offset:x})")
 | 
					                logging.debug(f"{sys_path / 'boot.dol'}      -> {iso_path}(0x{dol_offset:x}:0x{dol_end_offset:x})")
 | 
				
			||||||
                iso_file.seek( dol_offset )
 | 
					                iso_file.seek( dol_offset )
 | 
				
			||||||
@@ -862,7 +935,7 @@ class Gcm:
 | 
				
			|||||||
                        file_len   = int.from_bytes(fstbin_data[i+8:i+12], "big")
 | 
					                        file_len   = int.from_bytes(fstbin_data[i+8:i+12], "big")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (currentdir_path / name).stat().st_size != file_len:
 | 
					                        if (currentdir_path / name).stat().st_size != file_len:
 | 
				
			||||||
                            raise InvalidFSTFileSizeError(f"Error - Invalid file size: {currentdir_path / name} - use --rebuild-fst before packing files in the iso.")
 | 
					                            raise InvalidFSTFileSizeError(f"Error - Invalid file length: {currentdir_path / name} - use --rebuild-fst before packing files in the iso.")
 | 
				
			||||||
                        logging.debug(f"{currentdir_path / name} -> {iso_path}(0x{file_offset:x}:0x{file_offset + file_len:x})")
 | 
					                        logging.debug(f"{currentdir_path / name} -> {iso_path}(0x{file_offset:x}:0x{file_offset + file_len:x})")
 | 
				
			||||||
                        iso_file.seek(file_offset)
 | 
					                        iso_file.seek(file_offset)
 | 
				
			||||||
                        iso_file.write( (currentdir_path / name).read_bytes() )
 | 
					                        iso_file.write( (currentdir_path / name).read_bytes() )
 | 
				
			||||||
@@ -870,7 +943,7 @@ class Gcm:
 | 
				
			|||||||
            FSTDirNotFoundError, FSTFileNotFoundError, InvalidConfValueError, FstSizeOverflowError, ApploaderOverflowError):
 | 
					            FSTDirNotFoundError, FSTFileNotFoundError, InvalidConfValueError, FstSizeOverflowError, ApploaderOverflowError):
 | 
				
			||||||
            iso_path.unlink()
 | 
					            iso_path.unlink()
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
    def rebuild_fst(self, folder_path:Path, align:int):
 | 
					    def rebuild_fst(self, folder_path:Path, align:int, skip_conf:bool):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Rebuild FST generate a new file system by using all files in the root folder
 | 
					        Rebuild FST generate a new file system by using all files in the root folder
 | 
				
			||||||
        it patch boot.bin caracteristics, apploader.img and also file system changes.
 | 
					        it patch boot.bin caracteristics, apploader.img and also file system changes.
 | 
				
			||||||
@@ -882,18 +955,37 @@ class Gcm:
 | 
				
			|||||||
        root_path = folder_path / "root"
 | 
					        root_path = folder_path / "root"
 | 
				
			||||||
        sys_path = folder_path / "sys"
 | 
					        sys_path = folder_path / "sys"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dol_offset = align_top(Gcm.APPLOADER_OFFSET + (sys_path / "apploader.img").stat().st_size, align)
 | 
					        self.__bootbin = BootBin((sys_path / "boot.bin").read_bytes())
 | 
				
			||||||
        logging.info(f"Patching {Path('sys/boot.bin')} offset 0x{BootBin.DOLOFFSET_OFFSET:x} with new dol offset (0x{dol_offset:x})")
 | 
					        self.__bi2bin = Bi2Bin((sys_path / "bi2.bin").read_bytes())
 | 
				
			||||||
        self.__bootbin = BootBin(bytearray((sys_path / "boot.bin").read_bytes()))
 | 
					        self.__apploaderimg = ApploaderImg((sys_path / "apploader.img").read_bytes())
 | 
				
			||||||
        self.__bootbin.set_dol_offset(dol_offset)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fstbin_offset = align_top(dol_offset + (sys_path / "boot.dol").stat().st_size, align)
 | 
					        (
 | 
				
			||||||
        logging.info(f"Patching {Path('sys/boot.bin')} offset 0x{BootBin.FSTOFFSET_OFFSET:x} with new FST offset (0x{fstbin_offset:x})")
 | 
					            dol_offset,
 | 
				
			||||||
        self.__bootbin.set_fst_offset(fstbin_offset)
 | 
					            fst_offset,
 | 
				
			||||||
 | 
					            fst_len,
 | 
				
			||||||
 | 
					            fst_max_len,
 | 
				
			||||||
 | 
					            user_position,
 | 
				
			||||||
 | 
					            user_length
 | 
				
			||||||
 | 
					        ) = self.__load_conf(sys_path, get_conf_values = True) if not skip_conf else (None, None, 0, None, None, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fst_tree = FstTree(root_path, fstbin_offset, align=align)
 | 
					        if dol_offset is None:
 | 
				
			||||||
 | 
					            dol_offset = align_top(Gcm.APPLOADER_OFFSET + (sys_path / "apploader.img").stat().st_size, align)
 | 
				
			||||||
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x{BootBin.DOLOFFSET_OFFSET:x} with new dol offset (0x{dol_offset:x}).")
 | 
				
			||||||
 | 
					            self.__bootbin.set_dol_offset(dol_offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Sorting paths approach original fst sort, but in original fst specials chars are after and not before chars
 | 
					        dol_end_offset = align_top(dol_offset + (sys_path / "boot.dol").stat().st_size, align)
 | 
				
			||||||
 | 
					        # Default = FST after dol
 | 
				
			||||||
 | 
					        if fst_offset is None:
 | 
				
			||||||
 | 
					            fst_offset = dol_end_offset
 | 
				
			||||||
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x{BootBin.FSTOFFSET_OFFSET:x} with new FST offset (0x{fst_offset:x}).")
 | 
				
			||||||
 | 
					            self.__bootbin.set_fst_offset(fst_offset)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        fst_end_offset = fst_offset + fst_len
 | 
				
			||||||
 | 
					        fst_tree = FstTree(root_path, max(dol_end_offset, fst_offset, fst_end_offset), \
 | 
				
			||||||
 | 
					            is_fst_last = (dol_end_offset <= fst_offset and fst_len == 0), align=align)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Sorting paths approach original fst sort, but in original fst specials chars are after and not before chars.
 | 
				
			||||||
 | 
					        # Files / Folders are sometimes put in arbitrary order.
 | 
				
			||||||
        path_list = sorted([path for path in root_path.glob('**/*')], key=lambda s:Path(str(s).upper()))
 | 
					        path_list = sorted([path for path in root_path.glob('**/*')], key=lambda s:Path(str(s).upper()))
 | 
				
			||||||
        for path in path_list:
 | 
					        for path in path_list:
 | 
				
			||||||
            fst_tree.add_node_by_path(path)
 | 
					            fst_tree.add_node_by_path(path)
 | 
				
			||||||
@@ -901,14 +993,28 @@ class Gcm:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fst_path = sys_path / "fst.bin"
 | 
					        fst_path = sys_path / "fst.bin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        logging.info(f"Writing fst in {Path('sys/fst.bin')}")
 | 
					        logging.info(f"Writing fst in sys/fst.bin")
 | 
				
			||||||
        fst_path.write_bytes( fst_tree.generate_fst() )
 | 
					        fst_path.write_bytes( fst_tree.generate_fst() )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fstbin_len = fst_path.stat().st_size
 | 
					        if fst_len == 0:
 | 
				
			||||||
        logging.info(f"Patching {Path('sys/boot.bin')} offset 0x{BootBin.FSTLEN_OFFSET:x} with new FST size (0x{fstbin_len:x})")
 | 
					            fst_len = fst_path.stat().st_size
 | 
				
			||||||
        self.__bootbin.set_fst_len(fstbin_len)
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x{BootBin.FSTLEN_OFFSET:x} with new FST size (0x{fst_len:x}).")
 | 
				
			||||||
        logging.info(f"Patching {Path('sys/boot.bin')} offset 0x{BootBin.FSTMAXLEN_OFFSET:x} with new FST max size (0x{fstbin_len:x})")
 | 
					            self.__bootbin.set_fst_len(fst_len)
 | 
				
			||||||
        self.__bootbin.set_fst_max_len(fstbin_len)
 | 
					
 | 
				
			||||||
 | 
					        if fst_max_len is None and fst_len > self.__bootbin.fst_max_len():
 | 
				
			||||||
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x{BootBin.FSTMAXLEN_OFFSET:x} with new FST max size (0x{fst_len:x}).")
 | 
				
			||||||
 | 
					            self.__bootbin.set_fst_max_len(fst_len)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if user_position is None:
 | 
				
			||||||
 | 
					            # Allow fixed fst_len or dol after FST fixed by conf
 | 
				
			||||||
 | 
					            user_position = max(fst_tree.user_position(), fst_offset + fst_len, dol_end_offset)
 | 
				
			||||||
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x434 with new user position (0x{user_position:x}).")
 | 
				
			||||||
 | 
					            self.__bootbin.set_user_position(user_position)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if user_length is None:
 | 
				
			||||||
 | 
					            user_length = fst_tree.user_length()
 | 
				
			||||||
 | 
					            logging.info(f"Patching sys/boot.bin offset 0x438 with new user length (0x{user_length:x}).")
 | 
				
			||||||
 | 
					            self.__bootbin.set_user_length(user_length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        (sys_path / "boot.bin").write_bytes(self.__bootbin.data())
 | 
					        (sys_path / "boot.bin").write_bytes(self.__bootbin.data())
 | 
				
			||||||
    def __get_sys_from_folder(self, folder_path:Path):
 | 
					    def __get_sys_from_folder(self, folder_path:Path):
 | 
				
			||||||
@@ -972,7 +1078,9 @@ class Gcm:
 | 
				
			|||||||
            f"DolOffset = 0x{self.__bootbin.dol_offset():x}\n" + \
 | 
					            f"DolOffset = 0x{self.__bootbin.dol_offset():x}\n" + \
 | 
				
			||||||
            f"FstOffset = 0x{self.__bootbin.fst_offset():x}\n" + \
 | 
					            f"FstOffset = 0x{self.__bootbin.fst_offset():x}\n" + \
 | 
				
			||||||
            f"FstLen = 0x{self.__bootbin.fst_len():x}\n" + \
 | 
					            f"FstLen = 0x{self.__bootbin.fst_len():x}\n" + \
 | 
				
			||||||
            f"FstMaxLen = 0x{self.__bootbin.fst_max_len():x}\n\n" + \
 | 
					            f"FstMaxLen = 0x{self.__bootbin.fst_max_len():x}\n" + \
 | 
				
			||||||
 | 
					            f"UserPosition = 0x{self.__bootbin.user_position():x}\n" + \
 | 
				
			||||||
 | 
					            f"UserLength = 0x{self.__bootbin.user_length():x}\n\n" + \
 | 
				
			||||||
            "[bi2.bin]\n" + \
 | 
					            "[bi2.bin]\n" + \
 | 
				
			||||||
            f"DebugMonitorSize = 0x{self.__bi2bin.debug_monitor_size():x}\n" + \
 | 
					            f"DebugMonitorSize = 0x{self.__bi2bin.debug_monitor_size():x}\n" + \
 | 
				
			||||||
            f"SimulatedMemorySize = 0x{self.__bi2bin.simulated_memory_size():x}\n" + \
 | 
					            f"SimulatedMemorySize = 0x{self.__bi2bin.simulated_memory_size():x}\n" + \
 | 
				
			||||||
@@ -982,7 +1090,8 @@ class Gcm:
 | 
				
			|||||||
            f"TrackSize = 0x{self.__bi2bin.track_size():x}\n" + \
 | 
					            f"TrackSize = 0x{self.__bi2bin.track_size():x}\n" + \
 | 
				
			||||||
            f"CountryCode = {self.__bi2bin.country_code()}\n" + \
 | 
					            f"CountryCode = {self.__bi2bin.country_code()}\n" + \
 | 
				
			||||||
            f"TotalDisk = {self.__bi2bin.total_disk()}\n" + \
 | 
					            f"TotalDisk = {self.__bi2bin.total_disk()}\n" + \
 | 
				
			||||||
            f"LongFileNameSupport = {self.__bi2bin.long_file_name_support()}\n\n" + \
 | 
					            f"LongFileNameSupport = {self.__bi2bin.long_file_name_support()}\n" + \
 | 
				
			||||||
 | 
					            f"DolLimit = 0x{self.__bi2bin.dol_limit():x}\n\n" + \
 | 
				
			||||||
            "[apploader.img]\n" + \
 | 
					            "[apploader.img]\n" + \
 | 
				
			||||||
            f"Version = {self.__apploaderimg.version()}\n" + \
 | 
					            f"Version = {self.__apploaderimg.version()}\n" + \
 | 
				
			||||||
            f"EntryPoint = 0x{self.__apploaderimg.entry_point():x}\n" + \
 | 
					            f"EntryPoint = 0x{self.__apploaderimg.entry_point():x}\n" + \
 | 
				
			||||||
@@ -1066,12 +1175,12 @@ class Gcm:
 | 
				
			|||||||
        print(full_title + "\n".join([str(mem_obj) for mem_obj in mem_obj_list]))
 | 
					        print(full_title + "\n".join([str(mem_obj) for mem_obj in mem_obj_list]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pack(p_input:Path, p_output:Path, disable_ignore):
 | 
					def pack(p_input:Path, p_output:Path, disable_ignore:bool, skip_conf:bool = False):
 | 
				
			||||||
    logging.info("### Pack in new GCM iso")
 | 
					    logging.info("### Pack in new GCM iso")
 | 
				
			||||||
    if(p_output == Path(".")):
 | 
					    if(p_output == Path(".")):
 | 
				
			||||||
        p_output = Path(p_input.with_suffix(".iso"))
 | 
					        p_output = Path(p_input.with_suffix(".iso"))
 | 
				
			||||||
    logging.info(f"packing folder \"{p_input}\" in \"{p_output}\"")
 | 
					    logging.info(f"Packing folder \"{p_input}\" in \"{p_output}\"")
 | 
				
			||||||
    gcm.pack(p_input, p_output, disable_ignore)
 | 
					    gcm.pack(p_input, p_output, disable_ignore, skip_conf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def unpack(p_input:Path, p_output:Path):
 | 
					def unpack(p_input:Path, p_output:Path):
 | 
				
			||||||
@@ -1079,12 +1188,12 @@ def unpack(p_input:Path, p_output:Path):
 | 
				
			|||||||
    gcm.unpack(p_input, p_output)
 | 
					    gcm.unpack(p_input, p_output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def rebuild_fst(p_input:Path, align):
 | 
					def rebuild_fst(p_input:Path, align:int, skip_conf:bool = False):
 | 
				
			||||||
    logging.info("### Rebuilding FST and patching boot.bin")
 | 
					    logging.info("### Rebuilding FST and patching boot.bin")
 | 
				
			||||||
    if args.align < 1:
 | 
					    if args.align < 1:
 | 
				
			||||||
        raise BadAlignError("Error - Align must be > 0.")
 | 
					        raise BadAlignError("Error - Align must be > 0.")
 | 
				
			||||||
    logging.info(f"Using alignment: {args.align}")
 | 
					    logging.info(f"Using alignment: {args.align}")
 | 
				
			||||||
    gcm.rebuild_fst(p_input, align)
 | 
					    gcm.rebuild_fst(p_input, align, skip_conf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_argparser():
 | 
					def get_argparser():
 | 
				
			||||||
@@ -1127,8 +1236,8 @@ if __name__ == '__main__':
 | 
				
			|||||||
    elif args.rebuild_fst:
 | 
					    elif args.rebuild_fst:
 | 
				
			||||||
        rebuild_fst(p_input, args.align)
 | 
					        rebuild_fst(p_input, args.align)
 | 
				
			||||||
    elif args.rebuild_fst_pack:
 | 
					    elif args.rebuild_fst_pack:
 | 
				
			||||||
        rebuild_fst(p_input, args.align)
 | 
					        rebuild_fst(p_input, args.align) # rebuild fst parse and patch with conf
 | 
				
			||||||
        pack(p_input, p_output, args.disable_ignore)
 | 
					        pack(p_input, p_output, args.disable_ignore, skip_conf = True)
 | 
				
			||||||
    elif args.unpack_rebuild_fst:
 | 
					    elif args.unpack_rebuild_fst:
 | 
				
			||||||
        unpack(p_input, p_output)
 | 
					        unpack(p_input, p_output) # conf isn't enabled yet
 | 
				
			||||||
        rebuild_fst(p_output, args.align)
 | 
					        rebuild_fst(p_output, args.align, skip_conf = True)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user