Reverse Engineering Zuma Deluxe’s level file

It was really hot last weekend, and both my son and I ended up staying home. To kill the time, I ended up playing a small game called “Zuma Deluxe” with him. It’s probably a very old game, but still quite fun to play with. While playing, as an software developer, I was thinking how would i do the design if i were asked to make such game. One thing would be how to store the level design data in the file. So that question eventually led to this blog.

First thing I tried is google. Searching keywords “Zuma level file format” guided me to this one: http://spherematchers.proboards.com/thread/62/mod-zuma-deluxe?page=2. People seems to be discussing the level description file (which is an xml file) and other image files, but the most important “Curve” file is not addressed and remains secret.

So I thought about this: If i were told to design the game, a simple way is to store the track using multiple segments of straight lines. So you end up with a list of (x,y) pairs, each one is a point on the curve. Connecting all the points up with lines, you get the curve!

So is that how the game developers actually do? Let’s take a look. A quick dive into the game installation folder shows there are data files under “levels” directory, for example, <zuma_root_dir>/levels/triangle/triangle.dat.

So let’s start with this “triangle” level. The background picture of this level is this:

triangle

So i’m expecting the .dat file describing a curve matching the picture. Opening the file with a hex editor presents me with the following content:

hxd_1

By simply eye balling on the hex digits, i can tell it has a header of 16 bytes (first row), which seems to be the following structure:

typedef struct
{
char signature[4];
uint32_t unk1, unk2;
uint32_t size;
} header_t;

the “size” field is the one i’m particularly interested in, as it outlines the first section of the level data.  Looking into the binaries, and i realized, the data begins with a “count”, and then a group of element of length of 10 bytes.  Let’s say it’s a structure of the following:

type def struct
{
uint32_t x;
uint32_t y;
uint16_t unk;
} elem_t;

I don’t know if i’m guessing it correctly, so let’s try plotting the data out. I’m using python notebook for this task:

plot_1

Bingo! It matches what I was guessing! When i was doing this, the first element was confusing me for quite a while as it as a negative “y” coordinate. So i skipped the first element. Later I tried to explain to myself with the first element, and found it makes sense, as the curve starts out side of the screen. So, mystery solved! Well, not completely, as there is a unknown “short” field.

Anyway, i was eager to try this out, so I altered a couple points, and tried to load the level in game, expecting something strange will happen. But nothing! The game ran as usual if it were not changed.

So what’s going on? I realized that I only had first section of the level file decoded, not entire file. What’s left?

So here is the second section. Following the logic of the first section, the first 4 bytes look like another “size” field, but doesn’t quite match.

hxd_2

Anyway, let’s continue. After a couple strange numbers, the rest all the way to the end of file is something like a list of integers, with a slowly changing values. First i tried to plot them as (x, y) pairs, but that didn’t come up very well.  I don’t know what i was thinking, but i somehow, plotted the first two bytes of each 4-byte group, as “x,y” pairs, and it looks like this:

plot_2

Yes! This is definitely something! But how can a circle of dots relate to a curved track? Anyway, i started messing around with those data, and found:

  1. As long as being consistent with the header, changing the 1st section doesn’t make any visual differences. I even tried replace the entire section to a zero sized stub, the game still runs very well.
  2. Replacing the second section with that of other level file makes the game changes completely. It’s like i’m using this level’s background picture, but with the other level’s track.

These findings make me really thinking that the first section is not used at all. Then, how does the second section define the curve?

I was scratching my head for more than an hour while my son kept bugging me with all sorts of weird things. Then suddenly, i got the point! It can be an array of “delta_x, delta_y” for the points on the track!

To verify that, i did the following plotting. Again, the first couple bytes are strange so I skipped them:

plot_3

Fantastic! This proves my theory! Now all i need is to figure out two things:

  1. right scale, apparently the image i got is in very wrong scale
  2. origin, i’m expecting something between 640×480, and the first point should be something consistent as the value defined in first section

The first one is easy, looking at the current range, i think all i need is to divide the cx, cy by 100. The second one took me a couple seconds, by looking into the strange bytes at the beginning of the section:

 91 B1 AF 42 1F 0B 04 C2

Again, if i were to design this game and storing all the deltas, the first point should be somewhere. As we mentioned section 1 is not used at all, so this must be in section two, which leaves only these bytes. But their value doesn’t look like integers at all!

I almost instantly know what i should be looking into: floating points!  If i’m storing the deltas by a scale of 100, i probably want to divide them by 100. Storing the coordinates using 100 times of the actual coordinates on screen would be a good idea.

So that makes the following complete code:

plot4

Mission accomplished!

So what’s next? Maybe a custom Zuma level designer?

 

 

Advertisements
Posted in computer games, programming, reverse engineering | Tagged , , , , | 1 Comment

TI Stellaris launchpad with IAR EWM — where do my printf messages go

Last week while cleaning up old stuff, I found two TI Stellaris (they now renamed it to Tiva) launchpad development kits in my junk box. I guess I bought them when TI firstly released them and then completely forgot. They are great ARM development kits for beginners. I happen to have a work related project based on ARM Cortex M4 so I think it’s time to try them to get familiar with ARM embedded development. Instead of using TI’s CCS, I’m choosing IAR EWM simply because I don’t like Eclipse based IDEs.

As many other developers do, my first program will be a “Hello World” (well, blinking LED is another type of “Hello World” for embedded world, but I just found getting debug message is always more important than blinking things in real life). Things have gone really well when I finished the single line “printf(“Hello World!\n”)” in main.cpp, and then I started looking into project settings trying to find out where the default IAR runtime will output the result. I’m sure there will be someway redirecting the stdio from target uC to  host PC, it’s just hiding somewhere.

My first bet was the “Debug Log” pane, however, i was wrong, nothing showed up there. And then googling/binging/… until more than 10 minutes later, I finally found the answer:

First make sure your project is having stdout/stderr implemented “via semihosting” — This is the default option, but I changed it when I was trying to figure out where the message has gone :

000020

And this option is only available when you are in debugging mode:

000021

Here is the lovely “Hello World” message:

000022

OK. I hope this can save you some effort if you just started playing with the kit:)

Posted in Uncategorized | Leave a comment

Hacking a Dell power adapter — final (not really)

!!! WARNING: With this project, you power adapter will be reporting false information which may not match the original design. This may cause severe results such as file or damaging your laptop. Do it on your own risk!!!

 

As I mentioned in my previous post, there are at least two ways fixing the unidentified power adapter issue, and I chose the hard way, which is simulating how DS2502 works using a micro controller. This is all about learning one wire protocol and I did learnt a lot. I think the most important thing is timing, with a uC working at 16Mhz or 8Mhz, you need to carefully counting how many cycles your interrupt routine takes and providing the logical level in time.  And different optimization results between release vs debug configuration also needs to be taken into account.

Anyway, I sort of finished the project with something left not fully implemented. Here is the source code and pcb design. I also made the PCB by hand using toner-transfer method. It’s a great chance to learn the whole process from coding, PCB design, and PCB making…

Here are some pictures:

schematic:

Image

pcb layout:

Image

Final result:

Image

Image

Image

To proof it’s working, I successfully faked my 90W adater to 65W:

WP_20140225_012 WP_20140225_013

I was trying to make it display some weird wattage numbers but found dell may have some white-list and so far any wattage not 90W or 65W will not be recognized.

There are still unfinished things including importing the data from a working power adapter, storing multiple data and switching between them. I have all the hardware components ready but don’t have time finishing the software part yet, which should be pretty straight forward, except my limited RAM (128 bytes) and flash spaces (4KB).

Anyway, a good opportunity to learn one wire protocol with this project. The PCB design and code can be found at https://github.com/HclX/DELL_POWER_SPOOFER.git

 

Posted in MSP430 | Tagged , , | 18 Comments

Hacking a Dell power adapter — part III

Last night I worked for more than 2 hours only finding out the chip in the power adapter is damaged. This time, I want to use my working power adapter. Instead of trying to talk to it directly using OneWire protocol, I’d like to see what’s happening between laptop and the power adapter.  With a hand soldered adapter I was able to expose the signal pins from both power adapter side and laptop side and I’m going to hook it up with a uC to see what’s happening.

Without a scope or logic analyzer, it’s not easy to sniff the onewire protocol. So I decided to make a software one with MSP430G2553. This chip has a timer with capture capability and 512 bytes RAM.  So I should be able to setup the timer to capture both rising and falling edge of the signal line, and save the elapsed time to a 100-integer array in RAM.

Because of limited RAM, I will have to stop once the buffer is full. That means I will not get a full dump of the communication but it should be a good start.

OK. Let’s wire up and see what I can get. Having everything wired up, after plugging the power adapter into my laptop, the code running on uC quickly stops at the preset breakpoint which means I’ve collected 100 data about rising and falling edges (how stupid that TI’s code composer studio doesn’t allow you copy content in the expression watch window, I have to manually copy memory dump and convert them into decimal numbers using python):

[0, 1310, 23, 107, 931,

554, 25, 107, 412,

70, 10, 0
70, 10, 0
8, 72, 1
8, 71, 1
71, 10, 0
70, 10, 0
8, 72, 1
9, 72, 1

71, 10, 0
71, 21, 0
70, 9, 0
71, 10, 0
10, 70, 1
8, 72, 1
9, 70, 1
8, 73, 1

71, 10, 0
71, 10, 0
71, 10, 0
8, 72, 1
70, 10, 0
70, 21, 0
71, 9, 0
71, 10, 0

71, 10, 0
71, 10, 0
71, 10, 0
71, 10, 0
70, 10, 0
70, 10, 0
71, 10, 0
70, 11, 0

8, 72, 1
9, 84, 1
28, 53, 0
8, 72, 1
9, 73, 1
10, 73, 1
9, 72, 1
8, 74, 1

28, 53,
28, 5
4, 28,
52, 28,
53, 9, 72, 9]

I’m still assuming it’s OneWire communication. It’s easy to notice that the second line seems very likely to be the reset sequence: more than 480us low from host, and less than 60us high, then 60us to 240us low from device, and then pulling up.

After that, every pair of number is a read or write signal. I added the third row for what it writes/reads.

70/10 (or simliar) means 70us low and then 10us high. This should be “write 0”

8/72 (or simliar) means 8us low and then 72us high, this shoudl be “write 1”

Comparing to the OneWire spec, we can tell it’s writing 0xCC, which should be SKIP_ROM. Following that is 0xF0 (ReadMem), and two bytes starting address: 0x08, 0x00.

Then the numbers are getting weird, which is actually the reading sequence. Pairs like “8, 72” with first number less than 10 is a “read 1”, and “28, 53” is a “read 0”. According to the spec, after writing ReadMem command with start address, we should be reading a CRC code verifying the command and address are correctly received by the device. So in this case, the device returns a CRC code 0xFB.

Here is some quick C code calculating the CRC:


typedef unsigned char uint_8;

uint_8 CRC_8(uint_8 crc, uint_8 data)
 {
 for (int i = 0; i < 8; i++)
 {
 if ((crc ^ data) & 1)
 {
 crc = (crc >> 1) ^ 0x8C;
 }
 else
 {
 crc >>= 1;
 }

data >>= 1;
 }
 return crc;
 }

int _tmain(int argc, _TCHAR* argv[])
 {
 uint_8 crc = 0;
 crc = OW_CRC(crc, 0xF0);
 crc = OW_CRC(crc, 0x08);
 crc = OW_CRC(crc, 0x00);

return 0;
 }

Run it, and we got: 0xFB, yes! So it is OneWire protocol! I ran my one wire code and dumped the information from the adapter:

RomID: 11 63 4D 8B 00 00 00 14 . Starting from LSB to MSB. 0x11 is the family code about which I can’t find any useful information .

Memory dump:

String format: DELL00AC090195046CN09T2157161543835EAL03

Hex format:

44 45 4C 4C 30 30 41 43 30 39 30 31 39 35 30 34 36 43 4E 30 39 54 32 31 35 37 31 36 31 35 34 33 38 33 35 45  41 4C 30 33 E0 A9 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

Listening the onewire protocl between laptop and power adapter shows that the laptop is actually reading 3 bytes from starting address 0x08, which is “090”. It looks like “090” is the wattage, and “1950” is the voltage (19.5v), then “46” is the amperage (4.6A), the reset looks like a serial#. And, my laptop doesn’t even care all the other parts except the wattage, neither does it care the RomID of the chip!

Well, now we have at least one simple solution: Simply buy a DS2502 device, program it with the above information, and make a “adapter” like thing but hook the center pin to that DS2502 device.

But, I like to over-engineer things, so I’m going to make a MSP430 chip and faking itself like a DS2502 chip. By doing this I can report whatever information I want to. This will be a more flexible design in case some crazy DELL model checks the RomID. Even further, it can even “import” the data from multiple working power adapters and switching between different models. More importantly, it’s a good chance to learn the onewire protocol!

To be continued…

Posted in MSP430 | Tagged , , , | 8 Comments

Hacking the Dell laptop power adapter — part II

Knowing that the power adapter may have a DS2502-like chip, I started looking around for the OneWire protocol. There are actually plenty of documents and even source code for this protocol, and I happen to have some DS18B20 for verification purpose, I quickly came up with some code running on MSP430G2553 uC talking in this protocol. And I verified it’s working great with the DS18B20 device: I can read the unique device ID, and even get the room temperature.  After that, I wanted to try it with a power adapter. I choose a broken one I got from PC recycle pile. This one has broken laptop side connector, which is exactly what I need to connect the signal pin. So, 5 minutes wiring up, double check, and I ran my code. Guess what? Nothing!

I can’t even get it pass through the reset sequence, which is detected by device pulling down the signal wire, but I didn’t see that at all! I re-checked the wiring, and my code, verified it again with DS18B20, and found nothing wrong on my side.

After spending more than ten minutes checking everything, I decided to open the power brick to see what’s inside. After hurting one of my fingers I finally got it opened. And here is what I saw:

Image

This is the PCB side. The signal pin connects to a resistor (the black thing on top-left), and then go to the central pin of a TO-92 packaged component. The right pin is not connected, and left pin is grounded. There is also a diode-like device between ground and central pin, which looks like a reverse-voltage protection mechanism.

My multi-meter shows that the resistor is larger than 20Mohm, and zero ohm between any two of the three pins of the chip. All these results make me believe that this chip has been damaged. And it may be a problem of DELL’s design, since this signal wire has no shielding and the long wire can easily trap static electricity and damage the chip.

Here is a close look at the chip itself, and the reverse side of the PCB board

CaptureCapture

There are some text “01MFKVE BYTE TI” on the chip but I couldn’t find anything useful by searching it on internet.

Anyway, it’s not a waste of time, and I got this:

WP_20140207_005

By soldering the connector from power adapter side and a socket from a broken dell laptop, I exposed the signal wires from both sides and also the ground line. This will allow me to listen on the communication between laptop and a working power adapter, which is the next thing I’m gonna do.

To be continued…

Posted in 计算机与 Internet, MSP430 | Tagged , , , | 3 Comments

Hacking the Dell laptop power adapter

Recently I got a used dell laptop but the original power adapter is missing. Since the interface and power ratings seem to be pretty much same as my current dell, I thought I could be able to share the power adapter for both laptops, but I was wrong…

With the power adapter plugged, the laptop can be turned on, but I immediately noticed there are something on the BIOS screen saying that the adapter can not be identified, and the battery will not charge (the picture is from internet but it has almost identical information):

Image

So, that means there is something other than just power being transferred to the laptop. What is that? This really brings up my curiosity. Before cutting the cord and  counting wires, I did a search, and internet will never fail you. This is what I got:

http://www.laptop-junction.com/toast/content/inside-dell-ac-power-adapter-mystery-revealed

The post was created 5 years ago and I’m not sure if things have changed, but it worth a shot. So, a chip with OneWire protocol! Funny thing is, I’m currently working on a small wireless sensor network project which requires communicate with a temperature sensor called DS18B20:

ds18b20-pinout

And it’s using exactly the same OneWire protocol!

By simply tapping a digital analyzer I should be able to see what’s communicating between two sides, but I don’t have one. So, it’s time to write some code and hook up a uC to see what I can read out from the power adapter.

To be continued…

Posted in 计算机与 Internet, MSP430 | Tagged , , , | 6 Comments

Learning embedded things: Arduino like or something else…

Since the day I realized that my life is getting boring, I decided to do something fun. Embedded system and electronics look like very attractive to me. Talking about that, there are very popular “Arduino” things: you have the development board, and very good high level frameworks. By simply put some code together, you can make your own robots, wireless sensors, remote toys, …. Pretty cool! However, the “framework” hides too much details from you. It’s hard to understand how embedded system works and how the electronic signals make differences. Because of that, I have one Arduino board in my junk box untouched, instead, I started my adventure with MSP430 launch pad, which basically gives you nothing other than an IDE/compiler to work with. So far, I like that, at least it teaches me one thing: reading datasheet line by line to know how to configure your uC to do the right thing…

http://processors.wiki.ti.com/index.php/MSP430_LaunchPad

Posted in MSP430 | Leave a comment