
Сообщение от
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