import os import struct from pathlib import Path from tkinter import filedialog, messagebox import shutil import mmap class NDSHeader: def __init__(self, data): self.game_title = data[0:12].decode('ascii', errors='ignore').strip('\x00') self.game_code = data[12:16].decode('ascii', errors='ignore').strip('\x00') self.maker_code = data[16:18] self.arm9_rom_addr = struct.unpack(' len(fnt_data): return entry_offset = struct.unpack(' len(fnt_data): break name = fnt_data[offset:offset + name_length].decode('utf-8', errors='replace') offset += name_length if current_path: new_path = f'{current_path}/{name}' else: new_path = name if is_directory: if offset + 2 > len(fnt_data): break sub_folder_id = struct.unpack('= len(fat_entries): print(f'Warning: FAT index {file_entry.fat_index} out of range for {file_entry.path}') continue fat_entry = fat_entries[file_entry.fat_index] if fat_entry.size <= 0: continue filename = Path(file_entry.path).name output_path = self.map_folder_path / filename file_data = rom_data[fat_entry.start_addr:fat_entry.end_addr] try: with open(output_path, 'wb') as f: f.write(file_data) if callback and (i % 10 == 0 or i == total_files - 1): callback(f'Extracted {i + 1}/{total_files} map files...') except Exception as e: print(f'Error writing file {output_path}: {e}') print(f'Extracted {total_files} map files to {self.map_folder_path}') return True except Exception as e: print(f'Error extracting filtered files: {e}') import traceback traceback.print_exc() return False def _scan_map_files(self): self.dat_files = [] self.tex_files = [] if not self.map_folder_path or not self.map_folder_path.exists(): return print(f'\nScanning map folder: {self.map_folder_path}') file_count = 0 for file_path in self.map_folder_path.iterdir(): if file_path.is_file(): file_name = file_path.name.lower() file_count += 1 if '.map.dat' in file_name: self.dat_files.append(file_path) elif '.map.tex' in file_name: self.tex_files.append(file_path) self.dat_files.sort(key=lambda x: x.name) self.tex_files.sort(key=lambda x: x.name) print(f'Scan complete: {len(self.dat_files)} DAT files, {len(self.tex_files)} TEX files') def get_map_files(self): return (self.dat_files, self.tex_files) def get_map_folder(self): return self.map_folder_path