Files
SergObsidian/PERSONAL PROJECTS/PS1 DMA.md
2025-04-18 22:00:49 +05:00

148 lines
7.6 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.

### **DMA (Direct Memory Access) в PlayStation 1**
DMA в PS1 — это механизм, позволяющий устройствам (GPU, CD-ROM, SPU и др.) **передавать данные напрямую в RAM без участия CPU**. Это ускоряет работу системы, освобождая процессор для других задач.
---
## **1. Для чего нужен DMA в PS1?**
- **Ускорение передачи данных**: CPU (R3000A) слишком медленный для копирования больших объёмов данных.
- **Разгрузка CPU**: Позволяет играм одновременно:
- Рендерить графику (GPU).
- Загружать уровни с CD-ROM.
- Проигрывать музыку (SPU).
- **Параллельная работа устройств**: Например, CD-ROM может грузить данные, пока GPU рисует кадр.
---
## **2. Как работает DMA?**
### **2.1. Общий принцип**
1. **CPU настраивает DMA**: Указывает источник, приёмник и размер данных.
2. **DMA-контроллер берёт управление шиной**: CPU временно "засыпает".
3. **Данные копируются напрямую** из устройства в RAM (или наоборот).
4. **DMA завершает работу** и сообщает CPU через прерывание.
### **2.2. Регистры DMA**
Главный контроллер DMA находится по адресу **`0x1F8010F0`**, но каждый канал имеет свои регистры:
| Адрес | Назначение |
|----------------|--------------------------------|
| `0x1F8010F0` | **DPCR** (Управление каналами) |
| `0x1F8010F4` | **DICR** (Статус/прерывания) |
| `0x1F8010__` | Регистры конкретных каналов |
---
## **3. Каналы DMA и их назначение**
В PS1 есть **6 каналов DMA**, каждый закреплён за конкретным устройством:
| Канал | Устройство | Назначение |
|-------|------------|----------------------------------------------------------------------------|
| **0** | MDEC (IN) | Декодирование видео (например, FMV из MPEG). |
| **1** | MDEC (OUT) | Вывод декодированных данных. |
| **2** | GPU | Передача команд и данных в видеопроцессор (например, списки отображения). |
| **3** | CD-ROM | Чтение данных с диска. |
| **4** | SPU | Загрузка семплов и команд в звуковой процессор. |
| **5** | PIO (EXT) | Расширенный порт (редко используется). |
| **6** | OTC | Очистка RAM (используется для Ordering Table в GPU). |
---
## **4. Как настроить и запустить DMA?**
### **4.1. Общий алгоритм**
Для любого канала DMA нужно:
1. **Установить источник и приёмник**:
- Если передача **из RAM в устройство** (например, GPU):
- Источник: Адрес в RAM.
- Приёмник: Регистр устройства (например, `0x1F801810` для GPU).
- Если передача **из устройства в RAM** (например, CD-ROM):
- Источник: Данные устройства (буфер CD-ROM).
- Приёмник: Адрес в RAM.
2. **Задать размер блока** и режим DMA:
- Размер: Сколько слов (4 байта) передать.
- Режим:
- `0x01000000` — одношаговый (по одному слову).
- `0x01000200` — пакетный (пачками, быстрее).
3. **Включить канал** через **DPCR** и **DICR**.
---
### **4.2. Примеры кода**
#### **Пример 1: Передача данных в GPU (канал 2)**
```asm
; Настройка DMA для GPU
li a0, 0x1F8010A0 ; Адрес регистра DMA2 (GPU)
la a1, command_list ; Адрес данных в RAM
sw a1, 0(a0) ; Источник = command_list
li a0, 0x1F8010A4
li a1, 0x01000200 ; Размер + режим (пакетный)
sw a1, 0(a0)
li a0, 0x1F8010A8
li a1, 0x01000001 ; Включить DMA
sw a1, 0(a0)
```
#### **Пример 2: Чтение CD-ROM (канал 3)**
```c
#include <libcd.h>
void cd_read_sectors(int lba, int num_sectors, void *buffer) {
CdRead(num_sectors, (CdlLOC*)&lba, CD_READ_SPEED, buffer);
CdReadSync(0); // Ожидать завершения DMA
}
```
---
## **5. Важные нюансы**
### **5.1. Синхронизация**
- DMA работает **асинхронно**. Нужно ждать завершения:
- Через **прерывание** (если настроено в DICR).
- Через **опрос флага** (например, `CdReadSync` для CD-ROM).
### **5.2. Ограничения**
- **Размер блока**: Не более 64 КБ за одну передачу.
- **Выравнивание**: Адреса в RAM должны быть кратны 4.
### **5.3. Конфликты**
- Если два устройства пытаются использовать DMA одновременно, возможны **задержки**.
- Решение: планировать передачу данных между кадрами (например, в VBlank).
---
## **6. DMA и Ordering Table (GPU)**
Для 3D-рендеринга DMA используется для передачи **Ordering Table** (OT):
1. CPU формирует список примитивов в RAM.
2. DMA (канал 2) копирует OT в GPU.
3. GPU рендерит кадр, соблюдая порядок из OT.
**Пример очистки OT через DMA (канал 6)**:
```asm
li a0, 0x1F8010E0 ; DMA6 (OTC)
la a1, ot_buffer ; Адрес OT
sw a1, 0(a0)
li a0, 0x1F8010E4
li a1, 0x00010000 ; Размер (например, 256 слов)
sw a1, 0(a0)
li a0, 0x1F8010E8
li a1, 0x11000002 ; Режим: очистка OT
sw a1, 0(a0)
```
---
## **7. Итог**
- **DMA в PS1** — это ключевой механизм для быстрой передачи данных между устройствами и RAM.
- **6 каналов**, каждый закреплён за конкретным устройством (GPU, CD-ROM, SPU и др.).
- **Настройка** требует указания источника, приёмника и режима работы.
- **Оптимизация DMA** критична для производительности (например, загрузка уровней без лагов).
Для глубокого понимания изучите:
- [PSX DMA Hardware Specs](http://problemkaputt.de/psx-spx.htm#dmacontroller)
- [PsyQ SDK Docs](http://psx.arthus.net/sdk/PsyQ/DOCS/)
Это основа для создания плавных игр вроде *Crash Bandicoot* или *Tekken 3*! 🚀