|YaK:: WebLog #535 Topic : 2007-03-14 23.13.34 matt : hex editing xbox games to upgrade their resolution to (at least) 480p||[Changes] [Calendar] [Search] [Index] [PhotoTags]|
|[Back to weblog: pretention]|
I've been on a mission for about 6 months now to get some of my XBox games that display in 480i to display in 480p. I've got about 40 XBox game stockpiled that I haven't played yet, and most of them don't work under the 360's backward compatibility. (I also need their HD-DVD to support the high-def 24-bit audio that is available on most HD-DVDs if I'm to buy one before they're significantly cheaper.) I finally found a forum thread that gave me great information. (Love and smooches to radyn!) When I tried radyn's patch (see the forum post), I found it didn't quite do the job in the game we're currently playing ( Harry Potter and the Goblet of Fire ).
First, I needed to rip the game onto the XBox hard drive. Using a neat CD called Auto Installer Deluxe 3.10, I was able to install a great set of utilities and launchers (like XBox Media Center ). One of the utilities is called DVD2XBox , which will rip a game, movie, or even an ISO to the XBox hard drive. Once I ripped the game to the hard drive, I had to get it off the XBox and onto my laptop for editing. DVD2Xbox and XBMC both include ftp servers that are off by default and can run while they are running. After starting the ftp server in DVD2XBox and starting the game ripping, I connected my laptop directly to the XBox with an ethernet cable and ftp'd into it. The game was being ripped to /E/Games/Harry Potter GOF , so I cd'd into there, set the ftp client to bin mode, and fetched default.xbe to my laptop. I then opened it up in HEdit and went to apply the generic change mentioned in radyn's forum post.
Radyn did a good job of breaking down the problem and solution, but it isn't generic. The hex values have to match *exactly*. This means that if slightly different registers are used (which would change the ModRM byte or even the opcode byte), the hex patch won't match and won't apply. In the Goblet of Fire game, for instance, I found the second place I needed to patch:
8b 46 28 mov eax, [esi+28] 51 push ecx 8b 4e 2c mov ecx, [esi+2c] 52 push edx 8b 56 04 mov edx, [esi+4] 50 push eax
Note how it differs from radyn's generic patch both in the order of the copies out of the _D3DPRESENT_PARAMETERS_ struct (for some reason), and in the registers copied into. The patch is similar, just taking the different register into account:
51 push ecx 8b 4e 2c mov ecx, [esi+2c] 52 push edx 8b 56 04 mov edx, [esi+4] 90 nop 6a 40 push 0x40 90 nop
Looking for the SetVideoMode calls, we look before the call and remove the copying of [exx+28], the FLAGS part of the struct that determines whether interlaced or progressive mode will be used. We also remove the push of the register since the copy into it was already removed. That gives us a 4 bytes with which to play, which is plenty. I chose to push 0x40 instead of 0x00, as I want to absolutely force progressive mode and not even give it a chance to be interlaced. 0x00 would (hypothetically) auto-detect if progressive was available and use it.
This is just like a refactoring to me, just at a lower level. I'll call it "replace dynamic push with static". :)
If IDA exposed their patching functionality to the public, this would be a simple IDC script or plug-in. Since, as far as I know, they still hide that functionality to discourage their tool being used by crackers, some other tool would need to be used. It actually seems like a good use case for a bugreport once it gets a little farther along.
With these two hex edits, the game looks slightly better in that there are much fewer aliasing artifacts. Of course, it is now a little more obvious where the artists used detailed, 2D textures instead of real 3D models. The next step is to force the resolution to be 720p (1280x720 on a widescreen HDTV) from 480p (720x480 on a widescreen HDTV). radyn makes some limited mentions of what to do in the forum post, but it didn't work for me. (The game started, but the display was fux0red in a weird way.)
Also, because the XBox has shared RAM between the CPU and GPU, a higher resolution means less RAM available for the game. If the game runs out of memory, lock ups or other issues can occur. Since the XBox has the most memory of that generation of consoles, direct ports that had to run on the PS2 or GameCube might work just fine. Since there are 3 buffers for the video resolution, the amount of RAM used goes from 720x480 x 2bytes per pixel x 3 buffers (2 megabytes) to 1280x720x2x3 (5.5 megabytes). Games that had more effort put into them to use the XBox to full advantage (high quality textures, etc) might not work. It'll just be a matter of testing and documenting.
I'll keep hacking on it and make another blog post.
PS: Another route would be to edit the white list of 'approved' games in the 360's backward compatibility emulator. Add a game, try running it, see if it plays decently. I've been told there are plenty of games that work with minor framerate and visual issues. If there's any out there has tried this, search engines aren't showing me. If anyone has tried this, please let me know via email, IM, or a comment here.
Discussion:showing all 0 messages
|(last modified 2007-03-15) [Login]|