This is totally unrelated to atheism, but it’s related to one of my hobbies… so shut up, I’m going to talk about it. Give me my nerd space.
Recently, a few much more skilled hackers figured out how to use homebrew software modify a retail PS3 so that it will act like a development kit (devkit) system instead, complete with all the special debugging options usually reserved for those willing to fork over thousands of dollars for an official kit. One of the options available on a devkit is the use of an external hard drive as a Blu-ray drive emulator (BDEMU) – that is, devkits can use hard drives to simulate a PS3 game disc.
To facilitate this, there’s an official Sony program called ps3gen that lets developers create disc images of their games and write them onto their devkit’s hard drive so they can be played.
However, there are a few problems:
- It’s proprietary and confidential, and using it is legally shaky.
- It limits the hard drive to 4 games at a time, no matter how big the hard drive actually is.
- It doesn’t provide any means of retrieving a game you’ve previously written to the disk
To me, these limitations weren’t acceptable. I decided find a solution. Nobody had yet created an alternative to the official Sony program, so I set about making my own.
Although I’m a technical writer, I’ve been writing software (mostly for fun) for the last 21 years, since I first pounded out a simple little BASIC program on an Apple IIgs. I’ve done my best to keep on top of the latest developments in programming languages, tooling around in everything from Visual BASIC and Java to C, C#, Perl, Python, and more. I’ve written web scripts, dynamic HTML pages, database-driven software, GUIs for command-line software, Android apps, and so on. None of it for money… all of it for fun and pleasure, or (like in this case) to fill a need that nobody else has filled yet.
And so, over the last couple of weeks, in my spare time, I’ve worked on this project. It doesn’t look like much, but believe me, it was a tough slog.
To get started, I first had to understand how the official program formatted the BDEMU hard drive. It was time for some good old-fashioned reverse engineering.
- I had to figure out where it stored information about the number of game images on the drive.
- I had to understand what the various bits of information related to each image meant.
- I had to figure out how the images were laid out on the hard drive itself.
If this sounds easy, here’s what I spent hours staring at:
It’s enough to make you go crazy, but given enough hours and caffeine, I managed to figure it all out. Once all the reverse-engineering was done, I had to dig into the really annoying busywork of actually programming what I’d figured out. (I kid – I really enjoyed it.)
I went into the process knowing basically nothing about how hard drives were laid out, and what limitations there were on raw disk reading/writing (i.e., writing directly to disk rather than to a file). I didn’t even know how to get access to the programming functions I’d need to be able to do it.
I started off writing the program entirely in C#, hammering away at it with some half-understood copy/pasted code I’d found on the Internet that was similar to what I wanted to do. I then took the time to actually learn exactly how it all worked. After some frustration, I found out that the functions I was using wouldn’t allow me to jump to any arbitrary point on the disk and start working; they would only let me jump to a point that was at the start of a sector, then work from there. That was annoying.
So I used Cygwin (a Unix-style POSIX environment that runs on top of Windows) and wrote some software in C that did all the real heavy lifting. This made it much easier; Cygwin is set up to allow raw disk access in the same way that you’d write to any file in C. So now, I had all the basic functionality ready to use: finding a properly-formatted disk, opening the disk, finding the metadata for the games, reading the image type and title, and dumping the image to a file.
I had some trouble when I realized that I’d need to jump to a point in a hard drive that was beyond the ability of a 32-bit number to address. Much of the C language was written with 16-bit and 32-bit computing in mind, and the maximum number that can be stored in 32 bits is 4,294,967,295. 4,294,967,295 bytes is 1 byte short of 4GB, meaning that if I wanted to access part of a hard drive past that limit, I’d need to use 64-bit numbers instead. I knew how to do file management stuff in C using 32-bit numbers, but I didn’t know what the equivalent functions were for 64-bit numbers. Luckily, that was easy enough to find out, and so I managed to fix my code so that it could read any place on the disk and write files much larger than 4GB.
But there were still more problems. I wanted to create functions that let you increase or decrease the number of slots available for games, which meant that I’d have to find out how big the drive was (and therefore what the maximum number of slots would be). However, I didn’t know how to do this in C by itself; I could find and change the number of disk sectors currently allocated to the partition that contained all the images, but I didn’t know how to find out how big each sector was. Without that, I wouldn’t be able to calculate how many sectors the partition would need to fit a given number of images (each game slot takes up the full size of a double-layer Blu-ray disc, so you multiply that size by the number of games to get how much space will be required).
So I turned to C#. I figured out how to make a C# program launch another program and capture its output, and thereby made a user interface that sent commands to the C program and responded to its output. I could use C# to get the sector size, then pass it along to the C program to manage the number of sectors assigned to the partition.
Much of my program wound up like this: get user input in C#, pass along commands to the C program, respond to the C output using C#. For example, while the C program is dumping an image from the disk to a file, it frequently prints out the percent of the overall task that it has accomplished. The C# program captures this and uses it to advance a progress bar and let the user know everything’s working.
So… what did I learn from all this? Besides the specifics of how the BDEMU’s hard drive is laid out, I learned:
- How to read and write raw, unformatted disk partitions
- How to find and modify the size of a disk partition
- How to use Windows API calls to expand the functions available in C# and get access to some really nifty tricks
- How to use 64-bit addressing to access data past 4GB on a hard drive or in a file
- How to create child processes and capture their output in C#
- A lot more general stuff about programming in C#, including parts of the .NET API I’d never touched before
And more. All in all, I’d say it was worth it. And there’s still more to do…