⌂ YolkfolkThe Dizzy Fansite
Community discussion

Reversing Fantastic Dizzy

Started by rmallon on 4 November 2018 • 6,593 views

8 posts
#55733
Hi,

This might be of interest to some people here. I reverse engineered the DOS version of Fantastic Dizzy to figure out the file formats for the game. I wrote a blog post about it, which includes a github link to some tools I wrote for extracting, viewing and repacking the game assets: https://ryiron.wordpress.com/2018/11/04/reversing-fantastic-dizzy/
👍 0
#86957
Interesting read.

I'm not overly familiar with the DOS port of Fantastic Dizzy but it looks like you can use your tools to extract all kinds of graphics and audio which could be useful to any fan game makers.
👍 0
#87782

Ive installed python 2.7 but I'm having problems running the command line to get it to unpack.
I've always struggled with command line, I usually dump everything in a D: root folder to run commands without having to type directories

D:>C:Python27python.exe unpack.py DIZZY.NDX DIZZY.RES Traceback (most recent call last): File "unpack.py", line 19, in <module> from sprite_view import DizzySpriteSet, DizzySpriteInfo File "D:sprite_view.py", line 15, in <module> import pygame ImportError: No module named pygame

I'm really surprised that this community hasnt reverse engineered the games a long time ago.
Personally I've begun with the Amiga ADF disks, I can unpack them but have no idea how to Unpack the .Dat files to see sprites/bg/audio etc

I really just want the raw images to work on a remake project, screen grabbing everything is just going to be a pain in the balls

👍 0
#87783
Don't know if it's useful or not, but the fan games 'Dizzy Rescues Santa' and 'Excalibur Dizzy 680' both use graphic tiles made up from Fantasic Dizzy.
👍 0
#87784
.. knowing that people have done it doesnt really help, but I found a bunch of ripped sprites and i've decided to use screen capture to get what I need.
👍 0
#89315
Ah, Dizzy. He's been to Magic Land, Fantasy World, Treasure Island and even down the rapids. This game was largely an amalgamation of the designers' favorite things from all the games in the series.

Dizzy's an egg-person who lives in a magical world of dragons and trolls. His girlfriend Daisy's been captured by the evil wizard Zaks, who turned the kingdom into a place infested with dangerous creatures. Most of Dizzy's other buddies have evil spells of one sort or another cast on them too, and in order to help them and restore peace to the land, Diz has to find and use a selection of items. Thus it combines a run-and-jump platform game with an inventory-based problem solving game. There's also a lot of magic starts floating around, and Dizzy needs to find them all to break Zaks' magic spell and enter his castle to win the game. Go Dizzy go!

Which is great, you'd think. I love adventure games just about more than any other kind of video game. And Dizzy's world and the amount of puzzles he needs to solve are huge. Which is also great, you'd think. But there's the small matter of there being no save feature.

The kingdom is big, like four or five hours of play time big, and who has that kind of time (and is willing to admit it)? So for all the game's good points, unless you're emulating it, you have to start the whole questing and item collecting all over again every time you switch the power off.

Another slight flaw with the game is Dizzy's ability to only carry three items at a time, and with the large amount of objects that need to be found and taken to where they can be used, this can lead to a lot of backtracking and trying to remember where you left that crowbar that might open the trapdoor in the pirate ship blocking access to another vital item.

Aside from that, the game is pretty good, especially for long-time fans of the Dizzy series. The graphics are crisp and lively, things are easily recognizable (and if they're not, you can go to a subscreen to get a description of all the things Dizzy is carrying). The sound is pretty good, and the background music is some of the best from the Dizzy games I've played. I just wish Dizzy could do something to defend himself from all those rats and spiders and whatnot.
👍 0
#89317
I typically see the game finished in under two hours, and speedrunning has taken it under one hour!

Did you happen to find any new way to extract the game assets?
👍 0
#89682

I have written some simple tools for extracting, viewing and packing the resources of the original game. The tools are laid out on github .

Unpacking exe

The PCDIZZY.EXE binary file is packaged in Microsoft EXEPack format. Although there are many tools for Linux that can unpack such executable files, none of them seems to support the version used for Fantastic Dizzy. Therefore, I used the DOS version of UNP to unpack the executable file. After unpacking the executable file, it could be loaded into IDA. Conveniently, the unpacked version of the binary file still worked well, so you could debug it using the DOSBox debugger.

Data files

The game has two data files: DIZZY.NDX and DIZZY.RES. Extensions, as well as file sizes, give us a hint about what they may contain. The NDX file is approximately 8 KB in size, and the RES file is approximately 800 KB. Since the game is written in C, we can search the IDA open calls to see where the data files are opened. You can use this on automated payroll software also. In games for DOS written in assembly language, for this, you need to look for instructions in 21h (to open the file ah = 3d). The Dizzy binary file contains a wrapper function around open that allows you to specify the main name and file extension. She leads us to the next block of code:

It loads the DIZZY.RES and DIZZY.NDX files, and also stores file pointers in global variables. When backing up DOS binaries, an annoying problem arises: the registers in them are 16-bit, but pointers in some cases can be 32-bit. Here, FILE * pointers are 32 bits in size and returned from do_open_file in axe: dx. Notice that the strings are also 32-bit pointers, and the dizzy_basename is passed to the calling function on the stack (and this confused the IDA's auto-analysis confusing - he considered that this is the mode argument for open).

You can search where x_fizs contain entries for g_dizzy_res / and where files are read. At this stage, the DOSBox debugger is useful, because the likelihood of multiple read-access file operations is high, and using IDA to determine read offsets would be a fairly monotonous process. A good guide to building and using the DOSBox debugger can be found here.

When using IDA and the DOSBox debugger, it becomes obvious that the NDX file is used as an index for the RES file. Each entry in the NDX file is 16 bytes; it stores the fragment identifier, its size and offset in the RES file. Looking at how the RES data is read, you can see that the flag byte is first checked in the NDX file. If the 0x80 bit is not set, then the data is read directly from the RES file, otherwise, a more complex code path is executed. The flag is set for most fragments, so it is very likely that it means some kind of compression is used for these fragments.

Compression

The compression path begins with reading out from the base of the RES fragment two 32-bit words denoting the initial and final dimensions, and then the unpack function is called. In 1991, simple length-length coding (run-length encoding, RLE) and dictionary compression, such as various Liv-Zempel algorithms, were popular. The beginning of the unpacking cycle looks like this:

It only saves the current byte, receives the next token and continues to work. If the flag is cleared, a longer code path is selected, which ends with the rep moves instruction. This indicates that a dictionary is used in compression.

The compression algorithm is interesting for several reasons. First, it uses variable bit length coding. The absolute value is encoded as 1 flag and an 8-bit data value. Curiously, the bitstream is encoded as little-endian. This slightly complicates the analysis of unpacking by observing the RES file in a hexadecimal editor. For example, if the first three bytes of a fragment are encoded as absolute values, then the data is arranged as follows:

Байты: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD Токен 1: 6543210F 7 Токен 2: 543210F 76 Токен 3: 43210F 765

In addition, the unpacker can skip a byte when reading, if the counter cl returns to zero when the next token is received. I do not know whether this is an optimization, or a bug, or a hack created by a game developer, in order to fix the problem with my tools.

If the flag is cleared, the decompressor performs copying from the initial part of the unpacked data. In this case, the following bits encode the length and offset from which to copy. Along with this, I have also set binary retail erp software in india and its work accordingly.
The offset is encoded in 10 or 13 bits, and the desired option is indicated by a flag. This seems like a very strange choice, because it complicates the code a bit, and at best saves only 2 bits.

Length coding looks a bit strange. The unpacker reads the bits until it reaches the zero bit. Then the number of bits used to encode the length is two plus the number of non-zero bits. For example, when encoding length 58 (0x3a), the bitstream looks like this:

11110 111010

11 bits are required for encoding. Small lengths are better encoded because the minimum bit length is 2. Copying lengths up to 3 requires only 3 bits to encode, up to 7 requires 5 bits, and so on. I do not know for sure whether this kind of coding is a common technique.

The DOSBox debugger is also very useful for recreating the decompression algorithm. If you do not know what the unpacked data should look like, then it is difficult to understand whether the decompressor works correctly. Using the debugger, you can step through the entire decompression algorithm and save the dump of the unpacked memory for comparison.

Another useful feature is the flag in the NDX file, which indicates that the resource is compressed. Since the original game supports unpacked resources, we can repack the RES file without the need for a compression algorithm. Modifying and repacking fragments and then starting the game is a good way to check our assumptions about data formats.

Levels

Fantastic Dizzy is a game with an open world. Levels are areas with vertical or horizontal scrolling. The player moves between levels, reaching the end of the level or entering and leaving buildings. Although references to fragments in the RES file are made through 16-bit identifiers (IDs), the binary game file actually contains a table of matching level names with fragment identifiers. Each level consists of several fragments: a header, one or several layers, a tileset and a palette. There is a small redundancy here, because some levels use the same palette and tileset, but do not reuse the same fragments, so the RES file contains many duplicate resources.

Layers encode tiles for level. Additional layers can be used for different parts of the world or for background layers. For example, at the level tree1.stg there are eight layers for different parts of treetops and one common background layer. However, the underwater levels are divided into sea1.stg and sea2.stg, each of which has one foreground layer and one background layer.

Background layers are backgrounds of a fixed-width without scrolling, for example, a forest in a part of the game with treetops. The foreground and background tiles, which are located in front of and behind the character, are encoded in the same layer as the tiles on which you can walk. For example, the screenshot shows the level from the treetops from the beginning of the game:

Hope this will help you properly.

👍 0