Вход

Просмотр полной версии : Как быстро скроллить память на 2 пиксела?



Alex Rider
06.11.2013, 20:11
А знает кто-нибудь быстрый способ поскроллить строчку на экране на 2 пиксела в одном цикле перебора байтов? Ну, вернее, есть ли способ быстрее, чем 2 раза подряд на 1 пиксел?

jerri
06.11.2013, 21:10
А знает кто-нибудь быстрый способ поскроллить строчку на экране на 2 пиксела в одном цикле перебора байтов? Ну, вернее, есть ли способ быстрее, чем 2 раза подряд на 1 пиксел?

хмм
ну можно так


xor a
ex af,af
dup 31
ld a,(hl)
ex af,af'
rra
rr (hl)
rra
rr (hl)
inc l
edup
ex af,af'
rra
rr (hl)
rra
rr (hl)


либо вариант с табличками но сильно сомневаюсь что будет быстрее

Alex Rider
06.11.2013, 21:47
либо вариант с табличками но сильно сомневаюсь что будет быстрее
А что за вариант с табличками? У меня есть смутное подозрение, что скроллить придется не непрерывный кусок памяти, при этом границы "разрыва" не постоянны, так что вариант с dup-edup может либо не прокатить, либо обернуться геморроем с самомодифицирующимся кодом.

drbars
07.11.2013, 06:13
Так определись, чего именно скролить... потом уже процедуру придумывай.

alone
07.11.2013, 08:54
ну можно так
Это точно работает?
Я делал так:

dup NN
rl (hl)
ex af,af'
rl (hl)
ex af,af'
dec l
edup

jerri
07.11.2013, 09:44
А что за вариант с табличками? У меня есть смутное подозрение, что скроллить придется не непрерывный кусок памяти, при этом границы "разрыва" не постоянны, так что вариант с dup-edup может либо не прокатить, либо обернуться геморроем с самомодифицирующимся кодом.


с табличками это примерно так



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

Alex Rider
07.11.2013, 18:08
dup NN
rl (hl)
ex af,af'
rl (hl)
ex af,af'
dec l
edup

Надо больше спать по ночам, а не писать :( Идея использовать второй аккумулятор крутилась в голове, но как я мог не додуматься до такой простой реализации? Спасибо!

introspec
07.11.2013, 18:54
Идея использовать второй аккумулятор крутилась в голове, но как я мог не додуматься до такой простой реализации?Можно и с одним аккумулятором:

dup NN
rl (hl)
rla
rl (hl)
rra
dec l
edup

Hacker Grey
16.12.2013, 15:35
Сразу скажу - такты не считал.
Но попробуй - может так быстрее будет ?

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)

introspec
16.12.2013, 20:18
Сразу скажу - такты не считал.
Но попробуй - может так быстрее будет ?
Решение alone или моё - 42 такта на байт. У jerri чуть быстрее - 38 тактов на байт + таблица. Новое предложенное решение - 72 такта на 2 байта (36 тактов на байт), т.е. новый рекорд по скорости, причём без дополнительных затрат по памяти :)

Alex Rider
16.12.2013, 20:49
Круто, спасибо! Но переделывать уже поздно :) Во-превых, заоптимизил остальное, что мешало во фрейм уложиться. Во-вторых, сузил область скролла. В третьих, отправил готовое на сборку уже :) Буду иметь в виду сей фокус.

alone
17.12.2013, 13:05
pop hl
rr h
rr l
ex af,af'
rr h
rr l
ex af,af'
push hl
dec sp
dec sp
pop hl
rr h
rr l
ex af,af'
rr h
rr l
ex af,af'
ld (nn),hl

же :)

drbars
22.12.2013, 20:41
Потестил, с ADC не получается :(

Но, можно так:



LD C,(HL) ; 7
RL C ; 8
RLA ; 4
RL C ; 8
RRA ; 4
LD (HL),C ; 7


38 тактов на байт, без таблицы.

denpopov
27.05.2014, 07:42
некий слоупочный скроллер вышел, 44(или 48?)такта на байт.
нутром чую, что можно оптимизировать, но быстрее не выйдет.

drbars
27.05.2014, 07:58
А чего его дергает то? :rolleyes:

Ой, чё за жесть внутри? :v2_dizzy_facepalm:

denpopov
27.05.2014, 08:16
А чего его дергает то?
ничо не дергает вроде.


Ой, чё за жесть внутри?
киде?

jerri
27.05.2014, 10:19
denpopov, а чем тебе идеи предложенные ранее не понравились?

denpopov
27.05.2014, 10:31
denpopov, а чем тебе идеи предложенные ранее не понравились?
просто давно видел тему, возникла идея. Теперь выходит, что скроллить можно на 2-7 точек.
вот только как выводить букву - это вопрос

introspec
27.05.2014, 11:12
38 тактов на байт, без таблицы.А почему 4 такта DEC L не посчитал? :)

Reobne
27.05.2014, 16:00
Просто как вариант. В лоб, без таблиц и стека.
Скролл на 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

denpopov
27.05.2014, 16:29
Скролл на 3 бита(пикселя)
а значение D?

alone
02.06.2014, 16:15
Скролл на 3 бита(пикселя)
46 тактов на байт.
RLD: DEC L
+
RR (HL):INC L
=
41 такт на байт.

Titus
03.04.2015, 01:19
pop hl
rr h
rr l
ex af,af'
rr h
rr l
ex af,af'
ld (nn),hl

же :)

Это 33 такта на байт (кстати, перепутаны местами h и l).

А почему не 32 такта на байт:


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


Или даже 31.6 такта на байт:

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

Теоретически, на практике не проверял.

drbars
03.04.2015, 04:32
Сдвиг на 3 бита самый медленный :( Уж лучше таблицами.

---------- Post added at 07:32 ---------- Previous post was at 07:26 ----------

Titus, Ради спортивного интереса буду раз если поковыряешь моё творчество
http://zx-pk.ru/showthread.php?t=23544

Может есть идеи как оптимизировать?

Titus
03.04.2015, 05:37
Сдвиг на 3 бита самый медленный :( Уж лучше таблицами.
У меня на два же)

---------- Post added at 05:37 ---------- Previous post was at 05:33 ----------


Titus, Ради спортивного интереса буду раз если поковыряешь моё творчество
http://zx-pk.ru/showthread.php?t=23544

У тебя много ограничений.
Стек не используешь, а это золотое дно в ускорении.
Таблиц тоже используешь по минимуму, хотя памяти у тебя 128Кб.

drbars
03.04.2015, 07:13
Titus, это версия без таблиц. К сожалению оказалось менее универсальной и более тормозной для разно размерных спрайтов, если в неё внедрять изменение длины спрайта "на лету". Использовать стек, я думал.. но выходило тормознее.

Сейчас уже, в текущей версии кода, я всё переделал под таблицы и стек. По скорости одинаково вышло.

Просто основной приём, сдвига на 3 интересный получился за счет уже сдвинутого на 1 копирования в буфер скролирования :)
Дальше применяем RLD или RRD и получаем сдвиг на 3 более быстрый чем делать RL (HL). Жаль, что RLD/RRD не работают в регистрах.

Titus
03.04.2015, 07:20
Сейчас уже, в текущей версии кода, я всё переделал под таблицы и стек. По скорости одинаково вышло.

Чего ж ковырять то, что уже устарело) Надо ковырять актуальное)

drbars
03.04.2015, 07:33
Titus, в актуальном баланс между размером и скоростью главное. Была бы возможность строить мегакод для спрайтов в локации... но её нет.

Barmaley_m
09.04.2015, 22:57
Или даже 31.6 такта на байт:

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
Можно еще задействовать альтернативные регистры (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 тайловая графика.

Titus
09.04.2015, 23:47
Можно еще задействовать альтернативные регистры (EXX). И тогда может оправдять себя переставление SP (LD SP,nn) и запись в память через PUSH.

Нет, не оправдает. Попробуй напиши и рассчитай, сколько получится тактов.

Barmaley_m
10.04.2015, 16:21
Нет, не оправдает. Попробуй напиши и рассчитай, сколько получится тактов.
Пишем (скролл влево):


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

Этот фрагмент обрабатывает 12 байт. Растактовка:
На 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 такта.

Titus
10.04.2015, 19:26
Barmaley_m, круто)
Делай, пожалуйста, демы)

drbars
11.04.2015, 06:39
Barmaley_m, не работает. вся строка на 3 не сдвигается.

drbars
11.04.2015, 11:46
У меня как-то так получилось:
58 тактов / байт



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


Стековый вариант 57,5 тактов на байт :)

Если использовать прямую адресацию LD HL,(nn) / LD (nn),HL — получим 56 тактов на байт.



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



Если пишем стеком LD HL,(nn) / PUSH HL немного быстрее будет — 53,5 такта на байт.



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


Вариант без EX AF,AF', по скорости одинаково.


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

drbars
11.04.2015, 13:08
Если на 3 надо первым проходом rld вторым rr обратно. Хотя все это не актуальные извраты имхо.
Этот пример тут был уже, тоже нерабочий.

Titus
11.04.2015, 13:24
Этот пример тут был уже, тоже нерабочий.

Разве может Alone дать нерабочий пример)

Бармалей написал пример скроллинга на 2, а не на 3.

drbars
11.04.2015, 13:32
Разве может Alone дать нерабочий пример)
Бармалей написал пример скроллинга на 2, а не на 3.
У меня он чё-та не заработал. Как им строку сдвинуть в 32 байта на 3 точки влево? :)

Там ошибка, вот правильно:
37 тактов байт.



DUP 32 ; SCROLL 3
RLD
RR (HL)
DEC L
EDUP

Barmaley_m
11.04.2015, 22:45
У меня он чё-та не заработал.
Не понял, что не заработало, где ошибки?

Как им строку сдвинуть в 32 байта на 3 точки влево? :)
Тема о сдвиге на 2 точки. Мой код свигает на 2.

То, что 32 не делится на 12, означает, что надо двигать две группы по 12 и потом еще одну группу из 8 байт. Получить на базе моего кода сдвиг укороченной группы из 8 байт - задача несложная. Ее я оставил в качестве домашнего задания тем, кому это интересно.

Ну и вообще уже не раз было сказано, что, даже если сдвигать всю информацию чисто на регистрах, 8 тактов на сдвиг одного байта на один бит - это слишком много. Фреймового скролла на 2 пиксела на полный экран не получится. Почитайте все тему разработки Sea Dragon. Там было рассмотрено много разных вариантов, в итоге от "честного" скролла отказались в пользу тайловой графики.

drbars
12.04.2015, 07:49
То есть это правильно, а у алона ошибка? Мда...

Сам проверь.. DEL L после RR надо и всё.


RLD: DEC L
+
RR (HL):INC L
=
41 такт на байт.

---------- Post added at 11:49 ---------- Previous post was at 11:45 ----------


Не понял, что не заработало, где ошибки?
Вроде как читать стеком POP xx и записывать PUSH xx подходит для сдвига вправо RR x. Для сдвига влево читать с конца нужно, POP не годится, т.к. увеличивает SP на 2.

drbars
12.04.2015, 08:19
krt17, видимо значит мой вариант c RLD не рабочий... :)

drbars
12.04.2015, 10:23
krt17, Ага, я уже протестировал. Ну сами по себе команды RRD/RLD не особо удобные. Наверное можно придумать чтобы одним проходом сдвигалось на 3, но в ущерб скорости :)

Titus
12.04.2015, 14:27
Вспомнил еще один прикольный метод на 40 за байт

dec e, вообще-то)

---------- Post added at 14:27 ---------- Previous post was at 14:11 ----------

krt17, тебе тоже надо демы писать)

drbars
12.04.2015, 14:37
krt17, с таблицами всё прозрачно. Надо родить скролл влево на 3 точки в один проход с помощью команды RLD :)

Titus
12.04.2015, 14:42
Все мои демы на бумажке в тетрадке,а зачастую и просто в голове;), дальше не интересно.

Не уподобляйся мне, воплощай в реал)

Titus
12.04.2015, 15:02
Прикинул со стеком и табличкой в раскладке получается 36, но это уж совсем кощунство.

Выкладывай для всех свое кощунство)

Titus
12.04.2015, 15:31
По итогу 38 с табличкой на 3*8*#100 по скорости победитель, если я опять ничего не пропустил.

Пропустил) как на счет записи результата из А в регистры?

Titus
12.04.2015, 16:04
Да тут вообще полный крах и позор. Стирать не буду пусть останется как клеймо. Но 38 это я про другую говорил

ld a,(de)
ld l,a
ldd
dec h
ld h,(hl)
Это было написано еще до рома, все четко, вариант с ldd так сказать.

В начале темы jerry выкладывал сходную:


ld bc,head_table

dup nn
ld a,(de)
ldi
ld l,a
ld h,b
ld h,(hl)
edup

Titus
12.04.2015, 16:30
Судя по тому что никто не исправил, никто и не вникал как работает.

Суть и так понятна, но, видимо, действительно никто не вникал)

Barmaley_m
12.04.2015, 21:14
Вроде как читать стеком POP xx и записывать PUSH xx подходит для сдвига вправо RR x. Для сдвига влево читать с конца нужно, POP не годится, т.к. увеличивает SP на 2.
Какая разница, если в начале каждого блока стоит команда LD SP? Главное - что PUSH и POP читают и записывают в непрерывный блок памяти. Поэтому в этом месте моего кода ошибок нет.

jerri
12.04.2015, 21:15
Да похоже, но помечена примерно и не работает. ldi нужно после ld l,a. А так вообще отлично и табличка меньше. Судя по тому что никто не исправил, никто и не вникал как работает.

ну и сдвигает она вправо. :)

Alex Rider
14.04.2015, 02:09
Блин, вашу бы фантазию тогда, когда Heart Megademo писалась! Про скролл на 3 пикселя я вообще тогда не думал, казалось, что там и во фрейм для одной строчки не уложишься :)

goodboy
28.10.2015, 21:55
очередной буржуйский эксперимент (на 48к)

http://savepic.su/6311284.png

при нажатии любой клавиши - бежит быстрее

Titus
28.10.2015, 23:29
FF нужен, для наших уже давно пройденный этап, движок на примитивном пушере не писал только ААА

ААА - расшифровывается легко.
А что такое FF? 255? Или может Final Fantasy?

goodboy
28.10.2015, 23:40
А что такое FF?

LD BC,#40FF
LD E,#04
L8045: LD A,R
IN A,(C)
CP E
JP NZ,L8045

Titus
29.10.2015, 00:02
А почему порт FF адресуют шестнадцатибитно 40FF? В этом есть смысл?

SoftFelix
29.10.2015, 00:18
очередной буржуйский эксперимент (на 48к)
А сложно из этого SNA сделать SCL или TRD? Хотелось бы потестить на КАЕ с его портом #FF.

goodboy
29.10.2015, 00:31
А почему порт FF адресуют шестнадцатибитно 40FF? В этом есть смысл?
"The address of the port being accessed is placed on the data bus. If this is in the range 0x4000 to 0x7fff, the ULA treats this as an attempted access to contended memory and therefore introduces a delay"

http://www.worldofspectrum.org/faq/reference/48kreference.htm#IOContention

NEO SPECTRUMAN
29.10.2015, 00:37
Кстати какой смысл в LD A,R? Может он есть?
может для выравнивания по тактам? :v2_conf2:
не так много способов получить 9 тактовую задержку
только зачем тогда ничему не кратный 35 тактный цикл :v2_happy:

goodboy
29.10.2015, 00:48
Охохо, trdos нужен, сорри
попробуй сохранить блок ->32768,32768

troosh
30.10.2015, 00:01
Как насчет того, чтоб не сдвигать на 2 бита, а иметь четыре варианта знакогенератора (уже сдвинутый фонт на 0, 2, 4 и 6 бит) и каждый раз выводить с использование очередного варианта фонта?

Titus
30.10.2015, 04:32
Как насчет того, чтоб не сдвигать на 2 бита, а иметь четыре варианта знакогенератора (уже сдвинутый фонт на 0, 2, 4 и 6 бит) и каждый раз выводить с использование очередного варианта фонта?
Так и делают)

goodboy
30.10.2015, 23:10
http://savepic.su/6307760.png
вариант мультиколорного движка.
заточен под фирменный 48к,(ГГ двигается сам)