PDA

Просмотр полной версии : вопрос к SMT по исходникам анрила



boo_boo
19.01.2006, 05:58
hi!
пытаюсь портировать куски анрила на линух, начал с ВГ93... скомпилировать удалось, заставить работать пока нет.
думаю на задержки, все остальное вроде весчь в себе, поэтому вопрос:
в файле wd93cmd.cpp дважды встречается конструкция

comp.t_states + cpu.t
это что такое?
пытался всякую муть сюда пихать (счетчик циклов CPU, счетчик кадров и тп), в некоторых случаях при попытке чтения диска получалось disc error, в некоторых -- ошибка чтения... :(

SMT
19.01.2006, 08:29
это что такое?
та же самая вроде весчь в себе - это "текущее время" эмулируемого спектрума - число тактов от старта

вообще, хорошо, что уже есть ощутимые результаты

GriV
19.01.2006, 09:04
исходя из каких соображений идёт эмуляция Beeper и SPK?

SMT
19.01.2006, 09:06
глупый вопрос

boo_boo
19.01.2006, 14:19
это "текущее время" эмулируемого спектрума - число тактов от старта

ооо, спасибо! теперь при включенных задержках время опроса дисковода похоже на реальное...
все равно disc error, впрочем...
хм... после записи в регистр команд команды чтения сектора, и при последующих попытках что-то взять из регистра данных, младший бит регистра состояния (занято) перманентно установлен... :confused:
будем думать :)

SMT
19.01.2006, 17:08
ты взял глюкалку или фуз?

GriV
19.01.2006, 17:26
глупый вопрос

Вообще ничего не вижу глупого, может всё таки ответишь?

Знахарь
19.01.2006, 17:35
SMT - профессионал! Сразу видно, ибо "только проф. программеру проще объяснить, почему нельзя написать что-то, чем написать" :) кажется так было написано :)

Boo boo - молодец! Давай эмуль под линуха... Думаю там очередь желающих. Я, кстати, тоже не против.

boo_boo
19.01.2006, 18:24
ты взял глюкалку или фуз?
глюкалку... весь день долблюсь, без толку. впрочем, я довольно приблизительное представление имею о работе ВГ, так что оно не удивительно...

вот лог обращения к ВГ -- может, по нему видно, на каком этапе пошли глюки?


file /home/boo/!ZX/CM2DEMO.trd loaded in drive A

Захожу в TRDOS:

WD OUT(0xff,0x00) status = 10000000
WD OUT(0xff,0xff) status = 100
WD OUT(0x1f,0xd0) status = 10000100

32 раза: {
WD OUT(0xff,0xf7) status = 10000100
WD OUT(0xff,0xff) status = 10000100
}

Делаю CAT:

WD OUT(0xff,0x3c) status = 10000100
WD OUT(0x1f,0x08) status = 101 /*восстановление*/
WD IN(0xff)=0xbf status = 100 /*INTRQ*/
WD IN(0x1f)=0x24 status = 100100 /*состояние*/

2408 раз {
WD IN(0x1f)=0x26 status = 100110 /*дергаем состояние*/
}

WD OUT(0x1f,0x08) status = 100111 /*восстановление*/
WD IN(0xff)=0xbf status = 100100 /*INTRQ*/
WD OUT(0x7f,0x20) status = 100100
WD OUT(0x1f,0x18) status = 100111 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100100 /*INTRQ*/
WD OUT(0x7f,0x01) status = 100000
WD OUT(0x1f,0x18) status = 100011 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100000 /*INTRQ*/
WD IN(0x1f)=0x22 status = 100010
WD OUT(0x7f,0x00) status = 100000
WD OUT(0x1f,0x18) status = 100011 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100000 /*INTRQ*/
WD IN(0x1f)=0x26 status = 100110
WD OUT(0xff,0x3c) status = 100110
WD IN(0x1f)=0x26 status = 100110
WD IN(0x3f)=0x00 status = 100110
WD OUT(0x7f,0x00) status = 100100
WD OUT(0x1f,0x18) status = 100111 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100100 /*INTRQ*/
WD OUT(0x1f,0xc0) status = 100111 /*чтение адреса*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x06 status = 1
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x01 status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x63 status = 1
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x9b status = 1
WD IN(0xff)=0xbf status = 0 /*INTRQ*/
WD OUT(0x3f,0x00) status = 0 /*уст. 0 дорожку*/
WD OUT(0xff,0x3c) status = 0
WD IN(0x1f)=0x00 status = 0
WD IN(0x3f)=0x00 status = 0
WD OUT(0x7f,0x00) status = 0
WD OUT(0x1f,0x18) status = 1 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100100 /*INTRQ*/
WD OUT(0x1f,0xc0) status = 100101 /*чтение адреса*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x09 status = 1 /*данные*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x01 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x73 status = 1 /*данные*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0xa5 status = 1 /*данные*/
WD IN(0xff)=0xbf status = 0 /*INTRQ -- прочитали адрес*/
WD OUT(0x3f,0x00) status = 0 /*уст. 0 дорожку*/
WD OUT(0xff,0x3c) status = 0
WD IN(0x3f)=0x00 status = 0
WD OUT(0x7f,0x00) status = 0
WD IN(0x3f)=0x00 status = 0
WD OUT(0x1f,0x18) status = 1 /*поиск дорожки*/
WD IN(0xff)=0xbf status = 100100 /*INTRQ*/
WD OUT(0x3f,0x00) status = 100100 /*уст. 0 дорожку*/
WD OUT(0x5f,0x09) status = 100100 /*уст. 9 сектор*/
WD OUT(0x1f,0x80) status = 100101 /*чтение сектора*/
WD IN(0xff)=0x3f status = 1

30 раз: {
WD IN(0xff)=0x7f status = 11 /*DRQ*/
}

около 100 примерно таких кусков: {
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x7f status = 11 /*DRQ*/
WD IN(0x7f)=0x00 status = 1 /*данные*/
WD IN(0xff)=0x3f status = 1
WD IN(0xff)=0x7f status = 11 /*DRQ*/
}

WD IN(0xff)=0xbf status = 0 /*INTRQ -- считали 9й сектор*/
WD IN(0x1f)=0x00 status = 0 /*состояние -- типа все ок*/
WD OUT(0xff,0x37) status = 0 /

15 раз: {
WD OUT(0xff,0x3f) status = 10000000
WD OUT(0xff,0x37) status = 10000000
}

WD OUT(0xff,0x3f) status = 10000000
WD OUT(0xff,0x34) status = 10000000

15 раз: {
WD OUT(0xff,0x3c) status = 0
WD OUT(0xff,0x34) status = 0
}

WD OUT(0xff,0x3c) status = 0

Получаю Disc Error

UPD: хммм, выглядит так, будто вместо 9го сектора считалось хрен знает что, по случаю чего ошибка. но фигли тогда сошлась контрольная сумма? :confused:

SMT
19.01.2006, 18:37
GriV, слишком общий вопрос. всё равно, что рассказать "из каких соображений" телевизор показывает картинку. развёрнутый ответ сейчас не могу дать

boo, если догадаюсь в чём дело, напишу

SMT
19.01.2006, 18:53
похоже, спектрум нашёл и прочитал данные. вероятно, ошибка в загрузчике TRD-файлов, который сформировал неверные CRC для секторов (можно загрузить и сразу выгрузить в формате UDI, а потом сравнить с windows-версией). однако CRC для адресных меток сформированы верно (63,9B для 6-го сектора)

SMT
19.01.2006, 19:27
вернее, дело не в CRC (она, похоже, верная), а в том, что спектрум не нашёл код #10 в нужном месте системного сектора диска. либо TRD такой (c чистым 9-м сектором disc error - правильное поведение), либо данные не доходят до процессора из образа диска. всё равно проверь загрузчик TRD

GriV
19.01.2006, 20:15
GriV, слишком общий вопрос. всё равно, что рассказать "из каких соображений" телевизор показывает картинку. развёрнутый ответ сейчас не могу дать

Хорошо я подожду, но мне очень нужен этот ответ.

boo_boo
19.01.2006, 20:52
оооо, точно, блин, вот же я идиот -- сплошные нули читаются ^____^
нелюбовь к глобальным переменным меня подвела -- распихивая их по классам, не обратил внимания на конструкцию
memset(this, 0, sizeof(FDD)); :p

короче, победа, РАБОТАЕТ! надо еще проверить разные загрузчики, и тп, и тд, но в целом можно сказать, что альфа-версия порта модуля эмуляции ВГ93 из UnrealSpeccy под линукс готова! :)

SMT
19.01.2006, 21:42
но мне очень нужен этот ответэто зачем "очень"?

сейчас буду говорить много банальностей, умных прошу не читать ^_^

итак, саундблястер играет звук идёт не непрерывным потоком, а небольшими буферами, состоящими из семплов, для удобства (у меня) по времени равными 1 кадру (1/50 сек.)

имеем на входе переключение бита 4 в порту #FE в некоторые моменты в течение эмулируемого кадра, а на выходе хотим буфер со звуковыми сэмплами. если частота оцифровки 48khz, то размер буфера длиной в кадр равен 48000/50=960 семплов. теперь, задача, как заполнить этот буфер

предположим, что в начале кадра (пентагон, 71680 тактов в кадре) состояние #FE было 0. а через 5000 тактов туда выведена 1, потом через 5000 тактов - опять 0, и т.д. (тон в 700 герц). тогда, очевидно, нужно начало буфера заполнить 0 до семпла номер 66 (5000/71680*960 - пропорция такая), потом от семпла 67 до семпла 133 (второй вывод на такте 10000, соотв. номер семпла 10000/71680*960) некоторым ненулевым значением, зависящим от установленной громкости спикера

и так до конца буфера

когда буфер готов, он ставится в очередь звуковой карты на проигрывание (таким образом, в текущий момент практически во всех эмуляторах играют буферы от прошлого и даже, более вероятно, позапрошлого или поза- поза- прошлых кадров, но приходится с этим мириться в обмен на другие прелести эмуляторов)

в реальности мы видим, что из-за погрешностей округления при расчётах позиции семпла смены уровня, расстояния между фронтами в буфере не одинаковые, поэтому (и ещё по паре причин) возникают паразитные частоты (т.н. альясинг). что это такое и как с ними бороться, написано в любом более-менее уважающем себя учебнике по ЦОС, лучше мне и не сказать. рекомендую http://dsp-book.narod.ru

ну если уж такая лень открыть учебник, может, когда-нить и накатаю популярную лекцию типа этой

breeze
19.01.2006, 21:43
короче, победа, РАБОТАЕТ! надо еще проверить разные загрузчики, и тп, и тд, но в целом можно сказать, что альфа-версия порта модуля эмуляции ВГ93 из UnrealSpeccy под линукс готова! :)

классно! :eek: поздравляем ! надеюсь сие чудо можно будет скомпилить под FreeBSD ? (в будущем :rolleyes: )

boo_boo
19.01.2006, 22:26
классно! :eek: поздравляем ! надеюсь сие чудо можно будет скомпилить под FreeBSD ? (в будущем :rolleyes: )
пасиб ;)
сам выдранный из US ВГ93-эмулятор под чем угодно соберется -- там только стандартные сишные библиотеки юзаются. ZX-эмуль, на котором экспериментирую сейчас -- искореженная глюкалка, если обычная глюкалка пашет под фрей, то и с этим хозяйством не должно быть проблем :cool:

SMT
19.01.2006, 23:17
кста, выше я обшибся, не 700hz, а 350 в примере

GriV
20.01.2006, 00:20
ладно я понял, меня как раз антиалиасинг интересует.
Тут ведь дело в чём - например тот же dizzy выводит на стартовой заставке (оригинальная версия имеется в ввиду) вполне приличный музон - если просто тыркать состояние бипки в звуковой ряд, то ничего путёвого не выйдет - прото потому что в указанный отрезок времени - даже для 48кгц получается около 73 тактов - он (бипка) изменяет своё состояние и даже порой не один раз и конечно оттуда и вопрос. На реальном спекке как - имеется триггер на выходе бипки и SPK и имеется его внутренняя ёмкость которая приводит к немоментальному срабатыванию триггера - например в течении нескольких мкс изменяет свой уровень на противоположный (сигнал не прямоугольной формы). Т.е. в любом случае имеется немоментальный переход в противоположное состояние, а потом я изучил диаграммы, получаемые US - и получается так же - что сигнал у бипки изменяется не моментально прямоугольно - а через некоторое количество отсчётов - порядка 1-2 отсчётов выходного звукового ряда (48 кгц всё те же). Вот и оттуда вопрос - откуда этот "наклон" кривой изменения состояния бипки? Это его именно антиалиасинг даёт?

SMT
20.01.2006, 09:10
да