
1. Прошу прощения, что долго не писал.
2. Готов PS2 SDK.
Я хотел не упускать CD(DVD)-ROM Library, поэтому ссылки и гайд по установке 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.: прошу прощения за возможные опечатки.
