Да, ваша структура `s_gamePad` вполне подходит для работы с геймпадами PlayStation 1, но требует некоторых доработок для корректной работы с PsyQ SDK. Вот полное решение: ### 1. Улучшенная структура геймпада ```c #include #include #pragma pack(push, 1) // Выравнивание 1 байт typedef struct { uint8_t stat; // 0x00 - статус (0 = данные готовы) union { struct { uint8_t recvSize:4; // Размер полученных данных (4/8 байт) uint8_t type:4; // Тип контроллера (4=Digital, 5=Analog) }; uint8_t bConfig; // Объединение для удобства доступа }; // Кнопки (битовая маска, 1=не нажата, 0=нажата) union { struct { uint16_t select:1; // 0x0001 uint16_t :1; // Не используется uint16_t :1; // Не используется uint16_t start:1; // 0x0008 uint16_t up:1; // 0x0010 uint16_t right:1; // 0x0020 uint16_t down:1; // 0x0040 uint16_t left:1; // 0x0080 uint16_t l2:1; // 0x0100 uint16_t r2:1; // 0x0200 uint16_t l1:1; // 0x0400 uint16_t r1:1; // 0x0800 uint16_t triangle:1; // 0x1000 uint16_t circle:1; // 0x2000 uint16_t cross:1; // 0x4000 uint16_t square:1; // 0x8000 }; uint16_t buttons; // Полное слово кнопок }; // Аналоговые данные (для DualShock) uint8_t rightJoyX; // 0x03 Правый джойстик X uint8_t rightJoyY; // 0x04 Правый джойстик Y uint8_t leftJoyX; // 0x05 Левый джойстик X uint8_t leftJoyY; // 0x06 Левый джойстик Y } s_gamePad; #pragma pack(pop) // Восстановление выравнивания static s_gamePad gamePads[2]; // Буферы для двух геймпадов ``` ### 2. Функция инициализации ```c #define PAD_BUFFER_SIZE 34 void GamePadInit(void) { static uint8_t padData[2][PAD_BUFFER_SIZE] __attribute__((aligned(64))); // Инициализация буферов PadInitDirect(padData[0], padData[1]); // Начало опроса геймпадов PadStartCom(); // Очистка структур memset(gamePads, 0, sizeof(gamePads)); } ``` ### 3. Функция чтения состояния ```c void GamePadRead(void) { // Чтение сырых данных uint8_t* padRaw = (uint8_t*)PadRead(0); // Чтение порта 0 // Копирование и преобразование данных memcpy(&gamePads[0], padRaw, sizeof(s_gamePad)); // Инвертирование битов кнопок (в оригинале 1=не нажата) gamePads[0].buttons ^= 0xFFFF; // Аналогично для второго геймпада (порт 1) padRaw = (uint8_t*)PadRead(1); memcpy(&gamePads[1], padRaw, sizeof(s_gamePad)); gamePads[1].buttons ^= 0xFFFF; } ``` ### 4. Пример использования ```c void Update(void) { GamePadRead(); if (gamePads[0].cross) { // Кнопка X нажата на первом геймпаде } if (gamePads[1].type == 5) { // Аналоговый геймпад int stickX = gamePads[1].leftJoyX - 128; // -128..127 } } ``` ### Ключевые особенности: 1. **Битовые поля** - Позволяют удобно обращаться к каждой кнопке 2. **Union** - Даёт доступ как к отдельным кнопкам, так и ко всему слову 3. **Аналоговые данные** - Поддержка DualShock 4. **Выравнивание** - `#pragma pack(push, 1)` гарантирует правильный layout структуры 5. **Инверсия битов** - В PS1 1=не нажато, поэтому делаем XOR ### Совместимость: - Работает с Digital (SCPH-1080) и Analog (SCPH-1150) контроллерами - Поддерживает DualShock (аналоговые стики) - Корректно работает с PsyQ SDK 4.7 и новее Такой подход более типобезопасен и удобен для чтения, чем оригинальный вариант с прямым доступом к памяти.