Known Errors

Исходный текст программы был взят с сервера компании ID Software ftp://ftp.idsoftware.com.

The source code was taken from ID Software ftp site ftp://ftp.idsoftware.com.

Программа не свободна от ошибок.

This program has some number of errors.

Некоторые ошибки в PC весии программы, найденные хакерами, используются для создания спец-эффектов в разрабатываемых дополнительных сценариях. Например, одна из ошибок приводит к тому, что враги могут передвигаться внутри стен и неожиданно выходить из них на игровое поле!

Hackers use some errors in PC version of Wolf3d and Spear of Destiny for unusual effects creation in new scenario design. One of such error leads to enemy appearance directly from the wall!

Известно, что реакцией UNIX на события Bus Error и Segmentation Fault, связанные с неправильной адресацией, является сброс образа памяти процесса core и завершение задачи. Например, при попытке записи данных по нулевому адресу программа для Solaris завершается аварийно, в то время, как программа MSDOS сможет произвести запись и продолжит выполнение. Будет ли далее программа MSDOS выполняться правильно - предсказать трудно.

As you know, UNIX reaction for such events, related with wrong addressing, like Bus Error and Segmentation Fault is core dump and end of task. E.g. if program tries to write at address 0, it completes abnormally in Solaris, and will continue to go under MSDOS. Will MSDOS program run stable after that is not predictable.

Файлы сценариев, разработанные для коммерческих версий игр фирмой ID Software не содержат условий для проявления действия ошибок, т.к. они разрабатывались и тестировались совместно с исходным кодом программы.

It is not surprise that there are no conditions for error's results appearance in scenarios which was developed for commercial versions of games. All these scenarios was developed simultaneously with source code debugging.

Но одна ошибка осталась незамеченной.

But one error was missing.


Ошибка в функции CloseDoor()

Error in CloseDoor() function

В функции CloseDoor() (файл wl_act1.c) несколько раз повторяется следующий фрагмент с небольшими вариациями:

Function CloseDoor() (in wl_act1.c file) has the following fragment of code which repeats with slight differences:

        check = actorat[tilex - 1][tiley];
        if (check && ((check->x + MINDIST) >> TILESHIFT) == tilex) return;

Массив actorat служит для хранения многообразной информации, а не только адресов объектов - игроков. В частности, там находится информация о "дверях", представляющая собой небольшое число со значением заведомо меньшим, чем любой адрес в программе. Так, в конце функции CloseDoor() можно увидеть пример занесения в массив actorat такой информации:

Array "actorat" is used as storage for various type of information, not only objects addresses (object is enemy describing structure). In particular, it contains dynamic information about "doors" state. This is small number which is less that any address value. At the end of CloseDoor() function you can see how this information looks like:

//
// make the door space solid
//
        (unsigned) actorat[tilex][tiley] = door | 0x80;

Попытка использовать check в качестве указателя без дополнительной проверки приведёт к завершению работы программы Solaris и сбросу "core". Программа MSDOS будет продолжать выполняться, однако решение может быть принято неверное.

When you try to use "check" as a pointer you can obtain "core" under Solaris. PC version of program will use random data as checking result, and will have wrong behavior, but will continue.

Эта ошибка проявляется в wolf3d (Wolf5 Map 1). В этом сценарии имеется четыре двери, расположенные на соседних квадратах по одной горизонтальной прямой (9,57), (10,57), (11,57), (12,57). При закрытии двери проверяются смежные квадраты по горизонтали на наличие препятствующих закрытию двери причин. В этот момент и возникает ошибка.

This error exists in wolf3d (Wolf5 Map 1). There are four doors at adjacent horizontal quads (9,57), (10,57), (11,57), (12,57). When one of doors is closing, program checks two adjacent horizontal quad to know is there something which will prevent door's closing. Error will arise in this moment.

Её можно исправить, введя дополнительную проверку:

You can fix it by additional checking:

        check = actorat[tilex - 1][tiley];
        if ((uint_t) check >= MAXTILE &&
                ((check->x + MINDIST) >> TILESHIFT) == tilex) return;

Ошибка в функции VictorySpin() в программе wolf3d

Error in VictorySpin() function in wolf3d program

Ещё одна ошибка в программе wolf3d связана с триггером EndGame.

One more error in wolf3d relates with EndGame trigger.

При попадании на поле, помеченное признаком EndGame объект player раздваивается. Старый объект player начинается двигаться на север по программной траектории, формируемой в функции VictorySpin (wl_agent.c) и становится "камерой" показывающей движение порождённого объекта (SPR_BJ_*), который также движется на север.

When player object reaches spot with EndGame property, it will divide into two. Old player object will start to move toward north, along path, which is formed in VictorySpin (wl_agent.c) function, and will become "camera". This "camera" will show moving of engended object (SPR_BJ_*), which also will move toward north.

Ошибка происходит из-за того, что программная траектория для движения "камеры" по оси Y задаётся очень жёстко, а само движение "камеры" контролируется упрощённым образом. Если к северу от триггера EndGame меньше пяти свободных квадратов или "камера" имеет горизонтальную составляющую скорости и, при этом, находится слишком близко к вертикальной стене, то она может попасть внутрь стены.

The source of error is program trajectory algorithm.

В результате возникнет событие Segmentation Fault и сброс core.

As a result, Segmentation Fault and core dumped will arise.

В коммерческой версии программы файл MAPHEAD.WL6 сконструирован таким образом, что ошибка не проявляется. В файлах, разработанных пользователями, условия для возникновения ошибок встречаются очень часто.

Commercial version of MAPHEAD.WL6 was designed in such a way, that this error will not arise. In files, which was developed by users, such kind of errors can present.

Функция VictorySpin должна выглядеть следующим образом:

VictorySpin function must looks like:

void VictorySpin(void)
{
    long desty, y;
    int tilex, tiley;

    if (player->angle > 270) {
	player->angle -= tics * 3;
	if (player->angle < 270)
	    player->angle = 270;
    } else if (player->angle < 270) {
	player->angle += tics * 3;
	if (player->angle > 270)
	    player->angle = 270;
    }

    desty = ((long) player->tiley - 5) << TILESHIFT;

    y = player->y;

    if (player->y > desty) {
	player->y -= tics * 4096;
	if (player->y < desty)
	    player->y = desty;
    }

    tilex = player->x >> TILESHIFT;
    tiley = player->y >> TILESHIFT;

    player->x = (player->tilex << TILESHIFT) + TILEGLOBAL / 2;

    if (MAPSPOT(tilex, tiley, 0) < MAXWALLTILES) {
	player->y = y;
	if ((uint_t) actorat[tilex][tiley + 1] > MAXTILE)
	    playstate = ex_victorious;
    }
}

Продолжение следует...

To be continued...


Copyright © 2001, Vitaly Filatov, Moscow, Russia
Webmaster