Analysis of fonts and translation quest 1996 — I Have no Mouth and I Must Scream

All good!


Based on the eponymous novel Harlan Ellison (Harlan Ellison) the game I Have No Mouth and I Must Scream is one of the darkest game ever. Oppressive atmosphere does not let go until the denouement.

In the near future. Three superpowers, USA, Russia and China, each seeking to surpass rivals, has created a supercomputer for warfare. But they have miscalculated. United together, calling themselves the AM, three supercomputer, using the power given to them by people who wiped humanity from the face of the earth. Alive computer leaves only five who will be his toy for endless torture.

The last time I the described 8-bit font, and this time managed to parse 1-bit.
Both of the fonts are not encrypted and not compressed, which greatly simplified the task.

Tools: IDA, dosbox + debugger, winhex, GBS.

KDPW
image

The problem is to find a font among the files.
Clearly, such FONTS, files and folders, there is a resource file scream.res a size of 75.5 MB.
Use Process Monitor (FileMon ex) with a filter on dosbox made the table order of accesses to files, offsets, and sizes.
First started to watch .res file using GBS and ruin the blocks in scream.res in order to call them, found the storage location of the images of fonts:
image


Robin sketched their fonts Arial from taken seem to not have adjusted the width and alignment, but there was confidence that the game can translate the codes of the letters, consistent with cp1251.
Drawing characters will fit perfectly and Excel:


image

Later suggested a great link, comrades of SCUMMVM scratched game, there is a manual.

The font is 1-bit, i.e., one byte can be set to 8 pixels. Multiple bytes form a series. Some series form the height of the obtained memory block (height * length) bytes, or a rectangle resolution (height X (number * 8)).
Visual memory in the game look like this (green and red bars indicate bytes):
image
image

The game uses a small font and R3, R1 box.
the Structure of each font
Header — 1286 bytes, consists of
ITE_FONTHEADER, 6 bytes
INT16, c_height — maximum character height
INT16 c_width — maximum width of the symbol, the parameter is completely unnecessary,
INT16 row_length is the length of the row image of the font (in bytes)

Then 256 bytes, array indices, the indices I equated to cp1251 (AA is the index 192-255).
INT16 index[256] is the byte number at which to start a symbol.

Then 256 bytes, the array of the widths of characters:
BYTE width[256] — character width in pixels, can be any in reasonable limits, from 0 to infinity. Well, to 255 :)

Then 256 bytes, the flag. As I understand it from a series of experiments, he sets the left indent, in pixels.
BYTE flag[256] Unknown character flag (either 0 or 1)

Then 256 bytes are tracking how many pixels of a character rendered. Counting from left to right from 0 to infinity. To one byte.
Tracking BYTE[256] tracking

Following the header is a block of data (row_length * c_height) bytes in length.

Formula access to any beginning of the row:
font_data + (row_length * y)
where font_data — a pointer to the beginning of the font data, y is the row number.

Each character is ((width[index] — 1) / 8) + 1 bytes.


After these data, the artist of the forum gave pretty similar to the original dialog font. The original was reserved all sorts of icons and the umlauts are enough bytes to fit the original and Russian font. In stock in the end even 1 byte that I'm turning down. Wrote a program block copy from BMP, where he painted Russian font in a straight line right to the block of the game.


Began the second font:


Here was a school. The original block was very, very little space, that is, of the set to exclude 14 wacky characters, but this is clearly not enough for 66 Russian letters.

First I tried to play a number of bytes of the row, thinking that the game initialisere the buffer height, and byte range. Looked in winhex that the next block is another font, but it is not used in the game. Reset the unit, increased the length of the number, but received the same set of characters but with a shift. It turned out that the size of the data buffer is written somewhere in other place.
Tried to keep the length of the row unchanged, but the play index.
Nothing I have of all the ploys did not work, getting in the trash. As it turned out, I forgot that at the end of the resource file there is a table of offsets and sizes of blocks needed to play with her and everything would have turned out without patching.the EXE file )

Here I am confuse how dos header to throw out and remove the LE file that I can put in the IDA that it happily recognizes as a 32 bit LE file. Opened the file in winhex found a line "*** NULL assignment detected", and went up to MZ and the beginning of the cut to MZ.
Thank you cracklab.

Then got another problem, how to match the address in dosbox (it looks like a 180:200c61) and the address in IDA (looks like cseg01:0001AC1F) to see where the code is running and to make his analysis. On the SCUMMVM website offered a pretty stupid option, working, but extremely slow. I'm still waiting IDADOS when it will be possible to watch the code in IDA and immediately trace the power of dosbox. But until then... ask IDA to search for a sequence of approximately 10 bytes, what we see in dosbox debuger.
This game turned out to be the formula:
the address in dosbox — 1DFFFE h = address in IDA.

At this point, I was aware of the exact offset of started blocks of fonts and their sizes. Began to look for these numbers in IDA with a simple search, but found nothing.
Then in dosbox debuger asked a interruption for the positioning of the pointer read (int 21h, ah=42h, LSEEK). Before calling in CX:DX must have a value how to move the pointer: (CX * 65536) + DX.

A few jumps found 2 consecutive call to read 2 fonts from the game, not just those that are used.
In DX it was I needed. Rewind back a little and found the initialization block font that looks like this:
mov eax, 6 ( eventually patched to mov eax, 3)
call InitFont
mov eax, 8
call InitFont

just in block 5 and 7 font. Having played different numbers, looked as unused fonts appear in the game:
image
image
image
image

Looked at block sizes of fonts, chose the biggest, moved to block a small font, patched the executable file made from BMP import of Russian letters (bmp 256 colors just one byte equals one pixel, the conversion of a byte in bits comes second), corrected indices, trekking, width and the length of the series, increased per unit height to the letters on the top and bottom are not merged and finally got the final font.
Kept the original symbols, numbers, letters, added a number of Russian letters, including Her.
image
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Car navigation in detail

PostgreSQL: Analytics for DBA

Google has launched an online training course advanced search