Важная информация

User Tag List

Показано с 1 по 8 из 8

Тема: Помощь с оптимизацией кода

  1. #1
    Guru Аватар для moroz1999
    Регистрация
    17.01.2005
    Адрес
    Tallinn
    Сообщений
    2,517
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    86
    Поблагодарили
    39 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Помощь с оптимизацией кода

    Буду очень благодарен, если кто-нибудь придумает, как можно ускорить этот код без кардинальных изменений в способе вывода.

    Это - вывод монохромного спрайта с маской на произвольную координату экрана. Сам спрайт имеет произвольную высоту/ширину (в байтах, не в пикселях).
    Байты не смещаются на ходу, а используется предварительно рассчитанная таблица всех вариантов смещений для всех возможных вариантов байта (4кб).

    Код:
    SPRXCO		DB	4
    SPRYCO		DB	0
    SPRXLEN	 	DB	3
    SPRYLEN	 	DB	48
    SPRITESRC	EQU	#9B00
    
    
    
    DRAWSPRITE
    			;check if sprite should be displayed without shifting
    			LD	A,(SPRXCO)
    			AND	7
    			JP	Z,DRAWNOX		
    					
    		;--------------------------------------------------
    		;---------------INITIALISATION---------------------
    		;--------------------------------------------------
    
    			ADD	A,#B0			
    			LD	(RIGHTSIDE1+1),A
    			LD	(RIGHTSIDE2+1),A
    			LD	(RIGHTSIDE3+1),A
    			LD	(RIGHTSIDE4+1),A
    			ADD	A,8
    			LD	(LEFTSIDE1+1),A
    			LD	(LEFTSIDE2+1),A
    			LD	(LEFTSIDE3+1),A
    			LD	(LEFTSIDE4+1),A
    			
    			LD	BC,(SPRADR)		;BC = destination address on screen
    			LD	DE,SPRITESRC		;DE = source address in memory
    			LD	A,(SPRYLEN)		
    			LD	IXL,A			;ixl = sprite's height
    			
    			LD	A,(SPRXLEN)
    			DEC	A
    			LD	(DRAWSPRITEITELINE+2), A	;HARDCODED SPRITE'S WIDTH
    			
    		;----------------------------------------------
    		;---------------MAIN CYCLE---------------------
    		;----------------------------------------------
    			
    DRAWSPRITEITELINE 	
    			LD	IXH,0			;ixh = sprite's width, HERE GOES A HARDCODE FROM INIT
    			PUSH    BC
    			
    		;-------START DRAWING RIGHT SIDE OF LEFT BYTE--------	
    
    			LD	A,(DE)			;READ COPY BYTE OF MASK FOR NEXT SCREEN BYTE
    			EX	AF,AF'
    			LD	A,(DE)			;READ BYTE OF MASK
    		
    RIGHTSIDE1	
    			LD	H,00
    			LD	L,A			;HL = BYTE ADDRESS IN RIGHTSIDE PRESHIFTED TABLE
    			
    			LD	A,(BC)			;READ BYTE FROM SCREEN
    			OR	(HL)
    			XOR	(HL)			;APPLY PRESHIFTED MASK FROM TABLE
    			
    			LD	H,A			;SAVE TEMPORARY RESULT IN H
    		
    			INC	DE
    			LD	A,(DE)			;READ BYTE OF SPRITE
    			LD	L,A
    			
    			LD	A,H
    		
    RIGHTSIDE2		
    			LD	H,00			;HL = BYTE ADDRESS IN RIGHTSIDE PRESHIFTED TABLE
    			OR	(HL)			;APPLY PRESHIFTED SPRITE FROM TABLE
    			
    			LD	(BC),A			;LEFT HALFBYTE OF LEFT SIDE OF SPRITE IS DONE, PLACE IT BACK ON SCREEN
    			
    			INC	BC
    		
    			;-------START DRAWING LEFT SIDE OF CENTER BYTE--------
    DRAWSPRITEITECENTER	
    	
    			LD	A,L			;SAVE LEFT SPRITE BYTE IN A
    			EX	AF,AF'			;A = SAVED LEFT BYTE OF MASK 
    			
    LEFTSIDE1	
    			LD	H,00
    			LD	L,A			;HL = BYTE ADDRESS IN LEFTSIDE PRESHIFTED TABLE
    			
    			LD	A,(BC)			;READ FROM SCREEN
    			
    			OR	(HL)
    			XOR	(HL)			;APPLY LEFT MASK BYTE FROM TABLE
    			
    			LD	H,A			;SAVE TEMPORARY RESULT IN H 
    			
    			EX	AF,AF'			;A = SAVED LEFT BYTE OF SPRITE
    			LD	L,A
    			
    			LD	A,H			;RESTORE TEMPORARY RESULT
    			
    LEFTSIDE2	
    			LD	H,00			;HL = BYTE ADDRESS IN LEFTSIDE PRESHIFTED TABLE
    		
    			OR	(HL)			;APPLY LEFT SPRITE BYTE FROM TABLE
    			
    			LD	H,A			;SAVE TEMPORARY RESULT (READY LEFT SIDE OF ONSCREEN BYTE) IN H 
    			
    			INC	DE			
    		;-------START DRAWING RIGHT SIDE OF CENTER BYTE--------	
    		
    			LD	A,(DE)			;READ COPY BYTE OF MASK FOR NEXT SCREEN BYTE
    			EX	AF,AF'
    			
    			LD	A,(DE)			;READ BYTE OF MASK
    			LD	L,A			
    			
    			LD	A,H			;RESTORE TEMPORARY RESULT FROM H
    		
    RIGHTSIDE3	
    			LD	H,00			;HL = BYTE ADDRESS IN RIGHTSIDE PRESHIFTED TABLE
    		
    			OR	(HL)
    			XOR	(HL)			;APPLY PRESHIFTED MASK FROM TABLE
    			
    			LD	H,A			;SAVE TEMPORARY RESULT IN H
    			
    			INC	DE
    			LD	A,(DE)			;READ BYTE OF SPRITE
    			LD	L,A
    			
    			LD	A,H
    		
    RIGHTSIDE4	
    			LD	H,00			;HL = BYTE ADDRESS IN RIGHTSIDE PRESHIFTED TABLE
    			OR	(HL)			;APPLY PRESHIFTED SPRITE FROM TABLE
    			
    			LD	(BC),A			;LEFT HALFBYTE OF LEFT SIDE OF SPRITE IS DONE, PLACE IT BACK ON SCREEN
    			
    			INC	BC
    			
    			DEC	IXH
    			JR	NZ,DRAWSPRITEITECENTER
    		
    		;-------START DRAWING LEFT SIDE OF RIGHT BYTE--------
    			LD	A,L			;SAVE LEFT SPRITE BYTE IN A
    			EX	AF,AF'			;A = SAVED LEFT BYTE OF MASK 
    			
    LEFTSIDE3		
    			LD	H,00
    			LD	L,A			;HL = BYTE ADDRESS IN LEFTSIDE PRESHIFTED TABLE
    			
    			LD	A,(BC)			;READ FROM SCREEN
    			
    			OR	(HL)
    			XOR	(HL)			;APPLY LEFT MASK BYTE FROM TABLE
    			
    			LD	H,A			;SAVE TEMPORARY RESULT IN H 
    			
    			EX	AF,AF'			;A = SAVED LEFT BYTE OF SPRITE
    			LD	L,A
    			
    			LD	A,H			;RESTORE TEMPORARY RESULT
    			
    LEFTSIDE4	
    			LD	H,00			;HL = BYTE ADDRESS IN LEFTSIDE PRESHIFTED TABLE
    			
    			OR	(HL)			;APPLY LEFT SPRITE BYTE FROM TABLE
    			
    			LD	(BC),A
    			
    			INC	DE
    			POP	BC
    			
    			DEC	IXL
    			RET	Z
    			
    			INC	B
    			LD	A,B
    			AND	7
    
    			JR	NZ,DRAWSPRITEITELINE
    			LD	A,C
    			ADD	A,32
    			LD	C,A
    			JR	C,DRAWSPRITEITELINE
    			LD	A,B
    			SUB	8
    			LD	B,A
    			
    			JR	DRAWSPRITEITELINE
    Добавлено через 7 часов 28 минут
    не стану делать новую тему, но вопрос косвенно связан с предыдущим: расскажите пожалуйста в трех словах о выводе спрайтов стеком. параметры те же.
    в чем будет выигрыш? всё равно ведь спрайтам надо делать побитовое смещение или пользоваться табличкой, как сверху?

    ну, прежде всего, не нужно будет пользоваться downhl, верно? но разве это окупит затраты на переброску результата стеком?

    мне кажется, что я чего-то глобально недопонимаю в этом методе, потому что я почти не вижу ему применения при более-менее универсальном использовании.
    Последний раз редактировалось moroz1999; 10.11.2007 в 23:02. Причина: Добавлено сообщение

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #2
    Guru Аватар для moroz1999
    Регистрация
    17.01.2005
    Адрес
    Tallinn
    Сообщений
    2,517
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    86
    Поблагодарили
    39 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    ну ладно, то, что с кодом помочь ни у кого времени нет - это вполне ожидаемо и норм. но на вопросы-то всяко кто-нибудь может ответить?

    пока что вижу плюсы использования теневого экрана в следующем:
    1. основной: downhl практически не нужен. ни для спрайтов персонажей, ни для тайлов на бэкграунде
    2. обрезание экрана по бокам можно не делать. минусы - доп. затраты памяти плюс возникающее ограничение по ширине спрайта

    какие еще плюсы есть?

  4. #3
    Vitamin C++ Аватар для Vitamin
    Регистрация
    14.01.2005
    Адрес
    Таганрог, Россия
    Сообщений
    4,254
    Спасибо Благодарностей отдано 
    9
    Спасибо Благодарностей получено 
    80
    Поблагодарили
    34 сообщений
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Иногда вместо использования downhl используют табличку адресов. Иногда по ней же бегут стеком (например, в процедуре рисования линии).
    Иногда можно совместить вывод через стек и адресацию:

    Код:
    pop hl
    dup N
    pop bc
    ld a,(hl)
    and c
    xor b
    ld (hl),a
    inc l
    edup
    Напрямую выводить на экран через push не всегда эффективно- сказывается необходимость подстройки адресов

  5. #4
    Veteran
    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,055
    Спасибо Благодарностей отдано 
    219
    Спасибо Благодарностей получено 
    47
    Поблагодарили
    31 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Есть еще следующие возможности оптимизации:

    - вместо хранения таблицы сдвигов (каждый байт сдвинут на n бит) можно хранить каждый спрайт в разных вариантах сдвига. При этом потребуется в 8 раз больше памяти под спрайты, но код вывода может стать эффективнее

    - всякий универсальный код будет работать медленнее специализированного. Не следует пытаться получить "самую быструю" универсальную подпрограмму. Вместо этого лучше получить оптимальную подпрограмму для конкретно заданных размеров и конфигурации спрайта. Если спрайт большой, то можно получить некоторый выигрыш, исключив операцию считывания из экранной памяти (так как внутренние области спрайта будут полностью замещать экранные данные).

  6. #5
    Activist
    Регистрация
    23.01.2005
    Сообщений
    235
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    я всегда заранее сдвинутые спрайты использую, если надо быстро вывести на экран. еще обычно делаю так:

    xlen jr nn
    dup max_x_len
    ;output routine
    edup

    т.е. чтобы не использовать счетчик в цикле по х, можно один раз рассчитать на какое смещение перескочить в процедуре вывода. это смещение заносится в (xlen+1).

    удачи!

  7. #6
    DimkaM
    Гость

    По умолчанию

    moroz1999
    Извиняюсь, что поднимаю старую тему.

    Что получилось в конечном итоге, можешь поделится процедуркой?

  8. #7
    Guru Аватар для moroz1999
    Регистрация
    17.01.2005
    Адрес
    Tallinn
    Сообщений
    2,517
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    86
    Поблагодарили
    39 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    DimkaM, данная конкретная процедура осталась такой же. общие исходники (хоть в них и нет никакой конкретики) за неготовностью в паблик выкладывать пока не хочу.
    но, поскольку в обозримом будущем я вряд ли что доделаю, то смотри личные сообщения

  9. #8
    DimkaM
    Гость

    По умолчанию

    Спасибо.
    Буду исследовать,очень интересно узнать производительность.
    Сейчас только начинаю изучать ассемблер.
    Моя цель вывод спрайта 4x4знакоместа, с маской и координатами точностью до пикселя.
    Я написал процедуру со сдвигом, она кушает от 16500 до 32000 тактов на такой спрайт, но есть перспектива уменьшить до соответственно 16500-24000 тактов.

    Может у кого будут ещё предложения.

    Хранить в памяти сдвинутые спрайты нереально, у меня спрайтов на 16кб.

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Нужна помощь
    от Sonic в разделе Несортированное железо
    Ответов: 0
    Последнее: 06.02.2007, 12:12
  2. Как из кода получить текущее значение PC?
    от jim в разделе Программирование
    Ответов: 21
    Последнее: 01.06.2006, 11:12
  3. Помощь по GeneralSound
    от Знахарь в разделе Программирование
    Ответов: 7
    Последнее: 21.02.2006, 18:58
  4. Нужна помощь!
    от Vitamin в разделе Барахолка (архив)
    Ответов: 0
    Последнее: 03.04.2005, 00:35

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •