6.8 KiB
6.8 KiB
В PlayStation 1 (PS1) чтение данных с CD-ROM действительно использует DMA (Direct Memory Access), но с рядом особенностей, связанных с устройством привода и буферизацией. Разберём процесс детально.
1. Как устроено чтение с CD-ROM в PS1?
CD-ROM в PS1 работает через специализированный контроллер, который управляет:
- Механизмом привода (позиционирование головки).
- Декодированием данных (коррекция ошибок, деинтерливинг).
- Передачей данных в RAM через DMA.
1.1. Основные шаги чтения:
- Запрос сектора: CPU указывает номер сектора (LBA — Logical Block Address).
- Поиск и чтение: Привод физически находит сектор на диске.
- Декодирование: Данные проходят через:
- CIRC (Cross-Interleaved Reed-Solomon Code) — исправление ошибок.
- EDC/ECC (Error Detection/Correction) — проверка целостности.
- Буферизация: Данные временно хранятся в буфере CD-ROM (32 КБ).
- Передача в RAM: Через DMA-канал CDROM (канал 3).
2. Роль DMA в чтении CD-ROM
2.1. DMA-канал CD-ROM
- Канал 3 выделен специально для CD-ROM.
- Режимы передачи:
- Пакетный (Burst): Чтение нескольких секторов подряд (быстрее).
- Пошаговый (Single): Чтение по одному сектору (точнее).
2.2. Как CPU запускает DMA?
-
Настройка DMA:
- Указывается адрес в RAM (куда копировать).
- Задаётся размер блока (обычно 2048 байт на сектор).
- Выбирается режим (например,
DMA_CDROM_READ).
-
Запуск чтения:
// Пример на PsyQ SDK CdReadSector(1, 16, buffer); // Читать 16 секторов, начиная с LBA 1 CdReadSync(0); // Ожидать завершения -
Автоматическая передача:
- DMA забирает данные из буфера CD-ROM и копирует в RAM без участия CPU.
3. Технические детали
3.1. Размеры и форматы секторов
- Режим 1 (стандартный):
- 2048 байт полезных данных.
- Используется для игр (например,
DATA.BIN).
- Режим 2 (XA):
- 2336 байт (включая аудио/видео).
- Поддерживает ADPCM-аудио (например, CD-DA треки).
3.2. Буферизация и кэширование
- Буфер CD-ROM (32 КБ):
- Хранит до 16 секторов (Mode 1).
- DMA читает отсюда, пока привод ищет следующий сектор.
- Программный кэш:
- Многие игры кэшируют часто используемые данные в RAM (например, уровни).
4. Пример кода (PsyQ SDK)
4.1. Чтение одного сектора
#include <libcd.h>
void read_sector() {
uint8_t buffer[2048]; // Буфер в RAM
CdlLOC loc; // Позиция на диске (LBA)
// Преобразуем LBA в формат MSF (Minutes:Seconds:Frames)
CdIntToPos(1, &loc); // LBA 1 → 00:02:00
// Запуск чтения
CdRead(1, &loc, CD_READ_SPEED, buffer);
CdReadSync(0); // Ждём завершения DMA
}
4.2. Чтение нескольких секторов с DMA
#define SECTORS_TO_READ 10
void read_multiple_sectors() {
uint8_t big_buffer[2048 * SECTORS_TO_READ];
CdRead(SECTORS_TO_READ, (CdlLOC*)0, CD_READ_SPEED, big_buffer);
// Проверяем статус DMA
while (CdReadSync(1) == 0) {
VSync(0); // Ожидание + синхронизация с кадром
}
}
5. Оптимизации и проблемы
5.1. Задержки
- Seek Time: Привод тратит 100–300 мс на поиск сектора.
- Решение: Чтение последовательных секторов (меньше скачков головки).
5.2. Ошибки чтения
- CRC-проверка: Если данные повреждены, PS1 повторяет чтение.
- Метки защиты: Лицензионные диски имеют специальные метки (anti-piracy).
5.3. Потоковое чтение
- Игры с FMV (например, Metal Gear Solid) используют двойную буферизацию:
- Пока DMA передаёт один буфер в RAM, CD-ROM заполняет второй.
6. Как DMA взаимодействует с CD-ROM?
- CPU отправляет команду
CdRead(). - CD-ROM контроллер начинает чтение в свой буфер.
- DMA-контроллер (канал 3) забирает данные из буфера CD-ROM и копирует в RAM.
- Прерывание (
INT2) сигнализирует о завершении.
7. Полезные регистры
| Адрес | Назначение |
|---|---|
0x1F8010B0 |
DMA CD-ROM Control (канал 3) |
0x1F801800 |
CD-ROM Command/Status |
0x1F801802 |
CD-ROM Response FIFO |
Итог
- DMA (канал 3) используется для чтения данных с CD-ROM в RAM.
- Буфер CD-ROM (32 КБ) снижает нагрузку на привод.
- Оптимизации: Чтение последовательных секторов, кэширование.
- Задержки неизбежны из-за механического характера привода.
Для глубокого понимания изучите:
Это ключ к работе с дисками в стиле Resident Evil или Final Fantasy VII! 📀