5.6 KiB
5.6 KiB
Давайте тщательно разберём функцию fade_calculation — это ключевая функция управления плавными переходами яркости в игре. Вот полный анализ:
Назначение функции
Функция вычисляет плавные цветовые переходы для эффектов затемнения/появления, используя:
- Временную синхронизацию (через VSync)
- Циклическую анимацию на основе волновой таблицы
- Аппаратный формат цвета PS1 (BGR555)
Структура данных (DWORD_8007caa8)
Глобальная структура с такими ключевыми полями:
| Смещение | Тип | Описание |
|---|---|---|
| +0x00 | uint | Флаг активности (param_1 & 1) |
| +0x04 | int | Предыдущий таймстамп VSync |
| +0x08 | int | Дельта времени между кадрами |
| +0x14 | int | Шаг анимации |
| +0x18 | int | Базовое смещение |
| +0x1c | uint | Текущее смещение анимации |
| +0x84 | int | Позиция в волновой таблице (0-63) |
| +0x88 | short[64] | Волновая таблица (амплитуды) |
| +0x126 | ushort | Результирующий цвет (BGR555) |
| +0x128 | byte | Множитель красного (R) |
| +0x129 | byte | Множитель зелёного (G) |
| +0x12a | byte | Множитель синего (B) |
Пошаговая работа функции
-
Синхронизация времени:
iVar2 = callVsyncWithParam(0xffffffff); // Получаем текущее время *(int *)(DWORD_8007caa8 + 8) = iVar2 - *(int *)(DWORD_8007caa8 + 4); // Дельта времени -
Обновление позиции анимации:
iVar8 = iVar8 + *(int *)(dVar1 + 8); // Увеличиваем позицию на дельту времени iVar8 = iVar8 + (iVar2 >> 6) * -0x40; // Обеспечиваем цикл 0-63 (64 позиции) *(int *)(dVar1 + 0x84) = iVar8; // Сохраняем новую позицию -
Расчёт компонент цвета: Для каждой RGB-компоненты:
- Берётся значение из волновой таблицы по текущей позиции
- Умножается на множитель (0x128-0x12a)
- Нормализуется сдвигом
>> 0xC(деление на 4096)
// Красная компонента (R) (uint)*(byte *)(dVar1 + 0x128) * (int)*(short *)(dVar1 + (iVar8 + ...) * 2 + 0x88) >> 0xc; // Зелёная (G) - со смещением +0x20 (uint)*(byte *)(dVar1 + 0x129) * (int)*(short *)(dVar1 + (iVar6 + ...) * 2 + 0x88) >> 0xc; // Синяя (B) (uint)*(byte *)(dVar1 + 0x12a) * (int)*(short *)(dVar1 + (iVar7 + ...) * 2 + 0x88) >> 0xc; -
Формирование цвета: Компоненты объединяются в формат BGR555 с битом прозрачности:
*(ushort *)(dVar1 + 0x126) = (R & 0x1F) | ((G & 0x1F) << 5) | ((B & 0x1F) << 10) | 0x8000; // Флаг прозрачности -
Копирование состояния:
// Копирует 32 байта из +0x108...+0x124 в +0x50...+0x6c *(undefined4 *)(dVar1 + 0x50) = *(undefined4 *)(dVar1 + 0x108); // ... и так для 8 полей ...
Особенности волновой таблицы
- Содержит 64 значения (short) по смещению
+0x88 - Значения обычно в диапазоне 0-4095 (для >> 0xC)
- Зелёная компонента использует смещение +32 (+0x20) для фазового сдвига
Как управлять эффектом?
-
Скорость анимации:
- Измените шаг в
*(int *)(dVar1 + 8) - Или модифицируйте дельту времени в
callVsyncWithParam
- Измените шаг в
-
Интенсивность:
// Увеличьте множители (по умолчанию 0-255): *(byte *)(dVar1 + 0x128) = 0xFF; // Максимальный красный -
Палитра: Подмените волновую таблицу:
*(short *)(dVar1 + 0x88 + i*2) = new_value;
Пример работы
sequenceDiagram
loop Каждый кадр
VSync->>+fade_calculation: Время
fade_calculation->>Волновая таблица: Чтение амплитуды
fade_calculation->>RGB: Расчёт компонент
fade_calculation->>BGR555: Упаковка цвета
fade_calculation->>OT: Запись команды
end
Функция — это сердце системы плавных переходов, где все вычисления оптимизированы под PS1. Для модификации эффектов работайте с волновой таблицей и цветовыми множителями.