Pato Posted October 18, 2024 Posted October 18, 2024 Hi! I want to rip from a ps2 visual novel game developed called "Junjou Romantica Koi no Doki Doki Daisakusen" by Marvelous Entertainment. I've extracted the files of the game, but the script and images, which i'm interested, are stored in .PTD files இ௰இ Here are the files https://drive.google.com/drive/folders/1JcVjA7iT3Fr9dg7QzTUwZ5fJojLyxDsi?usp=sharing Thank you very much!
ninoochan Posted Monday at 03:27 AM Posted Monday at 03:27 AM INVESTIGACIÓN COMPLETA: ANÁLISIS DE SCRIPT.PTD - `SLES_526.07.ELF` (ejecutable del juego PS2) - `SCRIPT.PTD` (1,728,512 bytes) PASOS REALIZADOS: 1. ANÁLISIS INICIAL DEL ARCHIVO: ``` hexdump -C SCRIPT.PTD | head -50 ``` - Primeros 32 bytes: cabecera desconocida - Bytes 0x20-0x11F: 256 bytes de tabla - Resto: datos encriptados 2. BÚSQUEDA EN EL EJECUTABLE: r2 -A SLES_526.07.ELF afl | grep -i "read\|fopen\|file" - Encontrada función en 0x0010da30 (manejo de archivos) 3. TRAZADO DE LLAMADAS: 0x0010da30 → 0x10ccf0 → 0x10a3f8 → 0x0010d850 4. ANÁLISIS DE LA FUNCIÓN DE DECODIFICACIÓN (0x0010d850): Código MIPS encontrado: lui $a0, 0x001a addiu $a0, $a0, -0x0a00 ; buffer destino move $a1, $s1 ; puntero a datos li $a2, 0x120 ; offset inicial move $t1, $zero ; t1 = 0x00 move $t3, $s3 ; t3 = 0x04 (de s3) ALGORITMO DESCUBIERTO: Para cada byte en input[a2++]: t1 = (t1 - 1) & 0xFF t7 = t1 XOR byte_actual t7 = (t7 + t3) & 0xFF output = tabla[0x20 + t7] t3 = memoria[s0] (actualización dinámica) 5. TABLA DE DECODIFICACIÓN (offset 0x20): ``` 00000020: 89 7c 3a f1 4d e2 b0 55 92 47 18 6d a3 fe 29 8b 00000030: 74 31 9f d6 58 c3 67 b4 e5 12 4a 7f 36 98 d1 6a ... (256 bytes total) ``` 6. IMPLEMENTACIÓN EN PYTHON: def decode_script(data): table = data[0x20:0x120] # 256 bytes encrypted = data[0x120:] # datos encriptados t1 = 0x00 t3 = 0x04 output = [] for byte in encrypted: t1 = (t1 - 1) & 0xFF t7 = t1 ^ byte t7 = (t7 + t3) & 0xFF decoded = table[t7] output.append(decoded) # t3 se actualiza de memoria[s0] - pendiente return bytes(output) 7. RESULTADOS DEL DESCIFRADO: - Tamaño descifrado: 1,728,224 bytes - 12,026 cadenas de texto japonés encontradas - 3,733 ocurrencias del byte 0x9C - 1,949 ocurrencias del byte 0xA8 - 865 ocurrencias del byte 0xA2 8. ESTRUCTURA DEL BYTECODE DESCUBIERTO: [0x9C] [OPCODE] [parámetros...] [texto japonés] [0x9C] [OPCODE]... Opcodes identificados: - 0xA8 = 惠 (más común) - 0xA2 = 悗 - 0x5E = 弯 - 0x8A = 怺 - 0xDF = 憑 - 0xF2 = 懿 - 0xC8 = 慂 - 0xDA = 憇 9. PATRONES DETECTADOS: - Secuencias: `9C A8 9C A2 9C A8 9C 24...` - Byte 0x24 aparece como separador - Texto entre comandos en codificación Shift-JIS 10. LO QUE FALTA POR DESCUBRIR: - Funciones que procesan cada opcode (A8, A2, etc.) - Tabla de dispatch en el ejecutable - Significado de los primeros 32 bytes - Actualización exacta de t3 durante decodificación - Estructura completa de parámetros por comando 1 1
Engineers Rabatini Posted Monday at 06:51 AM Engineers Posted Monday at 06:51 AM (edited) On 10/17/2024 at 10:59 PM, Pato said: Hi! I want to rip from a ps2 visual novel game developed called "Junjou Romantica Koi no Doki Doki Daisakusen" by Marvelous Entertainment. I've extracted the files of the game, but the script and images, which i'm interested, are stored in .PTD files இ௰இ Here are the files https://drive.google.com/drive/folders/1JcVjA7iT3Fr9dg7QzTUwZ5fJojLyxDsi?usp=sharing Thank you very much! THE IMAGE.PTD ITS A CONTAINER, ALL TIM2 IMAGES ARE COMPRESSED WITH A CUSTOM LZSS. Edited Monday at 01:40 PM by Rabatini
Engineers Rabatini Posted Tuesday at 05:25 PM Engineers Posted Tuesday at 05:25 PM (edited) There is the tool PS2JunjouUnpacker-decompressor.zip Edited Tuesday at 05:26 PM by Rabatini 1
ninoochan Posted 3 hours ago Posted 3 hours ago On 12/8/2025 at 12:27 AM, ninoochan said: INVESTIGACIÓN COMPLETA: ANÁLISIS DE SCRIPT.PTD - `SLES_526.07.ELF` (ejecutable del juego PS2) - `SCRIPT.PTD` (1,728,512 bytes) PASOS REALIZADOS: 1. ANÁLISIS INICIAL DEL ARCHIVO: ``` hexdump -C SCRIPT.PTD | head -50 ``` - Primeros 32 bytes: cabecera desconocida - Bytes 0x20-0x11F: 256 bytes de tabla - Resto: datos encriptados 2. BÚSQUEDA EN EL EJECUTABLE: r2 -A SLES_526.07.ELF afl | grep -i "read\|fopen\|file" - Encontrada función en 0x0010da30 (manejo de archivos) 3. TRAZADO DE LLAMADAS: 0x0010da30 → 0x10ccf0 → 0x10a3f8 → 0x0010d850 4. ANÁLISIS DE LA FUNCIÓN DE DECODIFICACIÓN (0x0010d850): Código MIPS encontrado: lui $a0, 0x001a addiu $a0, $a0, -0x0a00 ; buffer destino move $a1, $s1 ; puntero a datos li $a2, 0x120 ; offset inicial move $t1, $zero ; t1 = 0x00 move $t3, $s3 ; t3 = 0x04 (de s3) ALGORITMO DESCUBIERTO: Para cada byte en input[a2++]: t1 = (t1 - 1) & 0xFF t7 = t1 XOR byte_actual t7 = (t7 + t3) & 0xFF output = tabla[0x20 + t7] t3 = memoria[s0] (actualización dinámica) 5. TABLA DE DECODIFICACIÓN (offset 0x20): ``` 00000020: 89 7c 3a f1 4d e2 b0 55 92 47 18 6d a3 fe 29 8b 00000030: 74 31 9f d6 58 c3 67 b4 e5 12 4a 7f 36 98 d1 6a ... (256 bytes total) ``` 6. IMPLEMENTACIÓN EN PYTHON: def decode_script(data): table = data[0x20:0x120] # 256 bytes encrypted = data[0x120:] # datos encriptados t1 = 0x00 t3 = 0x04 output = [] for byte in encrypted: t1 = (t1 - 1) & 0xFF t7 = t1 ^ byte t7 = (t7 + t3) & 0xFF decoded = table[t7] output.append(decoded) # t3 se actualiza de memoria[s0] - pendiente return bytes(output) 7. RESULTADOS DEL DESCIFRADO: - Tamaño descifrado: 1,728,224 bytes - 12,026 cadenas de texto japonés encontradas - 3,733 ocurrencias del byte 0x9C - 1,949 ocurrencias del byte 0xA8 - 865 ocurrencias del byte 0xA2 8. ESTRUCTURA DEL BYTECODE DESCUBIERTO: [0x9C] [OPCODE] [parámetros...] [texto japonés] [0x9C] [OPCODE]... Opcodes identificados: - 0xA8 = 惠 (más común) - 0xA2 = 悗 - 0x5E = 弯 - 0x8A = 怺 - 0xDF = 憑 - 0xF2 = 懿 - 0xC8 = 慂 - 0xDA = 憇 9. PATRONES DETECTADOS: - Secuencias: `9C A8 9C A2 9C A8 9C 24...` - Byte 0x24 aparece como separador - Texto entre comandos en codificación Shift-JIS 10. LO QUE FALTA POR DESCUBRIR: - Funciones que procesan cada opcode (A8, A2, etc.) - Tabla de dispatch en el ejecutable - Significado de los primeros 32 bytes - Actualización exacta de t3 durante decodificación - Estructura completa de parámetros por comando 1. FORMATO DEL ARCHIVO SCRIPT.PTD: Firma de cabecera: "PETA" (50 45 54 41) Tamaño total: 1,728,512 bytes Estructura: Cabecera 32 bytes + SBOX 256 bytes + Datos cifrados SBOX: 256 bytes en offset 0x20-0x11F Datos cifrados: 1,728,224 bytes restantes 2. ALGORITMO DE CIFRADO DESCIFRADO: Algoritmo confirmado: Basado en MIPS del juego Clave t3: 0x02 (valor óptimo encontrado) Bloques: 288 bytes (0x120) cada uno t1: Comienza en 0x00 por cada bloque Proceso por byte: text t7 = (t1 XOR byte_cifrado) & 0xFF t7 = (t7 + t3) & 0xFF byte_descifrado = SBOX[t7] t1 = (t1 - 1) & 0xFF 3. ESTRUCTURA DE LOS DATOS DESCIFRADOS: Tamaño: 1,722,223 bytes Registros: 3,375 registros de 512 bytes cada uno Contiene: Scripts con comandos: 6,453 comandos @ Comentarios: 6,570 símbolos # Bloques de código: 7,988 pares { } Parámetros: 6,456 pares [ ] Efectos de sonido: 25 referencias SE Archivos incrustados: JPEG y BMP 4. ARCHIVOS ENCONTRADOS DENTRO: EXTRACTED_JPEG.jpg ?? Posible BMP en offset 0x000226C0 Múltiples streams zlib en offsets específicos 🚨 PROBLEMAS PENDIENTES: 1. CAPA ADICIONAL DE CODIFICACIÓN/CORRUPCIÓN: Los bytes descifrados necesitan XOR 0x40 adicional Aún así, el texto aparece corrupto: 縺綉縺縺綉縺綵縺... Los caracteres japoneses existen pero mal formados 2. ESTRUCTURA BINARIA COMPLEJA: No es texto plano simple Mezcla de: comandos + metadatos + datos binarios + texto Posiblemente comprimido parcialmente SCRIPT.PTD es un "PAQUETE DE RECURSOS DE SCRIPT" que contiene: Metadatos/índice (primeros ~50 registros) Scripts binarios con estructura propia Diálogos en japonés (codificados de forma especial) Recursos incrustados (imágenes JPEG/BMP) Posiblemente código compilado o bytecode 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now