Destr, да, так и есть, A от 0 до 63.
Вид для печати
Destr, да, так и есть, A от 0 до 63.
Вот тебе ещё быстрее:
это будет 7+4+7+8+7= 33 такта :-) экономия однако, итого на 9 точек - 33*9 = 297 тактовКод:; BC = A * L
; A от 0 до 63, L от 0 до 255
; DE должно быть == #4000
add a,'MULTBL
ld h,a
ld c,(hl)
; add hl,de - добавление #40 это тоже самое что set 6,h
set 6,h
ld b,(hl)
Однако 64*256 - не самый правильный объём расчётов с точки зрения изображения на экране (одна треть экрана)
Можно сделать 128*192 (по оси X дискретность выше, по Y полный экран; или экран с X=0..191, Y=0..127)
Разместив таблицу последовательно (в каждые 256 байт 128 слов)
будет:
итого: 8+4+4+7+4+7=34 такта, зато считается половина экрана, и свободны DE и A :-)Код:; BC = H * L
; L от 0 до 127, H от 0 до 191
set 6,h - задали адрес откуда начинается таблица - #4000
; тут возможен вариант set 7,h - #8000, но тогда будет 0..127*0..127
rlc l - получили адрес младшего байта
ld c,(hl)
inc l
ld b,(hl)
В голом остатке получаем 297 тактов * 200 точек = 59400 тактов, т.е. теоретические шансы по "уложиться в фрейм 200 точек" есть, вопрос по производительности прорисовки остаётся актуальным.
Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах.
И ещё, ты строишь линии на 256 по X... будет ли меняться характер распределения (и если да, то насколько сильно), если использовать другое количество по X? Например 128, или то самое 10-20? У любой рисовалки есть подготовительная обязательная часть... Тут это станет сильно заметным...
И ещё, подправь наименования графиков (сгруппируй, чтобы удобнее читать было) в верхнем посте, не вижу что показывает второй график...
не тоже самое; добавь-ка мне #40 через set 6,h к, скажем, #6000 :)Цитата:
добавление #40 это тоже самое что set 6,h
а код куда размещать? в ПЗУ? :)Цитата:
Можно сделать 128*192
кстати,
для H от 64 до 127 будет выдавать неправильные значения.Цитата:
Код:set 6,h - задали адрес откуда начинается таблица - #4000
кстати да :) так, чтоб поржать.Цитата:
Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах
Отличная идея. Постараюсь сделать.
Если я правильно помню, я такие графики строил и ничего нового на них не увидел. Выглядят они по-другому, но только из-за того, что при изменении дельты по X незибежно меняются углы наклона, а прямые с одним и тем же углом наклона рисуются за время, пропорциональное их длине за вычетом тех самых подготовительной и финальных частей. Сравнивать такие графики корректно трудно, т.к. только часть линий (0,0)-(127,Y) имеет углы наклона в точности такие же, как линии (0,0)-(255,Y). Плюс к тому, могут быть небольшие отклонения, вызванные тем, что линии разной длины, даже одного и того же угла наклона, строятся по-разному из-за балансирования. (К слову, балансировку тоже, наверное, следовало бы отмечать при сравнении процедур.)
Что касается времени подготовки, наверное, достаточно для каждой процедуры дать время на короткой линии.
Ничего не понял. :)
Кстати, по поводу быстрых умножений-делений для прорисовки
Нужно быстрое преобразование dx; dy ---> dy1; dy2 для dx=256
причем dy1 - округленное (256*dy)/dx, а dy2 = dy1 + ((256*dy)/dx - dy1)*8
Например, для диагонали dx=255; dy=191 получится dy1=192; dy2=190
Зачем это надо? Чтоб избавиться от лишнего сложения в конструкции sub dy:jrnc:add dx
И тогда семь раз можно вычитать dy1, а на восьмой вычесть dy2, чтобы скорректировать ошибку
Экономия прямая по 4 такта на ступеньку (и вдвое больше косвенная в некоторых вариантах)
Есть вообще-то уже несколько набросков и без того заметно быстрей рассмотренных
но пока что я недоволен, надо еще быстрее (и попутно желательно покороче)
У меня получилось от 169946 тактов на (0,0)-(255,0) до 170832 такта на (0,0)-(255,175). Если это вставить в общий график, линии для Expert, Raider и Vitamin практически сольются. :)
Но: в отличие от названных процедур, бейсик выводит линии в цвете. Получается, полноценного конкурента у него все-таки нет. :)
У тебя 4 графика, их описание разбросано в посте (что не так важно, но несколько путает), но я не смог описание 2го графика вытащить :-) то ли это следует из дальнейшего обсуждения, то ли я читать разучился :-)Цитата:
Сообщение от Higgins
Согласен, моя ошибка... тогда так
Итого конечно на 3 такта больше (37 тактов), зато не используется тем не менее DE (что есть бонус на отсутствии затрат сохранения контекста этого регистра).Код:; BC = A * L
; L от 0 до 127, A от 0 до 191
add a,'MULTABL
ld h,a
rlc l - получили адрес младшего байта
ld c,(hl)
inc l
ld b,(hl)
Можно в теневое ПЗУ/ОЗУ. А можно сделать ограничения 0..176 точек (вместо 0..192), это около 4КБ даст, туда и код ложить. Однако цепляться вот не надо, у тебя там вообще 128кб надо было под одну таблицу...
Не хочу что то :-)
Построить линию длиной 1-2 точки и дать справочно базовое время работы.
Тем не менее информация интересная.
Кроме того, интересно как она построит (в тактах конечно) минимальной длины линию. Есть некий шанс что она это сделает быстрее указанных процедур. И ещё, Хотя бы 1 график на DRAW можно было бы сделать? Один из графиков (например 1й), уточночнить и добавить туда DRAW. И ещё, можно было бы графики сделать логарифмическими по оси тактов, тогда там лучшее видно будет.
Смысл обоих графиков один и тот же, но на втором показаны только две быстрейшие реализации, чтобы лучше видеть разницу.
Сейчас эти графики слиты в один и в таком виде выложены в первом сообщении темы.
Вот какие еще бродят мысли: сделать гистограммку, в которой для линий разных длин были бы даны минимальное и максимальное времена рисования. Тогда имея на руках сцену, разложенную по линиям с известными длиной и количеством можно было бы прикинуть возможное время построения, причем для любых углов, то есть как бы она ни была повернута.
Ну, на графиках такты все-таки не по экспоненте растут. ;-)
Чтобы вращать совсем быстро, надо использовать таблицу умножения 64(координаты в объекте)*256(рассчитанные координаты осей).
Каждая вершина n разворачивается в процедуру
x=OXx*X[n]+OYx*Y[n]+OZx*Z[n]
y=OXy*X[n]+OYy*Y[n]+OZy*Z[n]
;c=OXx
;e=OYx
;l=Ozx
ld b,X[n]
ld d,Y[n]
ld h,Z[n]
ld a,(bc)
add a,(hl)
exd
add a,(hl)
ld (scrX[n]),a
---
ld b,X[n+1]
ld h,Y[n+1]
ld d,Z[n+1]
ld a,(bc)
add a,(hl)
exd
add a,(hl)
ld (scrX[n+1]),a
...
59 тактов на координату.
Проверено, работает.
---------- Post added at 14:58 ---------- Previous post was at 14:53 ----------
Сейчас тут будут возгласы типа "точность никакая", так вот я отвечу.
1. Во-первых, точность принципиально выше, чем у JtN'а и аналогичных движков, потому что нет умножения умноженного.
2. Таблицы умножения, составленные с округлением вниз, - типичная ошибка, убивающая точность насмерть (JtN её тоже не избежал). Округлять надо правильно. См. исходники The Link.
2Alone> можно подробнее, что делается? Не понял с набегу.
Есть координаты в объекте: -32..31 каждая. В условном масштабе.
Есть координаты реальные: -128..127 каждая. В другом условном масштабе.
Есть оси OX (127,0,0), OY (0,127,0), OZ (0,0,127). В начале кадра мы их вертим и получаем координаты OXx,OXy,OXz, OYx,OYy,OYz, OZx,OZy,OZz.
Потом считаем вершины по три умножения на координату, как показано выше.
А почему ты говоришь про условный масштаб? Или таблица умножения разной может быть?
Разумеется!
Т.е. грубость обсчёта кроется только в неравномерности перехода более дальней плоскости обсчёта к более близкой (условном масштабе)? Чем больше страниц на обсчёт, тем качественней? Или иначе?
Грубость обсчёта заключается в том, что у суммы трёх чисел с ошибкой +-0.5 пикс. получается ошибка +-1.5 пикс. И число страниц на это не влияет.
Прикольно.
А у линии от Expert большие таблицы или строится в памяти код?
DrBars невольно ввел в заблуждение. У меня не самая быстрая линия, конечно. Если была бы нужна самая быстрая, она была бы написана совсем по-другому, с гигантскими таблицами, с гигантским кодом, выжимая каждый такт. А здесь стояла задача написать и быструю и вместе с тем компактную процедуру линии (для игры).
Sinus тоже ввел в заблуждение. Он что-то попутал. Никаких гигантских таблиц данных и кодов я не строю. Стек не использую.
Я использую "стандартные" для таких дел как установка точки 4 таблицы по 256 байт (то есть в сумме килобайт), чтобы по координатам x,y рассчитать экранный адрес и взять точку. Эти таблицы универсальны - они используются везде: и для того чтобы через plot выставить точку, и для того чтобы рассчитать адрес спрайта.
Размещаются таблицы по адресу выравненному на границу 256 байт и выглядят так:
256 байт - координата x -> начальное положение точки в байте.
256 байт - координата x -> x/8, это x-компонента добавляемая к след.экр. адресу:
256 байт - координата y -> младший байт адреса
256 байт - координата y -> старший байт адреса
В процедуре обращение к таблицам производится один раз, в самом начале, при вычислении экранного адреса по координате x,y (и взятии байта точки).
Таблицы можно или уменьшить до (384 байт экр.адр. + 8 байт сдвинутой точки), или совсем убрать, заменив на чуть более длинный расчет адреса, по типу как это делается процедурой в ROM. Это добавит лишних ~100..200 тактов на линию, но избавит от таблиц вообще.
Все это может оказаться ключевым значением для того, кто пишет игру.
можно сэкономить страничку на вертелку, если строить таблицы только для 32 засечек на каждой проекции каждой оси (9 таблиц):
ld hl,0
ld (OXxMUL),hl
ld (OXyMUL),hl
ld (OXzMUL),hl
ld (OYxMUL),hl
ld (OYyMUL),hl
ld (OYzMUL),hl
ld (OZxMUL),hl
ld (OZyMUL),hl
ld (OZzMUL),hl
...
macro zasec
add hl,de
ld (\0MUL+\1),hl
endm
macro tzasec
ld hl,(\0)
ld d,h,e,l
ld (\0MUL+2),hl
_=2
dup 30
_=_+2
zasec \0,_
edup
endm
tzasec OXx
tzasec OXy
tzasec OXz
tzasec OYx
tzasec OYy
tzasec OYz
tzasec OZx
tzasec OZy
tzasec OZz
(это 7700 тактов на кадр),
а координаты считать через
ld hl,(OXxMULx)
[xor a:sub l:ld l,a:sbc a,h:sub l:ld h,a]
ld de,(OYxMULx)
add/sbc hl,de
ld de,(OZxMULx)
add/sbc hl,de
:94*3
для 16-битных координат:
ld hl,(OXxMULX)
[xor a:sub l:ld l,a:sbc a,h:sub l:ld h,a]
ld de,(OXxMULx)
add/sbc hl,de
ld de,(OYxMULX)
add/sbc hl,de
ld de,(OYxMULx)
add/sbc hl,de
ld de,(OZxMULX)
add/sbc hl,de
ld de,(OZxMULx)
add/sbc hl,de
:193*3
Разделение на X и x - биты пополам
16 бит - 18 таблиц по 128 элементов (62208 t)
14 бит - 18 таблиц по 64 элемента (31104 t)
12 бит - 18 таблиц по 32 элемента (15552 t)
На практике 16-битные координаты внутри объекта не нужны.
Лучше с 16-битной точностью считать только координаты всего объекта, а сами вершины относительно объекта с 8-битной точностью.
Не прошло и 100 лет...
Вот моё "творчество" в виде быстрой и компактной процедуры рисования линий.
Пробовал более быстрые варианты, но предварительные расчеты в процедуре сжирают всю выгоду для небольших линий.
Неплохо! Я насчитал 244 такта на вход, не считая CALL. Но пока что по скорости обвязки ещё никто не переплюнул линию в Dies Irae (#9F6A) - там 192/227 тактов вход-выход.
Вот бы ещё фон за линией быстро восстанавливать :)
Cheburashka, и что делать с этим файлом, куда пихать?
дай исходник текстовый обычный для кросс-ассемблера
+1
Я тоже не в курсе, LINE.H - это чьих будет?
Vitamin, Можешь переделать свою процедуру рисования линии чтоб она работала без таблички, а точку (или координаты рассчитывала) ставила простой процедурой?
GM BIT, это не моя процедура. Если не ошибаюсь, ее автор- Unwinder.
Понятно.
Есть у кого процедура рисования линии (не ПЗУ)? Чем меньше тем лучше (скорость не важна)
Кроме этой http://zxpress.ru/article.php?id=7388 - она косячно рисует с апофисами на концах (как в Vibration) - ну или кто подскажет как это исправить
Что есть апофис?
Ну хрен знает как это назвать :)
http://s2.ipicture.ru/uploads/20130829/M5wxSvjR.png
http://s2.ipicture.ru/uploads/20130829/opvxpsh3.png
Процедура http://zxpress.ru/article.php?id=7388 рисует именно так (та которая коротенькая)
GM BIT, оно из этой точки рисует?
"апофис" никуда не денешь. он останется в любой процедуре. убирать только искуственно, т.е. разбивать линию на две, и рисовать их от краев к общей точке
Согласен
Помнится программка из Spectrum Expert.
Если в строке 20 будет LET E=DX, то будут эти самые хвостики.Код:(edit)
10 LЕТ DX=255:LЕТ DY=175:LЕТ Y=0
20 LЕТ Е=DX/2
30 FОR X=0 ТО DX
40 РLОТ X,Y
50 LЕТ Е=Е-DY
60 IF Е<0 ТНЕN LET Е=Е+DX:LЕТ Y=Y+1
70 NЕXТ X
Т.е. накопитель нужно приравнивать к DX/2.
Когда переводил её в асм то тоже пропустил деление, типа и так сойдет. А вот фиг...
Ну да.
Та что 50 строка должна быть после 60 (ну например 65)
И выглядеть как:
65 IF Е<0 ТНЕN LET Е=Е+DX:LЕТ Y=Y+1
Да когда это было!
(в год выхода того эксперта или чуть попозже)
С тех пор уж и дисков не осталось...
Позже я юзал линии из адвенчура или самописаные (но на основе того-же алгоритма "Б-Х") но без оптимизаций.
Хвастать нечем.
А поскольку вы тут ловите самую-присамую быструю - в том-же номере эксперта есть примеры на асме (правда только для одного квадранта)
так что желающие смогут сами дописать и потестить...
кстати, "Б-Х" можно поюзать и не для рисования линий, а например для задания вектора движения спрайтов :)