7.9 KiB
7.9 KiB
Эта функция является критически важным системным обработчиком ввода/вывода или управления состоянием в игре для PS1. Вот детальный разбор:
🔍 Основное назначение
Функция управляет:
- Очередью аппаратных событий (контроллеры, таймеры, DMA)
- Синхронизацией игрового состояния между различными подсистемами
- Обработкой ошибок и аварийных сценариев
📌 Полная реконструкция на 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);
// ... (аналогичная обработка аппаратного статуса)
}
🔧 Ключевые особенности
-
Управление состоянием:
- Использует конечный автомат с состояниями 0-4
- Обрабатывает как основные, так и вторичные события
-
Аппаратная синхронизация:
- Работает с регистрами PS1 (0x1F801xxx)
- Ожидает готовности аппаратуры через флаги
- Управляет таймерами (TMR_SYSCLOCK_VAL)
-
Обработка ошибок:
- Возвращает коды ошибок (-3 и другие)
- Проверяет статус после каждой операции
-
Оптимизации:
- Фиксированные смещения (0xF0 для блоков состояний)
- Пакетная обработка событий
🌟 Практическое применение
Эта функция может быть:
-
Драйвером контроллера:
- Обрабатывает ввод с геймпада
- Управляет вибрацией и другими эффектами
-
Менеджером DMA:
- Контролирует передачу данных
- Обрабатывает прерывания
-
Ядром аудиосистемы:
- Управляет SPU (звуковым процессором)
- Синхронизирует аудиопотоки
📊 Структура данных
// Пример системного состояния (0xF0 байт)
struct SystemState {
dword main_state; // 0x00: Основное состояние
byte sub_state[0x34]; // 0x04: Внутренние флаги
byte* data_buffer; // 0x38: Буфер данных
byte data_index; // 0x3C: Индекс в буфере
// ... другие поля ...
};
Эта функция - критически важный системный компонент, обеспечивающий:
- Стабильную работу с аппаратурой PS1
- Своевременную обработку событий
- Корректную синхронизацию подсистем игры