Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/fade calculation.md
2025-04-19 03:02:43 +05:00

5.6 KiB
Raw Blame History

Давайте тщательно разберём функцию 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. Синхронизация времени:

    iVar2 = callVsyncWithParam(0xffffffff); // Получаем текущее время
    *(int *)(DWORD_8007caa8 + 8) = iVar2 - *(int *)(DWORD_8007caa8 + 4); // Дельта времени
    
  2. Обновление позиции анимации:

    iVar8 = iVar8 + *(int *)(dVar1 + 8); // Увеличиваем позицию на дельту времени
    iVar8 = iVar8 + (iVar2 >> 6) * -0x40; // Обеспечиваем цикл 0-63 (64 позиции)
    *(int *)(dVar1 + 0x84) = iVar8; // Сохраняем новую позицию
    
  3. Расчёт компонент цвета: Для каждой 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;
    
  4. Формирование цвета: Компоненты объединяются в формат BGR555 с битом прозрачности:

    *(ushort *)(dVar1 + 0x126) = 
        (R & 0x1F) | 
        ((G & 0x1F) << 5) | 
        ((B & 0x1F) << 10) | 
        0x8000; // Флаг прозрачности
    
  5. Копирование состояния:

    // Копирует 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. Интенсивность:

    // Увеличьте множители (по умолчанию 0-255):
    *(byte *)(dVar1 + 0x128) = 0xFF; // Максимальный красный
    
  3. Палитра: Подмените волновую таблицу:

    *(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. Для модификации эффектов работайте с волновой таблицей и цветовыми множителями.