Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2

в 15:36, , рубрики: CXD2545, diy или сделай сам, ps1, psx, Verilog
В первой части. Мы поверхностно посмотрели, как работает микросхема CXD2545, которая является частью контроллера CDRom и стоит между данными считываемые лазером и остальной частью приставки. Я для себя поставил задачу проэмулировать чтение оглавления диска. Это то, что делает приставка, когда пытается понять, что за диск в ней вставлен. А главное результат сего действа достаточно просто можно наблюдать во встроенном CD плеере приставки. Зная, что во время попытки чтения оглавления она не дает двигать курсор, а по окончании показывает, сколько треков было найдено.

(Также здесь будут описаны ошибки, которые я допустил, пытаясь сделать этот эмулятор, может, кого-то это убережет, от необдуманных поступков)
Итак у нас есть PS1 с платой SCPH-5502, DE1 с CycloneII на борту, клон DSLogic Plus и большое желание проэмулировать CDRom.

3. Что такое TOC где он живет и как выглядит?

3.1 Смотрим логическим анализатором

Для начала я запустил анализатор, подключил его к основным исследуемым пинам. Стартанул захват и нажал кнопку, которая отвечала за закрытия крышки приставки. Эксперименты проводил на двух играх Forsaken и G-Police 2. Первая выбрана потому, что у неё должен быть большой TOC, так как у игры много аудио треков сопровождения. А вторая, потому что была под рукой. Полученные дампы можно посмотреть скачать здесь(Forsaken, G-Police 2) при помощи программы DSView. При беглом взгляде стало понятно, что надо искать информацию о том, как всё-таки хранится TOC.

(Нога SCOR снята криво, как оказалось у меня убит 7 канал на логическом анализаторе, но в момент, когда я с снимал, эти дампы я этого не знал)

3.2 Так что же такое TOC?

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 1
Ноги у CD-Data растут из CD-Audio. А на последних хранились аудио треки, их было несколько и чтобы бытовому плееру узнать, сколько их именно и какую длину они имеют, придумали TOC. TOC расшифровывается как Table of content, что можно перевести как оглавление. Так вот на CD-Audio было два потока данных: основной с аудиоданными, и субканальные данные. В аудиоданных были закодирован аудио поток в формате 16 бит, 44100 герц без компрессии(ну на самом деле туда ещё можно запихнуть DTS/AC3 но это уже совсем другая история). В субканальных данных была информация необходимая для сервисных нужд плеера, номер трека, текущее время воспроизведения трека диска. А также может быть куча дополнительной информации, в виде всяких CD-Text, регистрационных номеров диска в разных базах итд. Субканал сам подразделяется на восемь подканалов, именуемых буквами от P до W. В общем, хранить TOC в аудиоданных было не вариант, так как зачастую они напрямую шли на ЦАП и никак не анализировались. Поэтому данные решили хранить в субканале(он же субкод/subcode). Те, кому доводилось записывать компакт диски должны помнить, что привод в начале диска пишет загадочный Lead-In потом данные и потом Lead-Out. Так вот Lead-In как раз и содержит данные TOC. Который закодированы в Q канале.

3.3 Формат Q субканала

Не углубляясь в то, как устроено хранение данных на диске, нам пока достаточно знать следующее. Сектор на диске содержит 2352 байта(ну как таковой понятие сектор оно и не совсем верное). На каждый сектор приходится один блок субканальных данных. Каждый субканал несет 96 бит информации. Нас сейчас интересует только Q подканал.

Формат данных этого подканала достаточно прост.

Control Mode-Q(ADR) Data-Q CRC
4-Bit 4-Bit 72-Bit 16-Bit

Поле Control содержит тип текущего трека, аудио/дата, сколько каналов, есть ли предискажение, запрещено ли его копировать.

Варианты значений взяты из документа mmc2r11a.pdf

00x0b 2 audio channels without pre-emphasis
00x1b 2 audio channels with pre-emphasis of 50/15 µs
10x0b 4 audio channels without pre-emphasis
10x1b 4 audio channels with pre-emphasis of 50/15 µs
01x0b Data track, recorded uninterrupted
01x1b Data track, recorded increment
11xxb reserved
xx0xb digital copy prohibited
xx1xb digital copy permitted

Для нас интересны два варианта это 0x4 — дата трек, и 0x0 — аудио трек 2 канала.

Поле Mode-Q оно же ADR указывает, что дальше закодировано в Q канале. Нас интересует только
значение 0x1, которое отвечает за указание текущей позиции на диске. Также ещё есть вариант 0x2, который отвечает за Media Catalog Number и 0x3, отвечающий за ISRC. Но они нам на данный момент не нужны.

Формат Mode-Q 0x1 имеет следующий вид:

TRACK INDEX MIN SEC FRAME ZERO AMIN ASEC AFRAME
8-Bit 8-Bit 8-Bit 8-Bit 8-Bit 8-Bit 8-Bit 8-Bit 8-Bit

Где Track — номер текущего трека, для трека Lead-Out значение фиксировано 0xAA. Index по сути используется два варианта это 0 пауза «перед началом» трека, и 1 сам трек. По идее задумывалось, чтобы один трек можно было разбивать на дополнительные части, но видимо оказалось ненужным, либо его добавили из за особенности работы CIRC но сейчас не об этом.

MIN/SEC/FRAME относительное положение головки на диске, MIN может быть от 00 до 99, SEC от 00 до 59. FRAME от 00 до 74(адресация на CD дисках называется MSF как раз из-за этих параметров). Это значение описывает положение головки относительно начала текущего трека. Поля AMIN/ASEC/AFRAME описывают абсолютное положение головки от начала зоны дынных на диске. Зона данных идёт сразу за зоной Lead-In, и как бы это не было странно трек Lead-Out включен в зону данных. Диапазон значений такой же, как и у MIN/SEC/FRAME. Важный момент MIN/SEC/FRAME во время когда INDEX равен 0 идут на уменьшения значений, а при INDEX равный 1 на увеличение. Поля AMIN/ASEC/AFRAME всегда идут строго на увлечение. Поле ZERO всегда равно 0x00

Однако в зоне Lead-In поля имеют немного другие значения, а именно: MIN/SEC/FRAME и ZERO работают также как и везде. Поле TRACK равно 0x00, что в целом логично. Однако поле INDEX и
AMIN/ASEC/AFRAME отданы под описание трека и его параметров. INDEX указывает номер трека описываемого в TOC, а поля AMIN/ASEC/AFRAME его позицию, выраженную абсолютном времени на диске. Как же есть специальные значения выражено в виде INDEX с параметром 0xA0, 0xA1, 0xA2:

Index AMIN ASEC AFRAME
0xA0 Номер первого трека на диске обычно(всегда) 0x01 Тип трека:
0x00 — CD-DA or CD-ROM
0x10 — CD-I
0x20 — CD-ROM-XA
0x00
0xA1 Номер последнего трека 0x00 0x00
0xA2 AMIN начала Lead-Out ASEC начала Lead-Out AFRAME начала Lead-Out

Вот из этих записей и состоит TOC. Длинна же самого Lead-In, должна быть около 4500 секторов. В которых эти данные повторяются, что скорей всего сделано для надежности. Как строит TOC приставка, я точно не знаю. Но алгоритм должен быть достаточно прост, что-то похожее на следующее. Позиционируемся на Lead-In зная, что у него Track = 0x00. И начинаем заполнять адреса начала всех треков, используя данные из Q субканала, Само количество треков мы узнаем из служебной записи 0xA1. Когда все записи заполнены, считаем, что TOC прочитан.

По тестам с разными дисками стало понятно, что TOC на штамповке и на самописных болванках немного отличается. Например, относительно время в Lead-In на штамповке шло от 00:00:00 и просто по нарастающей. А на записанной болванке оно начиналось явно не с нулевой метки, и было рассчитано, так, что бы последний сектор Lead-in приходился на значение 99:59:74 то есть максимально возможное время в адресации MSF. Что, на мой взгляд, более верное решение, но приставке, да и другим приводам абсолютно безразличен этот факт.

3.4 Просто всякие мелочи

Lead-In это единственная область, в которой свои отметки времени не связаны с основной областью данных. Также трек Lead-In по сути является треком номер 0. Все остальные треки, включая трек Lead-Out, содержат две отметки времени время от начала области данных, и время от начала текущего трека. Данные всех треков закодированы в формате BCD, кроме номера трека Lead-Out он имеет значение 0xAA. Lead-Out служит для указания того что это конец диска (всякие мультисессии мы не рассматриваем), и дальше никаких данных не будет. CXD2545 умеет читать их все, но в PS1 он подключен, так что может читать только канал Q, да ещё и настроена, так что в последних двух байтах выдается не CRC, а PeakMeter.

4 Первые попытки эмуляции TOC

4.1 Размышления

(В статье описаны события 4-5 летней давности, поэтому могут быть неточности, прошу с понимание отнестись к этому)
Формат данных TOC известен, как он строится тоже ясно. Пришло время обдумать, как это всё эмулировать. У нас есть плата с Cyclone II но читать карту на Verilog и обрабатывать команды привода задача не очень веселая. Поэтому было принято решение собрать систему с «софт» процессором NiosII, к которому сделать свой модуль, который бы эмулировал тот самый CXD2545 и подключался к процессору как устройство мапированное на память. Учитывая, что автор не FPGA разработчик, неплохой такой план.

Что же для этого требуется:

  1. Сделать входную шину CLOK/DATA/XLAT которая по приходу XLAT дергает прерывание и дает прочитать, что от нас хочет приставка
  2. Сделать шину чтения субканала SQCK/SUBQ/SCOR по которой мы будем отправлять приставке данные

Саму шину данных делать пока не нужно, там при чтении TOC ничего нужного нет.

4.2 Первые наброски

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 2В SOPC Builder(графический интерфейс, для генерации процессорных системы в Quartus) бала создана система. Которая состояла из:
Nios II процессора, On-Chip памяти, UART модуль для отладки и таймера.

Убедившись, что система собирается, и потом, убедившись, что Nios II стартует как надо, и можно писать и отлаживать программы, я решил, что пришла пора написать первый компонент системы.

Он должен будет читать с данные с шины управления CXD2545, и передавать их в процессор.

Модуль я назвал CXD2545_CPU. Я решил, что для этой шины, нужно, что-то похожее на сдвиговый регистр, куда задвигаются команды, по сигналу XLAT регистр должен был копироваться в другой регистр, и дергать прерывание, чтобы процессор знал, что пришла команда от приставки. И посидев немного в мастере создания компонентов SOPC, была получена заготовка для модуля, из которой, я как смог слепил первый модуль. (Автор не FPGA разработчик, поэтому его Verilog код может нанести травму FPGA разработчикам, за что он сразу извиняется.)

Код модуля целиком

module CXD2545_CPU (
		input  wire        clk,         //            clock.clk
		input  wire        rst_n,       //                 .reset
		input  wire [3:0]  m_addr,      //     avalon_slave.address
		output wire [31:0] m_read_data, //                 .readdata
		input  wire [31:0] m_write_data,//                 .writedata
		input  wire        m_read,      //                 .read_n
		input  wire        m_write,     //                 .write_n
		output wire        m_irq,       // interrupt_sender.irq_n
	
		input  wire        CLOK,        //          cxd_cpu.export
		input  wire        DATA,        //                 .export
		input  wire        XLAT         //                 .export
	);

	reg [23:0] cxd_cmd;
	reg [23:0] cxd_cur_cmd;
	

	reg reg_cur_clok;
	reg reg_prev_clok;
	reg reg_data_cur;
	reg reg_cur_xlat;
	reg reg_prev_xlat;
	
	reg irq;
	
	assign m_read_data[23:0] = cxd_cmd;
	assign m_irq = irq;
	
	always @(posedge clk) begin
		if(rst_n == 1) begin
			irq <= 1'b1;
		end else begin

reg_prev_clok <= reg_cur_clok;
reg_cur_clok <= CLOK;

reg_prev_xlat <= reg_cur_xlat;
reg_cur_xlat <= XLAT;

reg_data_cur <= DATA;

if((reg_prev_clok ==1'b0) && (reg_cur_clok ==1'b1)) begin
cxd_cur_cmd[23:0] <= {reg_data_cur, cxd_cur_cmd[23:1]};
end

if((reg_prev_xlat ==1'b1) && (reg_cur_xlat ==1'b0)) begin
cxd_cmd <= cxd_cur_cmd;
irq <= 1'b0;
end

if((m_read == 1'b0) && (m_addr == 4'h1)) begin
irq <= 1'b1;
end

end

end

endmodule

Надо заметить это единственный модуль, который дожил до рабочей версии эмулятора и только он и сохранился из первой версии проекта. Но разберем его по порядку. У нас есть две группы сигналов, одна относится к шине Avalon-MM, с которой работает Nios II и вся его периферия. И ужа знакомая нам шина команд CXD2545. А также сигнал сброса системы, и сигнал тактировая системы. Вдаваться в работу всей шины Avalon-MM мне не хочется, кому интересно, думаю смогут найти её принципы работы сами. Поэтому вкратце опишу что делается в модуле (всё что описано ниже происходит по положительно фронту клока):

if(rst_n == 1) begin
	irq <= 1'b1;
end else begin

Если пришёл сигнал сброса мы убираем сигнал прерывания(активный уровень сигнала прерывания у нас 0). Если ресета не было:

reg_prev_clok <= reg_cur_clok;
reg_cur_clok <= CLOK;
	
reg_prev_xlat <= reg_cur_xlat;
reg_cur_xlat <= XLAT;
			
reg_data_cur <= DATA;

Запоминаем текущее значения пришедших сигналов в регистрах, а их старые значения CLOK/XLAT запоминаем в регистрах предыдущих значений.

if((reg_prev_clok ==1'b0) && (reg_cur_clok ==1'b1)) begin
	cxd_cur_cmd[23:0] <= {reg_data_cur, cxd_cur_cmd[23:1]};
end

Если прошлое значение clok было 0 а текущее стало 1(поймали фронт сигнала), задвигаем в регистр текущее значение линии DATA.

if((reg_prev_xlat == 1'b1) && (reg_cur_xlat == 1'b0)) begin
	cxd_cmd <= cxd_cur_cmd;
	irq <= 1'b0;
end

Если XLAT перешел из состояния 1 в 0 то переносим текущее значение сдвигового регистра, в регистр где хранится текущая команда и ставим запрос на прерывание.

if((m_read == 1'b0) && (m_addr == 4'h1)) begin
	irq <= 1'b1;
end

При чтении значения из адреса 0x4 относительно базового адреса модуля, сбрасываем запрос прерывания.

assign m_read_data[23:0] = cxd_cmd;
assign m_irq = irq;

Отображаем на шину данных Avalon-MM постоянно(независимо от запрошенного адреса) значения регистра cxd_cmd а на сигнал прерывания регистр irq. Для тех кто незнаком с Verilog следует уточнить, что в отличии от обычных программ, результатом компиляция программы на Verilog получает схема. И все конструкции которые описаны, выполняются одновременно. А система переходит из одного состояния в другое по событиям описанным в блоках always. И не смотря на то, что

reg_prev_clok <= reg_cur_clok;

Написано выше чем условие где это самый reg_prev_clok сравнивается с чем то. На момент сравнения он будет иметь значение которое имел когда мы вошли(если смотреть по тексту) в блок always, и поменяет его уже когда весь блок будет отработан. По началу обычным программистам это очень выносит мозг, но привыкнуть можно.

RTL представление модуля

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 3

После того как удалось это написать, я подключил DE1 параллельно чипу CXD2545. Набросал простую программу на Си под Nios II. И попробовал на приставке нажать кнопку, которая отвечает за мониторинг закрытия крышки. В консоль весело посыпались команды отдаваемые приставкой, приводу. Это была первая маленькая победа. И одна подняла энтузиазм до небывалых значений. Теперь надо было разобраться с командами, которые шли контроллеру и понять, как их эмулировать.

5. Команды CXD2545

Список команд достаточно небольшой, хотя если рассматривать их вместе с параметрами, то он огромен, но не все так страшно. За номер команды отвечает, первые 4 бита, остальное это параметры команды. Вот перечень команд с их описание:

Код Название блока команд Описание
0x0 Focus Control Команды управления фокусом, включить/выключить, и параметры фокуса, для эмуляции не очень и нужны.
0x1 Tracking Control Команды управления трекингом, включить/выключить, и параметры антишока, тормоза и прочее, для эмуляции тоже не нужны.
0x2 Tracking Mode Прямое управление линзой трекинга, включение выключение приводов салазок, и магнитного привода линзы, возможность двигать вперед/назад эти приводы, явно нужно будет эмулировать.
0x3 Select Огромный блок с кучей под блоков, в которых прописываются всякие тонкие настройки работы механики, усилителей и прочего, как оказалось для эмуляции не нужен, но первый взгляд на него очень сильно меня напугал.
0x4 Auto sequence Команды перехода по трекам, вперед или назад на 1/10/2N/M трек, но это не те треки которыми нумеруются аудиозаписи на диски, а дорожки спирали, на которой и записана вся информация на диске, обязательно для эмуляции.
0x5 Blind (A, E),Brake (B),Overflow (C, D) Тайминги разных фаз работы механики, для эмуляции не нужны.
0x6 Sled kick, brake (D),Kick (F) Ещё тайминги разных фаз работы механики, для эмуляции не нужны.
0x7 Auto sequence track jump count setting Число треков на которое надо прыгать для команды 0x4 при указании параметров 2N или M треков, для эмуляции нужна.
0x8 MODE specification Разные параметры работы CDRom, в принципе оказалось эмулировать не обязательно
0x9 Function specification Разные параметры работы CDRom, для эмуляции важен только флаг DSPB указывающий на какой скорости сейчас должен работать привод 1X или 2X
0xA Audio CTRL Параметры отвечающие за роботу привода в режиме Audio, по логам выходило что приставка устанавливает его один раз и больше не трогает, значит и эмулировать не надо.
0xB Traverse monitor counter setting Счетчик треков, который дергает ногу COUT при перемещении головки при помощи команд 0x2. Изначально я не понял его назначения, это стоило наверно 3х дней отладки.
0xС Spindle servo coefficient setting Параметры для работы механики, для эмуляции не нужны.
0xD CLV CTRL Параметры для работы механики, для эмуляции не нужны.
0xE CLV mode Управление шпинделем, раскрутка, тормоз, режим работы. Когда шпиндель крутится нужно выдавать данные субканала и основного канала, нужная команд

В общем как оказалось команд необходимых для эмуляции не так много и в целом они достаточно простые. Ну а раз так то пишем дальше.

6. Начинаем эмулировать

6.1 Первая попытка эмуляции

Так как проект почти все время находился в состоянии, ну зачем тут система контроля версий, ничего ещё не написано, то дальнейшее я описываю по памяти. В общем, я набросал код модуля, которые отвечал за вывод субканала, это было три 32х регистра, и вывод их через сдвиговый регистр. SCOR сигнал эмулировался при помощи, добавленного модуля PIO которые есть в базовой поставке ядер от Altera. Работало все просто после получение команды 0xE с параметром включить включения шпинделя, я по таймеру начинал бросать 75 раз в секунду, данные субканала. Сами данные я захардкодил, только параметры MSF рассчитывал на лету. Команды 0x4 и 0x2 эмулировались крайне слабо. И у меня зачесались руки проверить, как это работает. А для этого надо было отключить чип CXD2545. Глядя на схему из книжки, я решил отпаять L711, чтобы обесточить чип. После чего подключился к ногам CLOK/DATA/XLAT и SQCK/SUBQ/SCOR ну GND.

Первое включение показало что, CXD2545 видимо натягивает через другие ноги питания, и время от времени гадит на шину. После чего я не придумал ничего лучшего, чем отпаять это чип нафиг. Но на всякий перед этим снял ещё пачку всяких событий анализатором, старт с разных треков, попытка загрузки игр(хотя дальше черного экрана с логотипом PS оно уже не могло идти). Это как потом выяснится, это очень мне помогло. В итоге принес с работы 702 Lukey и феном снял этот чип. Загрузил прошивку в FPGA, стартанул программу Nios II. Включаю приставку, иииии… черный экран, ресет, ещё ресет, ничего. Обидно.

6.2 Поиск проблем

Первое что пришло в голову это то, что CXD2545 генерирует сигналы CDBCLK и CDLRCK, независимо от того идут данные или нет. Может их не хватает, подумал я, и при помощи PLL сгенерировал нужную частоту для CDBCLK и уже из неё получил CDLRCK. Подключил сразу всю шину данных CD. Включаю приставку, слышу заветный звук включения, но на первом логотипе, тот который на белом фоне всё виснет. И никаких команд приставка приводу не шлёт. Энтузиазм начинает падать. Но делать нечего начинаю более детально изучать, как всё работает.

6.3 Примерная схема работы привода CDRom

Посмотрев доступные источники родилась такая схема:

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 4

Через чип CXD1815 приставка общается с SUB-CPU, который управляет уже нашим чипом CXD2545. Который в свою очередь шлёт данные с сидирома назад в CXD1815, а уже именно он занимается тем, что либо декодирует данные как сектора в режиме дата, и позволяет их забрать приставке. Либо если это аудиоданные шлёт их в звуковой чип приставке. Также CXD2545 шлёт данные субканала и ещё пару служебных сигналов в SUB-CPU, который её и контролирует. Но ещё более интересный момент был дальше, оказалось, SUB-CPU тактируется от CXD2545. И когда я её убрал, команды посылать он уже не мог. По схеме из книги это должно подключаться так:

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 5

А что у нас за нога C16M:

Эмулятор CD-Rom для SonyPlaystation который я писал больше десяти лет. Часть 2 - 6

Ну почти 17 мегагерц да еще меняющиеся. Ну да ладно, что делать, подаю 17 мегагерц на этот пин. Ииии опять ничего. Но тут глаз зацепился за то, что почему-то в книжке ноги 67 и 68 замкнуты между собой. А по даташиту это выход частот, с разными делителями. А если посмотреть дальше то нога 64 отвечает за, то на какой частоте работает сам чип. Но по схеме из книге она висит в воздухе. Пришлось немного по изучать плату, чтобы понять, что нога 64 подключена к земле, что указывает на то, что микросхема работает от 16.9344MHz. А нога тактирования SUB-CPU подключена к пину 68, а не 69 и там должно быть около 4 мегагерц. Подав нужную частоту на SUP-CPU и включив приставку, я наконец увидел главный экран с выбором менеджера карточек и CDPlayer'а. Вот такие веселости может преподнести литература.

Лирическое отступление

Да ошибок в книжной схеме оказалось полно, особенно в плане подключения схемы управления фокусировки, и трекинга привода. Потом я нашел, почему так было нарисовано. Скорей всего книгу рисовали по схеме из скана сервис мануала на приставку, а он есть только в очень плохом качестве. И части схем видимо просто дорисовывали, так как не все линии там прорисованы нормально, хотя вроде именно это место там вполне разборчиво.

Запустил программу, нажал кнопку закрытия крышки, и поучил кучу команд 0x2 с пожеланием двинуть каретку влево. Но тут я быстро догадался, что она ждёт появления сигнала о том, что каретка уперлось в датчик нулевого положения. И по быстрому добавил этот сигнал. После этого ещё пришлось подтянуть SENS к высокому уровню, иначе приставка давала команду фокусировки, но дальше ничего не делала. Итак, не с первого раза, но достаточно быстро TOC считался и отобразился в сидиплеере. Это была первая значимая победа.

6.4 Эмулируем данные CDRom

И тут меня понесло. В систему был добавлен модуль SPI, через который я подключил SD карту. Работать с файловой системой мне не хотелось. Поэтому решил работать с RAW данными с карты. Написал подобие драйвера карты. При этом пришлось править алтеровский SPI драйвер, чтобы он держал ноги SPI в нужном состоянии. После этого я решил, надо разбить данные так, чтобы было удобно с ними работать со стороны Nios II.

Идея была такова, я делаю Dual Clock FIFO, со стороны Nios II я туда засовываю данные, а приставка их со своей стороны забирает. При этом как-то хотелось, ещё синхронизировать субканальные данные. В итоге родилась простая идея на один сектор, который у нас занимает 2352 байта, приходится 12 байт данных, делим 2352 на 12 и получаем что каждые 196 байт, на нужно вставлять 1 байт субканальных данных. Которые я бы пихал в другой сдвиговый регистр, а потом в конце сектора дергаю SCOR. Дальше мысль была проста, даем карте команду read multiple и спокойно тянем из SPI байты и бросаем их в FIFO, а каждый 197 байт в другое FIFO. Карта у нас на двадцати пяти мегагерцах работает, данные идут всего на двух(ну и на четырех на 2х скорости). Да ещё и FIFO есть, времени вагон, должно заработать.

6.5 Работает но криво

После долгих мытарств с Verilog и отладкой этой вроде простой задачи, оно таки заработало, аудио треки воспроизводились. Но с хрустом каким-то. Джитер PLL, подумал Штирлиц. И стал искать генератор на нужную частоту. И в каком-то из кучи древних сидиромов нашел, кажется на 33,86. Правда, это был вроде бы кварц, и пришлось делать обвязку. Но после подключения внешнего клока, проблема почти свелась к нулю, но только почти. В итоге я взял клоковый сигнал, который приходил на CXD2545 изначально. И это решило проблему на 99,9%, но время от времени, все равно были слышны щелчки. Ну, да и фиг сними. Пришло время загрузить игру. Учитывая все особенности диска, всякие прегапы постагапы, и прочее, был сгенерирован образ, которые я закинул на карту. Зажал кнопку крышки, и ничего, чуда не случилось.

6.6 Грузим игру(нет)

Стал изучать дампы которые снимал в момент запуска игр. Пришлось даже написать кучу вспомогательных утилит. И тогда всё стало ясно.

С диска данные читались вот в таком формате:

FF 00 FF FF FF FF FF FF FF FF 00 FF 80 01 62 07

Это выглядит очень неправильно. Потому, что data сектор на диске имеет заголовок:

SycnPattern MSF MODE DATA
12-byte 3-byte 1 byte 2,336
00 FF FF FF FF FF FF FF FF FF FF 00 MM:SS:FF 1/2 DATA

По сути, запись данных на диск ничем не отличается от записи аудио. Отличие есть только в данных субканала где указано что это тип трека Data. А учитывая, что на самом деле субканал по определенным причинам не связан жестко с данными, и может быть получен и в середине(или вообще на другом секторе) дата сектора, что для аудио значения особого не имеет. А вот для данных такое получение номера сектора неприемлемо. Поэтому был введен специальный формат сектора. И привод как раз по синхропоследовательности понимает, что именно сейчас начинается сектор, а по первым 3 байтам узнаёт какой именно сектор.

То есть в данных привода младший и старший байт поменяны местами, и должны идти так:
00 FF FF FF FF FF FF FF FF FF FF 00 01 80 07 62 Это больше походе на правду. Но:

SycnPattern MSF MODE DATA
00 FF FF FF FF FF FF FF FF FF FF 00 01:80:07 62 2,336

в MSF адресации параметр SS не может быть больше 59, а тут 80, да и MODE 62 что тоже не нормально. В целом это могло загнать в тупик но к тому моменту я уже знал, что данные сектора на диске скремблируют, как раз таки чтобы, на диске не встретилась где попало последовательно SycnPattern. И при дескремблировании мы получаем

SycnPattern MSF MODE DATA
00 FF FF FF FF FF FF FF FF FF FF 00 00:00:07 02 2,336

Ну и дальше данные трека тоже были найдены в образе диска. В общем CXD2545 вообще ничего не знает про сектора, она чисто декодирует данные с диска, остальным занимаются чипы которые стоят дальше. Да про всё это срамблирование/дескрамблирование автор узнал из книги «Техника защиты компакт-дисков от копирования» за авторством Криса Касперски. Рекомендую очень просто и понятно всё описано. В итоге, проведя скремблирования секторов в образе, и запустив приставку, секунд через 40-50 я увидел логотип PS на черном фоне. Дальше дело не шло, сколько не жди. Работало это всё не очень то и стабильно. И промаявшись с этим ещё около четырех дней, добавив работу на скорости 2Х на которою приставка переходила при начале загрузки игры. Я понял, что мне надо, более точный дамп лога загрузки игры.

6.7 Точка невозврата

Я был полон энтузиазма. Но у меня не было под рукой нормально паяльника и микроскопа тоже не было, Не было даже лампы настолько для нормального освещения. Но в итоге я решил припаять назад CXD2545 чтобы снять дамп загрузки игры(хотя привод был убит и не особо мог это делать и раньше). В итоге все окончилось очень печально. Я не то закоротил ноги и не смог разглядеть где. Не то содрал дорожки. Потом я нашёл как минимум пару содранных. Но при включении приставки она с дикой скоростью крутила диском. Я повторил пару попыток, окончательно угробив дорожки. Но так и не добился результата. В итоге я отпаял чип, проверил, что хотя бы TOC и аудиотреки читаются. И понял что назад пути нет. Вывод, не надо спешить. Я бы мог спокойно все сделать на работе, где был микроскоп, и нормальный паяльник, и освещение. Но теперь я был в ситуации, когда эмулятор почему-то не работает, по логическому анализатору, я не вижу что не так. И снять данные с рабочего варианта уже не могу. Я ещё пару дней помучился, и забросил это дело. Скорей всего из-за начала роллер сезона, и не желания сидеть ночи на пролет дома.

Конец второй серии

На этом я хочу завершить вторую часть, она и так получилось неприлично большая. Выводы, которые я для себя сделал. Схемам из книг верить можно не всегда. Паять плохим паяльником и без освещения, плохая идея. Спешка даже в момент когда ты переполнен энтузиазма, может его угробить, как и дело, которое ты делаешь.

В третьей части, мы все переделаем, и наконец запустим какую ни будь игру. Также узнаем, наконец, что же скрывалось за ногой SENS, и почему не грузилась ни одна игра.

Автор:
VBKesha

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js