Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/PSX code Gamepad code.md
2025-04-20 14:00:47 +05:00

119 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Да, ваша структура `s_gamePad` вполне подходит для работы с геймпадами PlayStation 1, но требует некоторых доработок для корректной работы с PsyQ SDK. Вот полное решение:
### 1. Улучшенная структура геймпада
```c
#include <sys/types.h>
#include <psxpad.h>
#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 и новее
Такой подход более типобезопасен и удобен для чтения, чем оригинальный вариант с прямым доступом к памяти.