Вход

Просмотр полной версии : Синхронизация в нижней части экрана



Jimmy Falcon
19.04.2020, 17:02
Спустя 30 лет после молодости решил под ностальгическим настроением намалевать игрулю под Спектрум. Пишу на АСМе в SpectnetIDE под Visual Studio. Штука исключительная, очень нравится.Хочу сделать XONIX. Нолики (враги) будут кубики из 4 пикселов, рутину рисования написал сам (т.к. готовые граф движки с первого взгляда сложны и громоздки, а спрайты мне в принципе не нужны). Программеры знают, что экран надо обновлять когда он не отрисовывается. Обратный луч отлавливаем через HALT. Сейчас пришел к такому алгориту:

while (1) {
HALT (начался обратный ход луча)
Рисуем врагов
Задержка (цикл)
Разные задачи (чтение клавы, перемещение игрока итд)
Удаляем врагов
Перемещаем координаты врагов
}

Схема эта работает, всё летает плавно на 50 Гц до 7 врагов (пока), проблема только в том, что подпрограмма рисования врагов выполняется разное кол-во циклов в зависимости от кол-ва врагов, и вся остальная часть программы сдвигается. Также и Разные задачи занимают разное время в зависимости от действий игрока. В принципе, это можно компенсировать табличной подстройкой задержки, но моя цель,что задержка должна автоматически заканчиваться когда луч начинает рисовать бордюр в нижней части экрана. Иными словами, мне нужно задержкой автоматически охватить всю видимую часть экрана, исключая бордюр. Но команда HALT наступает позже (когда бордюр полностью нарисован). Если ставить задержку сразу после HALT и дотягивать её до низа экрана, теряется добрая половина хорошего времени обратного хода когда я мог бы рисовать.

Поэтому вопрос такой: чем засинхронизироваться в нижней части экрана где начинается нижний бордюр? Нашёл в инете описание способа floating bus (никогда раньше о нем не слышал. Вкратце суть: если читать из несуществующего порта (например #FF), можно получить байты данных, которые "видеокарта" в данный момент выводит на экран. Описание вот http://sky.relative-path.com/zx/floating_bus.html), это конечно очень круто, но большие проблемы с совместимостью: на разных спектрумах работает по-разному, в эмуляторах тоже не очень корректно либо не работает совсем. Живой синклер 48к у меня есть, но пока руки не дошли его запустить (куплен на Ebay с неисправностью, повозиться с ним надо). Да и загружать постоянно на спектрум конечно долго и неудобно.

Может кто сталкивался с такой проблемой и знает её корректное решение?

goodboy
19.04.2020, 17:32
Нолики (враги) будут кубики из 4 пикселов, рутину рисования написал сам
как вариант http://spectrum4ever.org/download.php?t=fulltape&id=1392
только управление там больно мудрёное R/F,D/G

zebest
19.04.2020, 17:44
чем засинхронизироваться в нижней части экрана где начинается нижний бордюр?
это я так понимайю нижная часть бордюра?
https://s.micp.ru/pin2f.jpg
(синяя в данном случае) Тогда - зачем?
или все же нижнаяя треть экрана?)

Jimmy Falcon
19.04.2020, 18:08
это я так понимайю нижная часть бордюра?
https://s.micp.ru/pin2f.jpg
(синяя в данном случае) Тогда - зачем?
или все же нижнаяя треть экрана?)

Да, синяя часть. Зачем, я написал в 1м посте.

zebest
19.04.2020, 18:17
Ксоникс на бордюре?? хм. а синронить под какую машину? у них у всех разные тайминги, zx48\zx128\pent\далее со всеми остановками. Все равно я не знаю такого метода, чтобы отловить начало нижнего бордЕра. вон ,например, мультиколор задержками выровнять и то не могу :(

jerri
19.04.2020, 19:40
Jimmy Falcon, я предлагаю другой вариант.
если сможешь уложиться в 16000 тактов

то после HALT стираешь, потом рисуешь врагов.
врядли у тебя их много.

Jimmy Falcon
19.04.2020, 20:10
Ксоникс на бордюре?? хм. а синронить под какую машину? у них у всех разные тайминги, zx48\zx128\pent\далее со всеми остановками. Все равно я не знаю такого метода, чтобы отловить начало нижнего бордЕра. вон ,например, мультиколор задержками выровнять и то не могу :(

Ну вот методом плавающей шины можно, но я боюсь совместимость будет хреновая. То есть надо будет на всех машинах тестить. Я помню синклеровские игры которые хреново работали на Краснодаре из-за плохих таймингов, я так не хочу. ))


Jimmy Falcon, я предлагаю другой вариант.
если сможешь уложиться в 16000 тактов

то после HALT стираешь, потом рисуешь врагов.
врядли у тебя их много.

С небольшим количеством врагов (1-3) это работает, а на больше не хватает. Потому что в таком раскладе полностью пропадает тот кусок времени что показан на фотке выше синим цветом. При том, что мой вариант с задержкой легко тянет 7 врагов без лагов и мерцаний. А количество врагов в xonix растет бесконечно с каждым уровнем, хотелось бы сделать максимум.

Lethargeek
19.04.2020, 20:29
С небольшим количеством врагов (1-3) это работает, а на больше не хватает.
Нужно рисовать построчно (хотя бы по символьным строкам), тогда луч догонит ниже, и тактов у тебя будет больше. Еще можно в верхней трети экрана разместить инфопанель, хоть и не всегда красиво получится.

- - - Добавлено - - -

либо у тебя есть обязательный код примерно на те же 16k тактов, который выполняешь до отрисовки и потом уже за лучом спокойно рисуешь (тоже по строкам)

jerri
19.04.2020, 20:55
С небольшим количеством врагов (1-3) это работает, а на больше не хватает. Потому что в таком раскладе полностью пропадает тот кусок времени что показан на фотке выше синим цветом. При том, что мой вариант с задержкой легко тянет 7 врагов без лагов и мерцаний. А количество врагов в xonix растет бесконечно с каждым уровнем, хотелось бы сделать максимум.

ок

покажи процедуру рисования врага.

есть еще вариант
сделать статичное время отрисовки врага

Jimmy Falcon
20.04.2020, 10:58
В итоге так:


Sync:

ld e,#0f

uim2: ld a,(#5880); <<- шедевр программирования, почти анекдот
ld a,e; <<- про два jmp'а подряд :)
in a,(#fd)
cp e
jr nz,uim2

Область атрибутов экрана в которой хотим чтобы сработал этот Sync нужно закрасить кодом 0xF. HALT вообще убрал, прерывания запретил. В итоге, сходу 9 врагов летают на 50fps без тормозов! Работает на эмуляторе Specnetide. На других пока не пробовал. Пришла ещё мысль переписать немного процедуру передвижения врагов чтобы можно было переместить её в "рисовальную" часть растра (сейчас она в силу алгоритма находится в тёмной части). В общем, попозже погоняю на разных эмулях.

А вообще, если кому интересно, процедура проверки работы floating bus вот (целиком):

floating:

ld a,#f
ld b,32
ld hl,#5a40
um1: ld (hl),a
inc l
djnz um1

fl_bus:

ld e,#0f

um2: ld a,(#5880)
ld a,e
in a,(#fd)
cp #f
jp nz,um2
ld a,1
out (254),a
ld b,128
djnz $
ld a,7
out (254),a
jr fl_bus


Она должна рисовать синюю полосу на экране и такую же на бордюре. Если на бордюре не рисует, значит не пашет у вас. ) Попозже .tap скину для проверки.

zebest
20.04.2020, 12:09
Она должна рисовать синюю полосу на экране и такую же на бордюре. Если на бордюре не рисует, значит не пашет у вас. )
у нас из 4х попавшихся под руку эмулей - в 2х - работает, в 2х - нет. Это в софтовых.
В хард-эмуле в режиме пятногона - работает, в режиме zx48 - нет. Так, для статистики.
За пример - спасибо.

jerri
20.04.2020, 17:18
В итоге так:


Sync:

ld e,#0f

uim2: ld a,(#5880); <<- шедевр программирования, почти анекдот
ld a,e; <<- про два jmp'а подряд :)
in a,(#fd)
cp e
jr nz,uim2

Область атрибутов экрана в которой хотим чтобы сработал этот Sync нужно закрасить кодом 0xF. HALT вообще убрал, прерывания запретил. В итоге, сходу 9 врагов летают на 50fps без тормозов! Работает на эмуляторе Specnetide. На других пока не пробовал. Пришла ещё мысль переписать немного процедуру передвижения врагов чтобы можно было переместить её в "рисовальную" часть растра (сейчас она в силу алгоритма находится в тёмной части). В общем, попозже погоняю на разных эмулях.

А вообще, если кому интересно, процедура проверки работы floating bus вот (целиком):

floating:

ld a,#f
ld b,32
ld hl,#5a40
um1: ld (hl),a
inc l
djnz um1

fl_bus:

ld e,#0f

um2: ld a,(#5880)
ld a,e
in a,(#fd)
cp #f
jp nz,um2
ld a,1
out (254),a
ld b,128
djnz $
ld a,7
out (254),a
jr fl_bus


Она должна рисовать синюю полосу на экране и такую же на бордюре. Если на бордюре не рисует, значит не пашет у вас. ) Попозже .tap скину для проверки.Порт обычно берется #ff
Но это работает не везде.
Ты процедуру рисования врага кинь