Исходный текст программы был взят с сервера компании 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...
|
|