Цитата Сообщение от ivagor Посмотреть сообщение
Набросал упомянутый ранее вариант, надеюсь принципиальных ошибок нет. Стоит отметить, что порядок вывода очень своеобразный, конвертер графики надо делать аккуратно.

- - - Добавлено - - -

Скопипастил у jerri описание и не поправил: D - не совсем X, это X+старшая половина адреса начальной плоскости.
Спасибо за оптимизацию! Твой вариант самый быстрый.
Я его совсем незначительно ускорил (только в инициализации). примерно на 1,2% и сделал его чуточку понятнее для хранения данных (на мой вкус), хотя и далеко от идеала.

твой вариант
Код:
;----------------------------------------------------------------
; draw a sprite (24x24 pixels)
; author ivagor
; method: zig-zag, unrolled

; in:
; BC	sprite data
; DE	screen address (x,y)

			.macro DRAW_EVEN_LINE_IVAGOR()
			POP B
			MOV M,C
			DCR H
			MOV M,B
			DCR H
			POP B
			MOV M,C
			MOV H,E
			MOV M,B
			INR H
			POP B
			MOV M,C
			INR H
			MOV M,B
			MOV h,a
			POP B
			MOV M,C
			INR H
			MOV M,B
			INR H
			POP B
			MOV M,C
			DCR L
			.endmacro

			
			.macro DRAW_ODD_LINE_IVAGOR()
			MOV M,B
			DCR H
			POP B
			MOV M,C
			DCR H
			MOV M,B
			MOV H,E
			POP B
			MOV M,C
			INR H
			MOV M,B
			INR H
			POP B
			MOV M,C
			MOV H,D
			MOV M,B
			INR H
			POP B
			MOV M,C
			INR H
			MOV M,B
			DCR L
			.endmacro

			.function DS_ivagor
DrawSprite_ivagor:
			; store SP
			LXI		H,0				; (12)
			DAD		SP				; (12)
			SHLD	@restoreSP+1	; (20)
			; HL = BC
			MOV		H, B			; (8)
			MOV		L, C			; (8)
			; BC = (HL), HL +=2
			MOV		C, M			; (8)
			INX		H				; (8)
			MOV		B, M			; (8)
			INX		H				; (8)
			; SP = HL
			SPHL					; (8)
			
			; HL = DE
			XCHG					; (4)
			; D = screen X
			MOV		D, H			; (8)
			; E = second screen X
			MVI		A, $20			; (8)
			ADD		D				; (4)
			MOV		E, A			; (8)
			; A = third screen X
			MVI		A, $20			; (8)
			ADD		E				; (4)
			; X += 2
			INR		H				; (8)
			INR		H				; (8)
									; (160)
; screen format
; DRAW_EVEN_LINE_IVAGOR
; 1st screen buff : 3 <- 2 <- (1)
; 2nd screen buff : (4) -> 5 -> 6
; 3rd screen buff : (7) -> 8 -> 9
; y--
; DRAW_ODD_LINE_IVAGOR
; 3nd screen buff : 12 <- 11 <- 10
; 2nd screen buff : (13) -> 14 -> 15
; 1st screen buff : (16) -> 17 -> 18
; y--
; repeat

; HL = screen address (X + 2, Y)
; SP = sprite data + 2
; D - 1st screen buff X
; E - 2nd screen buff X
; A - 3rd screen buff X

			; first line
			MOV M,C
			DCR H
			MOV M,B
			DCR H
			POP B
			MOV M,C
			MOV H,E
			MOV M,B
			INR H
			POP B
			MOV M,C
			INR H
			MOV M,B
			MOV h,a
			POP B
			MOV M,C
			INR H
			MOV M,B
			INR H
			POP B
			MOV M,C
			DCR L

			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()	
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()	
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			DRAW_ODD_LINE_IVAGOR()
			DRAW_EVEN_LINE_IVAGOR()
			; 24th line
			MOV M,B
			DCR H
			POP B
			MOV M,C
			DCR H
			MOV M,B
			MOV H,E
			POP B
			MOV M,C
			INR H
			MOV M,B
			INR H
			POP B
			MOV M,C
			MOV H,D
			MOV M,B
			INR H
			POP B
			MOV M,C
			INR H
			MOV M,B

@restoreSP:	LXI		SP, TEMP_ADDR	; restore SP (12)
			RET
			.endfunction
Код:
;----------------------------------------------------------------
; draw a sprite (24x24 pixels)
; author: parallelno
; method: zig-zag
; in:
; BC	sprite data
; DE	screen address (x,y)
			.macro DRAW_EVEN_LINE_PARALLELNO2(_moveOneLineDown = true)
			POP B		; 1st screen space 
			MOV M,C
			INR H
			MOV M,B
			INR H
			POP B
			MOV M,C
			MOV H,E		; 2nd screen space 
			MOV M,B
			DCR H
			POP B
			MOV M,C
			DCR H
			MOV M,B
			MOV H,A		; 3rd screen space 
			POP B
			MOV M,C
			DCR H
			MOV M,B
			DCR H
			POP B
			MOV M,C
			.if _moveOneLineDown == true
			DCR	L
			.endif
			.endmacro

			.macro DRAW_ODD_LINE_PARALLELNO2(_moveOneLineDown = true)
			MOV M,B		; 3rd screen space 
			INR H
			POP B
			MOV M,C
			INR H
			MOV M,B
			MOV H,E		; 2nd screen space 
			POP B
			MOV M,C
			DCR H
			MOV M,B
			DCR H
			POP B
			MOV M,C
			MOV H,D		; 1st screen space 
			MOV M,B
			DCR H
			POP B
			MOV M,C
			DCR H
			MOV M,B
			.if _moveOneLineDown == true
			DCR	L
			.endif			
			.endmacro

			.function DS_parallelno2
DrawSprite_parallelno2:
			; store SP
			LXI		H, 0			; (12)
			DAD		SP				; (12)
			SHLD	@restoreSP + 1	; (20)
			; SP = BC
			MOV		H, B			; (8)
			MOV		L, C			; (8)
			SPHL					; (8)
			; D, E, A are initial X for 
			; the 1st, the 2nd, the 3rd screen buffs
			XCHG					; (4)
			MVI		A, 2			; (8)
			ADD 	H				; (4)
			MOV 	D, A			; (8)
			ADI     $20             ; (8)
			MOV     E, A            ; (8)
			ADI 	$20				; (8)
									; (108) total
; screen format
; DRAW_EVEN_LINE_PARALLELNO2()
; 1st screen buff : 1 -> 2 -> 3
; 2nd screen buff : 4 <- 5 <- (6)
; 3rd screen buff : 7 <- 8 <- (9)
; y--
; DRAW_ODD_LINE_PARALLELNO2()
; 3nd screen buff : 12 -> 11 -> 10
; 2nd screen buff : 13 <- 14 <- (15)
; 1st screen buff : 18 <- 17 <- (16)
; y--
; repeat

; HL - 1st screen buff XY
; SP - sprite data
; D - 1st screen buff X + 2
; E - 2nd screen buff X + 2
; A - 3rd screen buff X + 2

			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2()	
			DRAW_EVEN_LINE_PARALLELNO2()	
			DRAW_ODD_LINE_PARALLELNO2( false)

@restoreSP:	LXI		SP, TEMP_ADDR	; restore SP (12)
			RET
			.endfunction