Sep 9, 2007 at 11:50 PM
Join Date: Jul 15, 2007
Location: Australia
Posts: 6242
Age: 39
Pronouns: he/him
I tried posting this somewhere else but didn't get a response so:
Regarding mods for cave story ports.
http://pastebin.com/f5117e02
Does anyone know what to do with this?
Regarding mods for cave story ports.
andwhyisit said:This is my first time here, and I am wondering if it is possible to change a cave story pc mod to work with cave story psp, and if so, at what level of difficulty?
ufo_z said:It can be done, of course.
You have to swap out the data file with one that contains your modified files. The data file is a gzipped archive file with a simple format. (if you only edited the English version, switching between languages would probably be horribly broken, though). Also, if you modified the game exe in any way, you'd have to do the same sort of changes to the psp eboot - of course it's MIPS code instead of x86.
andwhyisit said:Everything else seems simple enough, but modifying the eboot to match the game exe seems complicated, especially when I want to use other people's mods, and I don't know how to program for either, all the programming languages I know are for the internet (eg. Actionscript, HTML, JavaScript, etc).
Is there program to easily compare the mod's exe to the original exe and spot all the differences in the code, 'cause this will at least make it easier.
In the meantime I will try to find out which mods don't rely on changes to the game's exe.
And I was given this .cpp file:andwhyisit said:What program did you use to create the data.csz file? I am having trouble extracting files.
Code:
#include <zlib.h>
#include <dirent.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
// make a file archive
typedef unsigned int u32;
const size_t FILENAME_LEN = 64;
const size_t BLOCKSIZE = 128;
const u32 VERSION = 0x10001000;
// 16 bytes
struct Header {
char id[4];
u32 version;
u32 size;
u32 files;
};
// 96 bytes
struct FileEntry {
char filename[FILENAME_LEN];
u32 size;
u32 offset;
u32 namehash;
u32 checksum;
u32 flags;
u32 locale;
u32 reserved1;
u32 reserved2;
};
enum FLAGS
{
FLAG_LOCALIZED = 1<<0,
FLAG_TSC = 1<<1
};
u32 calc_crc32(const void *data, u32 size)
{
u32 crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (const Bytef*)data, size);
return crc;
}
vector<FileEntry> files;
vector<string> filepaths;
u32 gsize;
void addFile(const char *filename, const struct stat *st)
{
assert(filename);
size_t namelen = strlen(filename);
if (namelen>FILENAME_LEN) {
fprintf(stderr, "Skipping file: %s (filename too long)\n", filename);
return;
}
string origname(filename);
FileEntry fe;
memset(&fe, 0, sizeof(FileEntry));
// check name for a locale?
if (!strcmp(filename+namelen-3,".en")) fe.locale = 1;
else if (!strcmp(filename+namelen-3,".jp")) fe.locale = 2;
if (fe.locale) {
namelen -= 3;
fe.flags |= FLAG_LOCALIZED;
}
strncpy(fe.filename, filename, namelen);
fe.size = st->st_size;
fe.namehash = calc_crc32(filename, namelen);
if (!strncmp(filename+namelen-4,".tsc",4)) fe.flags |= FLAG_TSC;
FILE *f = fopen(origname.c_str(),"rb");
char *buf = new char[fe.size];
fread(buf, fe.size, 1, f);
fclose(f);
fe.checksum = calc_crc32(buf,fe.size);
delete[] buf;
files.push_back(fe);
filepaths.push_back(origname);
}
void scanDir(const char *dirname) {
assert(dirname);
string basepath(dirname);
DIR *dir = opendir(dirname);
while (dirent *de = readdir(dir)) {
const char *filename = de->d_name;
string fullpath = basepath + "/";
fullpath += filename;
if (filename[0]!='.') {
//printf("%s\n",fullpath.c_str());
struct stat st;
stat(fullpath.c_str(), &st);
if (S_ISDIR(st.st_mode)) {
// recurse
scanDir(fullpath.c_str());
} else {
addFile(fullpath.c_str(), &st);
}
}
}
closedir(dir);
}
int roundUp(int value, int block = BLOCKSIZE)
{
int rem = value % block;
return rem ? (value + block - rem) : value;
}
void buildFile(const char *nameOut)
{
int num = files.size();
static char dummy[BLOCKSIZE];
memset(dummy, 0, BLOCKSIZE);
// fix up offsets
int headersize = sizeof(Header) + num * sizeof(FileEntry);
int firstoffset = roundUp(headersize);
int of = firstoffset;
for (vector<FileEntry>::iterator it = files.begin(); it != files.end(); ++it) {
it->offset = of;
of = roundUp(of+it->size);
}
Header h;
strncpy(h.id, "Cave", 4);
h.version = VERSION;
h.size = of;
gsize = of;
h.files = num;
FILE *fo = fopen(nameOut,"wb");
// write header
fwrite(&h, sizeof(Header), 1, fo);
// write file entries
for (vector<FileEntry>::iterator it = files.begin(); it != files.end(); ++it) {
FileEntry *fe = &(*it);
fwrite(fe, sizeof(FileEntry), 1, fo);
}
// pad
fwrite(dummy, firstoffset-headersize, 1, fo);
// write the files
for (u32 i=0; i<num; i++) {
FileEntry &fe = files[i];
string &name = filepaths[i];
FILE *fi = fopen(name.c_str(), "rb");
char *buf = new char[fe.size];
fread(buf, fe.size, 1, fi);
fclose(fi);
fwrite(buf, fe.size, 1, fo);
delete[] buf;
// pad
int toPad = roundUp(fe.size) - fe.size;
if (toPad) fwrite(dummy, toPad, 1, fo);
}
fclose(fo);
printf("%d files packed.\n", num);
}
void compressFile(const char *nameIn, const char *nameOut)
{
FILE *f = fopen(nameIn, "rb");
char *buf = new char[gsize];
fread(buf, gsize, 1, f);
fclose(f);
u32 len = compressBound(gsize);
char *buf2 = new char[len];
int res = compress2((Bytef*)buf2, (uLongf*)&len, (const Bytef*)buf, gsize, 9);
if (res != Z_OK) {
fprintf(stderr, "Couldn't compress data\n");
} else {
f = fopen(nameOut, "wb");
fwrite(&gsize, sizeof(u32), 1, f);
fwrite(buf2, len, 1, f);
fclose(f);
delete[] buf;
delete[] buf2;
printf("Compressed %d -> %d bytes\n", gsize, len);
}
}
int main(int argc, char *argv[])
{
scanDir("data");
buildFile("archive.dat");
compressFile("archive.dat", "data.csz");
return 0;
}
http://pastebin.com/f5117e02
Does anyone know what to do with this?