Pull to refresh

Программирование для PlayStation 2: CD(DVD)-ROM Library — часть первая

Reading time7 min
Views5.4K
image

1. Прошу прощения, что долго не писал.
2. Готов PS2 SDK.

Я хотел не упускать CD(DVD)-ROM Library, поэтому ссылки и гайд по установке PS2 SDK вы найдете в конце второй части этой статьи.
Тема достаточно сложная. Также буду благодарен, если кто-нибудь перельет на другой не платный хостинг PS2 SDK.
PS2 SDK доступен тут. Narod.ru.
Магнет (ссылка нормально не вставляется благодаря хабра-парсеру): magnet:?xt=urn:btih:F6114E45C5E392E6D213F2547C466FADB5DA5A13&dn=sce.zip&tr=udp%3a//tracker.openbittorrent.com%3a80/announce
Еще одна ссылка. Спасибо Konstantinus и ahmpro



CD(DVD)-ROM Library.



Для работы с приводом используются одновременно и IOP, и EE.
Библиотека, отвечающая за работу с приводом называется «libcdvd» (именно так).

Библиотека EE для подключения: «libcdvd.a».
Заголовочный файл: «libcdvd.h».
Библиотека IOP для подключения: «cdvdman.ilb».
Модули IOP: «cdvdman.irx» и «cdvdfsv.irx».

Сектора



Нормальный размер сектора для чтения данных представляет собой 2048 байт для DVD.
Для них существует единственный режим.
Ну, и стандартный размер для CD дисков (также 2048). Однако сектор может быть другим размером, но, на данный момент, это не имеет значения.

Скорость вращения и передача данных



PS2 использует метод CAV, таким образом, скорость диска сохраняется и является константой. Таким образом, скорость чтения данных будет разной на внешних и внутренних дорожках.
  • CD, внутренние дорожки – 10 скорость = 1500 КБ/с.
  • CD, внешние дорожки – 24 скорость = 3600 КБ/с.
  • DVD, внутренние дорожки – 1,6 скорость = 2000 КБ/с.
  • DVD, внешние дорожки – 4 скорость = 5000 КБ/с.


Как ни странно, скоростью вращения можно управлять следующими тремя способами:
— Использование потокового режима (SCECdSpinStm): частота вращения регулируется таким способом, что чтение может быть выполнено надежно при постоянной скорости передачи данных.
— Обычный режим данных (SCECdSpinNom): в начале будет сделана попытка чтения на максимальной скорости и, при ошибке чтения, скорость будет снижена до той, на которой чтение будет нормальным.
— Режим двухслойного диска (SCECdSpinDvdDL0): тоже самое, что и потоковый режим, только для двухслойного диска. Скорость считывается из нулевой дорожки.

Файловая система



Файловая система используется по формату ISO-9660.
Присутствуют ограничение на количество файлов и каталогов, однако, оно может быть увеличено за счет количества букв в именах файлов и папок.

Количество директорий в папке: 40.
Максимальный уровень вложенности: 8.
Количество файлов в директории: 30.
Имена файлов и папок должны состоять только из цифр, букв английского алфавита и подчеркивания. Все имена папок и файлов должны быть исключительно в верхнем регистре.
Название файла может включать в себя не больше 8 символов в имени файла и 3 символов в расширении.
Название папки может включать в себя не больше 8 символов.

Работа с диском



Для чтения диска требуется получить к нему доступ и указать режим.
После процессор проверяет его на легальность. =)
Потом вам снова требуется получить к нему доступ.
После инициализации программы требуется инициализировать дисковод функцией sceCdInit().
Функция sceCdInit принимает один из следующих параметров:
  • SCECdINIT – инициализация библиотеки, блокировка доступа и ожидание следующей команды.
  • SCECdINoD – только инициализация.
  • SCECdEXIT – закрытие библиотеки.

Функция возвращает число: 0 – инициализация не получилась, 1 – инициализация прошла нормально, 2 – инициализация уже была выполнена.

После этого требуется указать режим работы с дисководом функцией sceCdMmode(), который принимает один из двух параметров SCECdCD или SCECdDVD для CD и DVD дисков, соответственно. Возвращает 1 или 0, что соответствует получилось или нет.

Пример:

int main(){
  sceSifInitRpc(0);
  sceCdInit(SCECdINIT); /* Требуется после страта с CD/DVD */
  sceCdMmode(SCECdCD); /* Тип диска = CD-ROM */
  /* Замена модуля по умолчанию */
  while ( !sceSifRebootIop(IOPRP) );
  while( !sceSifSyncIop() );
  /* Инициализируем заного */
  sceSifInitRpc(0);
  sceCdInit(SCECdINIT);
  sceCdMmode(SCECdCD); /* Тип диска = CD-ROM */
  sceFsReset();
  /* последующий код… */

* This source code was highlighted with Source Code Highlighter.


Чтение файлов



Для чтения файла требуется вначале выяснить на каком секторе он находится.
Для этого существует функция sceCdSearchFile(), которая принимает следующие аргументы:
  • Указатель на файловую структуру привода (тип sceCdIFILE). В нем хранится LSN (logical sector number) и размер файла после работы функции.
  • Абсолютный путь к файлу с именем и расширением.

Возвращает 0 или 1, что означает файл не найден или найден, соответственно.

Т.е. примерно будет так: ret = sceCdSearchFile(&fp, "\\SYSTEM.CNF");

Эта информация кэшируется.

Для чтения файла существует функция sceCdRead(), которая принимает следующие параметры: LSN, количество секторов для чтения, буфер для чтения, тип чтения.
Требуется помнить, что функция не блокирующая, поэтому узнать о том, что передача данных закончена можно с помощью функции sceCdSync().

Функция sceCdSync() принимает один параметр, который может быт двух видов:
  • 0х00 – заблокирует поток до окончания работы команды. В этом случае функция вернет 0 после завершения.
  • 0х01 – проверит статус и вернет результат, не блокируя поток. В этом случае функция вернет 0 или 1.


Для того, чтобы указать какой вы используете тип чтения есть функция sceCdRMode(), которая принимает следующие параметры:
  • u_char – (от 0 до 255) количество повторов чтения до объявления ошибки чтения.
  • u_char – скорость вращения диска. Один из вариантов:
    • SCECdSpinStm – рекомендованная скорость;
    • SCECdSpinNom – начинать чтения диска с максимальной скорости и опуститься до той, на которой можно нормально читать.
    • SCECdSpinDvdDL0 – режим чтения двухслойных дисков.
  • u_char – размер сектора. Вид параметра только один: SCECdSecS2048, т.е. размер 2048 бит.
  • u_char – заполненные данные для выравнивания.


Данные для выравнивания служат для того, чтобы функция всегда занимала один и тот же размер памяти.

Также существует функция, через которую можно узнать о типе произошедшей ошибки —
sceCdGetError().
Возвращает тип ошибки или SCECdErNO, если ошибок не было.

Использование Callback



Вместо ожидания можно использовать функции обратного вызова. Назначаются они с помощью функции sceCdCallback(). Принимает параметром она указатель на адрес функции. Нужно учитывать, что функция вызывается независимо от того, какая асинхронная функция закончилась. Однако код причины вызова функции передается в первом параметре.
Нельзя назначать функцию во время исполнения вызванной функции кэлбака (извините за тавтологию).
Если вместо параметра передать 0, то кэлбэк будет снят.

Параметр, передаваемый в функцию от кэлбека может принимать следующие значения:
  • SCECdFuncRead – говорит о том, что закончила работу функция sceCdRead()
  • SCECdFuncSeek – закончила работу функция sceCdSeek();
  • SCECdFuncStandby – закончила работу функция sceCdStandby();
  • SCECdFuncStop – закончила работу функция sceCdStop();
  • SCECdFuncPause – закончила работу функция sceCdPause().


Нельзя назначать кэлбэком функции, типа sceCdRead();
Функция возвращает 0 или адрес на предыдущий кэлбэк.

Потоковое чтение



Для потокового чтения требуется использовать IOP память. Для использования потокового чтения требуется подключить модуль cdvdstm.irx через функцию sceSifLoadModule().

Поток загружается в память IOP и оттуда можно читать данные.

Следующие функции используются для потокового чтения.

sceCdStInit() – инициализация потока и установка буфера.
Параметры:
— емкость потока (определяется с помощью количества секторов по 2048 байт).
— количество частей потока (по спецификации — колец). Буфер с 3 или более частей должен иметь емкость более 16 секторов.
— адрес потока в памяти.
Для получения местоположения в памяти IOP требуется использовать функцию sceSifAllocIopHeap() из EE Kernel.
Функция возвращает 0 или 1, что равно False или True.

sceCdStStart() – запуск потокового заполнения.
Параметры:
— позиция для старта чтения с диска. Используется LSN.
— тип чтения, полученный через sceCdRMode().
Возвращает то же что и предыдущая.

sceCdStRead() – чтение данных из потока.
Параметры:
— количество секторов для чтения из буфера.
— адрес для чтения данных (должен быть выровнен до 64 байт).
— тип чтения: STMNBLK – вернет ту информацию, что есть в буфере; STMBLK – вернет данные, чт есть или ошибку.
— переменная для номера ошибки.
Возвращает количество прочитанных секторов.

Номера ошибок могут быть следующие:
  • 0x00 = SCECdErNO – ошибок нет.
  • 0x01 = SCECdErABRT – возвращена команда прекращения.
  • 0x13 = SCECdErNORDY – блок не прочитан.
  • 0х14 = SCECdErCUD – метод чтения не подходит для диска в приводе.
  • 0х20 = SCECdErIPI – ненормальное положение сектора.
  • 0х21 = SCECdErRILI – ненормальное количество секторов для чтения.
  • 0х30 = SCECdErREAD – проблемы при чтении с диска.
  • 0х31 = SCECdErTRMOPN – открылась крышка во время чтения.


sceCdStPause() – пауза потокового заполнения.
Параметров нет. Возвращает успешность операции в виде 0 или 1.

sceCdStResume() – возвращение потокового заполнения.
Параметров нет. Возвращает успешность операции.

sceCdStSeek() – смена позиции для чтения потока.
Параметром принимает LSN. Возвращает успешность операции.

sceCdStStat() – получить статус чтения потока в буфер.
Параметров нет. Возвращает 0 в случае ошибки или количество прочитанных секторов.

sceCdStStop() – остановка заполнения статуса потоком
Параметров нет. Возвращает успешность операции.

После вызова sceCdStInit() и выполнение инициализации вызова sceCdStStart() данные будут считываться в фоновом режиме, начиная с указанного сектора, и сохранять их в буфере. После того, как выполняется sceCdStRead(), данные в буфере могут быть прочитаны последовательно.
Обратите внимание, что следующие libcdvd функции не могут быть использованы для доступа к диску во время потоковой передачи (их объясню позже):
  • sceCdChangeThreadPriority()
  • sceCdGetToc()
  • sceCdInit()
  • sceCdMmode()
  • sceCdPause()
  • sceCdRead()
  • sceCdReadChain()
  • sceCdReadIOPm()
  • sceCdSearchFile()
  • sceCdSeek()
  • sceCdStandby()
  • sceCdStop()
  • sceCdSync()
  • sceCdDiskReady()
  • sceCdGetError()
  • sceCdGetReadPos()


Надо знать



Суть в том, что привод подключен к IOP и так или иначе приходится использовать функции IOP.
Следующие данные отличаются между IOP и EE:
— команда завершения чтения данных из EE означает о завершении поступлении данных в процессор EE, а не завершение чтения данных с диска;
— ошибки на стороне EE влияют на последующие действия на стороне IOP;
— при переносе данных на EE всегда будет происходить выравнивание памяти до 64 байт.
— приоритет потока в EE, который будет работать с диском, будет соответствовать приоритету в IOP, таким образом, будьте аккуратны, иначе можно потерять нормальную обработку других потоков IOP.

К концу первой части



Тема очень сложная. Во второй части я объясню остатки статьи и как устанавливать PS2 SDK на Windows и Linux.

P.S.: прошу прощения за возможные опечатки.
Tags:
Hubs:
+27
Comments7

Articles

Change theme settings