Я ещё не щупал, что за зверь, но есть шанс, что Pythran поможет?
Вид для печати
Я ещё не щупал, что за зверь, но есть шанс, что Pythran поможет?
Поработал немного над PyZX. За основу взял исходники Q-Master'а c GitHub.
1. Изменил заголовок окна. Теперь там отображается название эмулятора и FPS (можно отключить, изменив значение переменной).
2. Добавил иконку. Странно, но она отображается только в заголовке окна, а в панели задач нет. Победить проблему не смог, хотя на моём другом проекте всё отображается, как положено, в обои местах.
3. Добавил бордюр и его эмуляцию. Пришлось вбить костыль, потому что заготовка под обработку портов, которую сделал Q-Master, не работает должным образом. Обратил внимание на то, что где-то в основном коде эмуляции есть ошибка - при подаче команд BORDER 0...7, нижняя строка основного экрана закрашивается в цвет бордюра только в районе текста, а не целиком.
4. Исправил ошибку с яркими цветами чернил - чернильные цвета всегда отображались с выключенной яркостью.
5. Увеличил на несколько кадров FPS, максимально разгрузив от любых вычислений процедуру преобразования ZX-экрана в поверхность. Все данные берутся из заранее просчитанных табличек, а массив пишется в буфер за раз.
6. Сделал масштабирование экрана 1x, 2x и 3x. Переключать масштаб можно на лету клавишами F1-F3. По умолчанию эмулятор запускается с картинкой в двойном размере (можно изменить, откорректировав соответствующую константу).
А пулл-реквестик зафигачить?
PS: заготовка, да, пока не работает как надо, т.к. основная идея сделать поддержку ленты и загрузки с нее. Я сейчас там сильно.
- - - Добавлено - - -
@CityAceE:
Посмотрел код и не понял зачем костыль если можно было поправить xOutFE?
Заберу твой код в мастер на гитхабе, не возражаешь?
- - - Добавлено - - -
Еще раз посмотрел кусок с видео. Что не понял совсем:
1. Странное копирование скринов и при смене режима один из скринов остается старого размера. Чем тебе не угодила ф-ция init и почему при каждом импорте будет дергаться весь цикл заполнения всех таблиц и пересоздание скринов - неясно.
2. Зачем-то выполняется лишнее копирование в fill_screen_map() которого я, как-раз, старался избежать. Я не понял зачем гонять данные туда-сюда, учитывая что bytearray через + заполняется не просто медленно, а адово медленно. Понятнее было-бы однократное создание массива нужной длины и его уже заполнения.
Выложил эту версию сюда по большей части для тебя, чтобы ты посмотрел и, если что-то приглянулось, перетянул бы к себе на GitHub. Твой опыт в Python существенно больше моего, поэтому скорее всего ты сможешь сделать лучше, чем то, как я сделал. Поэтому я и не стал делать pullrequest. А так, конечно, что нужно забирай!
Это первое, куда я сунулся. Прежде всего я поставил туда print(port, value) и начал из Basic менять цвет бордюра. Но, к сожалению, в эту процедуру доходит только 254, 254. Разбираться что к чему я не стал, поэтому закостылил, чтобы ты потом сделал правильно.
Есть три поверхности:
1. Основной экран - он может масштабироваться, его мы и видим в окне.
2. Второй экран, он же бордюр, его размер всегда 384х256.
3. Экран Спектрума, его размер всегда 256х192.
Вывод происходит следующим образом:
1. Экран Спектрума копируется на центр экран бордюра. На выходе получаем картинку Спектрума с бордюром размером 384х256.
2. Накладываем этот бутерброд на основной экран, предварительно растянув его:
screen.blit(pygame.transform.scale(second_screen, current_mode), (0, 0))
Как раз для того, чтобы исключить include video из spectrum.py я и упразднил её. Хотя, возможно, перед этим я в другие файлы проекта этот include добавил по необходимости. В твоём варианте всё равно все таблицы рассчитывались вне процедур и, соответственно, генерировались каждый раз при include. Я думаю, что генерацию таблиц нужно выносить в отдельную процедуру.
Не совсем понимаю о чём ты. В fill_screen_map() сейчас идёт заполнение zx_array, чтобы потом его разом записать в буфер. Так получилось быстрее по сравнению с тем, что было у тебя. Я когда всё это делал, всё время держал под рукой твою версию и сверял скорость с ней, чтобы не дай бог не получилось медленнее, а вообще я, естественно, старался сделать чуть быстрее и в итоге удалось выиграть несколько FPS.
Да, в какой-то момент после разворачивания циклов перестал работать append. В итоге нарисовались две альтернативы: + и extend. Я провёл замеры и оказалось, что "+" чуть-чуть быстрее, чем extend. И это даже быстрее, чем append в цикле или 8 append'ов подряд. Это место меня, конечно, тоже расстроило.
Так?
Замеры показывают, что скорости эти не добавляет. Скорее всего нужно придумывать что-то другое.Код:def fill_screen_map():
zx_videoram = Z80.memory.mem[16384:16384 + 6912]
zx_array = bytearray(49152)
mem = 0
for line_numb in range(192):
pix_addr = addr_pix[line_numb]
attr_addr = addr_attr[line_numb]
for i in range(32):
zx_array[mem:mem + 8] = pixelmap[zx_videoram[attr_addr + i]][zx_videoram[pix_addr + i]]
mem += 8
return bytes(zx_array)
---
Выкачал сейчас твой обновлённый вариант и сравнил по скорости со своим. Например, в Basic мой вариант примерно на 1 FPS показывает больше. Примерно та же ситуация и на титульном экране Exolon'а.
---
Проверил кусок кода, который я привёл вышел. И на моём другом проекте скорость поднялась не просто чуть-чуть, а вдвое! Старый вариант c "+" выдавал 72 FPS, а в новом варианте FPS поднялся до 144!
В панели отображается.
Win7, Python 3.6, pygame 1.9.4
https://i.imgur.com/RhUpPtz.png
Я часть забрал. Спасиб.
Да. Там была смешная ошибка, которую я починил почти сразу.
У тебя 4 поверхности и 1 из них сильно лишняя. Я вообще сократил все до 2х.
Ну собственно я хочу вообще слегка исправить эмуль в архитектурном плане. Сейчас основным является Z80, но это неверно. Основным должен стать spectrum и из себя дергать уже все остальное. Я убрал часть под процедуры и вернул инит. :)
Штука в моей версии такова, что потерей 1 фпс я с легкостью могу развернуть этот цикл в линию и попробовать даже мультиколоры показать. :) Хотя это можно и в твоей версии сделать, но чуть веселее.
Ну вот смотри, твоя процедура за время своей работы 2 раза копирует данные: 1 - из pixelmap в zx_array, 2 - из него в поверхность. У меня копирование происходит по 8 точек за раз и только 1 раз. Да, чуть медленнее чем скопом, но твой вариант в целом делает то-же самое. У меня есть предположение что если пользоваться не buffer.write, а достать непосредственно мап на поверхность, то я легко верну тот 1 фпс.
[/QUOTE]
Ну вот тут ничего не могу сказать. Если попробовать еще memoryview подключить - возможно еще вырастет.
- - - Добавлено - - -
У меня все норм. Правда не на твоей версии, а на моей, но в принципе там ничего не изменено связанное с иконкой
- - - Добавлено - - -
@CityAceE, я немного извратился с твоим вариантом и возможно чуть ускорил его даже.
Спасибо за совет! Добавил сверху ещё какое-то невероятное количество FPS (см. ниже), сделав вот так:
А у меня твоя версия выглядит во так:Код:zx_array = memoryview(bytearray(49152))
def fill_screen_map(zx_videoram=zx_screen):
mem = 0
for line_numb in range(192):
pix_addr = addr_pix[line_numb]
attr_addr = addr_attr[line_numb]
for i in range(32):
zx_array[mem:mem + 8] = pixelmap[zx_videoram[attr_addr + i]][zx_videoram[pix_addr + i]]
mem += 8
return zx_array.tobytes()
https://pic.maxiol.com/images/155070...254906935..png
А вот так выглядит мой проект:
https://pic.maxiol.com/images/155070...254906935..png
Попытался твою процедуру вывода на экран целиком к себе поместить, чтобы замерить скорость и сравнить. Но она сходу не заработала (экран оставался чёрным). Потыкался, сразу разобраться не получилось в чём проблем и я бросил. Но я успел увидеть, что FPS по сравнению с тем, что у меня было ранее (144) просел где-то на 10-15 кадров.
@Q-Master, у меня есть пакет "идеальных" файлов SNA, которые я делал уже давно. Я уже писал ранее, что получал их из TZX, поставив на паузу сразу после загрузки последнего байта и потратив несколько байтов стека кассетного загрузчика. Так вот из 36 файлов корректно запустилось на текущей версии PyZX гораздо меньше половины :( Не работают игры по-разному: какие-то сбрасывают виртуальный Спектрум, какие-то зависают, какие-то портят экран, из-за некоторых вылетает эмулятор, какая-то одна игра заставила что-то выводить в консоль. В общем, вот этот пакет снепшотов. Посмотри, вдруг удастся оперативно отыскать и профиксить ошибки эмуляции.
Ну вообще странно. Я пробовал перетаскивать твою процедуру целиком и не заметил изменений по фпс. Я вчера еще по разному игрался и пробовал вообще избавиться от конвертаций типов, но по фпс ничего не добился, а вот картинку испортил.
Качнул, надо проверить что там не так. 146% что с флагами лажа где-то. :)
Видимо, потому в PyZX процедура рисования экрана отнимает лишь жалкую часть от всего времени эмуляции. Соответственно, минимальные колебания скорости построения экрана слишком сложно заметить. Поэтому и нужно тестировать скорость этой процедуры отдельно от эмулятора - строть N-ное количество экранов и сравнивать с временем построения такого же количеств экранов, но уже по другому алгоритму. На всякий случай проговорил эту очевидную вещь, хотя убеждён, что ты это и сам прекрасно знаешь.
Загнал в профайлер, сижу, медитирую на результат.
Кто-нибудь может пояснить, с чего начать?
https://i.imgur.com/muxtmT8.png
Можно вот тут почитать https://habr.com/ru/company/mailru/blog/202832/
Забрал с гитхаба файлики, Exolon работает.
Сделал в EmuzWin снапшот, гружу в PyZX - появляется начальное меню, после нажатия на клавишу вылетает.
https://i.imgur.com/6bisLSg.png
P.S.
Fuse и SpecEmu с этим снапом работают нормально.
Я тоже нашёл. Пропущена документированная RLD
_eddict
нужно добавить
, 111: rld
по ходу, там ещё косяки в командах CB
например, куча RES, и вообще нет SET.
Если я сделаю фикс, его на гитхаб как пуллреквест пихать, или что?
P.S.
проверил ED/CD команды,
Обрабатывается ряд недокументированных для ED префикса:
76, 78, 84, 85, 92, 93, 100, 101, 102, 108, 109, 110, 113, 116, 117, 118, 124, 125, 126
если смотреть по http://clrhome.org/table/
то команды 93, 109, 125 это retn, а в эмуле обрабатываются reti
если смотреть по https://www.ime.usp.br/~einar/z80table/
то должно быть reti
кто может подтвердтить или опровергнуть правильность?
Кроме rld #ED, #6F (237, 111) - в коде вызывается rlda
вероятно также глюк с rrd #ED, #67 (237, 103) - в коде вызывается rrda
Судя по протестированным играм, там ещё полным полно косяков! И очень здорово, что ты какие-то из них выявил!
Да, именно так.
@Q-Master, ты как-то планируешь дальше эмулятор развивать?
Так, ещё поломашку нашёл. Валится загрузка *.Z80
Чтобы пофиксить, в load.py
добавить
И ещё команда adc16Код:import ports
...
заменить
#Z80.outb(254, ((tbyte >> 1) % 8)) # border
на
ports.port_out(254, ((tbyte >> 1) % 8)) # border
гадит через print
P.S.
запустил тест, даже до конца не отработал, уже тяжко
https://i.imgur.com/erPLUwf.png
Да уж, в каждой группе проблемы. Может быть там везде баг одной природы?
Bedazzle, чувствуешь в себе силы поискать и пофиксить хотя бы часть?
Чтобы сделать пулл-реквест, ты всё равно сначала должен к себе склонировать, напушить коммитов с фиксами, а потом уже пулл-реквест с ними в основную репу. Так что просто клонируй и делай фиксы, как нафиксишься - можно пулл-реквест делать. Люди смогут с твоей репы забирать данные в то же время.
Bedazzle, я так понимаю, снова полез в исходники?
Bedazzle, отлично! А где твои фиксы брать?
set3fromhl()
содержит peekb вместо pokeb, из-за этого Captain Trueno вылетает, если добежать вправо до упора.
Похоже, многие игры валятся из-за того, что 31й порт не реализован.
Поменял выборку адреса по регистру I.
Взять можно тут
Эти игрушки запускаются, и на первый взгляд, играются.
Action Reflex.sna
Ball Breaker 1.sna
Ball Breaker 2.sna
Bards Tale.sna
Batty.sna
Bomb Jack.sna
Bruce Lee.sna
Capitan Trueno 1.sna
Cybernoid 1.sna
Cybernoid 2.sna
Cyclone.sna
Eric And The Floaters.sna
Exolon.sna
Freddy Hardest 1.sna
Frost Byte.sna
Head Over Heels.sna
Heavy on the magick.sna
Legions Of Death.sna
Lord Of The Rings (Part 1).sna
Mermaid Madness.sna
Monty On The Run.sna
Movie.sna
Nebulus.sna
Penetrator.sna
Rick Dangerous.sna
Ruff and Reddy.sna
Saboteur 1.sna
Saboteur 2.sna
Scuba Dive.sna
Three Weeks In Paradise.sna
Yogi Bear.sna
Zynaps.sna
У этих явные проблемы с отображением спрайтов (исчезают вообще, или дико мерцают)
Arkanoid 2.sna
Batman.sna
Dizzy7.sna
Puzznic.sna
Storm Lord.sna
Валится с ошибкой чтения (возможно, криво снятый снап)
Ramparts.sna