Menu

ObjectCounter

Anonymous

Вступление

Игра обрабатывает различный код каждый кадр. (Поскольку идет в 60fps) Игровой цикл выглядит примерно так: Повторить:

jsr Обработать код объектов
jsr Обработать взаимодействия объектов
jsr Обработать другие вещи
jsr Обработать карту уровня
jsr Обработать спрайты объектов
tst ждать следующего кадра
jmp повторить

Коды связанные с объектами состоят из цикла , выполняемого 15 раз (поскольку у нас 15 слотов для объектов).

Начало цикла для спрайтов находится тут:

ROM $3063F:   BANK6:862F

Для счета текущего обрабатываемого объекта используются Y и $15 и $16 для хранения Y. То есть обработали один объект (выставили его спрайты), далее увеличиваем Y и $15 на 1, и так пока не достигнет $F. (завершаем цикл на 16-ом объекте так как у нас их всего 15-ть) Кроме того счетчик двух-направленный в зависимости от четности кадра. То есть в следующий раз счет пойдет не с первого по 15-ый объект, а с 15-ого по 1-ый. И на значении -1 завершится. Это сделано чтобы при лимите спрайтов обрабатывать объекты идущие в последних слотах, создает эффект мерцания спрайтов.

Баг: если лаг возникнет во время обработки этого цикла (то есть игра не успеет обработать весь нужный код за кадр), происходит запись неверного значения в память ячейку $15 (так как например $15 также используется во время опроса джойстиков)во время прерывания nmi и переключения кода в другое место рома (где и есть опрос джойстиков). После обработки его игра возвращается в исходное место и продолжит обрабатывать спрайты. В нормальных ситуациях когда игра всё оработала она сама ждет прерывания на следующий кадр. Это нормальная ситуация для всех игр, только тут ошибка состоит в том, что для счечтика взяли ячейку $15 которая используется и во время прерывания, и в результате лага значение $15 сбивается и цикл обработки спрайтов продолжится с неверным значением. В нормальных условиях значение должно быть от $00 до $0E. А после такого возврата после лага оно может быть любым хоть 20 хоть 66. И игра продолжит обработку спрайтов для несуществующих слотов объектов.

Отступление

Представим массив(таблицу) чисел созданную из 5-ти ячеек:

скорость
1
1
0
1
0

ускорение
5
0
5
5
5

поворот
2
2
0
0
2

Например машина #1 имеет параметры - 1/5/2 ; #2 - 1/0/2; Какие значения будут у машины #6? Мы ведь не вписывали ее в таблицу. Но данные в роме(или в памяти) то идут друг за другом и игре всё равно есть это или нет. 1 1 0 1 0 5 0 5 5 5 2 2 0 0 2 Поэтому для машины #6 возьмется цифра 5 (6-ая по счёту), далее 2, а третья вообще из следом идущих данных.

Детали

Теперь вернемся к жабам. Если значение счетчика сбилось мы продолжим обрабатывать несуществующие объекты: Например для объекта #17 - obj type id ($3C1) совпадет c $3D1 (player2_anim_frame); 03FD Objects_Xpos_L с 40D player2_Ypos_H; то есть для оработки спрайта объекта если надо считать его XposL для #17 она считается из ячейки 40D (player2Y). Вообщем для обработки спрайтов следующих объектов используются совершенно левые значения образуемые из последующих ячеек памяти.

Сам код вывода обработки спрайтов объекта состоит не только из чтения из нужных ячеек объектов LDA (координаты например) и запись в буфер спрайтов, но также и запись STA в некоторые ячейки. Причем есть как глобальные участки кода(для любых объектов), так и специфические для определенных. В частности для объекта tall walker (ходули), есть записи в ячейки:

STA     Objects_Z_floor,Y
STA     Objects_Y_shad,Y
STA     Objects_various_flags,Y
STA     Objects_Y_shad,Y

Для других объектов тоже могут быть записи в ячейки, да и в общем коде.(не изучалось пока)

В ситуации если значение объект-счетчика сбилось на #$3D, то

RAM:0475 Objects_Z_floor  475+3D = 4B2

а 4B2 это RAM:04B2 player2_state, то еcть запись

STA     Objects_Z_floor,Y, где Y =3d

запишет данные в ячейку 4b2 - в стейт флаги 2-ого объекта. А 5-ый бит стейта отвечает за наличие стика (палочки).

Теперь рассмотрим все условия именно этой комбинации:

  1. Должен возникнуть лаг и сбиться счечтик(так как лаг необязательно может пройти на этом месте, да и даже если в этом, не всегда - зависит от строчки).
  2. В завимости от четности кадра на число большее или меньшее чем #$3D. Так чтобы цикл обработался с этим числом.
  3. Рассмотренные STA идут только для объекта 'ходуля' (есть и другие - но не проверялись); поэтому перед выполнением этого участка кода вначале идет опроса кода на тип объекта:
    Узнаем тип объекта с номером #3D

    RAM:03C1 Objects_TypeID: . + 3D = равняется ячейка 3FE =

    RAM:03FE player2_Xpos_L:

То есть мы можем влиять на эту ячейку - меняя Xpos игрока мы и будем менять также ID объекта #3D. Нам нужно значение в этой ячейке = $11 или $12, для запуска кода спрайтов специфичного для Ходуль , где есть приведенные выше записи в в память STA. - В частности STA Objects_Z_floor,Y

BANK6:8659                 STY     tmp_var_16      ; slotID
BANK6:865B                 LDA     Objects_TypeID,Y


BANK6:8672                 CMP     #$11
BANK6:8674                 BEQ     loc_6000_86A2
BANK6:8676                 CMP     #$12
BANK6:8678                 BEQ     loc_6000_86A2

Кроме того STA (запись A) само число A должно оказаться любым чтобы создался стик - но так чтобы 05-ый бит в этом числе был равен 1. Вообщем тут 50/50 но на A косвенно влияют например $21 и $8D:

BANK6:89F0                 SBC     byte_0_21
BANK6:89F2                 SEC
BANK6:89F3                 SBC     #4
BANK6:89F5                 SBC     byte_0_8D
BANK6:89F7
BANK6:89F7 level4_stick_bug:                       ;  if Y = 3D
BANK6:89F7                 STA     Objects_Z_floor,Y

Таким образом происходит запись неверного числа в атрибут игрока и у него появляется в руках стик (палочка от ходули).

Это не единственный возможный баг из-за счетчика, так как возможны записи и в другие ячейки , и в эту же при других условиях - надо смотреть код, да и Y дает очень большой диапозон. Ведь он может сбится и продолжить обрабатывать сотню несуществующих слотов объектов. Другое дело что не все комбинации могут быть легко выполнены, а некоторые даже теоретически невыполнимы. Да и надо придумывать что кроме атрибут можно было бы полезным изменить. Но для начала надо научится вызывать лаг чтобы сбивать счечтик (на само число можно повлиять кнопками и в зависимости от четности кадра надо ставить число больше $F либо меньше $7F). А потом изучить все возможные STA.

Например для STA 0475 Objects_Z_floor, для счечтика от F до $7F возможны записи в ячейки - 475+F - 475+7F, дипозон 484-4F4. Только для Y отличного от 3D, для запуска этого кода ID считываться уже будет не с RAM:03FE player2_Xpos_L , а с 3С1+F - 3C1+7F, диапозон 3D0-440, то есть при 3d0=12 и Y =F возможна запис в 484. при 3d1=12 и y=10 возможна запись в 485 и т.д.

Ну и другие комбинации с STA/ ID. Для тех же ходуль есть еще записи в память, добавляем Y>F и смотрим куда записи пойдут.

STA     Objects_Y_shad,Y
STA     Objects_various_flags,Y

А для объекта номер 6 BANK6:867E CMP #6 есть запись например в :

BANK6:87EE                 STA     Objects_TargetID,Y

Related

Wiki: GlitchStick
Wiki: Glitch_List

MongoDB Logo MongoDB