Рисуем спрайт двух персонажей в сборке Z80
Следуя « Первые шаги в языке ассемблера Z80», я пытаюсь переместить спрайт с двумя старшими символами на ассемблере.
ORG 30000 ; Origin
LASTK EQU 23560 ; last key press (system variable)
PRINT EQU 8252 ; This means the label PRINT equates to 8252.
XOR a ; quick way to load accumulator with zero.
LD A, 2 ; set print channel to screen
CALL 5633 ; Open channel two (ie, write to screen)
LD HL, GFX ; set up UDGs
LD (23675), HL ; where the UDG characters are stored.
CALL 3503 ; clear the screen. CLS
MAINLP CALL PRTPLAY ; print player sprite
HALT ; Slow it down three times
HALT
HALT
LD BC, $FEFE ; load port address into BC, scan for right ("X")
IN A, (C) ; load port data into A
AND %0000100 ; looking for X
JR Z, GORIGHT ; if Z is press, go right
JR MAINLP ; loop back to continue scanning
GORIGHT LD A, (PLAYER+2) ; if player is at right edge, don't continue
CP 31
JR Z, MAINLP ; Jump Relative Zero
CALL UNDRAW
LD A, (PLAYER+2) ; get player's X coordinate
INC A ; add 1
LD (PLAYER+2), A
JR MAINLP
PRTPLAY LD DE, PLAYER ; print player graphic
LD BC, EOPLAYR-PLAYER
CALL PRINT
RET
UNDRAW LD A, " " ; change graphic to empty space
LD (PLAYER+3), A ; store it
CALL PRTPLAY ; undraw graphic from screen
LD A, 144 ; change graphic back to normal
LD (PLAYER+3), A ; store it
RET ; return to basic!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Player x, y
PLAYER DEFB 22, 12, 15, 144 ; print at Y, X, char 144 UDG (A)
DEFB 22, 13, 15, 145 ; print at Y+1, X, char 145 UDG (B)
EOPLAYR EQU $
; Graphics UDG Character
GFX DEFB 6, 62, 124, 52, 62, 60, 24, 60
DEFB 126, 126, 247, 251, 60, 118, 110, 119
Спрайт Manic Miner нарисован нормально. Однако, когда «x» нажимается для перехода вправо, перемещается только верхняя половина. Это означает, что либо отрисовка не работает, либо нижний символ не увеличивается. Я очень новичок в ассемблере и пытался понять, где я ошибся. Я подозреваю, что это то место, где DEFB явно указано быть на 144 и 145, но отрисовка только на 144. Однако это должно быть покрыто LD BC, EOPLAYR-PLAYER. Смущенный.
1 ответ
Итак, вы попытались самостоятельно расширить пример из книги... отлично, так вы больше всего научитесь.
Ваше подозрение отчасти верно, т.PRTPLAY
печатает все байты.
Таким образом, он печатает первый управляющий код AT, помещающий курсор в (x,12), затем он печатает символ UDG «A» 144, затем другой управляющий код AT, помещающий курсор в (x, 13), и символ UDG «B» 145.
The UNDRAW
изменяет только верхний символ 144 на пробел, поэтому он печатает пробел поверх спрайта и снова печатает UDG «B» поверх нижнего, оставляя спрайт видимым.
Чтобы исправить это (таким же обыденным способом, как работает оригинал):
UNDRAW LD A, " " ; change graphic to empty space
LD (PLAYER+3), A ; replace UDG A 144
LD (PLAYER+7), A ; replace UDG B 145
CALL PRTPLAY ; undraw graphic from screen
LD A, 144 ; change graphic back to normal
LD (PLAYER+3), A ; store it
LD A, 145
LD (PLAYER+7), A
RET ; return to caller
И аналогичным образом подпрограмма исправления координаты X управляющего кода AT теперь должна исправлять два места, поскольку в вашей строке печати есть два управляющих кода AT:
GORIGHT LD A, (PLAYER+2) ; if player is at right edge, don't continue
CP 31
JR Z, MAINLP ; Jump Relative Zero
CALL UNDRAW
LD A, (PLAYER+2) ; get player's X coordinate
INC A ; add 1
LD (PLAYER+2), A ; update X position of upper char 144
LD (PLAYER+6), A ; update X position of lower char 145
JR MAINLP
Вы можете захотеть пройти этот вид учебника, вызывая ПЗУ, используя подпрограммы BASIC для графики как можно быстрее, и искать более продвинутые учебники, рисующие непосредственно в видео ОЗУ без ПЗУ, так как этот пример очень медленный с точки зрения производительности (начало бы задыхается, если вы попытаетесь анимировать еще несколько спрайтов, подобных этому, в то время как с оптимизированной сборкой вы можете перемещать около 20+ спрайтов 8x16 за один кадр), и становится очень громоздким, если вы хотите делать более крупные спрайты, и внезапно вам приходится исправлять многие элементы управления AT кодов и много gfx-символов (144145), плюс это становится дополнительной головной болью, когда нужно отсечение по краям спрайта (а печатать нужно только часть символов, а не все).
Я имею в виду, что вы все равно должны попытаться понять, что и как делает учебник, в целом это достойный учебник, и вы можете применить свои навыки сборки Z80 на нем, но с точки зрения демо-сценера, делающего демонстрации ZX в течение многих лет (и нацеленного на высокопроизводительные полноэкранные трюки gfx) - этот код хорош только для того, чтобы научиться не писать код ZX. :)
Также может быть несколько проще следовать этому руководству, если вы знакомы с ZX BASIC и тем, какPRINT
работает на бейсике. Если вы совершенно не знакомы с ZX BASIC и только изучаете сборку Z80, то такие процедуры печати, вероятно, еще более запутаны, чем запись кода непосредственно в видеопамять без процедур ПЗУ.