чисто исторически мы меряем всё фреймами, успевает в один фрейм (в среднем 70000тактов) = 50фпс, в два 50/2 и.т.д что там эмуляторы показывают одному автору эмулятора известно.
время выполнения обычно меряется бордюрчиком
;ждём начала кадра
halt
;синий бордюрчик
ld a,1 : out (254),a
;что надо померять
call megaDraw
;белый бордюрчик
ld a,7 : out (254),a
и получаем синенькую полосочку чтобы визуально оценить скока процедура жрёт от всего кадра :)
P.S.
Перепроверил на Spectaculator — тот показал в два раза примерно меньший фпс. Хм, видимо эмулятор Unreal у меня где то в настройках разогнан, так что всё скромнее на самом деле.
Как ты фпс считал? :) он не может быть быстрее чем период обновления экрана в два раза, т.к. даже чистая пара ldpush тратит 10.5 тактов на байт, значит 4096байт*10.5 = 43008 а это уже больше чем полфрейма, а это без учёта медленной памяти и вспомогательных вычислений
Не смог всё-таки устоять перед искушением и на выходных реализовал технику LD:PUSH+кольцо для плавного скроллинга первых двух третей экрана. На эмуляторе получился фпс близкий к 128, то есть больше, чем период обновления экрана в два раза!
А ведь когда-то я считал, что на спектруме плавный скроллинг физически невозможен.
ну если просто по одному пиксели скролить то да, один сканлайн и мультиколор тут не помешает :) циклы статей по врехушкам тоже нужны, если нужно быстро вникнуть в тему, тем более на русском в основном только по спеку инфа.
я использовал уже GPL-ную (или creative commons, типа того) версию этой гифки в своей статье тут про NES как раз тут. у меня цикл статей тоже «по верхушкам» самых разных систем и техник ранних консолей и ПК.
но, насколько я понимаю, с техникой ldpush, которая быстро перекидывает на экран теневой буфер, для вертикалкьного скроллинга достаточно иметь всего один избыточный сканлайн, который и будет перерисовываться и два экрана не надо. два экрана это нужно было на тайловых чипах где проворачивание удобно привязать к степени двойки. а у вертикалки+лдпуш+кольцо это не требуется, по крайней мере если не связываться с multycolor, иначе не уверен.
гифки не робят но поди и так видел :)
Можно ускорить если сделать только один раз ld sp и выводить в «неленейную видеопамять» %) но там другие ньюансы сразу вылезут
для бесконечного скрола достаточно будет как у меня, буфера в два экрана высотой. просто дорисовывай строчку тайлов из массива карты. примерно как на нес скролинг делается в боянистой гифке с марио :) я так изначально делал в old tower в раннем прототипе без мультиколора.
Техника ldpush вообще очень понравилась (безотносительно мультиколора). Спектрум хоть и был первым моим ПК и дал импульс к судьбе программиста, но хардкорным спектрумистом я не стал и плаваю по верхушкам. Так что если она и широко известна в узких кругах, то я лично не знал.
Сейчас чем больше про неё думаю, тем больше нравится — если всё-таки сделать JP NEXT, то можно закольцевать в бесконечную ленту и сделать вертикальный скроллер бесконечным, дорисовывая медленно только одну полоску пикселей на кадр. Интересно еще попробовать всё-таки как то ускорить LD SP,END_OF_LINE, чтобы тоже минимизировать перевычисления в кольце.
В какой-то момент у меня оставалось мало памяти и я сделал умножение как написал introspec, но потом я свернул мультиколор в цикл и появилось лишних 3кб, поэтому сейчас по таблице. Считать приходится почаще т.к. ещё спрайты рисовать надо. Но в целом там была какая-то мизерная разница :) я честно не помню почему я перешёл на табличку, кажется не влазили спрайты чуть-чуть в верхний бордер и этот мизер пришелся ко двору.
Вставлять в концы строк jr и округлять до 64 байт это не вариант, т.к. неизбежно потеряется скорость и уменьшиться количество линий которые в 16кб влазят, а там всё впритык и так. В первом фрейме на классике тактов 400 остаётся всего.
Игра достаточно расточительна и съедает почти всю быструю память. Одна быстрая страница целиков под ldpush, во второй килобайт 7 пиксельный буфер для восстановления фона, третья быстрая под четыре мультиколорных буфера, базовый для восстановления цветов под спрайтами, два рабочих которые переключаются реаализуй double buffer и третий залитый красным для эффекта смерти героя. В целом свободно только 6кб из всей быстрой памяти :)
А вообще да — искать базу умножением на 51 надо нечасто: для определения опорной строки раз на кадр и еще для спрайтов по разу. Кроме того таблица должна быть не 128, а 320, рендер ведь идёт в этот бэк-буффер. Тем не менее меня всё-равно смущает фраза «что облегчает нам все вычисления», потому что такое разложение на степени двойки как по мне так ничего не облегчает — четыре члена это почти любое число можно покрыть от 0 до 256, кроме того вставив в концы строк JR можно попросту округлить их до 64 байт, а вот это уже действительно «многое облегчает». В общем послушаем что скажет Денис.
Оптимизация не делается ради оптимизации. Да, таблица работает быстрее умножения на константу, но выполнять это умножение Денису нужно раз за фрейм (даже и раз за два фрейма, если уж совсем точно). Т.е. мы тратим лишнюю сотню тактов на фрейм, 100/70000 — это меньше 0.2% общего времени. Думаю, что у Дениса были более эффективные способы потратить 256 байт на ускорение программы.
Таблица 128*2 — 256 байт «всего», что ровно и аккуратно ложится на 8-битные инструкции, а уже одно x*32 это 5 16-битных ADD HL,HL, а еще складывать надо, поэтому и интересно.
Господи боже мой, Аве Мария! Наконец-то кто-то, впервые за 30 лет, написал хорошую, годную, без авторского самолюбования, понятную обычному человеку статью про мультиколор!
время выполнения обычно меряется бордюрчиком
и получаем синенькую полосочку чтобы визуально оценить скока процедура жрёт от всего кадра :)
Перепроверил на Spectaculator — тот показал в два раза примерно меньший фпс. Хм, видимо эмулятор Unreal у меня где то в настройках разогнан, так что всё скромнее на самом деле.
А ведь когда-то я считал, что на спектруме плавный скроллинг физически невозможен.
но, насколько я понимаю, с техникой ldpush, которая быстро перекидывает на экран теневой буфер, для вертикалкьного скроллинга достаточно иметь всего один избыточный сканлайн, который и будет перерисовываться и два экрана не надо. два экрана это нужно было на тайловых чипах где проворачивание удобно привязать к степени двойки. а у вертикалки+лдпуш+кольцо это не требуется, по крайней мере если не связываться с multycolor, иначе не уверен.
Можно ускорить если сделать только один раз ld sp и выводить в «неленейную видеопамять» %) но там другие ньюансы сразу вылезут
Сейчас чем больше про неё думаю, тем больше нравится — если всё-таки сделать JP NEXT, то можно закольцевать в бесконечную ленту и сделать вертикальный скроллер бесконечным, дорисовывая медленно только одну полоску пикселей на кадр. Интересно еще попробовать всё-таки как то ускорить LD SP,END_OF_LINE, чтобы тоже минимизировать перевычисления в кольце.
Вставлять в концы строк jr и округлять до 64 байт это не вариант, т.к. неизбежно потеряется скорость и уменьшиться количество линий которые в 16кб влазят, а там всё впритык и так. В первом фрейме на классике тактов 400 остаётся всего.
Игра достаточно расточительна и съедает почти всю быструю память. Одна быстрая страница целиков под ldpush, во второй килобайт 7 пиксельный буфер для восстановления фона, третья быстрая под четыре мультиколорных буфера, базовый для восстановления цветов под спрайтами, два рабочих которые переключаются реаализуй double buffer и третий залитый красным для эффекта смерти героя. В целом свободно только 6кб из всей быстрой памяти :)
Мне кажется наоборот — уже слишком много людей понимают, как это делается. Чересчур много! Пора бы уже начать распонимать обратно :)
Денис, шапки долой! Замечательная статья!