Files
SergObsidian/PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md
2025-04-20 00:25:47 +05:00

7.9 KiB
Raw Blame History

Эта функция является критически важным системным обработчиком ввода/вывода или управления состоянием в игре для PS1. Вот детальный разбор:

🔍 Основное назначение

Функция управляет:

  1. Очередью аппаратных событий (контроллеры, таймеры, DMA)
  2. Синхронизацией игрового состояния между различными подсистемами
  3. Обработкой ошибок и аварийных сценариев

📌 Полная реконструкция на C

#define HW_REG_BASE 0x1F801000 // Базовый адрес аппаратных регистров PS1

int SystemEventManager(int system_state) 
{
    // 1. Проверка условий для обработки основного события
    if (gSystemActive && 
        !system_state[0x37] && 
        !system_state[0x38] && 
        (system_state == *(int*)(system_state + 0x10) || !system_state[0x39]) &&
        !**(char**)(system_state + 0x30)) 
    {
        gEventCallback(system_state); // Обработка события
    }

    // 2. Главный цикл обработки событий
    int retry_count = -1;
    if (gSystemActive) 
    {
        int offset = -0xF0;
        do {
            gEventCounter--;
            if (gEventCounter < 1) break;

            // Проверка вторичных условий
            if (retry_count >= 0) 
            {
                int secondary_state = *(int*)(system_state + 0xC) + offset;
                if (!secondary_state[0x37] && 
                    !secondary_state[0x38] &&
                    (secondary_state == *(int*)(secondary_state + 0x10) || !secondary_state[0x39]) &&
                    !**(char**)(secondary_state + 0x30)) 
                {
                    gEventCallback(secondary_state);
                }
            }

            // Обработка аппаратного события
            byte event_type = GetHardwareEvent(system_state, 1);
            int status = ProcessHardwareEvent(system_state, event_type);
            if (status < 0) return status;

            // Ожидание готовности аппаратуры
            uint16_t* hw_status = (uint16_t*)(gHardwareRegs + 4);
            TIMER_CLOCK = GetSystemClock();
            *gControlReg = 0xFFFFFF7F;
            HW_TIMEOUT = 60;

            while (*hw_status & 0x80) {
                status = CheckHardwareReady();
                if (status != 0) goto next_event;
                hw_status = (uint16_t*)(gHardwareRegs + 4);
            }

            *hw_status |= 0x10; // Установка флага готовности
            retry_count++;
            offset += 0xF0;
        } while (retry_count < 4);
    }

    // 3. Управление состоянием системы
    int state_index = 0;
    if (gEventCounter > 1) 
    {
        dword* state_ptr = &gSystemStates[gActiveSubsystem == 0];
        int subsystem_offset = (gActiveSubsystem == 0) ? 0xF0 : 0;

        do {
            dword current_state = *state_ptr;
            if ((int)current_state < 0) break;

            if (current_state > 0) {
                int target_state = *(int*)(gStateBuffer + subsystem_offset + 0xC) + (current_state - 1) * 0xF0;
                gStateCallback(target_state);
            }

            // Конечный автомат состояний
            switch(current_state) {
                case 3:
                    gStateCallback(target_state - 0xF0);
                    *state_ptr = 1;
                    break;
                case 1:
                case 2:
                    int base_state = gStateBuffer + subsystem_offset;
                    gStateCallback(base_state);
                    gSecondaryCallback(base_state);
                    *state_ptr = -1;
                    break;
                case 4:
                    *state_ptr = 3;
                    break;
            }

            // Дополнительная обработка
            event_type = GetHardwareEvent(system_state, gSystemActive);
            status = ProcessSecondaryEvent(system_state, event_type);
            if (status < 0) return status;

            // Повторная проверка аппаратуры
            hw_status = (uint16_t*)(gHardwareRegs + 4);
            TIMER_CLOCK = GetSystemClock();
            *gControlReg = 0xFFFFFF7F;
            HW_TIMEOUT = 60;

            while (*hw_status & 0x80) {
                status = CheckHardwareReady();
                if (status != 0) goto event_processed;
                hw_status = (uint16_t*)(gHardwareRegs + 4);
            }

            *hw_status |= 0x10;
            gEventCounter--;
        } while (gEventCounter > 1);
    }

    // 4. Финальная стадия обработки
    do {
        gEventCounter--;
        if (gEventCounter < 1) {
            while (!(*(uint16_t*)(gHardwareRegs + 4) & 2)); // Ожидание завершения
            byte* data_ptr = *(byte**)(system_state + 0x3C);
            data_ptr[*(byte*)(system_state + 0x44)++] = *(byte*)gHardwareRegs;
            gCompletionCallback(0);
            return 0;
        }

        event_type = GetHardwareEvent(system_state, gSystemActive);
        status = ProcessSecondaryEvent(system_state, event_type);
        if (status < 0) return status;
    } while (*(short*)(gHardwareRegs + 0xE) != 0x22);

    // ... (аналогичная обработка аппаратного статуса)
}

🔧 Ключевые особенности

  1. Управление состоянием:

    • Использует конечный автомат с состояниями 0-4
    • Обрабатывает как основные, так и вторичные события
  2. Аппаратная синхронизация:

    • Работает с регистрами PS1 (0x1F801xxx)
    • Ожидает готовности аппаратуры через флаги
    • Управляет таймерами (TMR_SYSCLOCK_VAL)
  3. Обработка ошибок:

    • Возвращает коды ошибок (-3 и другие)
    • Проверяет статус после каждой операции
  4. Оптимизации:

    • Фиксированные смещения (0xF0 для блоков состояний)
    • Пакетная обработка событий

🌟 Практическое применение

Эта функция может быть:

  1. Драйвером контроллера:

    • Обрабатывает ввод с геймпада
    • Управляет вибрацией и другими эффектами
  2. Менеджером DMA:

    • Контролирует передачу данных
    • Обрабатывает прерывания
  3. Ядром аудиосистемы:

    • Управляет SPU (звуковым процессором)
    • Синхронизирует аудиопотоки

📊 Структура данных

// Пример системного состояния (0xF0 байт)
struct SystemState {
    dword main_state;      // 0x00: Основное состояние
    byte sub_state[0x34];  // 0x04: Внутренние флаги
    byte* data_buffer;     // 0x38: Буфер данных
    byte data_index;       // 0x3C: Индекс в буфере
    // ... другие поля ...
};

Эта функция - критически важный системный компонент, обеспечивающий:

  • Стабильную работу с аппаратурой PS1
  • Своевременную обработку событий
  • Корректную синхронизацию подсистем игры