ivagor, вроде в emu какой то баг связанный с контроллером НГМД чинили в последнем билде.
Вид для печати
ivagor, вроде в emu какой то баг связанный с контроллером НГМД чинили в последнем билде.
Про починку околодискового бага я читал, поэтому пробовал в нескольких версиях (в т.ч. в последней), везде виснет. Присылать наверно пока смысла нет, возможно исправление странного бага с call поможет.
Не в emu, а в emu80. Есть ещё мой эмуль, исторически называется emu.
- - - Добавлено - - -
Да прикольно было бы. Но нужна отладочная информация. В принципе, листинг выдаваемый ассемблером подходит, но в разных ассемблерах они разного формата, предназначены для человека, а не для программы.
Прости пожалуйста. не знал про твой эмулятор.Цитата:
Не в emu, а в emu80. Есть ещё мой эмуль, исторически называется emu.
Мне очень в последнее время нравится retro assembler. Былио бы здорово иметь возможность отлаживать с его синтаксисом .Цитата:
Да прикольно было бы. Но нужна отладочная информация. В принципе, листинг выдаваемый ассемблером подходит, но в разных ассемблерах они разного формата, предназначены для человека, а не для программы.
Попробовал, к сожалению не помогло. Там проблема даже не с кодом моей программы. Если она в конце образа дискеты, то дос ее не может нормально загрузить и запустить. Если в начале - загружает и запускает, но там уже спотыкается на загрузке основного файла. Вероятно проблема в работе с образом, надо трассировать дос, но не хочется.
как я могу узнать в программе в каком режиме сейчас подключены квазидиски?
Мне нужно это делать в прерывании. я переключаю в прерывании квазидиск на нужный мне режим, и потом мне нужно востановить прежний режим.
Сейчас я делаю это через глобальную переменную в основной программе:
В прерывании когда мне нужно востановить режим я считываю ramDiskMode и записываю в out $10. Но ramDiskMode не гарантирует что квазидиск уже в этом режиме когда прерывание произошло между sta ramDiskMode и out $10.Код:mvi a, _command
sta ramDiskMode
out $10
Есть мысли сделать две глобальные переменные, одну до и одну после OUT или пытатся читать из порта 10, но для начала решил узнать у вас можеть есть способ лучше/проще.
Заранее спасибо!
Ну и что, намерение то установить именно режим записанный в ramDiskMode. Если между sta и out случится прерывание, то по выходу из прерывания уже будет ramDiskMode и следующий out его просто продублирует. Сильно заморачиваться этим вопросом имело бы смысл для некоей гипотетической супернавороченной операционной системы, а для игрушки и так вполне нормально. Чтение из 10h в квазах, насколько я знаю, не реализовано (в современных могли бы реализовать для той самой гипотетической ОС).
ivagor, вот я и руководствуясь этой логикой сделал так, но что-то идёт не так и спустя время начинают портится данные то в квизидиске, то в основной памяти.
Возможно просто не туда капаю.
Чтения конфигурации нет ни у одного из вариантов квазидисков, в том числе на комбодевайсах и ERAM.
Наиболее простым будет запрет прерываний до обращения к КД и разрешение после, тем более при подключении квазидиска в режиме "стек" и срабатывании прерывания данные на нём будут гарантировано испорчены, т.к. при вызове прерывания в стек пишется адрес возврата.
С восстановлением стека при чтении с квазидиска я справился, спасибо ребятам с этого форума.
- - - Добавлено - - -
О, спасибо ! Попробую.
Но было бы здорово понять в какой момент идёт порча данных. Чуть попозже выложу больше информации что у меня происходит.
- - - Добавлено - - -
А если в момент прерывания они запрещены, то вызов откладывается до следующего ei, или вообще пропускаются?
Если второе, то музыка в прерывании будет чудить и другие штуки завязанные на прерывание.
Спасибо за инфу. А недолго это сколько ?
- - - Добавлено - - -
Это помогло. Спасибо. Но вот очень хочется понять почему такое происходит.
Если кто-то поможет найти ошибку, заранее большое спасибо!
Ниже эээто код прерывания
все места в основной программе где используется квазидиск обернуты вот такими вставками:Код:Interruption2:
; get the return addr which this interruption call stored into the stack
xthl
shld @return + 1
pop h
shld @restoreHL + 1
; store psw as the first element in the interruption stack
; because the following dad psw corrupts it
push psw
pop h
shld STACK_INTERRUPTION_ADDR-2
lxi h, 0
dad sp
shld @restoreSP + 1
; restore two bytes that were corrupted by this interruption call
push b
; dismount ram disks to not damage the ram-disk data with the interruption stack
xra a
out $10
lxi sp, STACK_INTERRUPTION_ADDR-2
push b
push d
call GCPlayerUpdate
INTERRUPTION_MAIN_LOGIC()
pop d
pop b
pop psw
mov l, a
; restore the ram-disk mode
; ramDiskMode doesn't guarantee that a ram-disk is in this mode already. that mode could be applied only after the next command in the main program
lda ramDiskMode
out $10
; restore A
mov a, l
@restoreHL: lxi h, TEMP_ADDR
@restoreSP: lxi sp, TEMP_ADDR
ei
@return: jmp TEMP_ADDR
.closelabels
...Код:mvi a, _command
sta ramDiskMode
out $10
Последний билд можно взять тут.Код:xra a
sta ramDiskMode
out $10
https://github.com/parallelno/Vector...GameNoname.rom
call GCPlayerUpdate это плеер gigachad16 который начинает глючно играть вконце трека.
INTERRUPTION_MAIN_LOGIC() это код для опроса клавиатуры и прочего
Глюк влияет на музыку. Ее данные в основной памяти. После нескольких повторов трека, она становится все более поломанной. И только один раз я заметил что спрайты скелетов стали покарапчены. Их данные в квазидиске.Код:; interruption logic
mvi a, PORT0_OUT_IN
out 0
xra a
out 3
IN 2
inr a
sta anyKeyPressed
mvi a, $fe
out 3
IN 2
sta keyCode
mvi a, PORT0_OUT_OUT
out 0
lda borderColorIdx
out 2
lda scrOffsetY
out 3
lxi h, interruptionCounter
inr m
Эти глюки происходят только если игра не синхрониизированна с прерываниями, т.е не имеет hlt в основной цикле. то есть прерывание может прервать основную программу в любом месте.
Если добавить di/ei как посоветовал Pyk, то чинится.
Пытаясь починить баг, я попробовал записывать 0 в регистры AY, очищать буфер музыки по окончанию трека, перенес инициализацию и эти очистки в основную программу чтобы не делать прерывание слишком долгим, но это не помогло.
Буду очень благодарен если кто-то поможет найти багу! Заранее спасибо!
Про время удержания запроса прерывания боюсь соврать. Надо в схему заглянуть, но там не всегда очевидно.
Код в Interruption2 выглядит странно, но я может быть не разобрался. То есть я понимаю: мы аккуратно складываем состояние в переменные, чтобы не запортить еще больше стека. Но что такое push b и как он помогает restore two bytes that were corrupted by this interruption call ? Это видимо знаменитый "метод Медноногова", или что-то типа того? Я с ним незнаком, но выходит, что в паре bc тут каким-то образом находятся заветные восстановительные данные. А они там правда есть? Всегда-всегда? Как можно это гарантировать, если прерывания случаются вообще в любой момент?
svofski,
Если главная программа читает данные из стека для например рисования на экране или любых других случаев когда sp указывает не на стек главной программы, а на некие данные мы всегда читаем так pop B. Это гарантирует что bc можно использовать в прерывании для восстановления стека. Если же прерывание случилось когда главная программа использовала обычный стек, то push b в прерывании ничего не делает полезного, но и ничего не портит.
Не помню чей именно это метод изначально, но впервые я прочитал о нем от Jerry на этом форуме.
Кажется я нашел в чем была проблема. После того как в основной программе я делал xra a, out $10, я восстанавливал стек lxi sp, xxxx. Если прерывание происходило после out $10, то стек указывал на адрес в квазидиске где-то в районе 4k, это как раз попадало на музыку в основной памяти.
Поменял местами восстановление стека и выключение квазидиска и все стало работать как нужно. Можно двигаться дальше :)
- - - Добавлено - - -
Лечение не идеальное, так как прерывание будет корраптить данные квазидиска в этот момент и восстановить не получится, но в моем текущем случае это не страшно так как стек основной программы находиться в диапазоне $7ff80-$8000 и по эти адресам ничего полезного в квазидиске нет.
- - - Добавлено - - -
Лучше всего наверное использовать квазидиск для стека в основной программе. Это наверное упростит инициализацию данных после старта если программа будет больше 32к. Можно будет не боятся что стек запортит основную программу.
- - - Добавлено - - -
Если программа запускается из под операционной системы, может ли она менять данные ниже $100? Или они зарезервированы под систему?
- - - Добавлено - - -
Было бы интересно узнать, но не супер важно сейчас, так как основная программа не делает di
То есть на то место где обычно лежит адрес возврата, кладет содержимое bc. Ну что ж, наверное действительно в большинстве случаев это приемлемо. Все равно стремно как-то ;) Особенно при том, что еще и банки памяти щелкаются постоянно. Отлаживать такое можно рассудок потерять.
Да, именно так. Ну вы ребята опытные, я надеюсь что выручите советом если опять что-то забарахлит. Было бы классно получить больше функций отладки, это поможет тоже. :)
- - - Добавлено - - -
svofski, я до сих пор под впечатлением от gigachad16. Наверное ничего сложнее в игре уже не будет :)
Парадокс в том, что он на порядок проще любого другого плеера и писать его было легко и чуть-чуть прищурившись можно даже прочитать. Просто переключает задачки, а задачки -- тот же dezx0, который и так уже все видели и в который я вникал лишь минимально (и спасибо ivagor-у за такой классный dezx0!). Все крайне регулярное, никаких семиэтажных ветвлений, все управляется только данными.
Ну и кстати, имея ядро можно не ограничиваться использованием его только для проигрывания музыки. Как раз ему приходится пропускать два фрейма вхолостую. Можно туда добавить две другие задачи (им можно указать другой размер стека, побольше). В общем хоть всю игру можно так забацать.
- - - Добавлено - - -
Заглянул в схему. Все упирается в форму F50Гц, это шина 6.28, прямой выход D8.2. Понять длительность импульса без осциллографа я тут не в состоянии, а мой Вектор сейчас в собранном виде.
Насколько я понимаю, длительность F50 не влияет, по фронту взведется D26.2, и если INTE=0 (вход 10), то запрос INT сбросится.
Угу. Я просто почему-то был не уверен за то, как обрабатывается выход из сброса при поднятом клоке у D26.2.
Но в любом случае лучше программировать не надеясь на глюки микросхем.
Подскажите пожалуйста по адресам $80-$ff. Если там держать стек, будет ли это портить данные операционок на векторе?
- - - Добавлено - - -
И вопрос про квазидиск Баркаря. Его режим переключения на подмену памяти с $8000-$ffff как то по особому включается или всегда такой? Если ли возможность как то в программе определить какой тип квазидиска установлен?
Ребят, допустим я запускаю на Векторе Z80 какой-то .rom файл. Нужно ли делать какую-то специфичную инициализацию вначале, именно специфичную для Z80 Вектора?
В общем случае можно ничего специального не делать.
На векторе, если между фронтом F50 и проверкой запроса прерывания в проце прерывания запрещены, то прерывание пропускается.
ivagor, извини, но честно говоря не понял о чём ты пишешь.
Н.Н. Щелкунов, А.П. Дианов. Микропроцессорные средства и системы. М.Радио и связь, 1989, стр. 61-62
"При условии INT*INTE=1, которое проверяется в последнем такте каждого командного цикла (за исключением команды EI), МП должен перейти к процедуре обслуживания запроса".
С учетом того, что я написал выше - пропускается, не откладывается (уточню, что речь о стандартном 06Ц с ВМ80).
да
Спасибо!
Я это уточнял потому что эта информация объясняет починку бага командами ei/di которые посоветовал Pyk. Там лечилось похоже не из-за того что прерывание не могло быть вызвано до out $10, а из-за того что следующая за ei команда гарантированно выполнялась сразу после ei. Это была lxi sp,
Все зависит от задач. Если, например, нужно играть фоновую музыку по прерываниям, то не надо использовать ei и di. В этом случае надо так изменять sp, чтобы ничего не повредить.
Не могу найти подручного беззнакового умножения 8x8 -> 16. Ни у кого не завалялось?
Так, наверное, потому, что это тривиально ...
Если устраивает совсем медленно, то просто последовательным сложением. Один аргумент в A, второй в DE, нулим HL, и увеличиваем его командой DAD количеством раз, которое в регистре A. Это даже 8x16, между прочим.
Если множитель большой, где-то больше шести, то побитово в столбик. Множитель умножаем на два через XCHG: DAD H: XCHG
Upd: nevermind, нашел.
svofski, если не сложно, поделись пожалуйста. Я помню только в документации к векторовскому ассемблеру были описаны рутины умножения и деления кажется. Но сам код уже не помню.
Конечно, правда я уже забыл откуда сам списал.
Но вот правда же, была где-то страничка с хорошим сборником всевозможной арифметики для 8080.Код:; hl = h * l
mul8x8:
mov A,h ; Multiplier (-1) to A Register
mov e,l ; Multiplicand (127) to D,E Registers
MVI d,000h
LXI H,000h ; Clear H,L Registers to initialize Partial Product
MVI B,008h ; Iteration Count (8) to B Register
m88LOOP: DAD H ; Shift Partial Product left into Carry (H&L)
RAL ; Rotate Multiplier Bit to Carry
JNC m88NEXT ; Test Multiplier at Carry
DAD D ; Add Multiplicand to Partial Product (D&E)
; if Carry =1
ACI 000h ; (Add Carry Bit)
m88NEXT: DCR B ; Decrement Iteration Counter
JNZ m88LOOP ; Check Iterations
ret