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