CS:PSP Mods, maybe?

Sep 9, 2007 at 11:50 PM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
I tried posting this somewhere else but didn't get a response so:

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.
andwhyisit said:
What program did you use to create the data.csz file? I am having trouble extracting files.
And I was given this .cpp file:
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?
 
Sep 11, 2007 at 5:38 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
Anyone? :D

diph.php
 
Sep 11, 2007 at 11:08 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
xristosx said:
i haven't got a clue :D
Do you know anyone in this forum with knowledge of C++
 
Apr 12, 2010 at 12:29 AM
Vanished.
Bobomb says: "I need a hug!"
Join Date: Apr 5, 2008
Location:
Posts: 776
Sucess.

schokobecher@schokobecher-desktop:~/Desktop/doukutsu$ ./code
399 files packed.
Compressed 2174848 -> 478402 bytes
/home/schokobecher/Desktop/doukutsu/data.csz

You want my code?
YOU WANT IT?!
BEG FOR AN EXE!
 
Apr 12, 2010 at 1:20 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
Before I start begging:
1. Are you able to port it to a windows or dos executable? I don't exactly have linux.
2. Can you create a decompression program from what you have?
 
Apr 12, 2010 at 1:22 AM
Vanished.
Bobomb says: "I need a hug!"
Join Date: Apr 5, 2008
Location:
Posts: 776
1) No need for begging.
Exe does not work need to compile on windows.

2) I have no knowledge in C++
So Idunno.
Maybe JTE got some spare time...
No promises.
 
Apr 13, 2010 at 12:20 AM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
Oh, I know C++.

What exactly did you want again? Did you just want to compile that code?
 
Apr 13, 2010 at 1:06 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
Celtic Minstrel said:
Oh, I know C++.

What exactly did you want again? Did you just want to compile that code?
1. Port to windows.
2. Compile.
3. Link.
4. Alter code so that it decompresses files.
5. Compile.
6. Link.
7. ????
8. Profit!

That's the gist of it.
 
Apr 13, 2010 at 1:11 AM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
Hm. Well, it looks like it's using at least two POSIX headers, so porting would indeed be necessary. I'm not sure if I can help with that part... MSDN tends to be a decent resource for Windows programming, though, and I might be able to help out a little.

Compiling, on the other hand, I can give instructions for. Later.
 
Apr 13, 2010 at 2:12 AM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jun 12, 2007
Location:
Posts: 95
Age: 35
I made the exe in the zip linked through use of Mingw, which compiled it effortlessly with just #include <assert.h> and -lz added.
 
Apr 13, 2010 at 3:33 AM
Vanished.
Bobomb says: "I need a hug!"
Join Date: Apr 5, 2008
Location:
Posts: 776
andwhyisit said:
1. Port to windows.
2. Compile.
3. Link.
4. Alter code so that it decompresses files.
5. Compile.
6. Link.
7. ????
8. Profit!

That's the gist of it.

http://die-manufaktur.net/csz_compressor.zip

Are you blind, good sir?
Includes a Windows Exe.
The Linux Version.
and a fancy Readme.

Oh and the fixed source.
 
Apr 13, 2010 at 4:31 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
Schokobecher said:
Are you blind, good sir?
Includes a Windows Exe.
The Linux Version.
and a fancy Readme.

Oh and the fixed source.
Oh, my bad. That's awesome. Thanks.

Permission to host on the site? :p
 
Apr 13, 2010 at 4:45 AM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jun 12, 2007
Location:
Posts: 95
Age: 35
Yup, it seems they are blind to you, Schokobecher. Better luck next time.
 
Apr 17, 2010 at 9:28 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
I'm going to check out Mingw. I suppose now is a good time as any to start experimenting with c++.

EDIT: I took a look at the source code (and later in a hex editor to confirm it) and the first 4 bytes of the data.csz file represent the length of the original uncompressed archive.dat file. The original uncompressed size is required by the zlib "uncompress" function in order to decompress the file. By the looks of it I just might be able to produce a program that decompresses a data.csz file into an archive.dat file.

Wee! I'm learning c++! :eek:

EDIT2: I have developed a program to decompress a data.csz file into archive.dat.

http://www.mediafire.com/?yywdytwznqm (exe + source)

Don't make fun of my source code though, this is my first time writing c++ code. Now all I need to do is write a function that will extract all of the required files from archive.dat.
EDIT3: Aaaand I am done.

http://www.mediafire.com/?qg5j3t4rymm

The complete extracted and uncompressed data folder for the psp port of CS. It seems to be made for modding since maps, sound effects, orgs, font data and other information that is normally stored in the exe is now in the data folder.
 
Apr 17, 2010 at 7:52 PM
Creating A Legacy...
Bobomb says: "I need a hug!"
Join Date: Sep 6, 2009
Location: The Balcony
Posts: 852
Age: 29
ny idea on how to re-compress it? cus im gunna do a test mod for my psp. Any stuff you qant to test out by the way ill happily try for you, i think andywhy has a psp too
 
Apr 18, 2010 at 12:50 AM
Neophyte Member
"Fresh from the Bakery"
Join Date: Nov 8, 2009
Location:
Posts: 4
andwhyisit said:
I'm going to check out Mingw. I suppose now is a good time as any to start experimenting with c++.

EDIT: I took a look at the source code (and later in a hex editor to confirm it) and the first 4 bytes of the data.csz file represent the length of the original uncompressed archive.dat file. The original uncompressed size is required by the zlib "uncompress" function in order to decompress the file. By the looks of it I just might be able to produce a program that decompresses a data.csz file into an archive.dat file.

Wee! I'm learning c++! :D

EDIT2: I have developed a program to decompress a data.csz file into archive.dat.

http://www.mediafire.com/?yywdytwznqm (exe + source)

Don't make fun of my source code though, this is my first time writing c++ code. Now all I need to do is write a function that will extract all of the required files from archive.dat.
EDIT3: Aaaand I am done.

http://www.mediafire.com/?qg5j3t4rymm

The complete extracted and uncompressed data folder for the psp port of CS. It seems to be made for modding since maps, sound effects, orgs, font data and other information that is normally stored in the exe is now in the data folder.
Oh my, thanks!
Since I translated Cave Story to Spanish in November I wanted to put it in the PSP version, but there was no way to do it.
Two days ago I was trying with the compressor but I didn't get the port to work.
Now I've tried downloading your uncompressed data.csz, I've replaced the files and repacked it and it works! The only problem is that the font doesn't have the special characters that the PC version has (áéíóúÁÉÍÓÚñÑ¡¿), but now I'm working in it.
Any idea on where the places' names are? In the PC version they seem to be in the .exe (the only raw text that isn't on the external files, seemingly) and I've seen a file called map.dat in the PSP version. I've opened it but it only shows the map files name (not the one displayed in-game) and text in weird characters, maybe Japanese, which is weird, since the Japanese original version has the map names in English, and if they are the ones displayed in the Japanese version in-game there should be the English ones too, but they aren't.
 
Apr 18, 2010 at 4:41 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6211
Age: 38
ShySpy said:
I've opened it but it only shows the map files name (not the one displayed in-game) and text in weird characters, maybe Japanese, which is weird, since the Japanese original version has the map names in English, and if they are the ones displayed in the Japanese version in-game there should be the English ones too, but they aren't.
Yeah that's Japanese, sorry.

Okay I have discovered that the Japanese language mode files have the exact same name as their English counterparts, and as a result the English files were being overwritten. Sooo new zip file:

http://www.mediafire.com/?ejt4ko3jojl

data_en contains the data files in English only (don't worry, the game uses the English files in both English and Japanese language mode with this).

data_jp contains the data files in Japanese only.

data_enjp contains the data files in both languages (if you want to use the dual language feature), some files are suffixed with "(1)" for English and "(2)" for Japanese.

Rename the data folder you want to "data", and then run "pack.exe", "correct.exe" (for data_enjp only) and "compress.exe" in that order to create a data.csz file.

EDIT: Since I added "correct.exe" to the zip the below text is now outdated:
data_enjp is the data files in both languages, but they are suffixed with "(1)" for English and "(2)" for Japanese. There isn't much point in using this folder unless you really want the two language funtionality because, to be quite honest, it is time consuming. Use "pack.exe" to create an "archive.dat" file and open it in a hex editor. The info for each file is 96 bytes long and starts at address 0x000010. You will need edit the 85th byte of each duplicated file's info (e.g. Addr. 0x000184 in the case of "ArmsItem(1).pbm") to the number beside its name(01 for "(1)", 02 for "(2)"), and rename the file (e.g. both data/ArmsItem(1).pbm and data/ArmsItem(2).pbm into data/ArmsItem.pbm). Compress the file to a "data.csz" file with "compress.exe".

I may look into creating a program to automate the data_enjp conversion process later.
 
Apr 18, 2010 at 1:28 PM
Neophyte Member
"Fresh from the Bakery"
Join Date: Nov 8, 2009
Location:
Posts: 4
Andwhyisit, you deserve a statue :o

However, I'm having problems editing the maps' names. I've opened maps.dat with Wordpad and the text is very messy (maybe Wordpad isn't the best choice, but uh, I'm not very experienced in romhacking and similar works). I've tried editing Start Point, First Cave, Hermit Gunsmith and Mimiga Village and here's the results:
- Start Point as Punto de Inicio. The name doesn't even appear when you enter the map.
- First Cave as Primera Cueva. The first letter (P) doesn't show.
- Hermit Gunsmith as Artesano Ermitaño, though I've put Artesano Ermitano to avoid font problems until I can solve it. Like Punto de Inicio, it doesn't even appear.
- Mimiga Village as Pueblo Mimiga. It appears correctly.

Is there a better way to edit maps.dat?

And, about the font... It works very different than the Windows version, right? As I've seen, the original PC version uses a font from the PC (Courier New) and it has ALL characters, so there's no problem with translations and using special characters.
However, the PSP font is stored in three files: font.en.dat, font.jp.dat and sjisascii.tab. The first is obviously the English one and the one that I think I have to edit, the second one is the Japanese and the third... Something related to character tables, no idea if I have to edit it.
Can I get some help in this, too?
 
Top