Просмотр полной версии : Вывод тайлового бэкграунда
moroz1999
05.04.2008, 01:02
Где можно почитать примеры процедур заполнения экрана тайловым бэкграундом?
Размеры тайлов классические - 2x2. Интересуют как готовые примеры, так и общие принципы и сравнения методик.
У меня сейчас вывод одного тайла 2x2 в линейный буфер (не напрямую на экран) занимает примерно 700 тактов (без вывода аттрибутов), это много или нормально?
лучше кусок кода кинь... нагляднее будет....
moroz1999
05.04.2008, 14:46
да код недописан слегка, там один и тот же тайл выводится, то есть работы с картой пока нету попросту.
а так - буфер заполняется одним и тем же тайлом, лежащим по адресу #c000.
TILESHORIZONTAL EQU 16 ;TILES COUNT (HORIZONTAL)
TILESVERTICAL EQU 10 ;TILES COUNT (VERTICAL)
TILEW EQU 2 ;TILE WIDTH (not used)
TILEH EQU 2 ;TILE HEIGHT
SP_STORAGE DW 0
DRAWBACKGROUND
DI
LD (SP_STORAGE),SP
LD HL,FRAMEBUFFER+(FRAMEBUFFERLINE-SCREEN_WIDTH)/2
LD BC,FRAMEBUFFERLINE-TILEW+1
LD A,TILESVERTICAL
DRAWTILESLINE
EX AF,AF'
LD A,TILESHORIZONTAL
DRAWONETILE
LD SP,#c000 ;TILE ADDRESS IN MEMORY, HARDCODED AT THE MOMENT
DUP TILEH*8
POP DE
LD (HL),E
INC HL
LD (HL),D
ADD HL,BC
EDUP
LD DE,FRAMEBUFFERLINE*TILEH*8-TILEW
SBC HL,DE
DEC A
JP NZ,DRAWONETILE
; ONE LINE IS DRAWN, DRAW NEXT LINE
LD DE,FRAMEBUFFERLINE*TILEH*8-(TILESHORIZONTAL*TILEW)
ADD HL,DE
EX AF,AF'
DEC A
JP NZ,DRAWTILESLINE
LD SP,(SP_STORAGE)
EI
RET
основной минус - нельзя юзать прерывания, но это не сильно страшно, ибо время вывода одного тайла всё же известно, а, значит, теоретически можно дёрнуть halt после определённого их числа.
А чего не напрямую в экран? Если два экрана юзать должно быть очень даже ничего
moroz1999
05.04.2008, 16:46
А чего не напрямую в экран? Если два экрана юзать должно быть очень даже ничегоА вот это довольно сложный вопрос.
Самый быстрый из известных мне вариантов "down hl" тратит в среднем 36 тактов на линию (http://zxdn.narod.ru/coding/n125dnhl.txt).
Если подсчитать, то, избавившись от неё, в моём случае можно сэкономить:
((2*8)*10*16)*36 = 92160 тактов на отрисовке бэкграунда
плюс на отрисовку четырех спрайтов (4*6 знакомест в моём варианте): ((6*8)*4)*36 = 6912 тактов
в целом - 99 тысяч тактов на одну только down_hl.
процедура вывода буфера на экран у меня развернута и работает через стек, что при моём размере буфера (32*20 знакомест) выполняется за 65347 тактов.
Итого, чистый выигрыш в моём варианте - почти 35000 тактов на кадр, чего мне хватило, чтобы решить заморачиваться на отдельный буфер. Хотя изначально всё на 2 экрана и было сделано.
если позволяет место, то развернуть ЦЕЛИКОМ программу вывода на экран... и в неё уже подставлять значения..... у мну примерно похожее используется кое где....
Добавлено через 1 минуту
... если интересно покажу/кину исходник/ в понедельник... так как исход наработе...
Aprisobal
05.04.2008, 20:55
Где можно почитать примеры процедур заполнения экрана тайловым бэкграундом?
Размеры тайлов классические - 2x2. Интересуют как готовые примеры, так и общие принципы и сравнения методик.
У меня сейчас вывод одного тайла 2x2 в линейный буфер (не напрямую на экран) занимает примерно 700 тактов (без вывода аттрибутов), это много или нормально?Советую не заморачиваться сейчас на оптимизации вывода бэкграунда и оставить его пока как есть. Пока есть запал делать что-то (предположу, что это "что-то" есть какая-то игровая программа), нужно сделать это по-максимуму.
moroz1999
05.04.2008, 21:08
Советую не заморачиваться сейчас на оптимизации вывода бэкграунда и оставить его пока как есть. Пока есть запал делать что-то (предположу, что это "что-то" есть какая-то игровая программа), нужно сделать это по-максимуму.
ну, я уже более-менее наоптимизировался, но было любопытно восполнить пробел информации в голове.
а запал не пропадёт, я уже почти пять лет обучаюсь, переделываю, переписываю заново, и только сейчас начало выходить что-то, чем я доволен.
А вот это довольно сложный вопрос.
Ну а вот копирование из буфера на экран почему не учитываешь? В 35000 на экран влезешь?
Плюс процедуру downhl можно развернуть и не мучаться. в частности, она будет выглядеть примерно так:
dup tileh
ld a,h
dup 4
pop de
ld (hl),e
inc l
ld (hl),d
inc h
pop de
ld (hl),d
dec l
ld (hl),e
inc h
edup
ld h,a
ld a,l
add a,32
ld l,a
edup
Это неполная версия downhl- переход через границу трети надо обрабатывать отдельно, желательно между циклами вывода тайлов по вертикали
Плюс можно соптимизировать хвост развернутого цикла, если дальнейший адрес не нужен (обычно нужен)
crushers[4ePT]
06.04.2008, 00:17
интересно а почему все примеры "зациклены" на использовании стёка? ведь две команды ldi по тактам занимают то-же самое, занимают меньше места и "не обидятся" на прерывание во время работы? :v2_wink2:
p.s. ещё можно использовать особенность этой команды для возврата из цикла прорисовки по ret po. :v2_wink2:
Aprisobal
06.04.2008, 00:20
moroz1999, если строку буфера (FRAMEBUFFERLINE) задать в 32 байта, то можно будет INC HL заменить на INC L, что даст -2 такта на каждую строку спрайта. 192 строки х 16 спрайтов в строке х 2 такта = -6144.
ldi имеет неуправляемый фактор инкремента.
dup 4
ldi
ldi
dec de
ldd
ldd
inc de
inc d
edup
E=4*(16+16+6+16+16+6+4)=4*80=320ticks
dup 4
pop de
ld (hl),e
inc l
ld (hl),d
inc h
pop de
ld (hl),d
dec l
ld (hl),e
inc h
edup
E=4*(10+7+4+7+4+10+7+4+7+4)=4*64=256ticks
на 25% быстрее всетки...
crushers[4ePT]
06.04.2008, 00:40
ldi имеет неуправляемый фактор инкремента.
dup 4
ldi
ldi
dec de ;регистр hl будет бегать по кругу? :v2_wink2:
ldd
ldd
inc de
inc d
edup
E=4*(16+16+6+16+16+6+4)=4*80=320ticks
dup 4
pop de
ld (hl),e
inc l
ld (hl),d
inc h
pop de
ld (hl),d
dec l
ld (hl),e
inc h
edup
E=4*(10+7+4+7+4+10+7+4+7+4)=4*64=256ticks
на 25% быстрее всетки...
я имел ввиду так:
bc=размер спрайта
и в начале jr для "впрыгивания" в цикл в зависимости от d, после вызов знакоместа целиком и ещё раз "впрыгивание" в цикл для дорисовки остатка! :)
ld a,e
dup 8
ldi: ldi: ret po
ld e,a: inc d
edup
add a,#20: ld e,a: ret nc
ld a,d: sub 8: ld d,a: ret
Добавлено через 4 минуты
Хотя согласен немного медленнее но зато некритично к прерыванию.
;127557]dec de ;регистр hl будет бегать по кругу?
Да. А что, как-то иначе надо?
;127557]я имел ввиду так:
А затраты на вызов?
Вариант, приведенный в равные с вышеуказанным условия:
call outing ;17
outing:
ld a,e ;4
dup 8
ldi: ldi
ld e,a: inc d
edup ;8*(16+16+4+4)=8*40=320
add a,#20: ld e,a: ret nc ;7+4+5/10 = 16/21
ld a,d: sub 8: ld d,a: ret ;4+7+4+10 = 25
E=17+4+320+16/21+25=382/377
не айс
crushers[4ePT]
06.04.2008, 00:59
dup 4
ldi ;hl+1
ldi ;hl+1
dec de ;регистр hl будет бегать по кругу?
ldd ;hl-1
ldd ;hl-1
inc de
inc d
edup
E=4*(16+16+6+16+16+6+4)=4*80=320ticks
dup 4
pop de ;"hl"+2
ld (hl),e
inc l
ld (hl),d
inc h
pop de ;"hl"+2
ld (hl),d
dec l
ld (hl),e
inc h
edup
Я про то что будет тогда рисоватся не тайл размером 2б(ширина) а первые два байта. :v2_wink2:
ещё незабудь добавить цикл/проверку на "скопирован весь таил" в подсчёты скорости.
;127562]Я про то что будет тогда рисоватся не тайл размером 2б(ширина) а первые два байта.
а ну тогда еще больше тактов надо чтоб вернуть de на место (4 на каждую строчку).
;127562]ещё незабудь добавить цикл/проверку на "скопирован весь таил" в подсчёты скорости.
ну я изначально в равные условия загнал примеры, посему твой ускорился соотвецно.
crushers[4ePT]
06.04.2008, 01:15
понравилось решение в какой-то буржуйной аркаде (я их на данный момент перековыриваю кучками - unreal debuger незаменимая вещь :v2_thumb:)
ldi: ldi: ldi: inc d ;abc -графика в буфере
ldd: ldd: ldd: inc d ;fed -графика в буфере
а на экране соответственно abc, def только цикл djnz
поставили вместо простой ret po. всё прикрасно рисуется в одном экране (48к режим). правда спрайт надо "корявым" делать :v2_laugh:
;127564]ldi: ldi: ldi: inc d ;abc -графика в буфере
ldd: ldd: ldd: inc d ;fed -графика в буфере
дык та же фигня что и у меня с источником плюс вывод перекошенный на 1 байт
moroz1999
06.04.2008, 13:36
;127551']интересно а почему все примеры "зациклены" на использовании стёка?у меня есть еще одна причина, по которой я быстро отказался от ldi - банально не хватило одной пары свободных регистров.
Добавлено через 3 минуты
moroz1999, о! Если строку буфера (FRAMEBUFFERLINE) задать в 32 байтаспасибо, но от этого я, наверное, отказаться пока не смогу - у меня framebufferline сделан шириной в 40 байт. Это даёт такой небольшой плюс, что не нужно обрезать спрайты по горизонтали на границе экрана (правда по ширине спрайт ограничивается при этом 16 знакоместами).
Добавлено через 9 минут
отдельное спасибо за идею вывода змейкой - как-то мне это в голову не приходило, посмотрю как бы её применить.
с выводом графики напрямую на экран появляется еще один небольшой минус, о котором забыл сказать - спрайты придётся каждый раз копировать из верхней памяти.
можно реализовать кэширование на лету, конечно, но на этот счет надо еще подумать.
Добавлено через 11 минут
Ну а вот копирование из буфера на экран почему не учитываешь? В 35000 на экран влезешь?еще как учитываю! 35000 - это и есть разница между совокупными затратами на down_hl и копированием из буфера (65000).
crushers[4ePT]
06.04.2008, 23:37
moroz можешь показать процедуру копирования? весь экран хочешь обновлять?
moroz1999
07.04.2008, 09:30
процедура очень классическая - через push-pop. 65000 - засчет того. что размер копируемого пространства не 32/24, а 32/20.
Самой процедуры в чистом виде у меня нет, она генерится и занимает около восьми килобайт. Вот генератор, в комментах (справа, форум их визуально режет, надо курсором поскролить чтоб увидеть) есть перечень комманд, которые пишутся в память:
INITCOPYFRAME
LD BC,COPYFRAME_GENERATED
LD DE,SP_STORAGE
LD A,#ED ;LD (NN),
LD (BC),A
INC BC
LD A,#73 ;SP
LD (BC),A
INC BC
LD A,E ;N
LD (BC),A
INC BC
LD A,D ;N
LD (BC),A
INC BC
LD HL,#C000+SCREEN_WIDTH/2
LD (COPYFRAME_HL),HL
LD DE,FRAMEBUFFER+(FRAMEBUFFERLINE-SCREEN_WIDTH)/2
LD (COPYFRAME_DE),DE
LD A,SCREEN_HEIGHT
COPYROW
PUSH AF
LD A,2
COPYHALFROW
LD HL,(COPYFRAME_HL)
LD DE,(COPYFRAME_DE)
PUSH AF
LD A,#31 ;LD SP,
LD (BC),A
INC BC
LD A,E ;N
LD (BC),A
INC BC
LD A,D ;N
LD (BC),A
INC BC
LD A,#E1 ;POP HL
LD (BC),A
INC BC
LD A,#C1 ;POP BC
LD (BC),A
INC BC
LD A,#D1 ;POP DE
LD (BC),A
INC BC
LD A,#F1 ;POP AF
LD (BC),A
INC BC
LD A,#D9 ;EXX
LD (BC),A
INC BC
LD A,#08 ;EX AF,AF'
LD (BC),A
INC BC
LD A,#E1 ;POP HL
LD (BC),A
INC BC
LD A,#C1 ;POP BC
LD (BC),A
INC BC
LD A,#D1 ;POP DE
LD (BC),A
INC BC
LD A,#F1 ;POP AF
LD (BC),A
INC BC
LD A,#31 ;LD SP,
LD (BC),A
INC BC
LD A,L ;N
LD (BC),A
INC BC
LD A,H ;N
LD (BC),A
INC BC
LD A,#F5 ;PUSH AF
LD (BC),A
INC BC
LD A,#D5 ;PUSH DE
LD (BC),A
INC BC
LD A,#C5 ;PUSH BC
LD (BC),A
INC BC
LD A,#E5 ;PUSH HL
LD (BC),A
INC BC
LD A,#D9 ;EXX
LD (BC),A
INC BC
LD A,#08 ;EX AF,AF'
LD (BC),A
INC BC
LD A,#F5 ;PUSH AF
LD (BC),A
INC BC
LD A,#D5 ;PUSH DE
LD (BC),A
INC BC
LD A,#C5 ;PUSH BC
LD (BC),A
INC BC
LD A,#E5 ;PUSH HL
LD (BC),A
INC BC
LD HL,(COPYFRAME_HL)
LD DE,SCREEN_WIDTH/2
ADD HL,DE
LD (COPYFRAME_HL),HL
LD DE,(COPYFRAME_DE)
LD HL,SCREEN_WIDTH/2
ADD HL,DE
LD (COPYFRAME_DE),HL
POP AF
DEC A
JP NZ,COPYHALFROW
LD HL,(COPYFRAME_HL)
LD DE,SCREEN_WIDTH
AND A
SBC HL,DE
CALL DOWNHL
LD (COPYFRAME_HL),HL
LD HL,(COPYFRAME_DE)
LD DE,SCREEN_WIDTH
AND A
SBC HL,DE
LD DE,FRAMEBUFFERLINE
ADD HL,DE
LD (COPYFRAME_DE),HL
POP AF
DEC A
JP NZ,COPYROW
LD DE,SP_STORAGE
LD A,#ED ;LD SP,
LD (BC),A
INC BC
LD A,#7B ;(NN)
LD (BC),A
INC BC
LD A,E ;N
LD (BC),A
INC BC
LD A,D ;N
LD (BC),A
INC BC
LD A,#C9
LD (BC),A
INC BC
RET
Перераспредели регистры. Буфер назначения храни в HL, тогда не надо будет приседать с пересылкой через промежуточные регистры. В два раза сократишь исходник
moroz1999
07.04.2008, 18:38
Перераспредели регистры. Буфер назначения храни в HL, тогда не надо будет приседать с пересылкой через промежуточные регистры. В два раза сократишь исходникпогоди, это ты касательно вывода тайлов или касательно переброски буфера стеком на экран?
погоди, это ты касательно вывода тайлов или касательно переброски буфера стеком на экран?
Касательно процедуры генерации. Кстати, кинь сюды сразу и процедуру переброски на экран
moroz1999
07.04.2008, 18:42
;127644']весь экран хочешь обновлять?пока что так сделано просто для пробы. в идеале хотелось бы сделать отдельные процедуры познакоместного скролла во всех направлениях без повторного вывода всех тайлов, а бэкграунд просто кусками восстанавливать перед этим.
теоретически это подбросит еще fps, а на практике до этого руки дойдут очень нескоро.
опять же был бы признателен за любые примеры и материалы по познакоместному скроллингу экрана.
Добавлено через 2 минуты
Касательно процедуры генерации. Кстати, кинь сюды сразу и процедуру переброски на экранда процедура генерации написана по принципу - один раз подождали и всё, не вижу особого практического смысла её оптимизировать дальше, потому что лучше потратить силы на более эффективные вещи.
самой сгенеренной процедуры переброски буффера в виде исходников у меня уже нет, но вечером могу попытаться скинуть сюда типичный кусок сгенеренного кода из неё.
Добавлено через 4 минуты
вообще, если кому любопытно, то я могу выложить целиком исходники сюда, просто там особо нечего смотреть пока что, потому что очень и очень многое еще не сделано из базовых вещей.
самой сгенеренной процедуры переброски буффера в виде исходников у меня уже нет, но вечером могу попытаться скинуть сюда типичный кусок сгенеренного кода из неё.
Чтоб не мучаться и не заниматься ассемблированием, задай ее прямо в виде исходников, юзая директиву подмена адреса компиляции- легко модифицировать и разбираться
moroz1999
07.04.2008, 19:49
огого, я кажется понял, о чем ты, но совершенно не представлял, что такие возможности вообще есть.
огого, я кажется понял, о чем ты, но совершенно не представлял, что такие возможности вообще есть.
Дык DISP/ENT даже в самых древних компиляторах уже поддерживались :)
Стесняюсь спросить, а что такое "тайловая"? Погуглил - ссылок не густо, из обрывочных упоминаний понял что это "состоящая из кусочков". Ну это как из знакомест что ли?
moroz1999
07.04.2008, 23:18
Стесняюсь спросить, а что такое "тайловая"? Погуглил - ссылок не густо, из обрывочных упоминаний понял что это "состоящая из кусочков". Ну это как из знакомест что ли?я не рискну давать определение слову "тайл", но в этой теме говорится об отрисовке заднего фона из квадратных спрайтов равной ширины и высоты.
принцип таков, что картинка заднего фона делится на повторяющиеся пронумерованные кусочки, и хранится именно в виде набора номеров этих кусочков, а сами куски хранятся отдельно.
основной плюс этого подхода - огромная экономия памяти, основной минус - довольно терпимая потеря скорости.
вот здесь, например, фон (земля) явно сделан по этому принципу:
ftp://ftp.worldofspectrum.org/pub/sinclair/screens/in-game/s/StarFarce.gif
Да и вообще, технология, наверное, в каждой второй аркадной игре встречается.
Если не ошибаюсь, то на первых приставках тайлы обычно занимали одно знакоместо и выводились аппаратными средствами, так что потери скорости там не было.
Добавлено через 1 минуту
Дык DISP/ENT даже в самых древних компиляторах уже поддерживались :)да я всю жизнь асм на коленке учил :D, я и dup-то недавно только использовать начал, встретив где-то в текстах на zxdn, так что я совсем зелёный кодер пока :)
Добавлено через 17 минут
вот результат генерации, абсолютно классическая процедура - назначили sp, считали 16 байт. назначили sp - положили 16 байт.
сейчас посидел слегка с калькулятором, и высчитал, что если задействовать еще IX и IY, то получится чуть-чуть быстрее.
У меня получилось без них - 12,75 такта на байт
С использованием IX и IY получится - 12,4 такта на байт (что даст почти 1500 тактов выигрыша в сумме в моём случае, при том же размере пересыльщика)
Сейчас еще посмотрю в ZX-Review, там был какой-то заинтересовавший меня способ, на который по какой-то причине у меня чуть-чуть не хватало памяти.
да я всю жизнь асм на коленке учил
Почитай просто руководство к Alasm. Получишь примерное представление о возможностях современных (и не только) компиляторов.
crushers[4ePT]
08.04.2008, 01:04
В этой процедуре если и оптимизировать то оптимизировать по занимаемому месту под "генерилку".
В самой процедуре прорисовки можно только если добавить сохранение стёка по другому. :v2_wink2:
вывзов экранрефрешэра:
ld (refresh1+1),sp
jp refresh ;рефреш экрана
refresh1 ld sp,#3131
ret
refresh ld sp,#c014
pop hl,de,bc,af
exx: exa
pop hl,de,bc,af
.... ну и так далее только в конце
jp refresh1
Проблема только в том что под одну экранстраницу будут передёргивания (луч перегонит рефрешер экрана).
crushers[4ePT]
08.04.2008, 01:50
Неуверен что процедура генератора стала короче, но понятней немного должна стать :v2_wink2:
По поводу сдвига советую пересмотреть тогда сам внутренний экран таким образом чтобы "передвигать" по оси y или x можно было путём увеличения указателя на экран на ширину или 1 байт. Идеальный вариант сделать ширину строки 32байта, тогда сдвиг вправо будет просто инкремент указателя на 1, влево соответственно декремент а вниз или вверх на 256.
(inc/dec l - по оси x, inc/dec h - по оси y)
но тогда надо при выводе либо следить за стёком чтобы неулетел за границу 256байт либо использовать ld a,(hl): ld (de),a: inc l: inc e
ws_mason
17.04.2008, 06:20
Кстати, кидать данные через стек можно и с использованием прерываний. Я подсмотрел у Медноногова в исходниках Черного Ворона.
Вот тут мои исходники http://zx.pk.ru/showpost.php?p=32815&postcount=60
и хранится именно в виде набора номеров этих кусочков,
Мое замечание по слову "номеров". Скорость уже увеличится, если эти номера заменить реальным адресом тайла. Я так делал в Вере. Хотя сначала хранил именно номера, по которым потом высчитывался адрес - а это опять ведь тормоз... Хотя у меня тайлов было 512 и номера были двубайтовыми, потому замена их на адреса никак не сказалась на длине карты.
Кстати, кидать данные через стек можно и с использованием прерываний. Я подсмотрел у Медноногова в исходниках Черного Ворона.
Вот тут мои исходники http://zx.pk.ru/showpost.php?p=32815&postcount=60
А кто помнит в чём там трюк с восстановлением данных при вызове прерывания? Ведь графика по-любому затрется адресом возврата при поступлении прерывания... Если только каждый блок перед выводом где-то отмечать, а в обработчике прерывания заново переписывать из резервного хранилища...
если данные забираются через стек допустим в DE, то когда будет переход по im2 первым делом на то место куда впечатался адрес возврата пишут то что в DE
Lethargeek
06.11.2019, 13:45
Если только каждый блок перед выводом где-то отмечать, а в обработчике прерывания заново переписывать из резервного хранилища...
я не знаю, как там у Медноногова, но например в Commando испорченные байты блока восстанавливаются по контрольной ксорке
А кто помнит в чём там трюк с восстановлением данных при вызове прерывания? Ведь графика по-любому затрется адресом возврата при поступлении прерывания... Если только каждый блок перед выводом где-то отмечать, а в обработчике прерывания заново переписывать из резервного хранилища...
на прерваниях вот такая конструкция
ex (sp),hl ;сохраняем содержимое HL и забираем адрес возврата
ld (im_jmp0),hl ;сохраняем его для возврата из прерывания
pop hl ;восстанавливаем содержимое HL
ld (im_sp0),sp ;сохраняем содержимое стека для возврата
push bc ;восстанавливаем поврежденную графику
;все процедуры вывода спрайтов и графики
;оптимизированы для сохраниния данных таким способом
ld sp,im_stek ;дальше работаем в стеке прерывания
push hl,de,bc,af ;сохраняем основной набор регистров
;если потребуется сохранить остальные (требуется при
;проигрывании музыки), то их можно сохранить тут
call im_proc
pop af,bc,de,hl ;восстанавливаем регистры
ld sp,$ ;стек
im_sp0 equ $-2
ei ;статус прерываний
jp $ ;возвращаемся по раннее сохраненному адресу
im_jmp0 equ $-2
а на прерываниях например вот такая процедура вывода BG
ld hl,-6
add hl,sp
ld (tile_sp0),hl
ld hl,draw_buf
ld de,#4058
draw_bbuf1
xor a
draw_bbuf0
or (hl)
call nz,draw_tile
inc l
jp nz,draw_bbuf0
inc h
inc e
ld a,d
add a,8
ld d,a
cp #58
jp c,draw_bbuf1
ret
draw_tile
push hl,de
dec a
jp nz,draw_modded
ld (hl),a
;restore background
ld bc,back_tls-draw_buf
add hl,bc
ld c,l
ld l,(hl)
ld b,e
ld e,c
ld h,font_c/256
ld a,(hl)
ld (bc),a
ld h,font_d/2048
draw_tile0
add hl,hl
add hl,hl
add hl,hl
ld c,(hl)
inc l
ld b,(hl)
inc l
ld sp,hl
ex de,hl
dup 3
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
edup
ld (hl),c
inc h
ld (hl),b
ld sp,$
tile_sp0 equ $-2
pop de,hl
xor a
ret
для спрайтов можно придумать похожее или например вот
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld (draw_sp0),sp
ld sp,hl
dup 8
ld a,(de)
or c
xor b
ld (de),a
inc de
pop bc
edup
самое главное это контролировать во время отрисовки регистр в котором забираешь спрайт
Мое замечание по слову "номеров". Скорость уже увеличится, если эти номера заменить реальным адресом тайла. Я так делал в Вере.
Отличная игра получилась! А расскажи, как выбирал эти адреса и выводил на экран? Использовал буфер или напрямую? Как я понял, 512 тайлов 2*16 занимают 16КБ. Располагал их в #8000 или в #c000? Где хранилась карта?
Тут обсуждают по большей части вывод тайла, но имхо не хватат обсуждения полного цикла с выборкой из карты. Ибо все "быстрые" способы могут разбиться об накладные расходы на переключение sp. Нужен комплексный разбор.
зы. Ничего что я на ты?
- - - Добавлено - - -
самое главное это контролировать во время отрисовки регистр в котором забираешь спрайт
Спасибо за примеры!
Решил пока вопрос восстановления данных отодвинуть на второй план. Сейчас думаю как побыстрее вывести фон на экран. Задача усложняется выводом со смещением. Возможно ли вывести тайловый экран со смещением по горизонтали на несколько пикселей хотя бы за 100 Килотактов (Кт)? Интересует полный цикл от выборки из карты до вывода на экран. У меня пока получается порядка 150Кт при размере тайла 3*16Б и средней заполненности экрана от 1 до 4-х одинаковых тайлов подряд. Графику читаю стеком, на экран вывожу по (hl)
«змейкой». Если делаю чтение и запись стеком, то получается дольше из-за накладных расходов на переключение sp, плюс не хватает регистров. Но теоретически предел метода (sp)=>(hl) (pop rp; ld (hl),r;inc l = 5+7+4=16t/Б) больше чем (sp)=>(sp) (pop rp; push rp = 5 + 5.5 = 11.5t/Б).
Спасибо за примеры!
Решил пока вопрос восстановления данных отодвинуть на второй план. Сейчас думаю как побыстрее вывести фон на экран. Задача усложняется выводом со смещением. Возможно ли вывести тайловый экран со смещением по горизонтали на несколько пикселей хотя бы за 100 Килотактов (Кт)? Интересует полный цикл от выборки из карты до вывода на экран. У меня пока получается порядка 150Кт при размере тайла 3*16Б и средней заполненности экрана от 1 до 4-х одинаковых тайлов подряд. Графику читаю стеком, на экран вывожу по (hl)
«змейкой». Если делаю чтение и запись стеком, то получается дольше из-за накладных расходов на переключение sp, плюс не хватает регистров. Но теоретически предел метода (sp)=>(hl) (pop rp; ld (hl),r;inc l = 5+7+4=16t/Б) больше чем (sp)=>(sp) (pop rp; push rp = 5 + 5.5 = 11.5t/Б).
эта проблема решается только в комплексе. Универсального решения нет
Смотри StormLord (https://www.worldofspectrum.org/infoseekid.cgi?id=0004922&loadpics=3)
Смотри RoboCop (https://www.worldofspectrum.org/infoseekid.cgi?id=0004179&loadpics=3)
какой вариант тебе больше подходит?
эта проблема решается только в комплексе. Универсального решения нет
Смотри StormLord (https://www.worldofspectrum.org/infoseekid.cgi?id=0004922&loadpics=3)
Смотри RoboCop (https://www.worldofspectrum.org/infoseekid.cgi?id=0004179&loadpics=3)
какой вариант тебе больше подходит?
Вроде они одинаковые, простой равномерный горизонтальный скролл. Предлагаешь дизассемблировать и посмотреть как там устроено?
Вроде они одинаковые, простой равномерный горизонтальный скролл. Предлагаешь дизассемблировать и посмотреть как там устроено?
они вообще разные.
Штормлорд это 25 фпс и графика по OR
Робокоп это 12.5 фпс и графика с маской.
есть еще Beyond the Ice Palace (https://www.worldofspectrum.org/infoseekid.cgi?id=0000512&loadpics=3)
она что-то среднее между
вобщем посмотри определись что именно тебе нужно. И я тебе подскажу.
они вообще разные.
Штормлорд это 25 фпс и графика по OR
Робокоп это 12.5 фпс и графика с маской.
есть еще Beyond the Ice Palace (https://www.worldofspectrum.org/infoseekid.cgi?id=0000512&loadpics=3)
она что-то среднее между
вобщем посмотри определись что именно тебе нужно. И я тебе подскажу.
Под графикой по OR и с маской ты имеешь в виду спрайты? Конечно хочется чтобы была маска, но пока не понятно сколько на это останется ресурсов после вывода фона. Робокоп наверное ближе всего получается.
Под графикой по OR и с маской ты имеешь в виду спрайты? Конечно хочется чтобы была маска, но пока не понятно сколько на это останется ресурсов после вывода фона. Робокоп наверное ближе всего получается.
Нет. Так не пойдет.
Нужно какое то представление о том что ты хочешь получить.
Нарисуй свое представление как оно должно выглядеть.
Нет. Так не пойдет.
Нужно какое то представление о том что ты хочешь получить.
Нарисуй свое представление как оно должно выглядеть.
В моём воображении, это соник 3 на сеге. Ради фпс-а я готов пожертвовать вертикальным скроллом до пикселя (и скролить шагом в тайл, посмотреть, будет ли это приемлемо), да и горизонтальный хочу сделать с шагом в 2 пикселя, скролл может быть также в 4, 6, 8... в зависимости от скорости гг. Фоновое изображение скорее всего тоже не удастся сделать. Чтобы ускорить отрисовку, нужно отдельно закрашивать или даже пропускать пустые тайлы. Хочется чтобы был цвет, спрайты по маске. Хочется полный экран, чтобы было ощущение простора. Это 16*12 тайлов (2*2 знакоместа), но можно двумя строками сверху и снизу пожертвовать. Опять же, в итоге смотреть на геймплей. Совершенно не понятно как реализовывать игровую логику и сколько она будет кушать тактов. В общем, по ощущениям, хочется неприлично много, но хочется пройти этот путь самому, может быть найдётся какой-то приемлемый компромисс.
В моём воображении, это соник 3 на сеге. Ради фпс-а я готов пожертвовать вертикальным скроллом до пикселя (и скролить шагом в тайл, посмотреть, будет ли это приемлемо), да и горизонтальный хочу сделать с шагом в 2 пикселя, скролл может быть также в 4, 6, 8... в зависимости от скорости гг. Фоновое изображение скорее всего тоже не удастся сделать. Чтобы ускорить отрисовку, нужно отдельно закрашивать или даже пропускать пустые тайлы. Хочется чтобы был цвет, спрайты по маске. Хочется полный экран, чтобы было ощущение простора. Это 16*12 тайлов (2*2 знакоместа), но можно двумя строками сверху и снизу пожертвовать. Опять же, в итоге смотреть на геймплей. Совершенно не понятно как реализовывать игровую логику и сколько она будет кушать тактов. В общем, по ощущениям, хочется неприлично много, но хочется пройти этот путь самому, может быть найдётся какой-то приемлемый компромисс.Тогда изучай Batman the movie.
Там более подходящий алгоритм фона.
Но сразу забудь про полный экран.
Они все рассчитаны на 2/3 экрана.
изучай Batman the movie.
Там более подходящий алгоритм фона.
как вариант посмотрите Hong Kong Phooey
если не ошибаюсь там такой-же способ печати
Тогда изучай Batman the movie.
Там более подходящий алгоритм фона.
Но сразу забудь про полный экран.
Они все рассчитаны на 2/3 экрана.
Спасибо, буду посмотреть.
- - - Добавлено - - -
как вариант посмотрите Hong Kong Phooey
если не ошибаюсь там такой-же способ печати
Спасибо, гляну.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot