-
- ? gid
- 27.09.2017 10:54
Имеется в виду ПЗУ БОС БК11? или БК11М? или ПЗУ 017 от БК10? Там по-разному подпрограммы звука устроены. В мониторе десятки частота с каждым циклом уменьшается, в 11 - звук монотонный. Без модификации не обойтись, даже если попробовать подобрать константы.
- ? gid
- 26.09.2017 10:16
Отлично. Вот только на разворотах иногда не весь текст видно. И если недостающие буквы в словах можно угадать, то числа, которые не видны - фиг угадаешь.
А документы 00008-01.31.01, 00008-01.32.01, 00008-01.32.02-1, 00008-01.32.02-2, 00008-01.34.02-1 будут фоткаться? Или они уже совпадают с ДВКшными?
- ? gid
- 24.09.2017 20:20
Что ж... как сделать из любой оптической/лазерной мыши марсианку видимо не дождёмся. Значит далеко не любая мышь легко делается марсианкой.
А вот вам схема блока КМ: https://yadi.sk/i/fXcniRDj3NBaT9 (ссылка временная, как только получится, будет постоянная ссылка у меня на сайте)
Там видно, что одновременно херачится оба прерывания IRQ2 и IRQ3. Из-за того, что у ВМ1 нету очереди прерываний, и IRQ2 более приоритетен, то IRQ3 игнорируется.
А я, оказывается, у себя перерезал перемычку S5 и у меня не нужных мне прерываний по вектору 100 не генерировалось, а прерывания по вектору 270 никакой софт не использовал.
- ? gid
- 19.09.2017 12:31
попросим схему переделки оптических/лазерных мышей в студию...
- ? gid
- 13.09.2017 20:13
поправка:
У меня мышь Марсианка работала в Ксидос через блок КМ сразу. Я и не знал, что может быть по-другому.
- ? gid
- 13.09.2017 20:10
Мне тоже интересна схема, но самому рисовать лень.
А что правда блок КМ генерировал прерывание по вектору 100? Не IRQ3 по вектору 270? просто я за ним такого не замечал, на векторе 100 обычно сидела подпрограмма, которая опрашивала порт 177714 и двигала курсор мыши, чтобы он плавно двигался, без рывков.
Номиналы конденсаторов:
C1 = 10mk
C2..C9 = 68n
C10 = 4.7n
¤
У меня мышь Марсианка работала в Ксидос через блок КМ сразу. Я и не знал, может быть по-другому.
- ? gid
- 27.08.2017 16:55
Да, традиционно - при разборе любой команды со всеми относительными адресациями, действительный адрес вычисляется сразу после чтения смещения. Адрес источника вычисляется относительно адреса 1024, потому что после чтения аргумента источника счётчик команд равен 1024 - указывает на адрес аргумента приёмника. а адрес приёмника вычисляется после чтения аргумента приёмника.
- ? gid
- 14.07.2017 15:23
Да пожалуйста, пользуйтесь. У меня много всяких мнений, мне их не жалко, они всё равно в большинстве случаев неверные.
Вот видите - в далеком, аж 2011 году человек потерял файл шрифта. И с тех пор никто ему не помог, ни у кого шрифта такого не было. Очень может быть, что CD-Inc сам его и рисовал когда-то, он может.
А спектрумовский шрифт вот тут: http://zx-pk.ru/threads/14785-russkij-ttf-shrift-kak-na-spektrume.html
- ? gid
- 14.07.2017 13:22
Конечно же нету. Никому это не нужно было и никто естественно не делал этого. Но если Вы возьмётесь, и сделаете такой фонт, может он когда-нибудь ещё кому-нибудь кроме Вас пригодится.
- ? gid
- 23.06.2017 09:58
Наверное, уже ни у кого. Т.е. самого asm.com и asm.exe навалом в разных местах, а исходников почему-то нету.
Если нужен сам исходник, наверное мало кто поможет.
Если нужен работающий кроссассемблер под WIN7, то можно воспользоваться этой штукой - http://gid.pdp-11.ru/f/3.9.1703.5669/BKTurbo8.rar (для работы требуется vc_redist 2015).
- ? gid
- 06.06.2017 19:51
Таймер вложен в класс CPU потому что он является неотъемлемой частью CPU, расположен на кристалле CPU, среди других транзисторов. И так просто проще синхронизировать работу таймера с таймингами команд.
Ну, хотя, формально, его можно разместить где угодно. Этот рудимент не тянет на полноценный функциональный блок CPU.
Но мне так проще было. Поэтому.
Если в 177130 выставлять нужные биты СРАЗУ, то прошивка посчитает, что диск не крутится и вообще ничего работать не будет. Потому что она проверяет появление маркера и пропадание маркера, причём не когда хочешь, а с определённой задержкой.
Там ещё есть проблема межсекторных расстояний, которые в прошивке тоже задаются задержкой а потом просто идёт ожидание, пока не прочтётся нужный заголовок сектора, если мы уже проскочили мимо него, то совершается оборот диска, и в это время фиктивно читается вообще всё - не нужные секторы, маркеры гапов, заголовки. Пока не прочитается то, что нужно или не наступит предел ожидания - 5 гарантированных оборотов диска, т.е. индексный маркер должен появиться, и через некоторую задержку должен исчезнуть, иначе не считается.
А ещё есть проверка синхропоследовательстей чтобы убедиться, что ВП-128 правильно разбивает считанные MFM импульсы на байты, и не сбился нигде. Проверка на инверсный/прямой приём, хотя это наверное остатки кода от другого контроллера.
Если выдавать все нужные данные сразу, как в ЭД, то стандартная прошивка просто не будет работать, она на это не рассчитана. Нужно будет написать свою прошивку, которая будет работать по своему протоколу обмена данных.
- ? gid
- 06.06.2017 16:29
[тут значения трех переменных DWORD накладываются друг на друга с помощью AND и результат проверяется на !=0?]
Именно. Тут используется не логическое, а побитовое and. А если быть внимательным, то можно заметить, что m_Nbit содержит значение маски знакового бита, т.е. 0200 для байтовой операции и 0100000 для словной. Таким образом, в результате операций & у нас будет результат 0 или не 0 (0200 или 0100000). Всё корректно. Там даже комментарий есть, объясняющий смысл этой операции.
old - это предыдущее значение m_ALU, до операции, m_ALU - текущее значение.
¤
[Если мне не изменяет память, ВП-128 работает на частоте ВМ1.]
Изменяет. У ВП-128 свой кварц и генератор 4МГц, по крайней мере в контроллерах АльтПро. Про стандартный КНГМД не помню, может и нету. Правда для повышения стабильности лучше брать частоту ВМ1.
[Если гнать 128-ю, то останутся ли верными задержки и не полетит вся эмуляция к чертям?]
Задержки перестанут быть верными, надо при этом ещё и скорость вращения дискеты повышать.
У меня ВП-128 + ВМ1 синхронно на 6МГц на чтение кое-как работали, с 3.5" дисководом. С 5.25' - не работали. Но мой экземпляр ВП-128 не выдерживает долго такой частоты и зависает на шине.
¤
Отсюда мораль - эмуляцию 128-й оставлять, на 4Мгц и не париться. Однако с повышением частоты ВМ1 задержки в прошивке тоже надо будет корректировать. Ибо если проц будет быстрее работать, то и задержки, заданные SOBами будут меньше чем нужно. Поэтому нужно изобретать другой метод работы с ВП-128 и другую прошивку.
- ? gid
- 05.06.2017 11:39
>>? MM - 04.06.2017 18:47
[Один из наиболее полных наборов плавучки был в СМ-4 - см. её ТО.]
[Поиск видит только краткие ТТХ да схемы.]
Где найти ТО? Т.е. где найти инфу, из которой узнать, что вообще нужно искать? Перечень документов т.е.
А в СМ-4 аналог ВМ4 небось тоже собран на рассыпухе? Т.е. познав схему, можно будет познать внутреннее устройство ВМ4 или нет?
¤
>>? MM - 04.06.2017 21:12
[для подробногоо знакомления с предметом ( плавучкой ) следует воспользоваться оригинальными доками к PDP-11.]
Совет не удовлетворяет условию запроса. Оригинальные доки никто не удосужился перевести на русский.
¤
Кстати, никакой интересной инфы, кроме простого перечня плавучих команд с опкодами 017хххх я в просмотренных оригинальных доках не встречал. Потому что их слишком много, а какие из них нужно смотреть, чтобы узнать подробное описание, с принимаемыми параметрами, выходными данными, задействованными флагами, непонятно.
¤
>>? Spiridon - 05.06.2017 08:14
[сканов нет, есть в бумаге:]
Бумажную книгу невозможно скачать по интернету. Где сканы, Билли? Нам нужны сканы.
¤
Мне, как ленивому человеку, которому не очень-то и нужна техническая информация про FPU, но в перспективе и на всякий случай, вдруг пригодится, хотелось бы прямых ссылок, где чего скачать, чтобы почитать.
- ? gid
- 01.06.2017 10:33
[Можно ли относиться к написанию эмулятора БК на PC как к практическому средству изучения БК?]
Можно. Но это подход задом-наперёд. Потому что, не зная, как работает реальное изделие, невозможно сделать его эмуляцию.
Исходя из неверных/недостоверных представлений о функционировании изделия можно написать как-то работающую модель.
А потом, узнав что-то новое, уточнив знания, может оказаться, что модель построена в принципе неправильно и проще переписать всё заново, чем внести исправления, и так несколько раз. Таким образом скорее повышается скилл в программировании, но не в изучении БКшки.
[Что должно и не должно]
Простейшая модель - эмулятор БК0010-01 с бейсиком в ПЗУ, модель процессора - с таймингами Зальцмана, как раз рассчитанными на БК10 3Мгц, без правильного диспетчера прерываний, без учёта задержек прерываний. Как в BKBTL Никиты Зимина (за исключением прерываний, там приблизительно сделано). У меня в принципе та же модель, но немного переусложнённая за счёт того, что я не сам её делал с нуля, а доделывал и переделывал то, что было.
На счёт не должно - вопрос поставлен не правильно. Должно всё, но не всё возможно. Не нужно эмулировать то, без чего можно обойтись. Нужны компоненты: CPU (система команд их выполнение), Board (память, регистры ВП1-014, ВП1-037, можно даже тут регистры CPU) и периферия: адаптер клавиатуры, чтобы эмулировать клавиатуру БК, модуль вывода звука БК, и модуль экрана - это уже чисто платформозависимое программирование на РС.
А необязательно - эмулировать ВП1-037 целиком, а просто периодически обновлять экран как есть.
Этого совершенно достаточно для работы бейсика. Тем более, что бейсику совсем не нужны точные тайминги и синхронизация с таймерами и выводом на экран.
¤
[А где ещё есть тонкости кроме процессора?]
Во взаимодействии всех компонентов между собой на шине МПИ. Как раз которые заэмулирвоать сложнее всего.
- ? gid
- 26.05.2017 21:30
rss, не?
я сейчас только так слежу. ставить галочку, чтоб на почту сообщения приходили неохота, лень потом чистить.
- ? gid
- 26.05.2017 13:28
[получается что люди увлечённые техникой на z80 как то успешнее в жизни ]
Дело в том, что архитектура PDP-11, в отличие от Z80, так и не пошла в массы. И осталась уделом узкого круга ограниченных людей. Аудитория Z80 отличается от аудитории PDP-11 на порядки. Вот и отличия более ярко выражены.
К тому же, на мой взгляд, устройства для PDP-11 гораздо более сложнее устроены, чем Z80, и в разработке сложнее и соответственно дороже.
- ? gid
- 25.05.2017 18:58
Если есть схема - то смысл есть, без схемы - чисто для истории, чтобы где-нибудь в архиве лежало.
- ? gid
- 25.05.2017 18:56
Тут такая ситуация прослеживается - денег нет.
Есть небольшой процент людей, которых кризис никак не коснулся или они смогли перестроиться и выровняли своё финансовое положение. У них есть деньги, но они уже приобрели себе всё, что хотели, больше им не нужно.
И есть основной процент людей, у которых финансовое положение просело в 2 раза минимум, пропорционально девальвации рубля с 2014 года. Они бы и хотели бы что-либо приобрести, но позволить себе не могут - денег нету.
Это не только ретрокомпьютинга касается, это о ситуации вообще. И тенденций к улучшению не предвидится.
К президентским выборам поставлена задача максимально раскачать народ. Вызывать недовольство всем и везде, где только возможно.
Так что до 2019 года всё будет как сейчас или хуже. После - зависит от того, кто станет президентом и будет ли продолжен курс на мягкое удушение и последующий развал России.
- ? gid
- 16.05.2017 18:58
А чё такого? Ни один, не то что аудиофил, а даже радиолюбитель не будет использовать плоские красные советские конденсаторы в звуковом тракте, тем более с отломанными уголками ещё. Т.к. они фонят, звенят, шумят, их ёмкость чаще всего не соответствует той, что ни них написана и всё такое прочее.
- ? gid
- 16.05.2017 16:29
[БК-шный AY звук - ламповый]
Ну ещёб. Там на выходе, после резистивного делителя-микшера, можно сделать аналоговый тракт, причём у каждого свой, в меру своих познаний и возможностей. У меня, например, стоит ВЧ фильтр из плоского красного советского конденсатора (на который все говорят - Фуууу, говно какое) и диода КД522 вместо резистора, вносящий чудные искажения и хитро сглаживающий меандр в подобие синусоиды.
¤
[А другие форматы можете попробовать сделать?]
Геморно это. Я тупо ZXсный ассемблер вручную перевожу в БКшный. А особо непонятные места смотрю как сделано в исходниках AY_Emul. Занятие трудоёмкое и кропотливое, особенно когда ихние 8 битные вычисления в нормальный 16 битный вид переводить надо. Могу взяться, задолбаться и забросить нафиг.
- ? gid
- 16.05.2017 13:36
Итак, кому плеер PT3 на БК?
Проигрывает только PT3, более старые не понимает. Сделан только концепт - голый проигрыватель, кто захочет - может добавить визуальностей и удобств.
http://gid.pdp-11.ru/f/PT3.rar
В архиве образ дискеты с плеером и немного PT3 модулей с сайта Сергея Бульбы.
так же там исходник плеера, который можно скомпилировать моим кросс-ассемблером, или любым другим, понимающим длинные имена меток и 16ричные числа.
В качестве бонуса - старый самарский плеер Mplay, который проигрывает рокмониторовские snd и Sound Trackerовские stc модули.
Я уже не помню, зачем я его дизассемблировал, и вносил ли изменения, но его исходники тоже прилагаются. А вообще, как мне помнится, у самарцев были ещё какие-то плееры Sound Trackerовских модулей, если порыться, их где-то в образе Дмитрия Николаевича найти можно, или на разных дискетах под CSIDOS.
¤
При сравнении звучания PT3 модулей в эмуляторе БК и в плеере AY_Emul Сергея Бульбы, на БК музыка звучит медленнее, как будто в AY_Emul частота 50Гц больше БКшных 50Гц, и как будто чего-то не хватает, звук беднее и грязнее. Что возможно намекает, что есть куда улучшать эмуляцию AY в эмуляторе БК.
- ? gid
- 14.05.2017 16:59
Можно было скачать тут, на форуме, в своё время. Но 1) куда-то пропал поиск по форуму и так просто то, что нужно уже не найти. 2) все ссылки всё равно были на дропбокс, и уже протухли.
Поэтому вот: https://yadi.sk/d/aM3ClghH3J8eXN
Будем надеяться, что Дмитрий Николаевич возражать не будет.
- ? gid
- 13.05.2017 08:45
Смысла нет. В образе Дмитрия Николаевича есть всё это, и даже больше, либо уже в TSN, либо в SND, не надо мучиться выдирать, хочешь - так пользуйся, хочешь - сконвертируй в TSN и редактируй как хочешь.
- ? gid
- 12.05.2017 16:26
Что значит заработал? Я этим декомпилятором кучу snd из кучи демок обратно в tsn конвертировал. Не теряется абсолютно ничего. Единственно, что неиспользуемые сэмплы и паттерны в snd не попадают, соответственно и назад из ниоткуда не возвращаются. А так - получается tsn, звучащий абсолютно так, как было.
Единственно, не могу гарантировать отсутствие каких-нибудь ошибок, потому что, мне лень разобраться и откомментировать свой исходник. А я обычно, когда так делаю, всегда нахожу ошибки в своих прогах, которые тогда не видел.
- ? gid
- 12.05.2017 09:38
В этом архиве, вместе со всяким разным, в том числе есть исходники рокмонитора
http://gid.pdp-11.ru/f/3.9.1703.5669/BKTurbo8.rar
А там есть и компилятор TSN->SND, проигрыватель TSN и модуль воспроизведения SND. Правда не всё качественно откомментировано.
Так же туда приложен исходник декомпилятора SND->TSN без единого комментария, описания SND не сохранилось. В те времена я даже комментарии в коде не писал, т.к. драгоценного места на драгоценных дискетах было мало, а что там к чему я и так помнил.
А теперь, кто разберётся - молодец, кто не разберётся - тому и не нужно.
- ? gid
- 11.05.2017 15:59
только это описание .TSN файла. формат .SND совсем другой. Я когда-то писал декомпилятор .SND обратно в .TSN и не помню, сохранил я где-то описание .SND, или осталась только прога.
- ? gid
- 11.05.2017 14:54
Я уже писал, в посте от "gid - 06.05.2017 13:40", что фрейм у меня 40мс, так лучше.
¤
[Получается исполнение происходит рывками по размеру фрейма.]
Не исполнение, а эмуляция. Не будем же мы замедлять программу, имитируя быстродействие в 3МГц, вставляя задержки в виде Sleep(n) после каждой команды. Мы просто по-быстрому выполним всю пачку команд, укладывающихся во фрейм, а оставшееся время просто ничего не будем делать, имитируя тем самым заданное быстродействие.
[разве это достоверно?]
Таки это эмуляция, а не симуляция. Как можем, так и эмулируем.
[но если используется таймер 177706-177712]
то он тоже эмулируется, и работает точно так же - сколько тактов ВМ1 помещается во фрейм - столько тактов и обслуживается таймер, поэтому никакого расхождения.
[Или я что-то упустил?]
да. Все БКшные таймеры и счётчики тоже эмулируются, и всё засинхронизировано между собой. Чтобы независимо от длины фрейма, от эмулируемой частоты БК, звук работал с частотой дискретизации 44100 (по умолчанию), частота эмуляции вращения эмулируемого диска эмулируемой дискеты в эмулируемом дисководе была строго 5 об/сек. И чтобы такты БК равномерно распределялись между всеми событиями - квантом вращения дискеты, квантом звука.
¤
[LockVarType для чего использовать целое]
Потому что InterlockedCompareExchange не умеет байты, оно умеет только платформозависимый LONG
[bool не проще было бы]
не проще, даже если задать переменной свойство volatile, нет никаких гарантий, что при взаимодействии между потоками, не будет прочитано недостоверное значение переменной.
Я там до этого использовал Eventы, но они сильно тормозные.
¤
[А зачем 8 заголовков?]
Каждому буферу по заголовку, потому что в каждом заголовке свои параметры и флаги для каждого буфера. Иначе, как узнать, какой буфер подготовлен для передачи устройству, а какой свободен?
- ? gid
- 11.05.2017 11:47
В функции CMotherBoard::TimerThreadFunc() есть целых два ответа на этот вопрос.
А вот вам ещё один вариант. Я его давно наваял, но не видел в нём смысла, поэтому он валяется в черновиках.
UINT CMotherBoard::TimerThreadFunc()
{
#define ONE_SECOND_MS 1000
LARGE_INTEGER i1, i2, li_clock, res;
HANDLE hWaitableTimer = CreateWaitableTimer(nullptr, FALSE, nullptr); //самосбрасывающийся
if (hWaitableTimer == nullptr)
{
return -1;
}
if (QueryPerformanceFrequency(&li_clock)) //если этот метод возможно применять
{
//применим
do
{
QueryPerformanceCounter(&i1);
¤
//если процессор остановлен для каких-то целей, значит ничего выполнять не надо
//фрейм всегда выполняется полностью. Остановка делается только на границах фреймов.
if (IsCPURun())
{
// Выполняем набор инструкций
ExecuteFrame();
// Парсим скрипт, если он есть
m_pParent->GetScriptRunnerPtr()->RunScript();
}
QueryPerformanceCounter(&i2);
res.QuadPart = (i2.QuadPart - i1.QuadPart) * 10000000LL / li_clock.QuadPart; //сколько времени делались вычисления
// вычтем из времени, которое отводится на фрейм, время, которое заняли вычисления. Все расчёты в сотнях наносекунд,
// поэтому такие большие числа.
res.QuadPart = (10000LL * ONE_SECOND_MS / CPU_FRAMERATE) - res.QuadPart; //остаток, сколько надо подождать
//если есть что ждать - подождём.
if (res.QuadPart > 0)
{
SetWaitableTimer(hWaitableTimer, &res, 0, nullptr, nullptr, FALSE);
WaitForSingleObject(hWaitableTimer, INFINITE); // ждём срабатывания таймера.
}
} while (!m_lockKillTimerEvent.IsLocked()); //пока не придёт событие остановки
}
else
{
//иначе, ограничимся обычным таймером
res.QuadPart = -10000LL * ONE_SECOND_MS / CPU_FRAMERATE;
SetWaitableTimer(hWaitableTimer, &res, (ONE_SECOND_MS / CPU_FRAMERATE), nullptr, nullptr, FALSE); //периодический
do
{
//если процессор остановлен для каких-то целей, значит ничего выполнять не надо
//фрейм всегда выполняется полностью. Остановка делается только на границах фреймов.
if (IsCPURun())
{
// Выполняем набор инструкций
ExecuteFrame();
// Парсим скрипт, если он есть
m_pParent->GetScriptRunnerPtr()->RunScript();
}
// ждём срабатывания таймера.
WaitForSingleObject(hWaitableTimer, INFINITE);
} while (!m_lockKillTimerEvent.IsLocked()); //пока не придёт событие остановки
}
CancelWaitableTimer(hWaitableTimer);
CloseHandle(hWaitableTimer);
m_lockKillTimerEvent.UnLock();
return 0;
}
¤
код надо будет обратно отформатировать в любом редакторе, который это умеет.
- ? gid
- 10.05.2017 22:49
Даж не знаю. Если в эмуляторе - можно тупо в модуле CPU всем командам задать время выполнения 1 такт (0 нельзя, тогда нужно будет придумывать свой цикл обработки команд), нужен ведь разгон, а не достоверность. Задать частоту CPU как можно больше - экспериментировать надо. Отключить лишнее - эмуляцию вращения дискет, работу со звуком (эмуляция конденсатора и медиатакты), убрать эмуляцию хода луча ЭЛТ, поставить упрощенный вывод экрана - чем меньше вычислений, тем больше эмулируемых тактов влезет во фрейм.
в CMotherBoard::TimerThreadFunc() убрать таймеры, оставить просто цикл с проверкой на останов цикла и завершение потока - так мы получим чистую возможную производительность, без разделения на фреймы. Вернём таймеры обратно - снова получим фреймы, когда будет надо.
¤
Тайминги команд на PDP11/40 годятся только для PDP11/40, и больше ни для чего. Тайминги команд БК критически зависят от ВП1-037, и с таймингами голого ВМ1 не имеют ничего общего. Вообще.
- ? gid
- 10.05.2017 15:16
[На какие параметры мне обратить внимание?]
Там не в параметрах дело, а в конкретной реализации эмулируемого устройства. Например, я в эмуляторе ограничил максимальную частоту процессора ВМ1 40Мгц, потому что уже и при этом вычисления тупо не укладываются во фрейм. А значит и не возможна эмуляция работы устройства в реальном времени.
[то получается ли так, что его можно легко перевести на любую частоту?]
нет, чем сложнее и не оптимальнее эмуляция, тем ниже верхний порог быстродействия, который можно сэмулировать.
Например моя потактовая модель ВМ1 + ВП1-037 на основе верилога эмулирует работу на частоте 500кГц максимум. И ничего нельзя сделать с этой реализацией, пока или не появятся процессоры, работающие на терагерцевой частоте, или не будет переписана сама модель.
- ? gid
- 10.05.2017 10:05
Со звуковыми буферами всё просто - чем больше буфер, тем длиннее звук, туда помещаемый, соответственно, задержка между происходящим на экране и звуком заметнее, но вычислительные затраты на обработку и передачу данных звуковой карте меньше.
А чем меньше звуковой буфер, тем всё наоборот - задержка меньше, но нужно чаще эти буферы передавать железу. А там нужно залочить критическую секцию, обработать, разлочить - операции времязатратные.
Вот и получился компромисс - длина звукового буфера 10мс.
Затем, раньше количество самих звуковых буферов было довольно большое, но эта стратегия применима там, где нужна потоковая обработка данных, напр. стриминг. А для обработки в реальном времени, большое количество буферов избыточно, здесь просто недопустима ситуация с переполнением очереди. Поэтому вначале я сделал два буфера длиной в один фрейм каждый, убедился, что это плохо, и экспериментальным путём убедился, что буфера длиной 10мс достаточно, и оставил их столько, сколько влазит во фрейм, хотя по алгоритму достаточно всего 2 буфера, но мы не страдаем от недостатка памяти.
¤
Сам фрейм раньше был длительностью 20мс, но я решил отвязать все расчёты от длины фрейма, и теперь можно делать фрейм любой длительности 20*n мс (думаю, можно и меньше, но исхожу из расчёта, что минимально комфортная длина равна одному кадру в секунду, более мельтешить нет практического смысла), хоть секунду, хоть 10. Это повлияет на отзывчивость самой программы в некоторых местах на реакцию пользователя, только и всего.
¤
Про частоту не понял. Частота проца - эмулируемая вещь, она к фреймам и буферам отношения не имеет, сколько её полезает в фрейм, столько и полезает.
- ? gid
- 07.05.2017 15:37
В общем, я выше всё писал к тому, что нельзя заэмулировать то, чего нет. Можно лишь смоделировать, с разной степенью достоверности и реалистичности.
[и вперед.]
В таком случае, вам нужно было бы не к эмуляторам обратиться, а просто для начала расписать на бумаге желаемую модель: систему команд, прерываний, реакции на прерывания, всякие другие мелочи, которые сейчас не видны, но в процессе обязательно всплывут. И писать прогу - программную модель своего компьютера.
¤
[Но пока никаких вестей нет.]
Есть вестей. Некоторые люди на основе его трудов уже ПЛИС БКшку сделали для себя, я правда за результатами не следил, на сколько всё получилось, не в курсе. Собственно пока нет Pin-2-pin ПЛИС ВМ1, так и надобности в ней особой нету ни у кого.
- ? gid
- 07.05.2017 10:09
Правильно. Я тоже упёрся в этот тупик.
Чтобы сделать универсальный эмулятор, нужна потактовая эмуляция, чтобы сделать потактовую эмуляцию, нужна аппаратная реализация, хотя бы в виде схем и проектов, иначе можно тупо всем новшествам задать быстродействие 1 такт и не париться с релистичностью, всё равно этого в реале не будет, и как оно даолно быть никто никогда не узнает.
БК+: 100МГц, 32бит регистры, новые команды - это уже совсем другое железо, ничего общего с оригинальным не имеющее, соответственно, нужна своя аппаратная реализация, которую потом нужно заэмулировать.
¤
Например, я сейчас использую эмулятор как отладочный стенд, когда пишу что-нибудь для БК. Для этого он вполне подходит. Но как полноценная замена БК - нет.
Когда появится возможность сделать точную модель процессора ВМ1 с достаточным быстродействием, тогда и появится новый эмулятор.
- ? gid
- 06.05.2017 18:05
[то все съедет к чертям]
Естественно съедет. 10МГц и 3МГц - это же разные вещи, на 10МГц будет всё работать быстрее, но с совершенно неправильными таймингами, рассчитанными на 3МГц. Я поэтому возлагал большие надежды на точную потактовую модель на верилоге, но пока ничего не получается.
¤
[по крайней мере я не нашел пересчета времени выполнения команд в таблицах]
потому что мы увеличиваем частоту, а не уменьшаем время выполнения. Именно из-за этого длительность команд задаётся в тактах, а не в микросекундах. Именно поэтому во фрейме, длительность фрейма в миллисекундах переводится в количество тактов текущей частоты ВМ1. Именно поэтому там используется плавающая арифметика.
¤
[Но как тогда происходит выполнение при частоте, отличной от 3/4Мгц]
Просто фрейм не зависит от частоты, частота может быть совершенно какая угодно.
¤
Вот:
m_fTickCount += double(m_nCPUFreq) / CPU_FRAMERATE; //количество тактов процессора в текущем фрейме. При нестандартной частоте
//может быть совсем не целое число.
- ? gid
- 06.05.2017 14:52
[неистребимое мерцание экрана]
ошибка, читать как неистребимое дёрганье экрана. Изображение двигается рывками.
- ? gid
- 06.05.2017 13:40
Чё-то как-то сразу и не сказать по-простому.
1. для каждой команды есть определённое время выполнения в тактах, задаётся таблицами. Для БК10 - стабильное, для БК11 - сильно примерное, т.к. ВП1-037 довольно часто занят собой и все команды выполняются то за одно время, то за чуть большее, потому как просирается цикл ввода-вывода на шине, и приходится ждать следующего.
2. Длительность фрейма задана 40мс. Рассчитывается, сколько тактов процессора при текущей ТЧ влезает в фрейм, и всё остальное пропорционально тактам, и вот в этом цикле выполняется столько команд, сколько их длительностей полезает в фрейм.
3. сам фрейм вызывается из отдельного потока. CMotherBoard::TimerThreadFunc()
Там есть комментарий, что вообще-то точная синхронизация по звуковой подсистеме делается. У звука тоже есть звуковые буферы, которые передаются звуковой карте по мере заполнения, и пока буфер не отзвучит, следующий не передаётся, а поскольку звук звучит с заданной частотой дискретизации, получается довольно чёткая синхронизация.
И таймер в TimerThreadFunc() нужен только тогда, когда в системе вообще нет никакой звуковой карты.
4. Между фреймами не выполняется ничего, процессор ПиСи простаивает. Чем быстрее выполнятся вычисления во фрейме, тем дольше будет простаивать процессор.
¤
Но тут есть нюанс.
Мы ведь не можем всё по быстрому вычислить и по быстрому вывести на экран и в звук, а потом сидеть и ждать, когда придёт время выполнения следующего фрейма. Если на экран можно всё по-быстрому заранее вывести (из-за этого как я подозреваю у меня и неистребимое мерцание экрана), то звук приходится выводить хоть чуть-чуть в реальном времени. Поэтому фрейм разбит на 4 части, четырьмя звуковыми буферами. Т.е. фрейм выполняется в 4 рывка - по быстрому заполняет звуковой буфер, ждёт, пока предыдущий буфер отзвучит и передаёт заполненный, и так 4 раза. И так бесконечно в цикле.
¤
Я очень много экспериментировал с длительностями фрейма, количеством звуковых буферов и как этот фрейм выполнять, из-за чего код стал немного избыточным, переусложнённым и местами бессмысленным, зато остановился на том варианте, что сейчас есть, как наиболее компромиссном. Задержка звука - всего 10мс, на слух практически не заметна. Нагрузка фрейма на ядро - 40%-50% (у меня).
- ? gid
- 03.05.2017 10:35
[А не проще ли тогда вообще писать в .h только типы - bool FindTuning(int, DWORD, int); ?? И допустимо ли это?]
Допустимо, и даже практикуется. Например когда объявляешь переменную - указатель на функцию, там чтобы не загромождать код, пишут только тип.
А вот проще или нет, тут уж вам решать. Я, например, на просто Си обычно сперва пишу функцию, с параметрами в cpp файле, затем, при необходимости, просто копипащу объявление функции в h файл, мне нет смысла делать лишний труд и удалять имена переменных.
А в Си++ обычно делаю наоборот, в h файле в описании класса сперва пишу объявление функции, опять же с переменными, а потом средствами ИДЕ создаю определение функции cpp файле. Тут если не писать имена переменных сразу, то их придётся потом дописывать, опять лишние телодвижения.
¤
[А не приведет такое раздолбайство]
Это не раздолбайство, а нормальное поведение. И не костыль это, а изначально так задумано. При создании объекта класса, под него выделяется память, при уничтожении - освобождается. Всё логично.
¤
[приведение типов автоматом (типа массив+инт)]
массив+инт это никакое не приведение типов, это элементарное подведение указателя к нужному месту.
а автоматическое приведение типов, это
int i=5;
float f=i; //вот это
¤
Эта штука опасна тем, что при бесконтрольном применении и игнорировании предупреждений компилятора, можно при преобразовании типа с большей разрядностью в меньшую, получить неожиданный результат.
¤
Ну так за всё нужно платить, больше контроля и гибкости, требуют более ответственного подхода к коду.
- ? gid
- 02.05.2017 20:23
[И при компиляции нет ошибки типа определение отличается от предыдущего?]
Потому что в .h файле - объявление функции, и там имя переменной вообще не важно, его можно не указывать, там важен лишь тип передаваемого параметра.
¤
[Это нормально?]
В данном конкретном случае - вполне. Файл автоматически закрывается при уничтожении объекта CFile.
- ? gid
- 01.05.2017 20:35
даже не знаю, тут уже дело эстетики и разных желаний, нужно ли получить компактный код или быстродействующий, даже с отключенными оптимизациями.
надо включить опцию, которая генерирует при компиляции ассемблерный листинг, и посмотреть что получается, понравившийся вариант - оставить.
по мне, свич выглядит проще для понимания и работает быстрее, чем такое:
if (1 <= sectno && sectno <= 3)
{
sectorsize = 128 << sectno;
}
else
{
return false;
}
- ? gid
- 28.04.2017 19:43
[Это как?]
Очень просто.
m_drivedata - массив структур. структура имеет определённый размер.
m_drivedata + m_drive - передвинуть указатель к той структуре, номер которой равен m_drive. приведение типов делается автоматически.
[А случаем не m_drivedata + m_drive * sizeof(CFloppyDrive)??]
так тоже можно, но при этом сперва m_drivedata нужно преобразовать в BYTE*, а потом, результат сложения преобразовать обратно в CFloppyDrive* Зачем такой геморрой, когда можно тупо подвинуть индекс массива?
[Или компилятор сам поймет, что нужно поместить ссылку на элемент массива, на который указывает m_drive?]
именно. В этом то и прелесть Си. Ты имеешь полный контроль над данными. И если очень надо, можно заиметь доступ к каждому байтику чего угодно. И можно любые данные проинтерпретировать именно так, как нужно здесь и сейчас. Всякие дурацкие дельфи так не умеют, поэтому там очень трудно писать нормальные программы.[то в паскале весь этот ужас]
на си никто не мешает тоже написать абсолютно точно так же:
++*(int*)dwInstance;
¤
действие получается абсолютно то же, но я такие конструкции не люблю, поэтому стараюсь не применять.
- ? gid
- 27.04.2017 14:20
>>? vldmr@ - 26.04.2017 18:11
[скобки здесь нужны]
таки да, лажанулся я тут.
¤
[поддержана ли мыш марсианка в эмуляторе?]
Нет, не поддержана. Мышка как и джойстик эмулируется стрелками на доп.клавиатуре.
Нормальную поддержку сделать хочется, но не получается.
Какой-то редактор поддерживал. TurboVision вроде.
- ? gid
- 26.04.2017 17:02
[Чем было вызван такой подход?]
Я не разбираясь, хороший это метод или нет, просто взял это целиком из BKBTL.
Видимо так было проще, выделить одним куском память и в ней блоки организовать, чем навыделять кучу блоков.
- ? gid
- 26.04.2017 17:00
Тут всё просто, если понять суть указателя. Указатель - это адрес ячейки памяти, в которой хранится значение переменной.
WaveCallback - это Виндовс АПИшная функция, с жёстко заданными входными параметрами. В неё передаются пользовательские параметры, представляющие собой просто числовые значения.
Нам нужно в этой функции модифицировать статическую переменную m_nWaveFreeBlockCount. Поэтому мы передаём туда указатель на эту переменную, т.е. адрес этой переменной в памяти, а указатель сперва интерпретируем как число (в функции SoundGen_Initialize), чтобы удовлетворять условиями передачи параметров, поскольку адрес по сути и есть обычное число.
А чтобы адрес был всегда достоверен, переменная сделана статической.
А уже внутри WaveCallback нам входной параметр надо обратно интерпретировать как указатель.
[int *freeBlockCounter = reinterpret_cast<int *>(dwInstance);]
Вот тут как раз и делается это.
тут мы просто говорим, что входной параметр - это адрес нужной нам переменной, и адрес этой переменной запомним в переменной freeBlockCounter
[(*freeBlockCounter)++;]
скобки тут просто для красоты, они в общем-то не нужны, но мне скобок никогда не было жалко, и я всегда их ставлю там, где мне хочется, чтобы была как-то выделена и сгруппирована какая-либо операция.
Тут мы переменную m_nWaveFreeBlockCount, адрес которой теперь хранится в freeBlockCounter увеличиваем на единицу.
Вт как-то так.
- ? gid
- 26.04.2017 09:54
[вроде описание форматов zx есть в пачке в архиве?]
незнай, я в инете случайно нашёл только описание PT3 и то какое-то кривоватое. А нужны нормальные структурированные описания, где с какого смещения что находится, какие всевозможные значения этого чего, и что означает каждое значение, как его принято интерпретировать. В общем серьёзный талмуд хотя бы на пару страниц А4.
[Вот форматы на Паскале.]
Это как раз тот случай, когда с наличием исходника понимание процесса усложняется, чем с его отсутствием. Хоть бы капельку комментариев, что для чего нужно. Там в принципе имена переменных и функций понятны и самоописуемы, но для того, чтобы понять как это работает, придётся читать исходник как книгу, медленно, внимательно и конспектируя нужные места.
- ? gid
- 26.04.2017 09:42
Для БК11(М) не реализована эмуляция чтения с магнитофона как для БК10.
Поэтому для работы с магнитофоном на БК11(М) нужно делать так:
1. Отключить в опциях пункт "Эмулировать загрузку ленты"
Если нужна ещё запись с магнитофона - отключить "Эмулировать сохранение на ленту"
2. После этого в панели инструментов и меню "Файл" станет доступен пункт "Загрузить ленту..."
3. В мониторе или бейсике запускаем загрузку файла и жмём на "Загрузить ленту..."
4. Выбираем нужный .wav файл (по умолчанию - .tap, надо переключить фильтр) и слушаем как он загружается.
¤
Вот так. Надо это как-нибудь в документации описать будет.
Делать эмуляцию я счёл нецелесообразным, т.к. операция перехвата - ресурсоёмкая и не стоит заморачиваться ради 1.5 человека. Гораздо проще нужный .wav сконвертировать в .bin в "Опции"/"Менеджер лент", а его поместить в образ и пользоваться дисководом. Для бейсика - пользоваться дисковым бейсиком.
- ? gid
- 25.04.2017 20:26
Прокатит.
- ? gid
- 25.04.2017 20:24
[Я что-то не так делаю?]
Возможно. Вы не указали порядок своих действий.
¤
Прямо с магнитофона я никогда не пробовал. Мне такое даже в голову не приходило. И наверное это даже невозможно.
Обычно я загружал уже оцифрованный WAV файл.
- ? gid
- 25.04.2017 19:36
У меня изредка возникает такое желание. Но я беру себя в руки, смотрю на имеющиеся у меня исходники на ZX асме и описание формата PT3, и проходит.
Если бы были исходники плеера на Си, то я бы попробовал.
А ассемблеры ZX и x86 вызывают у меня тоску и уныние.
- ? gid
- 25.04.2017 19:18
[Почему InitOutMode вызывается по имени класса]
Потому что это статическая функция. Они так вызываются.
Функция сделана статической, потому что использует статическую переменную.
Зачем там так всё сделано - я не знаю, это ещё Юрий Калмыков всё придумывал.
Мне класс CDebugger вообще весь не нравится, его нужно переделывать полностью, почему и зачем он так устроен я не знаю, работает и ладно. Я туда в процессе столько костылей навтыкал, что это чудище уже мало на что пригодно.
- ? gid
- 25.04.2017 15:52
[Т.е в первом случае маска &O7777, а во втором &O7776. Тут не ошибка ли?]
Нету там ошибок. Смотрим в начале этих функций строку "addr &= 0177776;" т.е. младший бит мы изначально исключили, поэтому как писать: 007777 или 007776 абсолютно без разницы. С моей точки зрения. Но перфекционизма ради, можно 007777 исправить на 007776, ничего не изменится.
¤
[И не проще ли для ускорения вычислять адрес один раз в переменную, чем каждый раз заново?]
А где там каждый раз? Адрес вычисляется один раз за вызов функции, там где это необходимо. Там где не надо - не вычисляется лишний раз. А то, что там одна и та же формула накопипасчена, так зато ненавистное многим goto не используется.
¤
[используется num и тут же вычисляется адрес через addr]
А там специально комментарий такой написан: "//специально для регистров hdd smk512"
СМК умеет обращаться к слову по нечётным адресам, например 0177740 и 0177741 это два разных слова.
Поэтому, чтобы различать их введена переменная num у которой младший бит остаётся, а у addr - младший бит очищается.
Поэтому переменная addr используется там, где гарантированно не может быть обращения к регистрам СМК, а num - там где может быть.
В принципе, этот код за время писания, дописывания, переписывания и приделывания костылей для работы с СМК стал немного кривоват и избыточен, там слишком много в вызываемых функциях операций типа num & 0177776, но уж очень неохота браться за чистку. Там сперва надо расписать всю иерархию вызовов с учётом наследования, и убрать лишнее.
-
«
1 | ... | 11 | 12 | 13 | 14 | 15 | »
?