Просмотр полной версии : Вывод на экран со сдвигом в 4px
NovaStorm
27.01.2013, 18:10
Сейчас сделано так: в (hl) - текущее знакоместо на экране, в bc pop'аем данные для этого знакоместе(что были бы в нём без сдвига), в (de) - данные следующего по горизонтали знакоместа, скролл идёт влево.
По идее нужно 16битное значение [C или B] : (de) сдвинуть влево на 4 бита и загрузить в (hl).
Мой вариант разочаровывает производительностью =(
ld a,(de) ;правый байт
inc de ;для следующей итерации
ld (hl),c ;левый байт
rra
rra
rra
rra
rld
Можно ли сделать это быстрее?
В Silk Worm тупо копировали весь спрайт в буфер, сдвигали его там по RLD и потом уже выводили на экран.
Я тоже в буфере двигаю. Задача оптимизируется по скорости, когда чётко поставлена.
Процедура сдвигает 2 байта по адресу SPR_MOVE_BUF на полубайт вправо.
LD (SCRL_ST+1),SP
LD SP,SPR_MOVE_BUF
LD HL,ONEBYTE
POP BC
LD (ST_4+1),SP
XOR A
LD (HL),C
RRD
LD C,(HL)
LD (HL),B
RRD
LD B,(HL)
PUSH BC
ST_4 LD SP,0
; тут цикл кол-ва строк можно замутить
LD SP,(SCRL_ST+1)
RET
NovaStorm
27.01.2013, 20:39
Мне тайл вывести в одно знакоместо шириной надо. А если делать это через буфер, добавятся минимум запись/чтение, что будет наверное только хуже.
К слову на два пикселя сделано вот так:
ld a,(de)
inc de
rla
rl c
rla
rl c
ld (hl),c
Можно ли тут что улучшить? Арифметикой, например, или табличкой(кило-другое готов пожертвовать)? Я с такими извратами мало знаком =\
Попалась хорошая страничка про сдвиги http://www.chilliant.com/z80shift.html, но там делается через ADD HL, HL. А это мало того что тормознее, так мне ещё и в другую сторону надо.
RRD/RLD сам по себе довольно тормозной, я им в исключительных случаях пользуюсь.
Арифметикой, например, или табличкой
А весь набор спрайтов не продублировать (сдвинутый на нужную величину) ?
Быстрее уже некуда...
POP BC
LD (ST_4+1),SP
XOR A
LD (HL),C
RRD
LD C,(HL)
LD (HL),B
RRD
LD B,(HL)
PUSH BC
ST_4 LD SP,0
А что мешает делать RLD: DEC L или RRD:INC L?
---------- Post added at 11:33 ---------- Previous post was at 11:31 ----------
Мне тайл вывести в одно знакоместо шириной надо.
Лучше используй более крупные тайлы.
NovaStorm
29.01.2013, 14:08
А весь набор спрайтов не продублировать
За килобайт загрызу =Е
У меня 6Кб под тайлы, а вместе с кодом их вывода они должны влезть в страничку.
---------- Post added at 14:08 ---------- Previous post was at 14:04 ----------
Лучше используй более крупные тайлы.
Мне именно в одно знакоместо шириной выводить надо. Случай специфический уж больно.
Потому за сдвиги и взялся, что при не слишком катастрофичных затратах память тайлов экономится в разы.
Это на спрайтах придётся отрываться, храня сдвинутые.
А если вывести строчку тайлов в буфер, а потом оттуда сдвинуть на экран?
NovaStorm
29.01.2013, 18:03
>в буфер
Дык туда сначала записать надо будет, а потом прочитать. А у меня сразу куда надо пишется. Выгоды не будет.
Впрочем сейчас у меня всё равно другие проблемы нарисовались из-за которых всё прахом идёт.
Спрайт из банки во второй экран вывести можно только перебросив сначала вниз?
Ну, у тебя же и так 57 тактов на байт (если inc e).
А будет 16 (pop bc:ld (hl),c/b:inc h) + 22 (rld:dec l) + 16 (pop bc:ld (hl),c/b:inc l) = 54. Сплошная выгода. Если не считать памяти.
Одна идейка (просьба сильно не бить, мог напутать в показаниях):
;алгоритм вывода со сдвигом через две таблицы
*out++ = Hi2Lo[*in];
dup W-2
*out = Lo2Hi[*in++];
*out++ |= Hi2Lo[*in];
edup
*out = Lo2Hi[*in];
;примерный код
;hl - in de- out
;b - 'Hi2Lo
ld c,(hl) ;Hi2Lo + *in 7
ld a,(bc) ;Hi2Lo[*in] 7
ld (de),a ;*out++ 7
inc e ; 4
;=25
dup W-2
inc b ;Lo2Hi + *in 4
inc l ;in++ 4
ld a,(bc) ;Lo2Hi[*in++] 7
ld (de),a ; 7
dec b ; 4
ld c,(hl) ;Hi2Lo + *in 7
ld a,(bc) ;Hi2Lo[*in] 7
ex de,hl ; 4
or (hl) ;*out |= 7
ld (hl),a ; 7
inc l ;out++ 4
ex de,hl ; 4
edup ;=66 per cycle
inc b ;4
ld a,(bc) ;7
ld (de),a ;7
;=18
; E=25+18+66*(W-2) на линию
Затраты памяти- 512 байт на таблички.
NovaStorm
29.01.2013, 20:08
alone, Понял! Берём второй тайл уже сдвинутым. С памятью уже знаю как поступить, целиком дублировать не понадобится, анимированные тайлы сдвигать мне не надо. 4Кб в страничке ещё есть, может и хватит...
---------- Post added at 20:08 ---------- Previous post was at 19:32 ----------
Vitamin,
>на линию
Но мне-то хочется в столбик =)
Но мне-то хочется в столбик =)
Ну модифицируй алгоритм- в чем-то даже проще будет. Суть одна и та же- две таблицы. Причем сдвиг может быть любым, не обязательно 4 пиксела.
Alex Rider
29.01.2013, 20:57
Спрайт из банки во второй экран вывести можно только перебросив сначала вниз?
1) перебросить вниз;
2) щелкать страницами на каждый байт/слово/сколько регистров хватит;
3) хранить спрайт в 7-й банке.
NovaStorm
29.01.2013, 21:16
Vitamin, ну попробую понять, не можешь словами ещё описать? А то для меня асм почти write-only язык =(
Alex Rider,
Под вариант 3 памяти нетЪ.
>2) щелкать страницами
А может ли он быть быстрее переброса через стек?
Может ли вообще существовать такой вариант в разумном исполнении? Потому что переброс стеком - 13 тактов на байт, а попробовал пощёлкать:
ld bc,#7FFD
pop de: ld a,bank: out (c),a: ld a,(hl):and d: or e:ld (hl),a:inc l: ld a,bank: out (c),a
И лишних 19т/б. Может exx как-то можно задействовать?
Vitamin, ну попробую понять, не можешь словами ещё описать? А то для меня асм почти write-only язык =(
Ну я на псевдо-языке вначале описал что делается. В столбик не советую- будут большие накладные расходы.
Alex Rider
30.01.2013, 00:39
И лишних 19т/б. Может exx как-то можно задействовать?
Тут надо считать такты жоско, я ща не в состоянии прикинуть. С exx подстава в том, что адрес второго экрана у тебя в hl, он же тоже переключится на альтернативный... Как вариант - прикинь такие расклады:
-- bc тоже используется для переброски, а #7ffd в него заносится на каждой итерации (или используется альтернативный, например, а в de' хранятся исходная и целевая банки);
-- адрес хранится в ix/iy. Тогда можешь тягать одновременно bc (см. преыдущий пункт), de, hl, bc', de', hl'. Но! Операции с индексными регистрами ну очень меленные :(
-- как более мягкая альтернатива предыдущему пункту - для переброски используются bc, de, ix, iy, в альтернативных - 7ffd и банки.
Пока больше ничего выдумать не могу. Мне тут не так давно надо было крутить спрайт и кидать его на экран - использование альтернативных и индексных регистров сильно ускорило алгоритм. Но там ну очень уж частный случай.
А будет 16 (pop bc:ld (hl),c/b:inc h) + 22 (rld:dec l) + 16 (pop bc:ld (hl),c/b:inc l) = 54.
Даже rld:ldd вместо последних двух. Итого 50.
---------- Post added at 12:04 ---------- Previous post was at 12:02 ----------
alone, Понял! Берём второй тайл уже сдвинутым.
Нет, все тайлы без копий.
---------- Post added at 12:08 ---------- Previous post was at 12:04 ----------
>2) щелкать страницами
А может ли он быть быстрее переброса через стек?
Переброс в буфер сам по себе даёт ускорение. Не вижу смысла от него отказываться и усложнять задачу.
Кстати, на 48К (один экран) спрайты всё равно надо накладывать в буфере. Так что и для 48К это тоже выгодно.
Быструю и не сильно жручую по памяти переброску на экран можно сделать через pop: pop: pop: pop ... push: push: push: push.
NovaStorm
30.01.2013, 14:43
Быструю и не сильно жручую по памяти переброску на экран можно сделать через pop: pop: pop: pop ... push: push: push: push.
Это для одного спрайта, так как адреса фиксированные. Если делать pop hl:ld hl,(nn), то будет 13 тактов вместо 12,5 на байт, но и перемещать в буфер можно будет любой спрайт, а не один =)
---------- Post added at 14:40 ---------- Previous post was at 14:29 ----------
Ну, у тебя же и так 57 тактов на байт (если inc e).
63 у меня =(
С inc e подумаю.
Выводим столбец. В нём есть 4 пикселя от левого и 4 от правого тайлов.
В bc попаются данные левого тайла, из (de) берутся данные правого. В (hl) - экран. Вот полный код на две линии.
pop bc ;10
ld a,(de) ;7
inc de ;6
ld (hl),c ;7
rra
rra
rra
rra ;16
rld ;18
inc h ;4
;;
ld a,(de)
inc de
ld (hl),b
rra
rra
rra
rra
rld
inc h
Мозг в ступоре, пытаюсь осилить примеры.
---------- Post added at 14:43 ---------- Previous post was at 14:40 ----------
Или rld:ld b,(hl):rld:ld c,(hl): push bc - будет 46.5
Куда push? Oo
Одно знакоместо надо же в ширину.
Весь экран в ширину!
Ты сначала готовишь строку тайлов, потом её сдвигаешь и выводишь!
Насчёт вывода через push - невыгодно получается, я же забыл dec l. Надо rld:ldd.
---------- Post added at 14:58 ---------- Previous post was at 14:57 ----------
Это для одного спрайта, так как адреса фиксированные. Если делать pop hl:ld hl,(nn), то будет 13 тактов вместо 12,5 на байт, но и перемещать в буфер можно будет любой спрайт, а не один =)
Если делать pop hl:ld (nn),hl, то будет 12 килобайт кода.
NovaStorm
30.01.2013, 15:24
Да что ж я не могу объяснить-то? =(
Мне не надо весь экран, мне надо один столбик.
А кода на перекидывание спрайтов будет максимум 2*размер. Килобайт-полтора где-то от силы.
Зачем выводить один столбик?
И я не про перекидывание спрайтов, а про перекидывание экранного буфера на экран.
NovaStorm
30.01.2013, 17:21
Буфер я итак кидаю 12kb pop:ld.
А кроме этого столбца у меня всё уже нарисовано.
Я бы конечно мог показать, но спойлерить (если конечно что-то будет) не хочу.
NovaStorm
31.01.2013, 08:54
Поменял inc de на inc e, где можно. 360 тактов-то на экран не лишние =)
Не понимаю, зачем выводить один столб и при этом так загоняться с его оптимизацией... Он же весит всего 5% времени от силы.
NovaStorm
31.01.2013, 10:18
У меня он жрёт до 15-20% от перерисовки(без учёта спрайтов) _всего_ экрана.
Сейчас у меня за два прерывания скроллится экран по 2px и выводятся(из страницы 2го экрана, без переброса) три спрайта с маской 48х48. Ну и ещё остаётся чуток времени.
Проблема в том, что надо сделать вывод этих спрайтов в оба экрана из банок. В нижний-то можно непосредственно, а во второй напрямую и быстро мне способ неизвестен, а с перебросом в буфер нужно будет примерно ещё 7.5-8к тактов на спрайт, что уже не влезет в остаток времени от второго прерывания. Плюс музыка или хотя бы звук и логика ещё тыщи на три-четыре тактов =\.
Кроме вывода этого столбца оптимизировать уже нечего. Остальные алгоритмы предельно дубовы и эффективны =)
Если имеется скролл, то половина знакоместа уже нарисована.
Надо только наложить вторую половину:
1/2*pop bc
ld e,c/b
ld a,(de) ;таблица сдвига на 4
or (hl)
ld (hl),a
inc h
---------- Post added at 10:45 ---------- Previous post was at 10:44 ----------
Плюс музыка или хотя бы звук и логика ещё тыщи на три-четыре тактов =\.
Музыку можно разложить на регистры.
---------- Post added at 10:47 ---------- Previous post was at 10:45 ----------
Сейчас у меня за два прерывания скроллится экран по 2px
Хинт: можно хранить 4 сдвинутых копии экрана и перекидывать их на активный экран по очереди. И никаких битовых сдвигов.
NovaStorm
31.01.2013, 11:04
>Если имеется скролл, то половина знакоместа уже нарисована.
>Хинт: можно хранить 4 сдвинутых копии экрана и перекидывать их на активный экран по очереди. И никаких битовых сдвигов.
Ты меня обижаешь =)
Разумеется так и сделано, поэтому и нарисованной половины знакоместа нету и надо нарисовать его целиком.
---------- Post added at 11:04 ---------- Previous post was at 11:03 ----------
>Музыку можно разложить на регистры.
Всё равно ведь не меньше тыщи-полутора?
Разумеется так и сделано, поэтому и нарисованной половины знакоместа нету и надо нарисовать его целиком.
Какой код переброски? Давай оптимизируем.
Кстати, если выводить спрайты в эти буфера, то второй экран вообще не нужен. Спрайты могут лежать в верхней памяти. Код переброски на экран тоже.
>Музыку можно разложить на регистры.
Всё равно ведь не меньше тыщи-полутора?
Можно и меньше, но это уже будет экономия на спичках :)
NovaStorm
31.01.2013, 14:09
>Какой код переброски? Давай оптимизируем.
12 килов pop:ld, давай попробуем =)
Это в нижний экран. В верхний - пара-тройка килов pop:ld, остальное - цикл по 128 ldi.
В 7й страничке получается экран, переброска в него и вывод спрайта в этот экран(на будущее - из буфера спрайтов). Вниз от #C000 лежат четыре экранных буфера. И 1280 байт остатка, где и получается буфер спрайтов и код переключения страниц.
Почему так сделано... Просто одним экраном не обойтись. Перебросить экран даже c 12.5 тактов на байт(и тем более с 13 при pop:ld) за прерывание не удастся.
А в одно прерывание и не требуется укладываться. Твоя задача начать рисовать сверху позже луча и закончить рисовать снизу до второго прихода луча. Это 113000 тактов.
---------- Post added at 14:47 ---------- Previous post was at 14:46 ----------
12 килов pop:ld, давай попробуем =)
Каким образом они делают циклический сдвиг по X?
NovaStorm
31.01.2013, 15:18
Каким образом они делают циклический сдвиг по X?
Хе-хе, knowhow =)
Хотя мне казалось, что это уже где-то было, даже в worms'ах твоих.
Просто в SP грузится новое начало циклического буфера. Спрайты идут напрямую на экран, в буферах только бэк.
За лучом с буферами без спрайтов гнаться нельзя, отрисовать их не успеешь, тк не знаешь где они. Может с сортировкой по вертикали...
Я уж сколько думал над этим, а ты опять сомнений зародил =)
Спрайты надо рисовать в текущий буфер, а не на экран, тогда не надо ничего следить.
Если у тебя сдвиг нециклический, а тупо смещается начало буфера, то ты можешь копировать на экран через pop: pop: pop...push: push: push... - это должно быть быстрее.
---------- Post added at 15:42 ---------- Previous post was at 15:36 ----------
Хотя надо тогда копировщик для каждого X свой.
NovaStorm
31.01.2013, 16:42
>Хотя надо тогда копировщик для каждого X свой.
Угу, поэтому pop:ld. Сдвиг не циклический, буфер - да.
По поводу одного экрана... Надо подумать ещё. Его переброс - 80к тактов. Начинать его пересылать после начала отрисовки экрана лучом нельзя, тк память экрана неравномерна и мы скорее всего попадём под луч. Надо тогда делать линейный буфер, что сожрёт производительность =\
Плюс нужно хотя бы три спрайта, каждый тысяч на 10т...
К началу вывода спрайтов для п128 луч будет на 37 строке, в верхнюю треть вывести уже не успеем ничего. Рисовать придётся только во второй, а предпочтительней вообще в третьей. А я рисовать тоже по столбикам хотел, чтобы халявный клиппинг поиметь. Фигня какая-то получается =(
Надо тогда делать линейный буфер, что сожрёт производительность =\
Почему?
НоваШторм от нас что то прячет, хочет сделать из нас программистов :-)
Я вот задачу всё равно не понял, что откуда берётся и какие условия по наложению.
Возможно что можно достигнуть твоей поставленной цели, не решая ту задачу которую ты тут ставишь. АлКо правильно сказал - на спичках экономишь. На музыке - посмотри тему от ТМК (http://zx.pk.ru/showthread.php?t=14307) - можно тыщи 2-3 тактов сэкономить.
С экранами замут тоже не понял.
Держи экраны в основной памяти, в высокой держи перебросчик pop:push:...
Тогда пофигу какая верхняя страничка.
Какие у тебя фазы экранов? Какие фазы спрайтов?
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot