martes, 10 de mayo de 2011

Aprendiendo C: Satuxconv (IV)

El programa ya lee imágenes de CD en formato BIN, falta añadir soporte a las imágenes en formato ISO (el formato restante, MDF, es igual que BIN). De nuevo, mediante Okteta abrimos un archivo de este tipo para buscar las diferencias.

Nos encontramos que el título del juego se encuentra en la posición 95, 16 posiciones menos respecto a la imagen en formato BIN o MDF. Este patrón se repite en el resto de los campos.

La solución es fácil:
  • Comprobar si el archivo a abrir es una imagen ISO. Comprobaremos la extensiones del archivo que ha indicado el usuario.
  • Si es una ISO se activa una variable.
  • Al buscar un campo (por ejemplo la fecha) si la variable está activa se restará 16 caracteres a la posición de búsqueda.
Para comprobar si la extensión del fichero indicado es "iso" basta con este código:
if (strstr(argv[1], ".iso") != NULL)
imgiso = 1;
Y cada vez que comprobamos un campo añadimos esto:

void mostrar (int pos, int maximo){
for (i=1; i<=maximo; i++)
{
if (imgiso==1)
j = (pos + i) - 16;
else
j = (pos + i);
fseek(fichero, j, SEEK_SET);
fread(&buffer, 1, 1, fichero);
printf("%c", (char)buffer);
}
}
Sabiendo esto nos queda este programa:
/* Satuxconv */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int i; /* contador */
int j; /* contador 2 */
int buffer; /* Buffer de datos */
FILE* fichero; /*Fichero a abrir */
int imgiso = 0; /* flag */

void mostrar (int pos, int maximo){
for (i=1; i<=maximo; i++)
{
if (imgiso==1)
j = (pos + i) - 16;
else
j = (pos + i);
fseek(fichero, j, SEEK_SET);
fread(&buffer, 1, 1, fichero);
printf("%c", (char)buffer);
}
}

main (int argc, char *argv[])
{
int fecha[8]; /*Almacena la fecha*/
int regiona[3]; /*Region del juego*/

/*Comprobar parámetros y abrir fichero*/
if (argc < 2)
{
printf("Uso: satuxconv imagen.bin");
printf("\nActualmente se soportan imagenes BIN, ISO y MDF\n\n");
exit(0);
}

fichero=fopen(argv[1], "rb");
if (strstr(argv[1], ".iso") != NULL)
imgiso = 1;

printf("\nDatos de la imagen\n");
printf("------------------\n\n");

/*Obteniendo el titulo*/
printf("Título: ");
mostrar(111,27);

/*Obteniendo el desarrollador*/
printf("\nDesarrollador: ");
mostrar(31, 16);

/*Obteniendo el producto*/
printf("\nProducto: ");
mostrar(47,7);

/*Obteniendo la version*/
printf("\nVersión: ");
mostrar(57,6);
/*Obteniendo la fecha*/
printf("\nFecha: ");
for (i=1; i<=8; i++)
{
if (imgiso==1)
j = (63 + i) - 16;
else
j = (63 + i);
fseek(fichero, j, SEEK_SET);
fread(&fecha[i], 1, 1, fichero);
}
printf("%c%c/%c%c/%c%c%c%c\n", (char)fecha[7],(char)fecha[8], (char)fecha[5], (char)fecha[6], (char)fecha[1], (char)fecha[2], (char)fecha[3], (char)fecha[4]);

/*Obteniendo regiones*/
for (i=1; i<=3; i++)
{
if (imgiso==1)
j = (79 + i) - 16;
else
j= 79 + i;
fseek(fichero, j, SEEK_SET);
fread(&regiona[i], 1, 1, fichero);

/*Obteniendo regiones*/
for (i=1; i<=3; i++)
{
if (imgiso==1)
j = (79 + i) - 16;
else
j= 79 + i;
fseek(fichero, j, SEEK_SET);
fread(&regiona[i], 1, 1, fichero);
}
/* fseek(fichero, 96, SEEK_SET);
fread(&regionb, 1, 1, fichero);*/

/*Mostrar regiones*/
printf("\nRegión(es) del juego:\n");
for (i=1; i<=3; i++)
{
printf(" %c", (char)regiona[i]);
if ((char)regiona[i] == 'T')
printf(" - (Asia - NTSC)\n");
if ((char)regiona[i] == 'E')
printf(" - (Europa)\n");
if ((char)regiona[i] == 'U')
printf(" - (América del Norte)\n");
if ((char)regiona[i] == 'J')
printf(" - (Japón)\n");
if ((char)regiona[i] == 'B')
printf(" - (Centro/SudAmérica NTSC)\n");
if ((char)regiona[i] == 'K')
printf(" - (Corea)\n");
if ((char)regiona[i] == 'A')
printf(" - (Asia Este PAL)\n");
if ((char)regiona[i] == 'L')
printf(" - (Centro/SudAmérica PAL)\n");
}

/*Cerrar fichero*/
fclose(fichero);
}
Con esto nuestro programa ya puede leer tres tipos de imágenes de disco: BIN, MDF (MDF tiene el mismo formato que BIN) e ISO. Sólo queda acceder en modo escritura al fichero y cambiar la región por la deseada.