Compiling tgctogcm.c on Linux

Compiling tgctogcm.c on Linux

Pure technicalities!

This is a boring, but how necessary, part of game modding. Here is the story. Some tools were developed on Windows machines for game modding. Most of my machines are Linux. And I do not like to execute .exe files from the internet randomly. So I do my best to find the sources of the files and compile them.

I am not an expert in compiling C stuff, the details that matters when compiling 32 or 64 bits programs, or fluent with the C language. So, it may seem really simple for someone with a vast experience in that field, but it was quite instructive to me ;)

tgctogcm plays quite an important role for finding hiddent elements in multi game disc, as we may see in future posts. Fortunately, it is available with the source. I did not write it, all the credit goes to Plootid (the source is at the end of the article).

The story

If you want to have a working version of the tool and do not care about my errings with compilers, C and whatnot, just jump to the last section.

I first tried :

g++ tgctogcm.c -o tgc2gcm

It did not work.

tgcbis.c:25:61: error: ntohl was not declared in this scope

So, the trouble comes from the small functions ntohl, htonl… What they are supposed to do is to modify the machine representation of integers.

They are available on Linux and Windows, but the way to import them are different. You can add the following line to import it.

#include <arpa/inet.h>

Not, it compiles. And it works. Almost. If you use the executable, it will turn a tgc to a gcm file. But the gcm file will be corrupted. The issue was that the program has to be compiled in 32 bits. Once done, this works. The way to figure this out was to have a look at the .exe file. You can infer the compilation looking at some printable characters, and the following answer was quite useful : SuperUser

In a nutshell.

Simply run:

g++ -m32 tgctogcm.c tgc2gcm32

So you will have a 32 bits executable file, that will reproduce the behavior of the windows file exe :)

// tgctogcm.c -- Plootid 2004

#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char **argv) {

  FILE *tgcin, *gcmout;
  unsigned long tgcheader[14];
  unsigned long temp[3];
  int i;

  if (argc < 2) {
    printf("Usage: %s <infile.tgc> <outfile.gcm>\n", argv[0]);
    return 1;
  }

  if (!(tgcin = fopen(argv[1], "rb"))) {
    printf("Error: Couldn't open file %s\n", argv[1]);
    return 1;
  }

  fread(tgcheader, 4, 14, tgcin);

  for (i = 0; i < 14; i++) tgcheader[i] = ntohl(tgcheader[i]); //Byte-swap
  tgcheader[4] = tgcheader[4] - tgcheader[2]; // Update FST location
  tgcheader[7] = tgcheader[7] - tgcheader[2]; // Update DOL location
  tgcheader[9] = tgcheader[9] - tgcheader[2]; // Update File Area location
  //  for (i = 0; i < 14; i++) printf("%08X\n", tgcheader[i]); // Print tgc header

  if (tgcheader[0] != 0xAE0F38A2) {
    printf("Error: Input file does not appear to be a .tgc file\n");
    fclose(tgcin);
    return 1;
  }

  if (!(gcmout = fopen(argv[2], "w+b"))) {
    printf("Error: Couldn't open file %s\n", argv[2]);
    fclose(tgcin);
    return 1;
  }

  printf("TGCtoGCM by Plootid 2004\n\n");

  printf("Target filesize: %d bytes\n", tgcheader[9] + tgcheader[10]);
  printf("Copying GCM, please wait...\n");
  fseek(tgcin, tgcheader[2], SEEK_SET);
  while ( (i = getc(tgcin)) != EOF) putc(i, gcmout); //Copy gcm from tgc
  fflush(gcmout);
  fclose(tgcin);

  printf("Updating GCM...\n");

  // Update DOL and FST locations
  temp[0] = htonl(tgcheader[7]);
  temp[1] = htonl(tgcheader[4]);
  fseek(gcmout, 0x420L, SEEK_SET);
  fwrite(temp, 4, 2, gcmout);

  // Update FST
  fseek(gcmout, tgcheader[4], SEEK_SET);
  fread(temp, 4, 3, gcmout);
  for (i = ntohl(temp[2]) - 1; i > 0; i--) {
    fread(temp, 4, 3, gcmout);
    if (!(ntohl(temp[0]) & 0x01000000)) {
      temp[1] = htonl(ntohl(temp[1]) - tgcheader[13] + tgcheader[9]);
      fseek(gcmout, -12, SEEK_CUR);
      fwrite(temp, 4, 3, gcmout);
      fflush(gcmout);
    }
  }
  fclose(gcmout);
  printf("All Done!\n");
  return 0;
}

GamecubeKid

GamecubeKid
Passionate about Gamecube, coding, statistics, beta games...

Modding Star Wars Clone Wars

A work in progress about the files on the disc, part 2 Continue reading

The lost Dekoboko track

Published on January 05, 2018

Modding MKDD

Published on December 23, 2017