From 9913ce8b278ea1081269340cb4c50444ba979cbe Mon Sep 17 00:00:00 2001 From: sShemet Date: Sun, 20 Apr 2025 00:25:47 +0500 Subject: [PATCH] vault backup: 2025-04-20 00:25:47 --- .obsidian/workspace.json | 8 +- .../FUN_800453e0 SystemEventManager.md | 193 ++++++++++++++++++ PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md | 89 +++++++- 3 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 38ebbb6..f8925bc 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -41,12 +41,12 @@ "state": { "type": "markdown", "state": { - "file": "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md", + "file": "PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "FUN_80015674 Update Entity Stats" + "title": "PS1 Gamepad" } } ], @@ -207,8 +207,9 @@ }, "active": "dd912cc876184c4f", "lastOpenFiles": [ - "PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md", + "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md", "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md", + "PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md", "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80012df4 RenderInterface.md", "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80011f2c InitInterfaceManager.md", "PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md", @@ -242,7 +243,6 @@ "WORK & PROJECTS/Mol/Планы и диаграммы/00001_Редактор_форм/Архитектура редактора и генератора (Alfa + Mol).canvas", "WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud/Alfa cloud prod.canvas", "WORK & PROJECTS/Mol/Планы и диаграммы/00001_Быстрый старт/Быстрый старт.canvas", - "My/Diet 1.md", "My", "WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud", "Структура объектов испытаний.png", diff --git a/PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md b/PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md new file mode 100644 index 0000000..3baf636 --- /dev/null +++ b/PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md @@ -0,0 +1,193 @@ +Эта функция является **критически важным системным обработчиком ввода/вывода или управления состоянием** в игре для PS1. Вот детальный разбор: + +### 🔍 Основное назначение +Функция управляет: +1. **Очередью аппаратных событий** (контроллеры, таймеры, DMA) +2. **Синхронизацией игрового состояния** между различными подсистемами +3. **Обработкой ошибок** и аварийных сценариев + +### 📌 Полная реконструкция на C +```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 (звуковым процессором) + - Синхронизирует аудиопотоки + +### 📊 Структура данных +```c +// Пример системного состояния (0xF0 байт) +struct SystemState { + dword main_state; // 0x00: Основное состояние + byte sub_state[0x34]; // 0x04: Внутренние флаги + byte* data_buffer; // 0x38: Буфер данных + byte data_index; // 0x3C: Индекс в буфере + // ... другие поля ... +}; +``` + +Эта функция - критически важный системный компонент, обеспечивающий: +- Стабильную работу с аппаратурой PS1 +- Своевременную обработку событий +- Корректную синхронизацию подсистем игры \ No newline at end of file diff --git a/PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md index f7e6735..d794947 100644 --- a/PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md +++ b/PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md @@ -9,6 +9,7 @@ ### **1.2. Регистры управления** Основные регистры для работы с контроллерами: + | Адрес | Назначение | |----------------|---------------------------------------------------------------------------| | **0x1F801040** | **SIO_DATA** — Данные для отправки/приёма. | @@ -260,4 +261,90 @@ int main() { 3. Рекомендуется вызывать эту функцию один раз за кадр 4. В отличие от `PadRead()`, `PadChkVsync` не очищает буфер ввода -Функция `PadChkVsync` особенно полезна в играх, где важно точно определять момент подключения/отключения контроллеров во время gameplay, например, в multiplayer-играх с возможностью "hot-plug" контроллеров. \ No newline at end of file +Функция `PadChkVsync` особенно полезна в играх, где важно точно определять момент подключения/отключения контроллеров во время gameplay, например, в multiplayer-играх с возможностью "hot-plug" контроллеров. + +------- + + + +Да, функция **`PadInitDirect`** действительно существует в библиотеке PsyQ и является важной частью системы обработки ввода для PlayStation 1. Вот подробное объяснение: + +--- + +### 🔍 **Назначение PadInitDirect** +Функция **инициализирует систему обработки геймпадов** в режиме прямого доступа (Direct Access). Она: + +1. **Настраивает аппаратные порты контроллеров** (до 2-х геймпадов) +2. **Подготавливает буферы** для чтения состояния кнопок +3. **Активирует низкоуровневый доступ** к данным геймпадов +4. **Возвращает статус** инициализации (`1` = успех, `0` = ошибка) + +--- + +### 📜 **Синтаксис в PsyQ** +```c +#include + +int PadInitDirect(unsigned char *padBuf1, unsigned char *padBuf2); +``` +- **`padBuf1`** - буфер для геймпада на порту 1 (размер ≥ 34 байт) +- **`padBuf2`** - буфер для геймпада на порту 2 (может быть `NULL`) + +--- + +### 💻 **Пример использования** +```c +#define BUF_SIZE 34 + +int main() { + unsigned char pad1Buf[BUF_SIZE] __attribute__((aligned(64))); // Выравнивание для DMA + + if(PadInitDirect(pad1Buf, NULL)) { + printf("Геймпад 1 инициализирован!\n"); + } else { + printf("Ошибка инициализации!\n"); + return 1; + } + + // Далее можно использовать PadRead() +} +``` + +--- + +### 🔧 **Особенности работы** +1. **Требования к буферам**: + - Минимальный размер: **34 байта** + - Должны быть **64-байтно выровнены** (для DMA) + - Пример объявления: + ```c + unsigned char padBuf[34] __attribute__((aligned(64))); + ``` + +2. **Режимы работы**: + - Прямой доступ (`PadInitDirect`) - ручное управление + - Стандартный режим (`PadInit`) - автоматическое управление + +3. **Совместимость**: + - Поддерживает все типы контроллеров PS1: + - Обычные геймпады (Digital) + - Аналоговые джойстики (DualShock) + - Мышь PlayStation + +--- + +### ⚠️ **Важные нюансы** +1. **Перед использованием** необходимо вызвать `PadStartCom()` для начала обмена данными +2. **Для чтения** используется `PadRead()` после инициализации +3. **В мультиплеерных играх** нужно инициализировать оба порта: + ```c + PadInitDirect(pad1Buf, pad2Buf); + ``` + +--- + +### 📚 **Документация PsyQ** +В официальном **PsyQ SDK** функция описана в файлах: +- `libpad.h` - заголовочный файл +- `libpad.doc` - документация +- Примеры в `Samples/PAD` демонстрируют использование