jPSXdec is a cross-platform PlayStation 1 media decoder/converter.
Get the latest version here.

Monday, February 25, 2008

lain? lain!

The Serial Experiments Lain PSX Game Translation Project is really coming along. A few more wonderful translators have generously offered some help. We have roughly 7% of the game translated already.

Here are some exciting fruits of everyone's efforts so far (actual screenshots).



Sunday, February 17, 2008

nihongo niban

Much awesomeness has transpired recently. But first, the dull ramblings of jpsxdec status.

Looked up how to encode uncompressed (RGB) AVI files. It's not too complicated--Microsoft and other sites have usable documentation. Even found a Java class to get me started. But I got really excited when the hidden art of MJPG encoding was uncovered. It is so ridiculously easy, I can understand why no one ever describes how to do it.* Of course if we're gonna write AVI files, we need to know the frame-rate. Just a simple 400 lines of code is all that took.* Needed to also change the overall code design to a 'push' architecture with listeners. This had the additional bonus of pulling the actual file writing to the top-level interface--right where it belongs. :D

* /sarcasm

But overall things are looking pretty good. For the next release I want to add a new popup window showing the many decoding options.

Also in the future I want to allow for piping out uncompressed AVI to a program like ffmpeg or mencoder. For Windows I'll also include the infamous Video for Windows. Still need to add raw cd reading.

But while merrily carrying on with all this, out of nowhere came a fishy fellow with the powers of language transformation! He generously offered to spend some time with the S.E. Lain game. Sooo... efforts on jpsxdec are delayed as the Serial Experiments Lain PSX Game Translation Project commences (SELPGTP?).

But with 5.5 hours of audio, he has his work cut out for him. Do you share the powers of language transformation? We could really use your help.

On the technical side, we are working on adding the eventual translation into the game. And I present to you an actual screen shot based on an earlier idea.

Saturday, February 2, 2008

Amalgamation

Been busy with a bunch of different aspects of jpsxdec. Only the GUI and Code Design will be in the next release (v0.31 today!). The rest will show up in releases after that.

GUI
Even though it's a pretty lame GUI now, I hope it will drop the bar of entry a little.


Code Design
I had difficulty deciding on highest-level interface between the GUI/CLI and the logic. So I set it aside and worked on other things.

PSX YUV->yuv4mpeg2 conversion matrix
This will allow jpsxdec to output more accurate .yuv image sequences.

Frame Rate Calculation
I thought it was a good idea to guess the exact FF7 frame rate algorithm via trial-and-error. 8 hours later I finally saw that FF7 frame lengths do actually follow a pattern, but a ridiculous one. I hoped it would come to a frame rate of exactly 15/100.1% (half the rate of NTSC). That is close, but there was no way I could guess the underlying algorithm of this...


if (iMovieType == WACKED_NTSC1 && iThisFrame == 101)
iThisFrameLength = 11;
if (iMovieType == WACKED_NTSC2 && iThisFrame == 100)
iThisFrameLength = 11;
else if (iThisFrame == 200)
iThisFrameLength = 11;
else if (iThisFrame >= 203 && iThisFrame <= 298) {
if (((iThisFrame - 203) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 203) % 4) == 1)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 299)
iThisFrameLength = 11;
else if (iThisFrame >= 303 && iThisFrame <= 398) {
if (((iThisFrame - 303) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 303) % 4) == 1)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 399)
iThisFrameLength = 11;
else if (iThisFrame >= 402 && iThisFrame < 497) {
if (((iThisFrame - 402) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 402) % 4) == 2)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 498)
iThisFrameLength = 11;
else if (iThisFrame == 501)
iThisFrameLength = 11;
else if (iThisFrame >= 504 && iThisFrame <= 600) {
if (((iThisFrame - 504) % 4) == 0)
iThisFrameLength = 9;
else if (((iThisFrame - 504) % 4) == 2)
iThisFrameLength = 11;
else
iThisFrameLength = 10;
}
else
iThisFrameLength = 10;

Raw CD reading (Windows)
Made a native program to read raw CD sectors via DeviceIoControl. It's a simple interactive prompt that accepts commands to open/close a CD and read sectors. I even setup a Java program to communicate with the native program via stdin/out. Unfortunately it was slow, and was very vulnerable to deadlock while reading from stdin. I also started adding ASPI for raw CD reading, but there seems to be a lot more to using that API.

Encoding via VFW (Video for Windows)
I worked out a little program to convert a series of raw image and audio data into an AVI, using the oh-so-familiar Video for Windows popup. I wonder if it can handle accepting all the audio at once, then all the video at once....


JNI
Even though I said it would be a pain in the butt, I guess it's really not so bad. It's kinda like translating VB6 COM code into C++. This will likely speed up raw CD reading, and save me from communicating via stdin/out.

Code Design
Finally got back to this again. Since no solution was particularly attractive, I went with the simplest one. This will only use one optional callback listener (for progress status).

However, I have begun to think that the 'pull' architecture is not the best approach to begin with. A 'push' architecture is more applicable to this situation: as sectors are read from the disc, they need to be 'pushed' into the appropriate streams. Listeners can be added to collect the streams of interest. If jpsxdec was to ever play media in real time (not likely), this would be the necessary design. In any case, the 'push' approach would make decoding a little faster because there is less seek time.