Proyecto de traducción a ingles: Linda Cube Again

Foro dedicado al romhacking en general
Responder
Avatar de Usuario
gadesx
Administrador
Administrador
Mensajes: 1984
Registrado: 24 Ene 2011, 16:43
Ubicación: El puche
Contactar:

Proyecto de traducción a ingles: Linda Cube Again

Mensaje por gadesx » 23 Mar 2011, 02:21

Mirando en romhacking.net hoy alguien le ha metido mano
a otro RPG desconocido por aquí de PSX (y para la mayoria)

me refiero al Linda Cube Again [SCPS-10039], dicen que
tambien es medio supervivencia con mucha sangre, gore y tal xD.

Aunque parece que les falta algo por hacer del romhacking

http://www.romhacking.net/forum/index.p ... 376.0.html

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5520
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 23 Mar 2011, 10:13

Eso me lo apunto, que tengo que probar algunas herramientas de la PSX y puede que este juego me sirva. Además, dice el autor que todo está a la vista, textos/gráficos/sonido, lo que siempre ayuda (y es tiempo que no se pierde intentando averiguar las cosas).

¡¡¡ gadesx, te he dicho mil veces que dejes los juegos sangrientos y violentos, que luego no me duermes y te haces pis en la cama !!!

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5520
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 23 Mar 2011, 18:40

Pues ya lo he mirado. No me sirve para lo que quería probar, pero he comprobado que cambiando un solo bit de los textos el juego casca, lo que me hace suponer que lleva algún tipo de checksum. Como no me sirve y no tengo más tiempo para dedicarle, aquí está lo que he hecho después de comer para sacar todo del archivo, por si alguien quiere estudiar los ficheros sueltos y no liarse:

Código: Seleccionar todo

// char = 1 byte
// int  = 4 bytes

#include <stdio.h>
#include <stdlib.h>

#define ALL_FILES

#define SECTOR     0x0800
#define FILENAME   "linda.mic"
#define FOLDERNAME "linda"
#define TOTAL      0x0300   // 0x3000/0x10

#define UNK_NAME   "unknow.dat"
#define UNK_OFFSET &#40;TOTAL * 0x10&#41;
#define UNK_LENGTH 0xE800

#define STOP&#40;msg&#41; &#123; printf&#40;msg&#41;; return&#40;1&#41;; &#125;

int main&#40;void&#41; &#123;
  FILE *fp, *fp1;
  unsigned char name&#91;256&#93;, filename&#91;13&#93;, *buffer;
  unsigned int data&#91;4&#93;, offset, next;
  unsigned int i, j;

  if &#40;&#40;fp = fopen&#40;FILENAME, "rb"&#41;&#41; == NULL&#41; STOP&#40;"OPEN ERROR"&#41;;

  if &#40;mkdir&#40;FOLDERNAME&#41; > 0&#41; STOP&#40;"FOLDER ERROR"&#41;;

  sprintf&#40;name, "%s/%s", FOLDERNAME, UNK_NAME&#41;;

  if &#40;fseek&#40;fp, UNK_OFFSET, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
  if &#40;&#40;buffer = &#40;unsigned char *&#41; malloc&#40;0xE800&#41;&#41; == NULL&#41; STOP&#40;"MEMORY ERROR"&#41;;
  if &#40;fread&#40;buffer, UNK_LENGTH, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;

  if &#40;&#40;fp1 = fopen&#40;name, "wb"&#41;&#41; == NULL&#41; STOP&#40;"CREATE ERROR"&#41;;
  if &#40;fwrite&#40;buffer, UNK_LENGTH, 1, fp1&#41; != 1&#41; STOP&#40;"WRITE ERROR"&#41;;
  if &#40;fclose&#40;fp1&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

  free&#40;buffer&#41;;

  for &#40;i = 0; i < TOTAL; i++&#41; &#123;
    if &#40;fseek&#40;fp, 16 * i, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
    if &#40;fread&#40;&data, 4, 4, fp&#41; != 4&#41; STOP&#40;"READ ERROR"&#41;;

    if &#40;data&#91;1&#93;&#41; &#123;
      data&#91;0&#93; *= SECTOR;
      data&#91;1&#93; *= SECTOR;
      printf&#40;"section&#58;%04d  --->  offset=%08X  len=%08X  ???1=%08X  ???2=%08X\n", i, data&#91;0&#93;, data&#91;1&#93;, data&#91;2&#93;, data&#91;3&#93;&#41;;

#ifndef ALL_FILES
      sprintf&#40;name, "%s/%04d.tmp", FOLDERNAME, i&#41;;

      if &#40;fseek&#40;fp, data&#91;0&#93;, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
      if &#40;&#40;buffer = &#40;unsigned char *&#41; malloc&#40;data&#91;1&#93;&#41;&#41; == NULL&#41; STOP&#40;"MEMORY ERROR"&#41;;
      if &#40;fread&#40;buffer, data&#91;1&#93;, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;

      if &#40;&#40;fp1 = fopen&#40;name, "wb"&#41;&#41; == NULL&#41; STOP&#40;"CREATE ERROR"&#41;;
      if &#40;fwrite&#40;buffer, data&#91;1&#93;, 1, fp1&#41; != 1&#41; STOP&#40;"WRITE ERROR"&#41;;
      if &#40;fclose&#40;fp1&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

      free&#40;buffer&#41;;
#else
      sprintf&#40;name, "%s/%04d", FOLDERNAME, i&#41;;
      if &#40;mkdir&#40;name&#41; > 0&#41; STOP&#40;"MAKEDIR ERROR"&#41;;

      for &#40;j = 0; ; j++&#41; &#123;
        if &#40;fseek&#40;fp, data&#91;0&#93; + 16 * j, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
        if &#40;fread&#40;filename, 13, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;
        if &#40;!filename&#91;0&#93;&#41; break;

        if &#40;fseek&#40;fp, data&#91;0&#93; + 16 * j + 12, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
        if &#40;fread&#40;&offset, 4, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;
        if &#40;fseek&#40;fp, data&#91;0&#93; + 16 * &#40;j + 1&#41; + 12, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
        if &#40;fread&#40;&next, 4, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;

        offset >>= 8;
        next >>= 8;

        sprintf&#40;name, "%s/%04d/%03d-%s", FOLDERNAME, i, j, filename&#41;;
        printf&#40;"  - %08X&#58;%06X -> '%s'\n", data&#91;0&#93; + offset, next - offset, name&#41;;

        if &#40;fseek&#40;fp, data&#91;0&#93; + offset, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
        if &#40;&#40;buffer = &#40;unsigned char *&#41; malloc&#40;next - offset&#41;&#41; == NULL&#41; STOP&#40;"MEMORY ERROR"&#41;;
        if &#40;fread&#40;buffer, next - offset, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;

        if &#40;&#40;fp1 = fopen&#40;name, "wb"&#41;&#41; == NULL&#41; STOP&#40;"CREATE ERROR"&#41;;
        if &#40;fwrite&#40;buffer, next - offset, 1, fp1&#41; != 1&#41; STOP&#40;"WRITE ERROR"&#41;;
        if &#40;fclose&#40;fp1&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

        free&#40;buffer&#41;;
      &#125;
#endif
    &#125;
  &#125;

  if &#40;fclose&#40;fp&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

  return&#40;0&#41;;
&#125;

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5520
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 25 Mar 2011, 12:44

Una buena noticia de ese proyecto: Me comentan que ZeikJT, el autor, ha averiguado que poniendo a cero esos valores que parecen checksums el juego funciona después de modificar los textos :D:):D

Esta tarde/noche pondré la estructura del fichero, por si alguien se anima a hacer algo con ese juego y puede ayudarle. Hay otro fichero que contiene sonidos/música/gráficos, y también puede ser interesante echarle un vistazo, pues siempre hay gráficos que deben traducirse.

NOTA: He cambiado el título del post para indicar el nombre del juego.

Avatar de Usuario
gadesx
Administrador
Administrador
Mensajes: 1984
Registrado: 24 Ene 2011, 16:43
Ubicación: El puche
Contactar:

Mensaje por gadesx » 25 Mar 2011, 15:10

ok, viendo que avanza se puede dejar el post para hablar de el juego.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5520
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 25 Mar 2011, 19:17

Aquí una tontería para extraer las cosas de LINDA.PAC:

Código: Seleccionar todo

// char = 1 byte
// int  = 4 bytes

#include <stdio.h>
#include <stdlib.h>

#define FILENAME   "linda.pac"
#define FOLDERNAME "PAC"

#define STOP&#40;msg&#41; &#123; printf&#40;msg&#41;; return&#40;1&#41;; &#125;

int main&#40;void&#41; &#123;
  FILE *fp, *fp1;
  unsigned char name&#91;256&#93;, filename&#91;13&#93;, *buffer;
  unsigned int data&#91;3&#93;;
  unsigned int i;

  if &#40;&#40;fp = fopen&#40;FILENAME, "rb"&#41;&#41; == NULL&#41; STOP&#40;"OPEN ERROR"&#41;;

  sprintf&#40;name, "%s", FOLDERNAME&#41;;
  if &#40;mkdir&#40;name&#41; > 0&#41; STOP&#40;"MAKEDIR ERROR"&#41;;

  for &#40;i = 0; ; i++&#41; &#123;
    if &#40;fseek&#40;fp, 24 * i, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
    if &#40;fread&#40;filename, 13, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;
    if &#40;!filename&#91;0&#93;&#41; break;

    if &#40;fseek&#40;fp, 24 * i + 12, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
    if &#40;fread&#40;&data, 4, 3, fp&#41; != 3&#41; STOP&#40;"READ ERROR"&#41;;

    data&#91;0&#93; >>= 8;
    data&#91;0&#93; <<= 3;

    sprintf&#40;name, "%s/%s", FOLDERNAME, filename&#41;;
    printf&#40;"%08X&#58;%08X %08X -> '%s'\n", data&#91;0&#93;, data&#91;1&#93;, data&#91;2&#93;, name&#41;;

    if &#40;fseek&#40;fp, data&#91;0&#93;, SEEK_SET&#41;&#41; STOP&#40;"SEEK ERROR"&#41;;
    if &#40;&#40;buffer = &#40;unsigned char *&#41; malloc&#40;data&#91;1&#93;&#41;&#41; == NULL&#41; STOP&#40;"MEMORY ERROR"&#41;;
    if &#40;fread&#40;buffer, data&#91;1&#93;, 1, fp&#41; != 1&#41; STOP&#40;"READ ERROR"&#41;;

    if &#40;&#40;fp1 = fopen&#40;name, "wb"&#41;&#41; == NULL&#41; STOP&#40;"CREATE ERROR"&#41;;
    if &#40;fwrite&#40;buffer, data&#91;1&#93;, 1, fp1&#41; != 1&#41; STOP&#40;"WRITE ERROR"&#41;;
    if &#40;fclose&#40;fp1&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

    free&#40;buffer&#41;;
  &#125;

  if &#40;fclose&#40;fp&#41; == EOF&#41; STOP&#40;"CLOSE ERROR"&#41;;

  return&#40;0&#41;;
&#125;

Ahora un explicación muy sencilla de los ficheros:

Código: Seleccionar todo

fichero LINDA.MIC
-----------------

Cabecera con 0x0300 entradas de 16 bytes&#58;
- 4 bytes&#58; offset &#40;multiplicar por 0x0800&#41;
- 4 bytes&#58; longitud &#40;multiplicar por 0x0800&#41;
- 4 bytes&#58; tal vez la fecha/hora???
- 4 bytes&#58; algún tipo de checksum???

Si los 16 bytes están a 0 significa que no hay entrada.
Cada entrada es un sistema de archivos.


Cada entrada comienza por una serie de datos de 16 bytes&#58;
- 13 bytes&#58; nombre ASCIIZ de un fichero, rellenado con ceros
- 3 bytes&#58; offset relativo a los datos desde el inicio de la entrada

El último dato solo contiene el offset ya que la longitud de cada fichero se
obtiene como diferencia entre dos offsets consecutivos, por lo que es necesario
para calcular la longitud del último fichero.

El primer fichero extraído siempre es 'PROG.BIN', que es donde están los textos
codificados en Shift-JIS, y en ocasiones ese fichero es el mismo que existe en
otras entradas.


NOTA&#58; Entre la cabecera y los datos hay una parte que no sé exactamente lo que
es, una secuencia de 0x01, entremezclados con 0x03 y 0x05. Hay tantos 0x03 como
0x05 y coinciden con el número de entradas reales que hay en la cabecera, pero
no lo he mirado más a fondo para saber qué significa. Esta parte va desde 0x3000
hasta 0xA605, rellenándose con ceros hasta 0x11800, inicio de los datos reales.


fichero LINDA.PAC
-----------------

Cada entrada comienza por una serie de datos de 16 bytes&#58;
- 13 bytes&#58; nombre ASCIIZ de un fichero, rellenado con ceros
- 3 bytes&#58; offset &#40;multiplìcar por 0x08&#41;
- 4 bytes&#58; longitud
- 4 bytes&#58; checksum?

Los datos acaban cuando la entrada sólo contenga ceros.

Los ficheros que se extraen de aquí son los de sonido, música, gráficos, ..., en
el formato habitual de SONY para la consola&#58; SEQ, TIM, VAB, ...


NOTAS
-----

Los ficheros TIMZ parecen estar, a simple vista, comprimidos con LZSS de 8 bits
y sin ningún tipo de cabecera.

Los ficheros OBJ también, con los 4 primeros bytes indicando la longitud del
fichero descomprimido, los 4 siguientes la longitud comprimida, los 4 siguientes
no tengo no idea, y después vienen ya los datos comprimidos.

Avatar de Usuario
ZeikJT
Mensajes: 2
Registrado: 23 Mar 2011, 20:31

Mensaje por ZeikJT » 26 Mar 2011, 01:13

CUE escribió:

Código: Seleccionar todo

fichero LINDA.MIC
-----------------

Cabecera con 0x0300 entradas de 16 bytes&#58;
- 4 bytes&#58; offset &#40;multiplicar por 0x0800&#41;
- 4 bytes&#58; longitud &#40;multiplicar por 0x0800&#41;
- 4 bytes&#58; tal vez la fecha/hora???
- 4 bytes&#58; algún tipo de checksum???

Si los 16 bytes están a 0 significa que no hay entrada.
Cada entrada es un sistema de archivos.


NOTA&#58; Entre la cabecera y los datos hay una parte que no sé exactamente lo que
es, una secuencia de 0x01, entremezclados con 0x03 y 0x05. Hay tantos 0x03 como
0x05 y coinciden con el número de entradas reales que hay en la cabecera, pero
no lo he mirado más a fondo para saber qué significa. Esta parte va desde 0x3000
hasta 0xA605, rellenándose con ceros hasta 0x11800, inicio de los datos reales.
Casi. Esa segunda entrada de 4 bytes no es la longitud. Los sets de 0x03 y 0x05 con 0x01 en el medio son los que indican la longitud. 0x03 es el prinicipio y 0x05 es el fin, cuentan como un byte. Sumas los 0x01 en el medio mas dos (0x03, 0x05) y multiplicas por 0x800 para obtener la longitud. Estan en orden, con el primer set de 0x01 indicando el tamaño del header (0x11800). Tienes que ir en orden.

Yo he hecho una tabla con valores importantes:
http://pastebin.com/F3P4xP92
EO es el offset de la entrada
E es la entrada, entera
FO es el offset del fichero mismo
SO es el offset de la longitud de el fichero (los 0x03, 0x01, 0x05)
FS es la longitud del fichero

Ah, tambien, si los primeros cuatro bytes son 0 ya se considera una entrada vacia. No hay que borrar todo.

Perdoname por mi español... hace mucho que no escribo :P

====

Ah, y aca esta el programa que yo escribi. Esta en MVC++
http://pastebin.com/pgDmHCxy
Última edición por ZeikJT el 26 Mar 2011, 20:55, editado 2 veces en total.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5520
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 26 Mar 2011, 09:43

Hola, ZeikJT, bienvenido y ánimo con tu proyecto :)

Me temo que estás equivocado :(
La tabla de 01-03-05 no indica la longitud. Son los 4 bytes que yo menciono.

Mira los datos de la primera entrada que has puesto:
0000 - 2A070000640000000602182251002F74 - 0011800 - 3023 - 23000

Según eso la longitud es de 0x23000 bytes, pero si observas los ficheros que hay en esa entrada verás que a partir de M101.OBJ, y hasta M103F.OBJ, tienen un offset mayor, indicando que el final del fichero es 0x31A60, coincidiendo con los datos que indico. Eso prueba que la longitud viene determinada por los 4 bytes de la cabecera, en número de sectores (1 sector = 0x800 bytes, una medida usual en juegos de la PSX):
[img]http://img859.imageshack.us/img859/6854/linda.png[/img]

Avatar de Usuario
ZeikJT
Mensajes: 2
Registrado: 23 Mar 2011, 20:31

Mensaje por ZeikJT » 26 Mar 2011, 10:49

CUE escribió:Hola, ZeikJT, bienvenido y ánimo con tu proyecto :)

Me temo que estás equivocado :(
La tabla de 01-03-05 no indica la longitud. Son los 4 bytes que yo menciono.

Mira los datos de la primera entrada que has puesto:
0000 - 2A070000640000000602182251002F74 - 0011800 - 3023 - 23000

Según eso la longitud es de 0x23000 bytes, pero si observas los ficheros que hay en esa entrada verás que a partir de M101.OBJ, y hasta M103F.OBJ, tienen un offset mayor, indicando que el final del fichero es 0x31A60, coincidiendo con los datos que indico. Eso prueba que la longitud viene determinada por los 4 bytes de la cabecera, en número de sectores (1 sector = 0x800 bytes, una medida usual en juegos de la PSX):
AHHhhh! Tienes razon. Yo no estaba usando el primer set de 4 bytes para determinar el offset! Lo estaba usando como un identificador! Sabes que los sets de 0x03, 0x01, 0x05 estan en orden del archivo. 2300 (a 0x2B30) tiene la longitud que yo habia puesto para 2A07.

Ahora que entiendo como funcionan las entradas mejor puedo ponerles los nombres correctos...


El number de bytes 0x01 mas dos (0x05 y 0x03) es la longitud en orden del archivo.
El primer set (como no tiene 0x03 o 0x05) es solo para indicar el primer offset, el tamaño del header.
Hice otra table con los ficheros en orden del archivo. Ademas el BSO es el offset de los sets de 0x03 0x01 0x05 que corresponded al fichero:


---

23000000460000005A011822A0C3F7A0
690000005E0000005B01182252C2FC3F

01010101010101010101010101010101
01010101010101010101010101010101 <-- 0x23
010101
03010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010503010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010105

---

23000000460000005A011822A0C3F7A0
690000005E0000005B01182252C2FC3F

01010101010101010101010101010101
01010101010101010101010101010101
01010103010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101 <-- 0x46
01010101010101010101010101010101
010101010101010105
03010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010105

---

23000000460000005A011822A0C3F7A0
690000005E0000005B01182252C2FC3F

Para ir en orden del archivo sumas el offset del primero y la longitud.
0x23 + 0x46 = 0x69

---

23000000460000005A011822A0C3F7A0
690000005E0000005B01182252C2FC3F

01010101010101010101010101010101
01010101010101010101010101010101
01010103010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010503010101010101
01010101010101010101010101010101
01010101010101010101010101010101
01010101010101010101010101010101 <-- 0x5E
01010101010101010101010101010101
01010101010101010101010101010101
01010101010105

Responder