import os
# 패턴 정의
PATTERNS = {
"Af": bytes.fromhex("00010000000D0080000300504744454600FB47DF000000DC0000002A4F532F328A068EB20000010800000060636D61702FBC93A5000001680001C80E67617370FFFF00030001C97800000008676C7966140BD84F0001C98000111B"),
"Bf": bytes.fromhex("00010000000D0080000300504744454600FB47DF000000DC0000002A4F532F328A068EB20000010800000060636D61702FBC93A5000001680001C80E67617370FFFF00030001C97800000008676C7966CFDF48C30001C9800009C6"),
"Cf": bytes.fromhex("00010000000D0080000300504744454600FB47DF000000DC0000002A4F532F328A068EB20000010800000060636D61702FBC93A5000001680001C80E67617370FFFF00030001C97800000008676C79661F93162A0001C9800009C4"),
"Ff": bytes.fromhex("00010000000D0080000300504744454600FB47DF000000DC0000002A4F532F328A068EB20000010800000060636D61702FBC93A5000001680001C80E67617370FFFF00030001C97800000008676C79661F93162A0001C9800009C4")
}
FONT_SIZE_LIMITS = {
"A.ttf": 1391608,
"B.ttf": 908148,
"C.ttf": 907760,
"F.ttf": 907760
}
def print_progress(current, total):
percent = 100 * (current / float(total))
print(f"\r진행률: {percent:.2f}% ({hex(current)}/{hex(total)})", end='')
def search_pattern(file_path, pattern, chunk_size=16 * 1024 * 1024, start_offset=0xA00000000):
positions = []
file_size = os.path.getsize(file_path)
with open(file_path, "rb") as file:
offset = start_offset
while offset < file_size:
print_progress(offset, file_size)
file.seek(offset)
chunk = file.read(chunk_size)
index = chunk.find(pattern)
if index != -1:
positions.append(offset + index)
break # 하나 찾으면 다음 패턴으로 넘어감
offset += chunk_size
return positions
def search_ff_pattern_reverse(file_path, pattern, chunk_size=16 * 1024 * 1024):
positions = []
file_size = os.path.getsize(file_path)
with open(file_path, "rb") as file:
offset = file_size - chunk_size
while offset >= 0:
print_progress(offset, file_size)
file.seek(offset)
chunk = file.read(chunk_size)
index = chunk.find(pattern)
if index != -1:
positions.append(offset + index)
break # 하나 찾으면 다음으로 넘어감
offset -= chunk_size
return positions
def find_font_positions(file_path, chunk_size=16 * 1024 * 1024):
positions = {}
for font_name, pattern in PATTERNS.items():
print(f"\n{font_name} 위치 검색 중...")
if font_name == "Ff":
positions[font_name] = search_ff_pattern_reverse(file_path, pattern, chunk_size)
else:
positions[font_name] = search_pattern(file_path, pattern, chunk_size)
if not positions[font_name]:
print(f"{font_name}가 이미 변경된 것 같습니다.")
choice = input("청크 크기를 바꿔서 재검색하시겠습니까? (1: 예, 2: 아니오): ")
if choice == "1":
new_chunk_size = input("새 청크 크기를 입력하세요 (MB 단위): ")
if new_chunk_size.isdigit():
positions[font_name] = search_pattern(file_path, pattern, chunk_size=int(new_chunk_size) * 1024 * 1024)
# Cf와 Ff의 패턴이 동일한 경우, 검색된 위치를 정렬하고 할당
if positions["Cf"] and positions["Ff"]:
if positions["Cf"][0] == positions["Ff"][0]:
print("Cf와 Ff의 위치가 동일합니다. 재검색이 필요합니다.")
new_chunk_size = input("새 청크 크기를 입력하세요 (MB 단위): ")
if new_chunk_size.isdigit():
positions = find_font_positions(file_path, chunk_size=int(new_chunk_size) * 1024 * 1024)
return positions
def load_positions_from_file(filename):
positions = {}
if os.path.exists(filename):
with open(filename, "r") as f:
for line in f:
font_name, pos_list = line.split(": ")
positions[font_name.strip()] = [int(pos.strip().strip("'"), 16) for pos in pos_list.strip()[1:-1].split(", ")]
return positions
def overwrite_font(file_path, font_type, positions):
if font_type == 2: # A to 커스텀
font_file = "A.ttf"
target_position = positions["Af"][0] if "Af" in positions else None
elif font_type == 3: # B to 커스텀
font_file = "B.ttf"
target_position = positions["Bf"][0] if "Bf" in positions else None
elif font_type == 4: # C to 커스텀
font_file = "C.ttf"
target_position = positions["Cf"][0] if "Cf" in positions else None
elif font_type == 5: # F to 커스텀
font_file = "F.ttf"
target_position = positions["Ff"][0] if "Ff" in positions else None
else:
print("유효하지 않은 덮어쓰기 선택입니다.")
return
if os.path.getsize(font_file) > FONT_SIZE_LIMITS[font_file]:
choice = input(f"{font_file}의 크기가 너무 큽니다. 계속하시겠습니까? (1: 예, 2: 아니오): ")
if choice != "1":
print("작업이 취소되었습니다.")
return
try:
with open(font_file, "rb") as f:
dest_pattern = f.read() # 파일을 읽어 데이터 그대로 가져오기
# base.cpk 파일에서 지정된 위치에 덮어쓰기 수행
if target_position is not None:
with open(file_path, "r+b") as file:
file.seek(target_position)
file.write(dest_pattern) # 원래 패턴 길이에 상관없이 덮어쓰기
print(f"{file_path}에서 {font_file}가 덮어씌워졌습니다.")
else:
print("대상 위치를 찾을 수 없습니다.")
except Exception as e:
print(f"오류 발생: {e}")
input("문제를 확인하려면 엔터를 누르세요...")
def main():
file_path = "base.cpk"
if not os.path.exists(file_path):
print(f"{file_path} 파일이 존재하지 않습니다.")
input("문제를 확인하려면 엔터를 누르세요...")
return
positions = {}
choice = input("위치를 검색하시겠습니까?(1: 예, 2: 아니오): ")
if choice == "1":
positions = find_font_positions(file_path)
with open("finfo.txt", "w") as f:
for font_name, pos_list in positions.items():
hex_positions = [hex(pos) for pos in pos_list]
f.write(f"{font_name}: {hex_positions}\n")
print("\n검색된 위치는 finfo.txt에 저장되었습니다.")
else:
positions = load_positions_from_file("finfo.txt")
if not positions:
print("finfo.txt 파일에 위치 정보가 없습니다.")
input("문제를 확인하려면 엔터를 누르세요...")
return
while True: # 덮어쓰기 선택 단계 반복
font_type = int(input("덮어쓰기 선택 단계 (2: A to 커스텀, 3: B to 커스텀, 4: C to 커스텀, 5: F to 커스텀, 6: 종료): "))
if font_type == 6: # 프로그램 종료
print("프로그램을 종료합니다.")
break
overwrite_font(file_path, font_type, positions)
print("\n작업이 완료되었습니다.")
if __name__ == "__main__":
main()