Created
March 13, 2020 05:24
-
-
Save ahmubashshir/39831cb534ebc05c7483ec2e4de2f2d5 to your computer and use it in GitHub Desktop.
To the Moon.rgssad extractor, forked from http://ancurio.bplaced.net/stuff/ttm_pack.c and edited...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ttm_unpack: An unpacker for the game "To the Moon"'s datafiles. | |
* | |
* Copyright (c) 2012, David Gow <[email protected]> | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted, provided that the above | |
* copyright notice and this permission notice appear in all copies. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR | |
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
*/ | |
/* | |
* To compile: cc -o ttm_unpack ttm_unpack.c | |
* | |
* To run: cd <path to To the Moon> | |
* ttm_unpack [optional packname] | |
* mv To\ the\ Moon.rgssad To\ the\ Moon.rgssad.old | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#define MAXBUF 1024 | |
uint32_t decryptState = 0xdeadcafe; | |
unsigned char* strip(unsigned char* str, const size_t n) | |
{ | |
unsigned char buffer[MAXBUF] = {'\0'}; | |
size_t i = 0; | |
size_t j = 0; | |
size_t max = (n<MAXBUF)? n : MAXBUF -1; | |
while (i < max ) | |
{ | |
if ( str[i]>=32 && str[i]<=255 ) | |
{ | |
buffer[j++] = str[i]; | |
} | |
i++; | |
} | |
memset(str, '\0', max); | |
i = 0; | |
while( i < j) | |
{ | |
str[i] = buffer[i]; | |
i++; | |
} | |
str[j] = '\0'; | |
return str; | |
} | |
void advanceDecryptor() | |
{ | |
decryptState = decryptState * 7 + 3; | |
} | |
void extractAll(FILE *packfile) | |
{ | |
uint32_t sig; | |
fread(&sig,sizeof(sig),1,packfile); | |
if (sig != 1397966674) | |
{ | |
printf("Error: not a valid 'To the Moon' datafile.\n"); | |
exit(-1); | |
} | |
fread(&sig,sizeof(sig),1,packfile); | |
if (sig != 16794689) | |
{ | |
printf("Error: not a valid 'To the Moon' datafile.\n"); | |
exit(-1); | |
} | |
int numFiles = 0; | |
// For each file... | |
while (!feof(packfile)) | |
{ | |
// Get the length of the filename | |
uint32_t fileNameLen; | |
fread(&fileNameLen,sizeof(fileNameLen),1,packfile); | |
fileNameLen ^= decryptState; | |
advanceDecryptor(); | |
// feof(), of course, won't trigger unless we've tried to read _after_ the | |
// end of the file, so re-check here. | |
if (feof(packfile)) break; | |
// Read and decrypt the filename | |
char *fileName = malloc(fileNameLen+1); | |
fread(fileName,sizeof(char),fileNameLen,packfile); | |
// Better make this compile as c89 | |
int i; | |
for (i = 0; i < fileNameLen; ++i) | |
{ | |
fileName[i] ^= (decryptState & 0xFF); | |
advanceDecryptor(); | |
// A nice hack to mkdir everything. | |
if (fileName[i] == '\\') | |
{ | |
fileName[i] = '\0'; | |
mkdir(fileName, S_IRWXU); | |
fileName[i] = '/'; | |
} | |
} | |
strip( fileName, fileNameLen ); | |
printf("Extracting: \"%s\"...\n",fileName); | |
// Get the file size | |
uint32_t fileSize; | |
fread(&fileSize, sizeof(fileSize),1,packfile); | |
fileSize ^= decryptState; | |
advanceDecryptor(); | |
// Save off the decryptor state, we need to restore it later | |
uint32_t oldDecryptState = decryptState; | |
// Open an output file | |
FILE *outFile = fopen(fileName,"wb"); | |
if (!outFile) | |
{ | |
printf("Error: could not create \"%s\".\n",fileName); | |
printf("Check that you have write permissions to the current directory.\n"); | |
printf("Extraction will now halt.\n"); | |
fclose(packfile); | |
exit(-1); | |
} | |
// Read and decrypt the file | |
long idx; | |
for (idx = 0; idx < fileSize; ++idx) | |
{ | |
char c = fgetc(packfile); | |
char xorValue = ((char*)(&decryptState))[(idx&3)]; | |
c ^= xorValue; | |
fputc(c, outFile); | |
if ((idx&3) == 3) advanceDecryptor(); | |
} | |
// Close | |
fclose(outFile); | |
// And finally, restore the decryptor state. | |
// This is a bit weird, but seems to have been done | |
// to make sure the game has fast random-access to packed | |
// files. | |
decryptState = oldDecryptState; | |
numFiles++; | |
} | |
printf("Extracted %d files!\n", numFiles); | |
} | |
int main(int argc, char **argv) | |
{ | |
char *filename = "To the Moon.rgssad"; | |
if (argc > 1) | |
{ | |
filename = argv[1]; | |
} | |
FILE *packfile = fopen(filename, "rb"); | |
if (!packfile) | |
{ | |
printf("Error: could not open pack file \"%s\".\n", filename); | |
printf("Make sure you're in the game directory.\n"); | |
return -1; | |
} | |
extractAll(packfile); | |
fclose(packfile); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment