Eliminate the bug in the 2000 Shockwave game

Original author: Matthew Pitts
  • Transfer
image

The replacement history of a single byte


Cartoon Cartoon Summer Resort


It was the summer of 2000. I was six, I just finished first grade, and the holidays started. This meant that I could play for a long time on the street, watch cartoons and turn on my father's computer with Windows 98 to search for games in a completely new, unexplored region called the Internet. One of my favorites was the Cartoon Network website. I found a lot of exciting flash-games based on television cartoons on it. That summer they released a series of games called “Cartoon Cartoon Summer Resort”.


Gameplay of the first episode of Cartoon Cartoon Summer Resort

This game was a two-dimensional RPG / adventure game from the top side view, consisting of four episodes. The player controlled a cartoon character who was on vacation at a resort with other cartoon characters. In each episode at the resort there was a problem that needed to be solved. The player had to solve it, interacting with the characters and finding items or exchanging them.

Returning for 18 years ahead


During one of the recent bouts of nostalgia, I remembered this game and realized that I would play it again. She has already turned almost two decades, so it was difficult to find a working link.

In addition, no modern browser would launch the ancient and vulnerable Shockwave player ... with the exception of Internet Explorer. Probably, I was the first person to find a justified reason to use Internet Explorer in 2018.

After playing a bit, I noticed moments that were impossible to ignore. For example, monotonous background music playing in an infinite loop, and poor collision detection.

The same bug


After some time I found a bug in the game:

When I move through areas where nothing should happen, a dialog box sometimes appears.

As you can see from the animation, in the game you can rent a boat to move around in the water. When you try to rent another boat, the message “Today there are no rented boats!” Appears. If you sail to the north and walk along the right edge of the island, but the same text that should appear at the boat pier will open.


At this stage, any sensible person who respects his time and energy would consider the bug a minor nuisance, reminding himself that it was a mediocre web game for children, created two decades ago, and would continue to play. But not me.

Already having all my knowledge of programming and looking at the game, I perceived this bug strangely appealing. It seemed to me that I had unearthed an ancient tomb and found an untouched puzzle in it that could have disappeared, and so was not solved by anyone. For me, this bug was an opportunity to learn and discover something new. Interestingly, it was these possibilities that gave me the process of the game itself in childhood. There is something almost poetic about how something can quite unintentionally set new tasks if you look at it from a different angle.

Deconstruction of the game


To fix the bug, I needed to understand the inner workings of the game. After studying the question, I learned that the game was created on Shockwave in the Director application . When working with Director projects are saved as a file .dir(Director). This file is similar to a PSD file for Photoshop. Just as the PSD file contains non-destructive information about layers and text, the project .dirsaves all the resources, raw source code, and other information that helps in the development process. Director was used to animate scenes in the proprietary scripting language Lingo .

If the game were saved in a file .dir, I could just open it in Director and easily learn how the game works. However, the game is published as a file .dcr. File.dcr- This is a compiled version of the Director project. That is, all the source code is compiled into a bytecode running on the Shockwave platform. This process is similar to how the PSD file is simplified and becomes a PNG image. The PNG image (in our case, the DCR file) is smaller in size, but does not contain information about layers or edits, and is intended only for distribution.

This meant that I was holding a 500-KB binary object without documentation about its structure. Even if I figured out how to find a low-level byte-code, it seems no one performed the reverse-engineering of the Lingo byte-code and did not document the principle of operation of the Shockwave platform. All of this information is proprietary, owned by Adobe, which has no reason to publish it. Chances to understand the game looked pretty bleak.

Decompression


Feeling defeated because I most likely will not be able to eliminate this bug, I decided to find out whether it is possible in some way to extract resources from the game. I figured it was possible to find a section of compressed data or something like that. After searching, I found a couple of programs called offzip and packzip . These tools can search for zlib data in arbitrary binary files, show offsets and extract them into separate files.

I started offzip with a DCR file and to my surprise, he really found the archives! 249 pieces, to be precise. I extracted all these files into a folder and began to study the results. There were 206 files , 38 files , 4 files and a single file .

$ ./offzip.exe -a 1.dcr

- open input file: 1.dcr
- zip data to check: 32 bytes
- zip windowBits: 15
- seek offset: 0x00000000 (0)
+------------+-----+----------------------------+----------------------+
| hex_offset | ... | zip -> unzip size / offset | spaces before | info |
+------------+-----+----------------------------+----------------------+
0x00000026 . 164 -> 214 / 0x000000ca _ 38 8:7:26:0:1:7b6349f6
0x000000d3 .. 3932 -> 9169 / 0x0000102f _ 9 8:7:26:0:1:c1079d84
...
0x00080490 . 265 -> 472 / 0x00080599 _ 0 8:7:26:0:1:04d6b43f
0x00080599 . 209 -> 366 / 0x0008066a _ 0 8:7:26:0:1:7da3ba08

- 249 valid compressed streams found
- 0x0004040d -> 0x001565c8 bytes covering the 50% of the file


.dat.fff.atn.ini


Discoveries


I started with an INI file, but there was no benefit from it. It was a simple font conversion table from Directory 7.0 between Windows and Mac. Then I went to the DAT files. Most of them had a size of 1KB, so I started with a huge, sized 144KB. I opened it in a hex editor and studied. These were mostly illegible data. However, over time, I found a few words in them that seemed to be Lingo identifiers.


Analyzing large DAT files gave me some clues, some interesting messages remained in them. I found out that Photoshop 3.0 was most likely used for graphics. I also learned that the game had an internal map editing tool called Map-O-Matic v1. I would like to see how it looked and was created.

I also found the name of the company that developed the game: Funny Garbage . The name of the lead developer was also in the file, but I will not call him. It was great to discover the author of the game, which I tried hard to fix after almost 20 years, and finally see the face of the person who became the likely cause of this agony. All these crumbs of information were of course interesting, but they didn’t help much.

Breakthrough


Then I began to study the files in the hex editor .fff. To my great surprise, all the data in these files was readable and looked like map data:


I manually extracted some of this data and cleaned it up in a text editor. What I did was very much like an array of JSON: It was very important, because I managed to learn a lot about how the game worked.

[
#member: "block.104",
#type: #FLOR,
#location: [16, 9],
#width: 64,
#WSHIFT: 0,
#height: 32,
#HSHIFT: 0,
#data: [
#item: [
#name: "",
#type: #WALL,
#visi: [
#visiObj: "",
#visiAct: "",
#inviObj: "",
#inviAct: ""
],
#COND: [[#hasObj: "", #hasAct: "", #giveObj: "sunscreen", #giveAct: "gotscreen"], #none, #none, #none]
],
#move: [#U: 0, #d: 0, #L: 0, #R: 0, #COND: 1, #TIMEA: 0, #TIMEB: 0],
#message: [
[#text: "You bought the sun screen.", #plrObj: "", #plrAct: ""],
[#text: "No more sunscreen today!", #plrObj: "", #plrAct: "gotscreen"]
]
]
]




  1. The game expects map, text, and event data to be in Lingo Objects like JSON objects.
  2. Each entry #memberis a drawing, block or character drawn.
  3. Offsets coordinates and sizes #membercan be edited.

Knowing that the game’s dialogs were saved to these files, I wrote a short line for exporting only one dialog to the file:

grep -a -o '#text: "[^"]*' Uncompressed/*.fff | awk '{print $0,"\r"}' > Dialogue.txt

With this file, I can quickly find the wrong text and see what file it was in:


The erroneous text is either in 0004eda0.fffor in 0004f396.fff. In our case, the text of the bug was in the first file. We know this because immediately after it is the message that we receive when interacting with Og, who is a character on the same map as the tile with the bug.

Bug fix


Now I could open 0004eda0.fffand find the row about the boat in the hex editor. Having found it, I was able to detect an object associated with it #member. Then change its properties and save the file. Then I squeezed it again and patched it into the original DCR game file using packzip.


$ ./packzip -o 0x0004EDA0 Uncompressed/0004eda0.fff test.dcr

When I change the type of block with block.11on block.13and patch the game, I can clearly see the outline of the erroneous tile:


By changing the ID of the tile, you can see the boundaries of the problem area.

The very fix of the bug is ridiculously simple. All I had to do was change the identifier for this erroneous tile #messageto #fessage:


Now, if we patch the changes and go back to this area, the messages will no longer appear!


Eliminate the bug in the game, literally changing 1 byte

Why is it possible to correct the error?


I can only assume that the game engine will probably check the tile on which it stands when the player moves. If any condition is met, it displays the message corresponding to this tile from the array #message. After a change #messageto #fessagean array reference #messagethat the code is looking for, is no longer located. He considers this an empty (or undefined?) Object and displays nothing.

Consider an example on JS:

functionfoo(bar) {
    if (bar["message"] !== undefined) {
        // display the message
    }
}

Suppose we cannot change a function foo(), but we need to change the result. We have access to the data transmitted to it. You can rename the property of the messageobject being transferred and the function will think that it was not there.

How did this bug come about?


I suppose that because of laziness. The developers used to create this area map editor. Most likely, they copied already ready maps into new areas, and then changed them. It's easier than creating everything from scratch. But since the events and text data are mixed, they most likely overlooked some places and forgot to remove or replace them. It looks most logical, because the erroneous dialogue was often taken from the neighboring card, where it was used correctly.

Why waste so much labor on something so insignificant?


I do not know. Perhaps because of nostalgia?

Also popular now: