Просмотр полной версии : вопрос к SMT по исходникам анрила
hi!
пытаюсь портировать куски анрила на линух, начал с ВГ93... скомпилировать удалось, заставить работать пока нет.
думаю на задержки, все остальное вроде весчь в себе, поэтому вопрос:
в файле wd93cmd.cpp дважды встречается конструкция
comp.t_states + cpu.t
это что такое?
пытался всякую муть сюда пихать (счетчик циклов CPU, счетчик кадров и тп), в некоторых случаях при попытке чтения диска получалось disc error, в некоторых -- ошибка чтения... :(
это что такое?
та же самая вроде весчь в себе - это "текущее время" эмулируемого спектрума - число тактов от старта
вообще, хорошо, что уже есть ощутимые результаты
исходя из каких соображений идёт эмуляция Beeper и SPK?
это "текущее время" эмулируемого спектрума - число тактов от старта
ооо, спасибо! теперь при включенных задержках время опроса дисковода похоже на реальное...
все равно disc error, впрочем...
хм... после записи в регистр команд команды чтения сектора, и при последующих попытках что-то взять из регистра данных, младший бит регистра состояния (занято) перманентно установлен... :confused:
будем думать :)
ты взял глюкалку или фуз?
глупый вопрос
Вообще ничего не вижу глупого, может всё таки ответишь?
SMT - профессионал! Сразу видно, ибо "только проф. программеру проще объяснить, почему нельзя написать что-то, чем написать" :) кажется так было написано :)
Boo boo - молодец! Давай эмуль под линуха... Думаю там очередь желающих. Я, кстати, тоже не против.
ты взял глюкалку или фуз?
глюкалку... весь день долблюсь, без толку. впрочем, я довольно приблизительное представление имею о работе ВГ, так что оно не удивительно...
вот лог обращения к ВГ -- может, по нему видно, на каком этапе пошли глюки?
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:
GriV, слишком общий вопрос. всё равно, что рассказать "из каких соображений" телевизор показывает картинку. развёрнутый ответ сейчас не могу дать
boo, если догадаюсь в чём дело, напишу
похоже, спектрум нашёл и прочитал данные. вероятно, ошибка в загрузчике TRD-файлов, который сформировал неверные CRC для секторов (можно загрузить и сразу выгрузить в формате UDI, а потом сравнить с windows-версией). однако CRC для адресных меток сформированы верно (63,9B для 6-го сектора)
вернее, дело не в CRC (она, похоже, верная), а в том, что спектрум не нашёл код #10 в нужном месте системного сектора диска. либо TRD такой (c чистым 9-м сектором disc error - правильное поведение), либо данные не доходят до процессора из образа диска. всё равно проверь загрузчик TRD
GriV, слишком общий вопрос. всё равно, что рассказать "из каких соображений" телевизор показывает картинку. развёрнутый ответ сейчас не могу дать
Хорошо я подожду, но мне очень нужен этот ответ.
оооо, точно, блин, вот же я идиот -- сплошные нули читаются ^____^
нелюбовь к глобальным переменным меня подвела -- распихивая их по классам, не обратил внимания на конструкцию
memset(this, 0, sizeof(FDD)); :p
короче, победа, РАБОТАЕТ! надо еще проверить разные загрузчики, и тп, и тд, но в целом можно сказать, что альфа-версия порта модуля эмуляции ВГ93 из UnrealSpeccy под линукс готова! :)
но мне очень нужен этот ответэто зачем "очень"?
сейчас буду говорить много банальностей, умных прошу не читать ^_^
итак, саундблястер играет звук идёт не непрерывным потоком, а небольшими буферами, состоящими из семплов, для удобства (у меня) по времени равными 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
ну если уж такая лень открыть учебник, может, когда-нить и накатаю популярную лекцию типа этой
короче, победа, РАБОТАЕТ! надо еще проверить разные загрузчики, и тп, и тд, но в целом можно сказать, что альфа-версия порта модуля эмуляции ВГ93 из UnrealSpeccy под линукс готова! :)
классно! :eek: поздравляем ! надеюсь сие чудо можно будет скомпилить под FreeBSD ? (в будущем :rolleyes: )
классно! :eek: поздравляем ! надеюсь сие чудо можно будет скомпилить под FreeBSD ? (в будущем :rolleyes: )
пасиб ;)
сам выдранный из US ВГ93-эмулятор под чем угодно соберется -- там только стандартные сишные библиотеки юзаются. ZX-эмуль, на котором экспериментирую сейчас -- искореженная глюкалка, если обычная глюкалка пашет под фрей, то и с этим хозяйством не должно быть проблем :cool:
кста, выше я обшибся, не 700hz, а 350 в примере
ладно я понял, меня как раз антиалиасинг интересует.
Тут ведь дело в чём - например тот же dizzy выводит на стартовой заставке (оригинальная версия имеется в ввиду) вполне приличный музон - если просто тыркать состояние бипки в звуковой ряд, то ничего путёвого не выйдет - прото потому что в указанный отрезок времени - даже для 48кгц получается около 73 тактов - он (бипка) изменяет своё состояние и даже порой не один раз и конечно оттуда и вопрос. На реальном спекке как - имеется триггер на выходе бипки и SPK и имеется его внутренняя ёмкость которая приводит к немоментальному срабатыванию триггера - например в течении нескольких мкс изменяет свой уровень на противоположный (сигнал не прямоугольной формы). Т.е. в любом случае имеется немоментальный переход в противоположное состояние, а потом я изучил диаграммы, получаемые US - и получается так же - что сигнал у бипки изменяется не моментально прямоугольно - а через некоторое количество отсчётов - порядка 1-2 отсчётов выходного звукового ряда (48 кгц всё те же). Вот и оттуда вопрос - откуда этот "наклон" кривой изменения состояния бипки? Это его именно антиалиасинг даёт?
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot