В PlayStation 1 (PS1) взаимодействие с контроллерами (геймпадами, мышками, световыми пистолетами и т.д.) осуществляется через **порты ввода-вывода (I/O)** и специализированные **контроллеры SIO (Serial Input/Output)**. Вот детальное объяснение процесса: --- ## **1. Аппаратная основа** ### **1.1. Порты контроллеров** - PS1 имеет **два порта** для подключения устройств (Multitap позволяет расширить до 4–8 игроков). - Каждый порт использует **протокол SPI** (Serial Peripheral Interface) для обмена данными. ### **1.2. Регистры управления** Основные регистры для работы с контроллерами: | Адрес | Назначение | |----------------|---------------------------------------------------------------------------| | **0x1F801040** | **SIO_DATA** — Данные для отправки/приёма. | | **0x1F801044** | **SIO_STAT** — Статус операции (готовность, ошибки). | | **0x1F801048** | **SIO_MODE** — Настройка режима (скорость, прерывания). | | **0x1F801050** | **SIO_CTRL** — Управление передачей (старт/стоп). | --- ## **2. Протокол обмена данными** ### **2.1. Формат команд** Контроллеры PS1 понимают **5-байтовые команды**: 1. **Стартовый байт** (`0x01`) — начало передачи. 2. **Команда** (например, `0x42` — запрос состояния кнопок). 3. **Данные** (зависит от типа устройства). ### **2.2. Пример запроса состояния кнопок** ```asm ; 1. Запись команды в SIO_DATA li t0, 0x1F801040 li t1, 0x01000042 // Старт (0x01) + команда (0x42) sw t1, 0(t0) ; 2. Ожидание готовности wait_ready: lw t2, 0x1F801044(SIO_STAT) andi t2, t2, 0x0002 // Проверка бита "Готов к передаче" beqz t2, wait_ready ; 3. Чтение ответа (5 байт) lw t3, 0x1F801040(SIO_DATA) // Первые 4 байта lw t4, 0x1F801040(SIO_DATA) // Последний байт ``` --- ## **3. Типы контроллеров и их ответы** ### **3.1. Стандартный геймпад (Digital Pad)** - **Команда**: `0x42`. - **Ответ**: 5 байт: ``` [0x41][0x5A][Кнопки 1][Кнопки 2][Аналоговые данные (если есть)] ``` - **Распаковка кнопок**: - Байт 3: `SELECT`, `L3`, `R3`, `START`, `UP`, `RIGHT`, `DOWN`, `LEFT`. - Байт 4: `L2`, `R2`, `L1`, `R1`, `TRIANGLE`, `CIRCLE`, `CROSS`, `SQUARE`. ### **3.2. Аналоговый джойстик (DualShock)** - Поддерживает **вибрацию** и **аналоговые стики**. - **Команды**: - `0x43` — запрос аналоговых данных. - `0x4D` — управление моторчиками. --- ## **4. Как игры обрабатывают ввод?** 1. **Инициализация порта**: ```c InitPad(1, 0, NULL, 0); // Порт 1, без буфера ``` 2. **Чтение состояния**: ```c struct PadButtonStatus pad; ReadPadStatus(&pad, 0); // Чтение порта 1 ``` 3. **Проверка кнопок**: ```c if (pad.buttons & PAD_CROSS) { // Кнопка CROSS нажата } ``` --- ## **5. Прерывания и синхронизация** - **Прерывание IRQ7** используется для обработки ввода. - Игры часто опрашивают контроллеры **во время VBlank**, чтобы избежать задержек. --- ## **6. Псевдокод полного цикла** ```c while (1) { VSync(0); // Синхронизация с кадром PollPad(); // Опрос контроллера if (PAD_PRESSED(PAD_UP)) { player_y--; } } ``` --- ## **7. Интересные нюансы** - **Light Gun** (GunCon) требует **строгой синхронизации** с лучом ЭЛТ. - **Multitap** усложняет протокол (нужно переключать устройства). --- ## **8. Полезные ссылки** - [PSX Controller Protocol](http://problemkaputt.de/psx-spx.htm#controllersandmemorycards) - [PsyQ SDK Pad Docs](http://psx.arthus.net/sdk/PsyQ/DOCS/PADZ.HTM) Это основа для работы с любыми контроллерами PS1 — от классического геймпада до танцевальных ковриков! 🎮