Wanting to make a PSO Private Server in Java

GunvoltEXE

Member
Hi, guys. I'm wanting to make a PSO Private Server in Java. I think I should start with the login server, right? Or would I need a shipgate server first?

I know I'll need to figure out what packets get sent, when, and what they do. Does anyone have any info on this I could get? Anything helps.

I've been coding for around 10 years, I think. I mostly did offline game dev, but I'm starting to do apps now, and I've always wanted to make a PSO Server since I first heard about them, which was probably also 10 years ago, lol.

Anyway, can anyone help me figure out where to start, and where to get info for packets?
 

GunvoltEXE

Member
Yeah, I'm wanting to do it from scratch.

Also according to this repo - https://github.com/justnoxx/psobb-tethealla - there's a login server, a patch server, and a ship server. I'm wondering which one of these does the client send the first packet to basically. I'd assume it's the Login Server, but I could be wrong, so I'm asking. :D
 

Sodaboy

Administrator
Staff member
If you've played PSO, you should already know the order in which to make this?

Client always connects to the patch server, then the login server (which sends the list of ships to connect to).
 

kion

Garbage Human
Don't forget there's also Sylverant for comparing source code. I played around with the server a little bit, but not much. You can get Teth running on your local machine to test how it works as is.

The MySQL implementation and table structure is pretty simple to get familiar with. You can write tools to add new players, or do other administrative tasks. From there there's a login server, a patch server and the game server, so you could look at the login and patch server to see what function they have and how to implement them in another language.

For the game server, you can get something like wireshark to look at what packets are being sent to and from the server. Easy implementation might be to write a small proxy server, that way you can piggy back off what's already there. For packets you know how to handle, you can respond from Java, otherwise send them to Teth to be handled.

Also document and write out what ever you can for all of the formats. The more you write down and get on paper, the less stuff you have to remember in your head. It always helps me a ton when ever I go back and read what I wrote about something before. And it doesn't have to be perfect, "as far as I know it seems to work like this, next thing I need to play around with is this."
 

Soly

Member
That's a big project lol.. even if it's just porting.
There was someone who was porting it to C# right? ... Sadly I don't recall the name right now, look around in the forum and you could get in contact with him, he could give you some tips or something. xD
 

GunvoltEXE

Member
Hi, everyone. Thank you all for the great replies so far!

I've decided to go with kion's idea about a proxy server, and am getting pretty far with it, being able to catch and modify the Copywrite Message Packet, but I want to be able to send a command to my Teth Serv making my character say something, and I can't find anything on chat bubble packets.

Also, I tried using NetMon to figure things out about the chat packets myself, but I'm not seeing any plain text in any of the packets, are the chat messages encrypted? If so, does anyone have any documentation on how to encrypt/decrypt a chat packet?
 

Soly

Member
The packets are encrypted yeah and you won't be able to decrypt them out of nowhere, you have to work with the connections from the patch to the login and then ship.
 

GunvoltEXE

Member
Soly said:
The packets are encrypted yeah and you won't be able to decrypt them out of nowhere, you have to work with the connections from the patch to the login and then ship.
Sorry, but I'm not understanding this all the way. Could you explain a bit more about "working with the connections?" Are you saying to use the Client or Server to encrypt/decrypt them somehow? Or am I completely off? lol.
 

Sodaboy

Administrator
Staff member
All packets between the client and server are encrypted, not just the chat packets. The state of the encryption is also changed with every packet... So, if you're making something in-between them, like a proxy, you would need that in-between to be the primary thing that connects to the server and have whatever else connect to the in-between.
 

GunvoltEXE

Member
Oh, that! Yeah, I already got that part all set up. I connect to my proxy port, and then my proxy connects to my server port. Right now I'm able to send and receive packets just fine, and even managed to get the copyright packet, modify the text inside it (It's not encrypted like the chat is I guess) and send it to the client. Right now I basically want to force my character to say something from the proxy.

I.E.
instead of [type something in pso] -> [proxy] ->[server]
I want to [type something into proxy text box, and hit send] -> [server gets chat packet with text from proxy] -> [server sends to client making it show up on screen, I think]
 

Sodaboy

Administrator
Staff member
Then if you're already decrypting, there isn't anything special with the chat packet. However, all chat text is in Unicode, so you've got 2 bytes (or 1 "word") for every letter. Make sure you're searching for text that way.

Packet # for chat is 0x06.
 

Mylandra

Member
Encryption is only blowfish, there's a bunch of libraries freely available on the net or simply copy the functions used by Tethealla. You can just dump the key from the client to set it up. I wish you luck in this thousand of hours ordeal hahaha
 

GunvoltEXE

Member
Thanks for the posts, guys. They're really helpful :D

One thing, how do I dump the blowfish key in the client and/or where would I find the encrypt/decrypt functions in Teth?

I found this:

Code:
/* Start Encryption Packet */

unsigned char Packet03[] = {
	0xC8, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x68, 0x61, 0x6E, 0x74, 0x61, 0x73, 0x79,
	0x20, 0x53, 0x74, 0x61, 0x72, 0x20, 0x4F, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x42, 0x6C, 0x75,
	0x65, 0x20, 0x42, 0x75, 0x72, 0x73, 0x74, 0x20, 0x47, 0x61, 0x6D, 0x65, 0x20, 0x53, 0x65, 0x72,
	0x76, 0x65, 0x72, 0x2E, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31,
	0x39, 0x39, 0x39, 0x2D, 0x32, 0x30, 0x30, 0x34, 0x20, 0x53, 0x4F, 0x4E, 0x49, 0x43, 0x54, 0x45,
	0x41, 0x4D, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
	0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
	0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
	0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
	0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
	0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
	0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30
};

Is this the key?

According to the wiki http://sylverant.net/wiki/index.php/Packet_0x03 there are client and server encryption vectors in this. Is that what I need?
 

Sodaboy

Administrator
Staff member
I don't think you'll really understand your own server software, should it ever come to fruition, if you're going to ask what everything means every step of the way.

You've got to be able to reverse engineer... But, really, not sure why you're reinventing the wheel...

Since most of the reverse engineering is already done by others for you, why don't you just go look at either the source code for my proxy or even the Tethealla Ship or Login server? Search for the word "crypt" or even "encrypt" and you'd have your answers...

Let me help you with the Packet03, though, taken from ship_server.c (actually def_functions.h now):

Code:
	memcpy(&connect->sndbuf[0], &Packet03[0], sizeof (Packet03));
	for (c = 0; c<0x30; c++)
	{
		connect->sndbuf[0x68 + c] = xrand() % 256;
		connect->sndbuf[0x98 + c] = xrand() % 256;
	}
	connect->snddata += sizeof (Packet03);
	cipher_ptr = &connect->server_cipher;
	pso_crypt_table_init_bb(cipher_ptr, &connect->sndbuf[0x68]);
	cipher_ptr = &connect->client_cipher;
	pso_crypt_table_init_bb(cipher_ptr, &connect->sndbuf[0x98]);
	connect->crypt_on = 1;
	connect->sendCheck[SEND_PACKET_03] = 1;

As you can get from the code, the entirety of Packet03 is copied into a buffer to send but before it's sent, we put a bunch of random values in specific parts of the packet. What could those values be? Well, we see they're pointed to for initializing the PSO BB encryption. "&connect->sndbuf[0x68]" and "&connect->sndbuf[0x98]".

Could they possibly be the encryption key? If you said yes, you would be right.
 

Xenon

Member
For what it's worth, you're more than welcome to look my implementation of a psobb server: https://github.com/dcrodman/archon. Granted I haven't touched it in a good while, but it's relevant and started off with the same goals you have in mind. It's also written in Go and pretty heavily commented, which is rather easier to digest than C. I'll chip in my experience for kicks:

Most of the work I've done has involved reading the source code of Tethealla, Newserv/Aeon, and Sylverant in order to figure out what each of the packets do and how the client responds. As Sodaboy said, it's not worth reverse engineering each of the packets on your own as he and Fuzziqer did an absurd amount of work on that and you're better off learning from them than trying to do all over again by yourself. Plus, just because you look at a packet definition in the code and look at some of the values that get stuffed into various fields doesn't mean that you understand how to actually use it. The biggest challenge for me has been figuring out how all of the packets (and the associated data) relate and how they collectively determine client state.

The implementation side is also a lot more than just reading Tethealla and then reproducing it; it's a lot of code and the PSO protocol has a fearsome number of subtleties. It's an iterative process: you figure out what packet you need to handle (hint: a packet sniffer is helpful here), you determine how the response is structured (likely from another server), you implement your version of it and test, then repeat. Generally step 2 has involved figuring out how they handle whatever functionality I'm working on and then deciding how to represent that on my side. Sometimes I write code that looks very similar to what the others do, and sometimes I've found it fits better with my design to build something differently.

I toyed with the idea of writing a proxy to sit on top of Tethealla and implement the server little by little, but you're dealing with low level code and the amount of plumbing required to share that kind of state is a nontrivial effort. Just personal opinion (as all of this is), but I'd also steer clear of Java for something like this. This is a binary protocol and I couldn't think of a way I liked for translating between Java objects and the raw packet data when I was first designing this, and in my opinion the way data is expressed by the protocol doesn't map well to an object oriented design.

I don't mean to discourage you, but you're looking at a hard project. Take it on and give it a shot, but be prepared for enormous amounts of frustration and a lot of time spent pouring over packet dumps and byte operations in C code. And kiss a small piece of your sanity goodbye :D

tl;dr: Shit's difficult
 

Aleron Ives

Member
Xenon said:
Just personal opinion (as all of this is), but I'd also steer clear of Java for something like this. This is a binary protocol and I couldn't think of a way I liked for translating between Java objects and the raw packet data when I was first designing this, and in my opinion the way data is expressed by the protocol doesn't map well to an object oriented design.
I would also be concerned about writing a server in a language that is notorious for being slow and memory inefficient, which are two language attributes that are the opposite of what you want for server design.
 

Mylandra

Member
The time difference between coding a server in C and java is minimal at best. The real time difference will be there only for someone who already has expertise in a specific language. C is not so much harder to code than any other language unless you have never used it before and/or know nothing about low-level languages. Maybe it's not a starting language because beginners don't know anything about freeing their objects/managing the process memory, but that has little to do with how much time it takes to build a software. There are things I do faster and better in assembly than any other language, does that mean it's the fastest language to code in? No, it all depends on what you are building.

Java's processing speed is irrelevant in this case because pso servers will hardly serve more than a hundred pso players so it's not really important that a well-built C server will handle ten thousand connections. Time tells us again that code may be just as important than the language if not more as far as processing speed goes. Java applications tend to be slow and memory inefficient mostly because more newbies attempt java than C and make a mess of the softwares they've worked on. More often than not, creating a mess in C means your software crashes unexpectably for no reason at all and no one will use it so no one will ever say anything about the software running slow. A Java application can be fast enough for it's purpose as long as the coder knows what he's doing (That doesn't mean I like java, but it does the job either way lol).
 

Xenon

Member
I didn't mean to spark a language standoff, but as Mylandra said the scale at which any PSO server will be operating is imo nowhere near significant enough for performance to strongly influence the choice of language. C is stupid fast and, written well, can yield an immensely scalable server application but with dramatically more code required than a higher level language; that's why high level languages exist. Java is easier to write and conceptualize (and thus debug, largely due to less control), which results in a shorter development cycle and but lower performance metrics in most cases. Though for the record, I mostly write Java code for work and our backend servers handle millions of requests per minute for a user base of tens of millions of people.

Languages are tools, and some are better suited to certain classes of jobs than others. I considered but chose not to use Java because I don't think it maps well to the challenges you encounter with this particular project (which I still stand by). Some may feel differently and can perhaps design a PSOBB server in a more Java-friendly way, which is perfectly fine. Or any language for that matter, it's totally up to you. The bottom line is to use whatever you feel the most comfortable with or that you think is best suited to the task.
 

kion

Garbage Human
I don't think that language implementation really matters beyond preference as far as PSO private servers go. I'm mostly curious about the motivations. With well established communities and implementations like Tethealla and Sylverant, does the server really need to be ported to another language?
 

Soly

Member
Well.. I have been thinking of the idea too, on C# (what I use mostly nowadays), not to make a performance/language/etc war... but just to do it. Maybe you could have some sort of design war then .. but at least me, there wouldn't really be any motivation than just for the heck of it (and with that it would probably die really fast :p, as I haven't even tried)
 
Top