А знает кто-нибудь быстрый способ поскроллить строчку на экране на 2 пиксела в одном цикле перебора байтов? Ну, вернее, есть ли способ быстрее, чем 2 раза подряд на 1 пиксел?
Вид для печати
А знает кто-нибудь быстрый способ поскроллить строчку на экране на 2 пиксела в одном цикле перебора байтов? Ну, вернее, есть ли способ быстрее, чем 2 раза подряд на 1 пиксел?
Так определись, чего именно скролить... потом уже процедуру придумывай.
с табличками это примерно так
по алгоритмуКод:ld bc,head_table
dup nn
ld a,(de)
ldi
ld l,a
ld h,b
ld h,(hl)
edup
данный скроллер позволяет скроллить на расстояние от 1 до 6 бит без изменения программы
и соответственно таблицы занимают от (2+1)*256 до (64+1)*256
как это работает:
у нас есть так называемая head_table где прописаны адреса таблиц скролла откуда мы уже берем сдвинутые данные для следующего байта.
генератор головной таблицы
генератор таблиц скроллаКод:ld hl,head_table
ld de,roll_table
ht0
ld a,l
and #03 ;размерность таблицы 2 бита (сдвиг на 2)
add a,d
ld (hl),a
inc l
jr nz,ht0
Код:ld hl,roll_table
ld bc,#0400 ;размерность таблицы (2 бита *2 значения)
rt0
push bc
rt1
ld b,2 ; на сколько битов скролл
ld a,c
ld (hl),l
rt2
rra
rr (hl)
djnz rt2
inc l
jr nz,rt1
inc h
pop bc
inc c
djnz rt0
Сразу скажу - такты не считал.
Но попробуй - может так быстрее будет ?
pop hl
rr h
rr l
ex af,af'
rr h
rr l
ex af,af'
push hl
dec sp
dec sp
(или INC sp - смотрю куда крутить ну и RR или RL)
Круто, спасибо! Но переделывать уже поздно :) Во-превых, заоптимизил остальное, что мешало во фрейм уложиться. Во-вторых, сузил область скролла. В третьих, отправил готовое на сборку уже :) Буду иметь в виду сей фокус.
Потестил, с ADC не получается :(
Но, можно так:
38 тактов на байт, без таблицы.Цитата:
LD C,(HL) ; 7
RL C ; 8
RLA ; 4
RL C ; 8
RRA ; 4
LD (HL),C ; 7
некий слоупочный скроллер вышел, 44(или 48?)такта на байт.
нутром чую, что можно оптимизировать, но быстрее не выйдет.
А чего его дергает то? :rolleyes:
Ой, чё за жесть внутри? :v2_dizzy_facepalm:
denpopov, а чем тебе идеи предложенные ранее не понравились?
Просто как вариант. В лоб, без таблиц и стека.
Скролл на 3 бита(пикселя)
46 тактов на байт.
Код:LD C,$F8
....
LD A,(HL)
RLCA
RLCA
RLCA
LD E,A
XOR D
AND C
XOR D
LD (HL),A
DEC L
LD A,(HL)
RLCA
RLCA
RLCA
LD D,A
XOR E
AND C
XOR E
LD (HL),A
DEC L
Скрытый текст
Код:LD HL,$401f
LD BC,$8f8
loop
LD A,(HL)
RLCA
RLCA
RLCA
LD D,A
AND C
LD (HL),A
DEC L
DUP 15
LD A,(HL)
RLCA
RLCA
RLCA
LD E,A
XOR D
AND C
XOR D
LD (HL),A
DEC L
LD A,(HL)
RLCA
RLCA
RLCA
LD D,A
XOR E
AND C
XOR E
LD (HL),A
DEC L
EDUP
LD A,(HL)
RLCA
RLCA
RLCA
LD E,A
XOR D
AND C
XOR D
LD (HL),A
LD DE,256+31
ADD HL,DE
DEC B
JP NZ,loop
[свернуть]
Это 33 такта на байт (кстати, перепутаны местами h и l).
А почему не 32 такта на байт:
Или даже 31.6 такта на байт:Код:POP HL 10
POP DE 10
RR L 8
RR H 8
RR E 8
RR D 8
EX AF,AF' 4
RR L 8
RR H 8
RR E 8
RR D 8
EX AF,AF' 4
LD (nn),HL 16
LD (nn),DE 20
Теоретически, на практике не проверял.Код:POP HL 10
POP DE 10
POP BC 10
RR L 8
RR H 8
RR E 8
RR D 8
RR C 8
RR B 8
EX AF,AF' 4
RR L 8
RR H 8
RR E 8
RR D 8
RR C 8
RR B 8
EX AF,AF' 4
LD (nn),HL 16
LD (nn),DE 20
LD (nn),BC 20
Сдвиг на 3 бита самый медленный :( Уж лучше таблицами.
---------- Post added at 07:32 ---------- Previous post was at 07:26 ----------
Titus, Ради спортивного интереса буду раз если поковыряешь моё творчество
http://zx-pk.ru/showthread.php?t=23544
Может есть идеи как оптимизировать?
Titus, это версия без таблиц. К сожалению оказалось менее универсальной и более тормозной для разно размерных спрайтов, если в неё внедрять изменение длины спрайта "на лету". Использовать стек, я думал.. но выходило тормознее.
Сейчас уже, в текущей версии кода, я всё переделал под таблицы и стек. По скорости одинаково вышло.
Просто основной приём, сдвига на 3 интересный получился за счет уже сдвинутого на 1 копирования в буфер скролирования :)
Дальше применяем RLD или RRD и получаем сдвиг на 3 более быстрый чем делать RL (HL). Жаль, что RLD/RRD не работают в регистрах.
Titus, в актуальном баланс между размером и скоростью главное. Была бы возможность строить мегакод для спрайтов в локации... но её нет.
Можно еще задействовать альтернативные регистры (EXX). И тогда может оправдять себя переставление SP (LD SP,nn) и запись в память через PUSH.
В пределе имеем (при неограниченном кол-ве регистров):
2x RL r - 16 тактов на байт
1x PUSH rp, 1xPOP rp на каждые 2 байта, 21/2=10.5 тактов на байт
поэтому любой алгоритм такого типа не сможет сделать быстрее, чем 26,5 тактов на байт. Это без учета установок SP, без учета EXX.
Но даже и с такой оптимистической скоростью, если скроллить одну треть экрана - то это будет более 54272 тактов. За один фрейм больше, чем 1/3 экрана, не проскроллишь.
Поэтому я думаю, что в реальных играх и демах нужно использовать трюки, создавать иллюзию скролла, а не сам скролл. Типа как в Sea Dragon тайловая графика.
Пишем (скролл влево):
Этот фрагмент обрабатывает 12 байт. Растактовка:Код:LD SP,nn ;10
POP HL ;10
POP DE ;10
POP BC ;10
RL H ;8
RL L ;8
RL D ;8
RL E ;8
RL B ;8
RL C ;8
EXX ;4
POP HL;10
POP DE ;10
POP BC ;10
RL H ;8
RL L ;8
RL D ;8
RL E ;8
RL B ;8
RL C ;8
EXX ;4
EX AF,AF' ;4
RL H ;8
RL L ;8
RL D ;8
RL E ;8
RL B ;8
RL C ;8
EXX ;4
RL H ;8
RL L ;8
RL D ;8
RL E ;8
RL B ;8
RL C ;8
EX AF,AF' ;4
PUSH BC ;11
PUSH DE ;11
PUSH HL ;11
EXX ;4
PUSH BC ;11
PUSH DE ;11
PUSH HL ;11
На POP - 6*10 = 60 тактов
На PUSH - 6*11 = 66 тактов
На LD SP - 10 тактов
На EXX - 4*4 = 16 тактов
На EX AF,AF' - 2*4 = 8 тактов
На RL - 12*2*8 = 192 такта
Всего 352 такта
На каждый байт - 29 + 1/3 тактов в среднем.
Хоть 4 команды EXX сжирают 16 тактов, а одна LD SP - 10 тактов - то кажется, что без EXX будет быстрее. Однако, если делать блоками по 6 байт без EXX - то будет:
POP - 3*10 = 30
PUSH - 3*11 = 33
LD SP - 10
EX AF,AF' - 8
RL - 6*2*8 = 96
Всего - 177
На каждый байт - 29.5 тактов в среднем. Чуть больше.
Причина в том, что при обработке блоками по 12 байт встречается в 2 раза меньше команд EX AF,AF' в среднем. То есть с EXX потеря 6 тактов на EXX, однако выигрыш 8 тактов на EX AF,AF'. В конечном счете выигрыш в 2 такта.
Barmaley_m, круто)
Делай, пожалуйста, демы)
Barmaley_m, не работает. вся строка на 3 не сдвигается.
У меня как-то так получилось:
58 тактов / байт
Стековый вариант 57,5 тактов на байт :)Код:LD HL,#401F
DUP 32 ; SCROLL 3
LD C,(HL)
RL C
EX AF,AF'
RL C
EX AF,AF'
RLA
RL C
RRA
LD (HL),C
DEC L
EDUP
Если использовать прямую адресацию LD HL,(nn) / LD (nn),HL — получим 56 тактов на байт.
Если пишем стеком LD HL,(nn) / PUSH HL немного быстрее будет — 53,5 такта на байт.Код:LD (STACK+1),SP
LD HL,#401E
DUP 16 ; SCROLL 3
LD SP,HL
DEC L
DEC L
POP DE
RL D
EX AF,AF'
RL D
EX AF,AF'
RLA
RL D
RRA
RL E
EX AF,AF'
RL E
EX AF,AF'
RLA
RL E
RRA
PUSH DE
EDUP
STACK:
LD SP,#0000
Вариант без EX AF,AF', по скорости одинаково.Код:ADR=#401E
LD (STACK+1),SP
LD SP,#4020
DUP 16 ; SCROLL 3
LD HL,(ADR)
RL H
EX AF,AF'
RL H
EX AF,AF'
RLA
RL H
RRA
RL L
EX AF,AF'
RL L
EX AF,AF'
RLA
RL L
RRA
PUSH HL
ADR=ADR-2
EDUP
STACK
LD SP,#0000
Код:ADR=#401E
LD (STACK+1),SP
LD SP,#4020
DUP 16 ; SCROLL 3
LD HL,(ADR)
RL H
RLA
RL H
RLA
RL H
RRA
RRA
RL L
RLA
RL L
RLA
RL L
RRA
RRA
PUSH HL
ADR=ADR-2
EDUP
STACK
LD SP,#0000
Не понял, что не заработало, где ошибки?
Тема о сдвиге на 2 точки. Мой код свигает на 2.
То, что 32 не делится на 12, означает, что надо двигать две группы по 12 и потом еще одну группу из 8 байт. Получить на базе моего кода сдвиг укороченной группы из 8 байт - задача несложная. Ее я оставил в качестве домашнего задания тем, кому это интересно.
Ну и вообще уже не раз было сказано, что, даже если сдвигать всю информацию чисто на регистрах, 8 тактов на сдвиг одного байта на один бит - это слишком много. Фреймового скролла на 2 пиксела на полный экран не получится. Почитайте все тему разработки Sea Dragon. Там было рассмотрено много разных вариантов, в итоге от "честного" скролла отказались в пользу тайловой графики.
Сам проверь.. DEL L после RR надо и всё.
---------- Post added at 11:49 ---------- Previous post was at 11:45 ----------
Вроде как читать стеком POP xx и записывать PUSH xx подходит для сдвига вправо RR x. Для сдвига влево читать с конца нужно, POP не годится, т.к. увеличивает SP на 2.
krt17, видимо значит мой вариант c RLD не рабочий... :)