DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

dm64ex.c (5136B)


      1 // =====================================================================
      2 // DOOM 64 EXTRACTOR
      3 // =====================================================================
      4 
      5 #include <stdlib.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 #include <stdarg.h>
      9 
     10 typedef unsigned char byte;
     11 
     12 void show_info(void)
     13 {
     14     printf("\n");
     15     printf("     ################(ERICK194)################\n");
     16     printf("     #            DOOM 64 EXTRACTOR           #\n");
     17     printf("     #     CREATED BY ERICK VASQUEZ GARCIA    #\n");
     18     printf("     #              Doom 64.z64               #\n");
     19     printf("     #         (USA/EUR/JAP) VERSION          #\n");
     20     printf("     #                                        #\n");
     21     printf("     # USE:                                   #\n");
     22     printf("     # Doom64Extractor.exe -i \"RomImage.z64\"  #\n");
     23     printf("     ##########################################\n");
     24     printf("\n");
     25 }
     26 
     27 void do_error(const char *s, ...)
     28 {
     29     va_list args;
     30     va_start(args, s);
     31     vfprintf(stderr, s, args);
     32     fprintf(stderr, "\n");
     33     va_end(args);
     34     exit(0);
     35 }
     36 
     37 byte header[65];
     38 int region = -1;
     39 
     40 int read_header(FILE *f, int offset)
     41 {
     42     byte a;
     43 
     44     fseek(f, offset, SEEK_SET);
     45 
     46     for (int i = 0; i < 64; i++)
     47     {
     48         fread(&a, sizeof(byte), 1, f);
     49         header[i] = a;
     50     }
     51 
     52     if (header[0x3E] == 0x45) // Region USA
     53     {
     54         if (header[0x10] == 0xA8) // Original release
     55         {
     56             region = 0;
     57             printf("Region USA\n");
     58         }
     59         else if (header[0x10] == 0x42) // Revision 1 release
     60         {
     61             region = 3;
     62             printf("Region USA, Revision 1\n");
     63         }
     64         else
     65         {
     66             do_error("Error Region %d\n", region);
     67             exit(0);
     68         }
     69     }
     70     else if (header[0x3E] == 0x50) // Region EUR
     71     {
     72         region = 1;
     73         printf("Region EUR\n");
     74     }
     75     else if (header[0x3E] == 0x4A) // Region JAP
     76     {
     77         region = 2;
     78         printf("Region JAP\n");
     79     }
     80     else
     81     {
     82         do_error("Error Region %d\n", region);
     83         exit(0);
     84     }
     85 
     86     return 0;
     87 }
     88 
     89 byte name1[6] = {'D', 'o', 'o', 'm', '6', '4'}; // Usa, Eur
     90 byte name2[6] = {'D', 'O', 'O', 'M', '6', '4'}; // Jap
     91 
     92 int check_name(void)
     93 {
     94     for (int i = 0; i < 6; i++)
     95     {
     96         if (region == 2) // Jap
     97         {
     98             if (header[0x20 + i] != name2[i])
     99             {
    100                 return 0;
    101             }
    102         }
    103         else
    104         {
    105             if (header[0x20 + i] != name1[i])
    106             {
    107                 return 0;
    108             }
    109         }
    110     }
    111 
    112     return 1;
    113 }
    114 
    115 int WAD_offset[4]   = {0x63D10 , 0x63F60 , 0x64580 , 0x63DC0};
    116 int WAD_size[4]     = {0x5D18B0, 0x5D6CDC, 0x5D8478, 0x5D301C};
    117 
    118 int WMD_offset[4]   = {0x6355C0, 0x63AC40, 0x63CA00, 0x636DE0};
    119 int WMD_size[4]     = {0xB9E0  , 0xB9E0  , 0xB9E0  , 0xB9E0};
    120 
    121 int WSD_offset[4]   = {0x640FA0, 0x646620, 0x6483E0, 0x6427C0};
    122 int WSD_size[4]     = {0x142F8 , 0x142F8 , 0x142F8 , 0x142F8};
    123 
    124 int WDD_offset[4]   = {0x6552A0, 0x65A920, 0x65C6E0, 0x656AC0};
    125 int WDD_size[4]     = {0x1716C4, 0x1716C4, 0x1716C4, 0x1716C4};
    126 
    127 int main(int argc, char *argv[])
    128 {
    129     byte a;
    130 
    131     // Parse arguments
    132     char *romname;
    133     for (int i = 1; i < argc; i++)
    134     {
    135         if (argv[i][0] == '-')
    136         {
    137             if (!strcmp(argv[i], "-i"))
    138             {
    139                 i++;
    140                 romname = argv[i];
    141             }
    142         }
    143     }
    144 
    145     show_info();
    146     if (argc == 1)
    147     {
    148         exit(0);
    149     }
    150 
    151     FILE *in, *out;
    152     in = fopen(romname, "rb");
    153 
    154     if (!in)
    155     {
    156         do_error("Cannot open %s\n", romname);
    157         exit(0);
    158     }
    159 
    160     read_header(in, 0);
    161 
    162     if (!check_name())
    163     {
    164         do_error("Not a Doom 64 Rom\n");
    165         exit(0);
    166     }
    167 
    168     // Extract the file DOOM64.WAD
    169     printf("Extracting DOOM64.WAD ");
    170     fseek(in, WAD_offset[region], SEEK_SET);
    171     out = fopen("DOOM64.WAD", "wb");
    172     for (int i = 0; i < WAD_size[region]; i++)
    173     {
    174         fread(&a, sizeof(byte), 1, in);
    175         fwrite(&a, sizeof(byte), 1, out);
    176     }
    177     fclose(out);
    178     printf("Ok\n");
    179 
    180     // Extract the file DOOM64.WMD
    181     printf("Extracting DOOM64.WMD ");
    182     fseek(in, WMD_offset[region], SEEK_SET);
    183     out = fopen("DOOM64.WMD", "wb");
    184     for (int i = 0; i < WMD_size[region]; i++)
    185     {
    186         fread(&a, sizeof(byte), 1, in);
    187         fwrite(&a, sizeof(byte), 1, out);
    188     }
    189     fclose(out);
    190     printf("Ok\n");
    191 
    192     // Extract the file DOOM64.WSD
    193     printf("Extracting DOOM64.WSD ");
    194     fseek(in, WSD_offset[region], SEEK_SET);
    195     out = fopen("DOOM64.WSD", "wb");
    196     for (int i = 0; i < WSD_size[region]; i++)
    197     {
    198         fread(&a, sizeof(byte), 1, in);
    199         fwrite(&a, sizeof(byte), 1, out);
    200     }
    201     fclose(out);
    202     printf("Ok\n");
    203 
    204     // Extract the file DOOM64.WDD
    205     printf("Extracting DOOM64.WDD ");
    206     fseek(in, WDD_offset[region], SEEK_SET);
    207     out = fopen("DOOM64.WDD", "wb");
    208     for (int i = 0; i < WDD_size[region]; i++)
    209     {
    210         fread(&a, sizeof(byte), 1, in);
    211         fwrite(&a, sizeof(byte), 1, out);
    212     }
    213     fclose(out);
    214     printf("Ok\n");
    215 
    216     fclose(in);
    217 
    218     printf("\nCompleted\n");
    219     return 0;
    220 }