quinta-feira, 6 de fevereiro de 2020

Gráficos em assembly (I)

No seguimento do artigo sobre primitivas básicas para usar em assembly para texto, desta vamos fornecer as bases para primitivas básicas para usar gráficos em assembly.

No ZX Spectrum, a forma mais simples (não a mais rápida) de escrever pontos /rectas / círculos no ecrã, é usando as rotinas da ROM.

O ecrã são 256 linhas horizontais (x), e 192 verticais (y); no entanto em BASIC, e usando as entradas oficiais das rotinas da ROM, só se consegue desenhar nas 176 linhas superiores.

Para a rotina de gráficos usando a ROM, as coordenadas começam de baixo.

Então:
(0,0)          - canto inferior esquerdo
(255,0)      - canto inferior direito
(0,175)      - canto superior esquerdo
(255,175)  - canto inferior direito

O  posição do último pixel a ser desenhado fica também armazenado na variável X,Y sendo colocado na variável de dois bytes COORDS $5C7D

Para ver se um ponto está a 1 ou 0 (POINT):
;B=Y
;C=X
;retorna:
;A=0 ou 1 

POINT:

       CALL $22CE   ; entrada não oficial de POINT-SUB $22CB
       JP   $2DD5   ; FP-TO-A 
Nota:
FP-TO-A 
POINT-SUB

Para marcar um ponto no ecrã (PLOT):
; B=Y
; C=X

PLOT:
       JP $22DF    ; entrada não oficial de PLOT $22DC
Nota:
PLOT

Para fazer uma linha (DRAW), tomando como ponto de origem o ultimo pixel X,Y desenhado por rotinas de ROM (COORDS):
; B=Y de deslocação de destino (pixels)
; D -> sinal de B (01 Positivo, $FF negativo) 
; C=X de deslocação de destino (pixels)
; E -> sinal de C (01 Positivo, $FF negativo)

DRAW:
        CALL     $24BA  ; entrada não oficial de DRAW_LINE $24B7
        RET
Nota:
DRAW_LINE

Para fazer um círculo, é preciso colocar os argumentos X, Y e Z no stack floating point do ZX Spectrum:
; B = X
; C = Y
; D = RADIUS in pixels (Z)

CIRCLE:
        ; PUSH  X in FP stack

        PUSH    DE
        PUSH    BC
        LD      A,B
        CALL    $2D28 ; STACK_A

        POP     BC

        ; PUSH Y

        LD      A,C
        CALL    $2D28 ; STACK_A

        POP     DE

        ; PUSH Z

        LD      A,D
        CALL    $2D28 ; STACK_A

        JP      $232D ; CIRCLE - entrada não oficial
Nota:
CIRCLE

Uma vez que o stack FP é usado nas rotinas CIRCLE, e DRAW da ROM, e estas corrompem HL',  existe um imperativo de ter HL´ a $2758 antes de voltar ao BASIC. Pode-se afirmar que é um bug na ROM ele não ser restaurado em todas em situações.

É necessário atribuir $2758 a HL´ antes de voltar ao BASIC, ou, de outra forma, o ZX Spectrum crasha.
 RET_TO_BASIC:

        ; USING FP CALCULATOR CORRUPTS HL'
        ; so we need to restore it
        ; to be able to return to BASIC

        EXX
        LD      HL,$2758
        EXX
        RET

Rotina exemplo:
source pixels rom.asm  TAP

PS: A limitação da rotina PLOT não usar as 16 linhas de pixels inferiores está built-in na rotina de ROM em $22AA: The Pixel address/PIXEL_ADD subroutine.

 Em $22AA onde está LD A,$AF (175), substituir por LD A,$BF (191) para usar o ecrã inteiro.

 Aliás, para usar uma rotina que desenhe no ecrã inteiro, mas só usando a rotina PLOT, se não for uma ROM com patchs:
 ; B=Y
 ; C=X


PLOT:
       CALL PLOT_SUB
       JP         $0D4D ; TEMPS

PLOT_SUB:

       LD        ($5C7D),BC
       LD        A,$BF
       JP        $22AC ; entrada não oficial para PLOT_SUB na ROM

 PPS: na ROM original, o LD ($5C7D),BC devia estar depois do teste contra 175, e não antes.

Sem comentários:

Enviar um comentário