cursos:ensamblador:gfx2_direccionamiento

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cursos:ensamblador:gfx2_direccionamiento [13-01-2024 10:59] sromerocursos:ensamblador:gfx2_direccionamiento [21-01-2024 17:22] (actual) – [Optimizaciones para Get_Pixel_Offset_HR] sromero
Línea 54: Línea 54:
 \\  \\ 
   * **Área de imagen**:   * **Área de imagen**:
-    * El área de imagen se divide en 3 tercios de pantalla de 2KB de memoria cada uno, que van de $4000 a $47FF (tercio superior), de $4800 a $4FFF (tercio central) y de $5000 a $57FF (tercio inferior).+    * El área de imagen se divide en 3 tercios de pantalla de 2KB de memoria cada uno, que van de $4000 a $47ff (tercio superior), de $4800 a $4fff (tercio central) y de $5000 a $57ff (tercio inferior).
     * Cada uno de los tercios comprende 8 líneas de 32 bloques horizontales (256x64 píxeles). Dentro de cada uno de esos 2KB, tenemos, de forma lineal, 64 bloques de 32 bytes (256 píxeles) de información que representan cada scanline de esos 8 bloques.     * Cada uno de los tercios comprende 8 líneas de 32 bloques horizontales (256x64 píxeles). Dentro de cada uno de esos 2KB, tenemos, de forma lineal, 64 bloques de 32 bytes (256 píxeles) de información que representan cada scanline de esos 8 bloques.
     * Los primeros 32 bytes de dicho bloque contienen la información del scanline 0 del bloque 0. Avanzando de 32 en 32 bytes tenemos los datos del scanline 0 del bloque 1, el scanline 0 del bloque 2, el scanline 0 del bloque 3, etc, hasta que llegamos al scanline 7 del bloque 0. Los siguientes 32 bytes repiten el proceso pero con el scanline 1 de cada bloque.     * Los primeros 32 bytes de dicho bloque contienen la información del scanline 0 del bloque 0. Avanzando de 32 en 32 bytes tenemos los datos del scanline 0 del bloque 1, el scanline 0 del bloque 2, el scanline 0 del bloque 3, etc, hasta que llegamos al scanline 7 del bloque 0. Los siguientes 32 bytes repiten el proceso pero con el scanline 1 de cada bloque.
Línea 66: Línea 66:
   * **Area de atributos**:   * **Area de atributos**:
      * El área de atributos se encuentra en memoria inmediatamente después del área de imagen, por lo que empieza en la posición de memoria 16384+6144 = 22528 ($5800).      * El área de atributos se encuentra en memoria inmediatamente después del área de imagen, por lo que empieza en la posición de memoria 16384+6144 = 22528 ($5800).
-     * Cada byte del área de atributos se denomina //atributo// y define el valor de color de tinta, papel, brillo y flash de un carácter / bloque de la pantalla. Esto implica que el área de atributos ocupa 32x24x1 = 768 bytes en memoria, por lo que empieza en 22528 ($5800) y acaba en 23295 ($5AFF).+     * Cada byte del área de atributos se denomina //atributo// y define el valor de color de tinta, papel, brillo y flash de un carácter / bloque de la pantalla. Esto implica que el área de atributos ocupa 32x24x1 = 768 bytes en memoria, por lo que empieza en 22528 ($5800) y acaba en 23295 ($5aff).
      * Los diferentes bits de un atributo de carácter son: Bit 7 = FLASH, Bit 6 = BRIGHT, Bits 5-3 = PAPER, Bits 2-0 = INK.      * Los diferentes bits de un atributo de carácter son: Bit 7 = FLASH, Bit 6 = BRIGHT, Bits 5-3 = PAPER, Bits 2-0 = INK.
      * Los valores de tinta y papel son un valor de 0-7 que junto al brillo como bit más significativo componen un índice (B-I-I-I) contra una paleta de colores interna definida en la ULA, donde el 0 es el color negro y el 15 el blanco de brillo máximo.      * Los valores de tinta y papel son un valor de 0-7 que junto al brillo como bit más significativo componen un índice (B-I-I-I) contra una paleta de colores interna definida en la ULA, donde el 0 es el color negro y el 15 el blanco de brillo máximo.
Línea 116: Línea 116:
 | 3 | $5860 | 22624 | 0101100001100000b | | 3 | $5860 | 22624 | 0101100001100000b |
 | 4 | $5880 | 22656 | 0101100010000000b | | 4 | $5880 | 22656 | 0101100010000000b |
-| 5 | $58A0 | 22688 | 0101100010100000b | +| 5 | $58a0 | 22688 | 0101100010100000b | 
-| 6 | $58C0 | 22720 | 0101100011000000b | +| 6 | $58c0 | 22720 | 0101100011000000b | 
-| 7 | $58E0 | 22752 | 0101100011100000b |+| 7 | $58e0 | 22752 | 0101100011100000b |
 | 8 | $5900 | 22784 | 0101100100000000b | | 8 | $5900 | 22784 | 0101100100000000b |
 | 9 | $5920 | 22816 | 0101100100100000b | | 9 | $5920 | 22816 | 0101100100100000b |
Línea 124: Línea 124:
 | 11 | $5960 | 22880 | 0101100101100000b | | 11 | $5960 | 22880 | 0101100101100000b |
 | 12 | $5980 | 22912 | 0101100110000000b | | 12 | $5980 | 22912 | 0101100110000000b |
-| 13 | $59A0 | 22944 | 0101100110100000b | +| 13 | $59a0 | 22944 | 0101100110100000b | 
-| 14 | $59C0 | 22976 | 0101100111000000b | +| 14 | $59c0 | 22976 | 0101100111000000b | 
-| 15 | $59E0 | 23008 | 0101100111100000b | +| 15 | $59e0 | 23008 | 0101100111100000b | 
-| 16 | $5A00 | 23040 | 0101101000000000b | +| 16 | $5a00 | 23040 | 0101101000000000b | 
-| 17 | $5A20 | 23072 | 0101101000100000b | +| 17 | $5a20 | 23072 | 0101101000100000b | 
-| 18 | $5A40 | 23104 | 0101101001000000b | +| 18 | $5a40 | 23104 | 0101101001000000b | 
-| 19 | $5A60 | 23136 | 0101101001100000b | +| 19 | $5a60 | 23136 | 0101101001100000b | 
-| 20 | $5A80 | 23168 | 0101101010000000b | +| 20 | $5a80 | 23168 | 0101101010000000b | 
-| 21 | $5AA0 | 23200 | 0101101010100000b | +| 21 | $5aa0 | 23200 | 0101101010100000b | 
-| 22 | $5AC0 | 23232 | 0101101011000000b | +| 22 | $5ac0 | 23232 | 0101101011000000b | 
-| 23 | $5AE0 | 23264 | 0101101011100000b |+| 23 | $5ae0 | 23264 | 0101101011100000b |
 //Direcciones del atributo en el carácter (0,f)// //Direcciones del atributo en el carácter (0,f)//
 \\  \\ 
Línea 167: Línea 167:
 Get_Attribute_Offset_LR_SLOW: Get_Attribute_Offset_LR_SLOW:
     ; calcular dir_atributo como "inicio_attr + (32*f) + c"     ; calcular dir_atributo como "inicio_attr + (32*f) + c"
-    LD H, 0 +    ld h, 0 
-    LD LB         ; HL = "fila" +    ld lb                  ; HL = "fila" 
-    ADD HLHL      ; HL = HL*2 +    add hlhl               ; HL = HL*2 
-    ADD HLHL      ; HL = HL*4 +    add hlhl               ; HL = HL*4 
-    ADD HLHL      ; HL = HL*8 +    add hlhl               ; HL = HL*8 
-    ADD HLHL      ; HL = HL*16 +    add hlhl               ; HL = HL*16 
-    ADD HLHL      ; HL = HL*32 +    add hlhl               ; HL = HL*32 
-    LD D, 0 +    ld d, 0 
-    LD EC         ; DE = "columna" +    ld ec                  ; DE = "columna" 
-    ADD HLDE      ; HL = fila*32 + columna +    add hlde               ; HL = fila*32 + columna 
-    LD DE, 22528    ; Direccion de inicio de atributos +    ld de, 22528             ; Direccion de inicio de atributos 
-    ADD HLDE      ; HL = 22528 + fila*32 + columna +    add hlde               ; HL = 22528 + fila*32 + columna 
-    RET+    ret
 </code> </code>
  
Línea 197: Línea 197:
 | 4 | $5880 | 22656 | //010110//**00100**00000b | | 4 | $5880 | 22656 | //010110//**00100**00000b |
 | (...) | (...) | (...) | (...) | | (...) | (...) | (...) | (...) |
-| 21 | $5AA0 | 23200 | //010110//**10101**00000b | +| 21 | $5aa0 | 23200 | //010110//**10101**00000b | 
-| 22 | $5AC0 | 23232 | //010110//**10110**00000b | +| 22 | $5ac0 | 23232 | //010110//**10110**00000b | 
-| 23 | $5AE0 | 23264 | //010110//**10111**00000b |+| 23 | $5ae0 | 23264 | //010110//**10111**00000b |
  
-  * Los 6 bits más significativos de la dirección son 010110, que es la parte de la dirección que provoca que todas las posiciones estén entre $5800 y $5AFF.+  * Los 6 bits más significativos de la dirección son 010110, que es la parte de la dirección que provoca que todas las posiciones estén entre $5800 y $5aff.
   * Los bits 5, 6, 7 y 8 se corresponden con la fila que queremos consultar.   * Los bits 5, 6, 7 y 8 se corresponden con la fila que queremos consultar.
   * Los bits 0, 1, 2, 3 y 4 los utilizaremos para acceder a a la columna deseada. En la tabla anterior son siempre 0 porque estamos mostrando las direcciones de inicio de cada fila, es decir, de (0,f), por lo que estos bits 0-4 son 0.   * Los bits 0, 1, 2, 3 y 4 los utilizaremos para acceder a a la columna deseada. En la tabla anterior son siempre 0 porque estamos mostrando las direcciones de inicio de cada fila, es decir, de (0,f), por lo que estos bits 0-4 son 0.
Línea 226: Línea 226:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Attribute_Offset_LR: Get_Attribute_Offset_LR:
-    LD AB            ; Ponemos en A la fila (000FFFFFb) +    ld ab                  ; Ponemos en A la fila (000FFFFFb) 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    RRCA               ; Desplazamos A 3 veces (A=A>>3) +    rrca                     ; Desplazamos A 3 veces (A=A>>3) 
-    AND 3              ; A = A AND 00000011 = los 2 bits mas +    and %00000011            ; A = A and %00000011 = los 2 bits mas 
-                       ; altos de FILA (000FFFFFb -> 000000FFb+                             ; altos de FILA (%000FFFFF -> %000000FF
-    ADD A$58         ; Ponemos los bits 15-10 como 010110b +    add a%01011000         ; Ponemos los bits 15-10 como 010110b 
-    LD HA            ; Lo cargamos en el byte alto de HL +    ld ha                  ; Lo cargamos en el byte alto de HL 
-    LD AB            ; Recuperamos de nuevo en A la FILA +    ld ab                  ; Recuperamos de nuevo en A la FILA 
-    AND 7              ; Nos quedamos con los 3 bits que faltan +    and %00000111            ; Nos quedamos con los 3 bits que faltan 
-    RRCA +    rrca 
-    RRCA               ; Los rotamos para colocarlos en su +    rrca                     ; Los rotamos para colocarlos en su 
-    RRCA               ; ubicacion final (<<5 = >>3) +    rrca                     ; ubicacion final (<<5 = >>3) 
-    ADD AC           ; Sumamos el numero de columna +    add ac                 ; Sumamos el numero de columna 
-    LD LA            ; Lo colocamos en L +    ld la                  ; Lo colocamos en L 
-    RET                ; HL = 010110FFFFFCCCCCb+    ret                      ; HL = %010110FFFFFCCCCC
 </code> </code>
  
Línea 251: Línea 251:
  
 <code z80> <code z80>
-    LD B, 10 +    ld b, 10 
-    LD C, 12 +    ld c, 12 
-    CALL Get_Attribute_Offset_LR+    call Get_Attribute_Offset_LR
  
-    LD A, 85             ; Brillo + Magenta sobre Cyan +    ld a, 85                 ; Brillo + Magenta sobre Cyan 
-    LD (HL), A           ; Establecemos el atributo de (12,10)+    ld (hl), a               ; Establecemos el atributo de (12,10)
 </code> </code>
  
Línea 266: Línea 266:
  
 <code z80> <code z80>
-    SRL B +    srl b 
-    SRL B +    srl b 
-    SRL B              ; B = B/8 -> Ahora B es FILA+    srl b                    ; B = B/8 -> Ahora B es FILA
  
-    SRL C +    srl c 
-    SRL C +    srl c 
-    SRL C              ; C = C/8 -> Ahora C es COLUMNA+    srl c                    ; C = C/8 -> Ahora C es COLUMNA
 </code> </code>
  
Línea 287: Línea 287:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Attribute_Offset_HR: Get_Attribute_Offset_HR:
-    SRL B +    srl b 
-    SRL B +    srl b 
-    SRL B              ; B = B/8 -> Ahora B es FILA+    srl b                    ; B = B/8 -> Ahora B es FILA
  
-    SRL C +    srl c 
-    SRL C +    srl c 
-    SRL C              ; C = C/8 -> Ahora C es COLUMNA+    srl c                    ; C = C/8 -> Ahora C es COLUMNA
  
-    LD AB +    ld ab 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    RRCA               ; Desplazamos A 3 veces (A=A>>3) +    rrca                     ; Desplazamos A 3 veces (A=A>>3) 
-    AND 3              ; A = A AND 00000011 = los 2 bits mas +    and %00000011            ; A = A and 00000011 = los 2 bits mas 
-                       ; altos de FILA (000FFFFFb -> 000000FFb) +                             ; altos de FILA (000FFFFFb -> 000000FFb) 
- +    add a%01011000         ; Ponemos los bits 15-10 como 010110b 
-    ADD A$58         ; Ponemos los bits 15-10 como 010110b +    ld ha                  ; Lo cargamos en el byte alto de HL 
-    LD HA            ; Lo cargamos en el byte alto de HL +    ld ab                  ; Recuperamos de nuevo en A la FILA 
-    LD AB            ; Recuperamos de nuevo en A la FILA +    and %00000011            ; Nos quedamos con los 3 bits que faltan 
-    AND 7              ; Nos quedamos con los 3 bits que faltan +    rrca 
-    RRCA +    rrca                     ; Los rotamos para colocarlos en su 
-    RRCA               ; Los rotamos para colocarlos en su +    rrca                     ; ubicacion final (<<5 = >>3) 
-    RRCA               ; ubicacion final (<<5 = >>3) +    add ac                 ; Sumamos el numero de columna 
-    ADD AC           ; Sumamos el numero de columna +    ld la                  ; Lo colocamos en L 
-    LD LA            ; Lo colocamos en L +    ret                      ; HL = 010110FFFFFCCCCCb
-    RET                ; HL = 010110FFFFFCCCCCb+
 </code> </code>
  
Línea 332: Línea 331:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Attribute_Coordinates_LR: Get_Attribute_Coordinates_LR:
-                      ; Descomponemos HL = 010110FF FFFCCCCCb +                             ; Descomponemos HL = 010110FF FFFCCCCCb 
-    LD AH            ; A = 010110FFb +    ld ah                  ; A = 010110FFb 
-    AND 3              ; A = bits 0, 1 de HL = 2 bits altos de F, CF=0 +    and %00000011            ; A = bits 0, 1 de HL = 2 bits altos de F, CF=0 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    RLCA               ; Rotacion a izquierda 000000FFb -> 000FF000b +    rlca                     ; Rotacion a izquierda 000000FFb -> 000FF000b 
-    LD BA            ; B = 000FF000b+    ld ba                  ; B = 000FF000b
  
-    LD AL +    ld al 
-    AND 224            ; Nos quedamos con los 3 bits mas altos +    and %11100000            ; Nos quedamos con los 3 bits mas altos 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    RLCA               ; Rotacion a izquierda FFF00000b -> 00000FFFb +    rlca                     ; Rotacion a izquierda FFF00000b -> 00000FFFb 
-    OR B               ; A = A + B = 000FFFFFb +    or b                     ; A = A + B = 000FFFFFb 
-    LD BA            ; B = FILA+    ld ba                  ; B = FILA
  
-    LD AL +    ld al 
-    AND 31             ; Nos quedamos con los 5 bits mas bajos +    and %00011111            ; Nos quedamos con los 5 bits mas bajos 
-    LD CA            ; C = COLUMNA+    ld ca                  ; C = COLUMNA
  
-    RET+    ret
 </code> </code>
  
Línea 369: Línea 368:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Attribute_Coordinates_HR: Get_Attribute_Coordinates_HR:
-                       ; Descomponemos HL = 010110FF FFFCCCCCb +                             ; Descomponemos HL = 010110FF FFFCCCCCb 
-    LD AH            ; A = 010110FFb +    ld ah                  ; A = 010110FFb 
-    AND              ; A = bits 0, 1 de HL = 2 bits altos de F, CF=0 +    and                    ; A = bits 0, 1 de HL = 2 bits altos de F, CF=0 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    RLCA               ; Rotacion a izquierda 000000FFb -> 000FF000b +    rlca                     ; Rotacion a izquierda 000000FFb -> 000FF000b 
-    LD BA            ; B = 000FF000b+    ld ba                  ; B = 000FF000b
  
-    LD AL +    ld al 
-    AND 224            ; Nos quedamos con los 3 bits mas altos +    and %11100000            ; Nos quedamos con los 3 bits mas altos 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    RLCA               ; Rotacion a izquierda FFF00000b -> 00000FFFb +    rlca                     ; Rotacion a izquierda FFF00000b -> 00000FFFb 
-    OR B               ; A = A + B = 000FFFFFb +    or b                     ; A = A + B = 000FFFFFb 
-    LD BA            ; B = FILA+    ld ba                  ; B = FILA
  
-    LD AL +    ld al 
-    AND 31             ; Nos quedamos con los 5 bits mas bajos +    and %00011111            ; Nos quedamos con los 5 bits mas bajos 
-    LD CA            ; C = COLUMNA+    ld ca                  ; C = COLUMNA
  
-    SLA C +    sla c 
-    SLA C +    sla c 
-    SLA C              ; C = C*8+    sla c                    ; C = C*8
  
-    SLA B +    sla b 
-    SLA B +    sla b 
-    SLA B              ; B = B*8+    sla b                    ; B = B*8
  
-    RET+    ret
 </code> </code>
  
Línea 409: Línea 408:
 <code z80> <code z80>
 Atributo_derecha: Atributo_derecha:
-    INC HL            ; HL = HL + 1+    inc hl                   ; HL = HL + 1
  
 Atributo_izquierda: Atributo_izquierda:
-    DEC HL            ; HL = HL - 1+    dec hl                   ; HL = HL - 1
  
 Atributo_abajo: Atributo_abajo:
-    LD DE, 32 +    ld de, 32 
-    ADD HLDE        ; HL = HL + 32+    add hlde               ; HL = HL + 32
  
 Atributo_arriba: Atributo_arriba:
-    LD DE, -32 +    ld de, -32 
-    ADD HLDE        ; HL = HL - 32+    add hlde               ; HL = HL - 32
 </code> </code>
  
Línea 427: Línea 426:
 <code z80> <code z80>
 Atributo_abajo_sin_usar_DE_2: Atributo_abajo_sin_usar_DE_2:
-    LD AL           ; A = L +    ld al                  ; A = L 
-    ADD 32            ; Sumamos A = A + 32 . El Carry Flag se ve afectado. +    add a, 32                ; Sumamos A = A + 32 . El Carry Flag se ve afectado. 
-    LD LA           ; Guardamos en L (L = L+32) +    ld la                  ; Guardamos en L (L = L+32) 
-    JR NC, attrab_noinc +    jr nc, attrab_noinc 
-    INC H +    inc h 
-attrab_noinc:         ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32+attrab_noinc:                ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32
  
 Atributo_arriba_sin_usar_DE: Atributo_arriba_sin_usar_DE:
-    LD AL           ; A = L +    ld al                  ; A = L 
-    SUB 32            ; Restamos A = A - 32 . El Carry Flag se ve afectado. +    sub 32                   ; Restamos A = A - 32 . El Carry Flag se ve afectado. 
-    LD LA           ; Guardamos en L (L = L-32) +    ld la                  ; Guardamos en L (L = L-32) 
-    JR NC, attrab_nodec +    jr nc, attrab_nodec 
-    DEC H +    dec h 
-attrab_nodec:         ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32+attrab_nodec:                ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32
  
 </code> </code>
Línea 447: Línea 446:
  
 <code z80> <code z80>
-    JR NC, attrab_noinc +    jr nc, attrab_noinc 
-    INC H+    inc h
 attrab_noinc: attrab_noinc:
 </code> </code>
Línea 455: Línea 454:
  
 <code z80> <code z80>
-    LD A, 0           ; Ponemos A a cero, no podemos usar un "XOR A+    ld a, 0                  ; Ponemos A a cero, no podemos usar un "xor a
-                      ; o un "OR A" porque afectariamos al Carry Flag. +                             ; o un "or a" porque afectariamos al Carry Flag. 
-    ADC H             ; A = H + CarryFlag +    adc a, h                 ; A = H + CarryFlag 
-    LD HA           ; H = H + CarryFlag +    ld ha                  ; H = H + CarryFlag 
-                      ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32+                             ; Ahora HL = (H+CF)*256 + (L+32) = HL + 32
 </code> </code>
  
- Este código no utiliza DE pero se apoya en el registro A para los cálculos. Si necesitamos preservar su valor, siempre podemos realizar un ''EX AFAF<nowiki>'</nowiki>'' antes y después de la ejecución de la rutina.+ Este código no utiliza DE pero se apoya en el registro A para los cálculos. Si necesitamos preservar su valor, siempre podemos realizar un ''ex afaf<nowiki>'</nowiki>'' antes y después de la ejecución de la rutina.
  
 \\  \\ 
Línea 483: Línea 482:
 \\  \\ 
  
- Nótese que podemos realizar las 2 primeras rutinas de forma que devuelvan el offset calculado bien en el registro DE o bien en el registro HL. Según utilicemos los registros en el código que llama a la rutina, puede sernos más conveniente recibir el valor en uno u otro registro. Si resulta necesario, podemos adaptar el código de las rutinas para que funcionen con uno u otro registro, o utilizar al final de la misma (o tras el ''CALL'') un ''EX HL, DE'' que devuelva el resultado en el registro que más nos interese.+ Nótese que podemos realizar las 2 primeras rutinas de forma que devuelvan el offset calculado bien en el registro DE o bien en el registro HL. Según utilicemos los registros en el código que llama a la rutina, puede sernos más conveniente recibir el valor en uno u otro registro. Si resulta necesario, podemos adaptar el código de las rutinas para que funcionen con uno u otro registro, o utilizar al final de la misma (o tras el ''call'') un ''EX HL, DE'' que devuelva el resultado en el registro que más nos interese.
  
  
Línea 503: Línea 502:
 | 3 | $4060 | 16480 | 0100000001100000b | 0 (00b) | 3 | | 3 | $4060 | 16480 | 0100000001100000b | 0 (00b) | 3 |
 | 4 | $4080 | 16512 | 0100000010000000b | 0 (00b) | 4 | | 4 | $4080 | 16512 | 0100000010000000b | 0 (00b) | 4 |
-| 5 | $40A0 | 16544 | 0100000010100000b | 0 (00b) | 5 | +| 5 | $40a0 | 16544 | 0100000010100000b | 0 (00b) | 5 | 
-| 6 | $40C0 | 16576 | 0100000011000000b | 0 (00b) | 6 | +| 6 | $40c0 | 16576 | 0100000011000000b | 0 (00b) | 6 | 
-| 7 | $40E0 | 16608 | 0100000011100000b | 0 (00b) | 7 |+| 7 | $40e0 | 16608 | 0100000011100000b | 0 (00b) | 7 |
 | 8 | $4800 | 18432 | 0100100000000000b | 1 (01b) | 0 | | 8 | $4800 | 18432 | 0100100000000000b | 1 (01b) | 0 |
 | 9 | $4820 | 18464 | 0100100000100000b | 1 (01b) | 1 | | 9 | $4820 | 18464 | 0100100000100000b | 1 (01b) | 1 |
Línea 511: Línea 510:
 | 11 | $4860 | 18528 | 0100100001100000b | 1 (01b) | 3 | | 11 | $4860 | 18528 | 0100100001100000b | 1 (01b) | 3 |
 | 12 | $4880 | 18560 | 0100100010000000b | 1 (01b) | 4 | | 12 | $4880 | 18560 | 0100100010000000b | 1 (01b) | 4 |
-| 13 | $48A0 | 18592 | 0100100010100000b | 1 (01b) | 5 | +| 13 | $48a0 | 18592 | 0100100010100000b | 1 (01b) | 5 | 
-| 14 | $48C0 | 18624 | 0100100011000000b | 1 (01b) | 6 | +| 14 | $48c0 | 18624 | 0100100011000000b | 1 (01b) | 6 | 
-| 15 | $48E0 | 18656 | 0100100011100000b | 1 (01b) | 7 |+| 15 | $48e0 | 18656 | 0100100011100000b | 1 (01b) | 7 |
 | 16 | $5000 | 20480 | 0101000000000000b | 2 (10b) | 0 | | 16 | $5000 | 20480 | 0101000000000000b | 2 (10b) | 0 |
 | 17 | $5020 | 20512 | 0101000000100000b | 2 (10b) | 1 | | 17 | $5020 | 20512 | 0101000000100000b | 2 (10b) | 1 |
Línea 519: Línea 518:
 | 19 | $5060 | 20576 | 0101000001100000b | 2 (10b) | 3 | | 19 | $5060 | 20576 | 0101000001100000b | 2 (10b) | 3 |
 | 20 | $5080 | 20608 | 0101000010000000b | 2 (10b) | 4 | | 20 | $5080 | 20608 | 0101000010000000b | 2 (10b) | 4 |
-| 21 | $50A0 | 20640 | 0101000010100000b | 2 (10b) | 5 | +| 21 | $50a0 | 20640 | 0101000010100000b | 2 (10b) | 5 | 
-| 22 | $50C0 | 20672 | 0101000011000000b | 2 (10b) | 6 | +| 22 | $50c0 | 20672 | 0101000011000000b | 2 (10b) | 6 | 
-| 23 | $50E0 | 20704 | 0101000011100000b | 2 (10b) | 7 |+| 23 | $50e0 | 20704 | 0101000011100000b | 2 (10b) | 7 |
 \\  \\ 
  
Línea 537: Línea 536:
 | 10 | $4840 | 18496 | **010**//01//000**010**00000b | 1 (01b) | 2 | | 10 | $4840 | 18496 | **010**//01//000**010**00000b | 1 (01b) | 2 |
 | (...) | (...) | (...) | (...) | (...) | (...) | | (...) | (...) | (...) | (...) | (...) | (...) |
-| 23 | $50E0 | 20704 | **010**//10//000**111**00000b | 2 (10b) | 7 |+| 23 | $50e0 | 20704 | **010**//10//000**111**00000b | 2 (10b) | 7 |
  
  Lo primero que puede llamarnos la atención es lo siguiente:  Lo primero que puede llamarnos la atención es lo siguiente:
Línea 548: Línea 547:
     * Conclusión: el número de tercio se corresponde con los 2 bits superiores de la coordenada Y, de tal forma que las fila (0,7) están en el tercio 00b, las filas 8-15 en el tercio 01b, y las 16-23 en el 10b.     * Conclusión: el número de tercio se corresponde con los 2 bits superiores de la coordenada Y, de tal forma que las fila (0,7) están en el tercio 00b, las filas 8-15 en el tercio 01b, y las 16-23 en el 10b.
   * Hay una relación directa entre el número de fila dentro de cada tercio (0-7) y los 3 bits superiores (5-7) del byte bajo de la dirección.   * Hay una relación directa entre el número de fila dentro de cada tercio (0-7) y los 3 bits superiores (5-7) del byte bajo de la dirección.
-  * Los 3 bytes más significativos de la dirección son siempre 010b. Esta es la parte de la composición de la dirección que ubica el offset en memoria en el rango de direcciones del área de imagen de la videoram ($4000 a $57FF).+  * Los 3 bytes más significativos de la dirección son siempre 010b. Esta es la parte de la composición de la dirección que ubica el offset en memoria en el rango de direcciones del área de imagen de la videoram ($4000 a $57ff).
   * Los 5 bytes menos significativos de la dirección son siempre cero en la tabla. En realidad, representan a la columna (posición c de carácter dentro de los 32 bytes de datos horizontales) pero al estar calculando direcciones de inicio de línea (c = 0 = 00000b), en nuestro caso son siempre cero.   * Los 5 bytes menos significativos de la dirección son siempre cero en la tabla. En realidad, representan a la columna (posición c de carácter dentro de los 32 bytes de datos horizontales) pero al estar calculando direcciones de inicio de línea (c = 0 = 00000b), en nuestro caso son siempre cero.
 \\  \\ 
Línea 577: Línea 576:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Line_Offset_LR: Get_Line_Offset_LR:
-    LD AB         ; A = B, para extraer los bits de tercio +    ld ab                  ; A = B, para extraer los bits de tercio 
-    AND $18         ; A = A AND 00011000b +    and %00011000            ; A = A and 00011000b 
-                    ; A = estado de bits de TERCIO desde FILA +                             ; A = estado de bits de TERCIO desde FILA 
-    ADD A$40      ; Sumamos $40 (bits superiores = 010) +    add a%01000000         ; Sumamos $40 (bits superiores = 010) 
-    LD HA         ; Ya tenemos la parte alta calculada +    ld ha                  ; Ya tenemos la parte alta calculada 
-                    ; H = 010TT000 +                             ; H = 010TT000 
-    LD AB         ; Ahora calculamos la parte baja +    ld ab                  ; Ahora calculamos la parte baja 
-    AND 7           ; Nos quedamos con los bits más bajos de FILA +    and %00000111            ; Nos quedamos con los bits más bajos de FILA 
-                    ; que coinciden con FT (Fila dentro del tercio) +                             ; que coinciden con FT (Fila dentro del tercio) 
-    RRCA            ; Ahora A = 00000NNNb  (donde N=FT) +    rrca                     ; Ahora A = 00000NNNb  (donde N=FT) 
-    RRCA            ; Desplazamos A 3 veces +    rrca                     ; Desplazamos A 3 veces 
-    RRCA            ; A = NNN00000b +    rrca                     ; A = NNN00000b 
-    LD LA         ; Lo cargamos en la parte baja de la direccion +    ld la                  ; Lo cargamos en la parte baja de la direccion 
-    RET             ; HL = 010TT000NNN00000b+    ret                      ; HL = 010TT000NNN00000b
 </code> </code>
  
Línea 629: Línea 628:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Char_Offset_LR: Get_Char_Offset_LR:
-    LD AB         ; A = B, para extraer los bits de tercio +    ld ab                  ; A = B, para extraer los bits de tercio 
-    AND $18         ; A = A AND 00011000b +    and %00011000            ; A = A and 00011000b 
-                    ; A = estado de bits de TERCIO desde FILA +                             ; A = estado de bits de TERCIO desde FILA 
-    ADD A$40      ; Sumamos $40 (bits superiores = 010) +    add a%01000000         ; Sumamos $40 (bits superiores = 010) 
-    LD HA         ; Ya tenemos la parte alta calculada +    ld ha                  ; Ya tenemos la parte alta calculada 
-                    ; H = 010TT000 +                             ; H = 010TT000 
-    LD AB         ; Ahora calculamos la parte baja +    ld ab                  ; Ahora calculamos la parte baja 
-    AND 7           ; Nos quedamos con los bits más bajos de FILA +    and %00000111            ; Nos quedamos con los bits más bajos de FILA 
-                    ; que coinciden con FT (Fila dentro del tercio) +                             ; que coinciden con FT (Fila dentro del tercio) 
-    RRCA            ; Ahora A = 00000NNNb     (N=FT) +    rrca                     ; Ahora A = 00000NNNb     (N=FT) 
-    RRCA            ; Desplazamos A 3 veces a la derecha +    rrca                     ; Desplazamos A 3 veces a la derecha 
-    RRCA            ; A = NNN00000b +    rrca                     ; A = NNN00000b 
-    ADD AC        ; Sumamos COLUMNA -> A = NNNCCCCCb +    add ac                 ; Sumamos COLUMNA -> A = NNNCCCCCb 
-    LD LA         ; Lo cargamos en la parte baja de la direccion +    ld la                  ; Lo cargamos en la parte baja de la direccion 
-    RET             ; HL = 010TT000NNNCCCCCb+    ret                      ; HL = 010TT000NNNCCCCCb
 </code> </code>
  
Línea 658: Línea 657:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Char_Offset_HR: Get_Char_Offset_HR:
-    SRL B +    srl b 
-    SRL B +    srl b 
-    SRL B           ; B = B/8 -> Ahora B es FILA+    srl b                    ; B = B/8 -> Ahora B es FILA
  
-    SRL C +    srl c 
-    SRL C +    srl c 
-    SRL C           ; C = C/8 -> Ahora C es COLUMNA+    srl c                    ; C = C/8 -> Ahora C es COLUMNA
  
-    (...)           ; Resto de la rutina Get_Char_Offset_LR +    (...)                    ; Resto de la rutina Get_Char_Offset_LR 
-    RET+    ret
 </code> </code>
  
Línea 688: Línea 687:
     ; HL = 010TT000 NNNCCCCCb ->     ; HL = 010TT000 NNNCCCCCb ->
     ;      Fila = 000TTNNNb y Columna = 000CCCCCb     ;      Fila = 000TTNNNb y Columna = 000CCCCCb
-                    ; Calculo de la fila: 
-    LD A, H         ; A = H, para extraer los bits de tercio 
-    AND $18         ; A = 000TT000b 
-    LD B, A         ; B = A = 000TT000b 
  
-    LD AL         ; A = L, para extraer los bits de N (FT) +                             ; Calculo de la fila: 
-    AND $E0         ; A = A AND 11100000b = NNN00000b +    ld ah                  ; A = H, para extraer los bits de tercio 
-    RLC A           ; Rotamos A 3 veces a la izquierda +    and %00011000            ; A = 000TT000b 
-    RLC A +    ld ba                  ; B = A = 000TT000b
-    RLC A           ; A = 00000NNNb +
-    OR B            ; A = A OR B = 000TTNNNb +
-    LD BA         ; B = A = 000TTNNNb+
  
-                    ; Calculo de la columna: +    ld a, l                  ; A = L, para extraer los bits de N (FT) 
-    LD AL         ; A = L, para extraer los bits de columna +    and %0b11100000          ; A = A and 11100000b = NNN00000b 
-    AND $1F         ; Nos quedamos con los ultimos 5 bits de L +    rlc a                    ; Rotamos A 3 veces a la izquierda 
-    LD CA         ; C = Columna +    rlc a 
-    RET             ; HL = 010TT000NNNCCCCCb+    rlc a                    ; A = 00000NNNb 
 +    or b                     ; A = A or b = 000TTNNNb 
 +    ld b, a                  ; B = A = 000TTNNNb 
 + 
 +                             ; Calculo de la columna: 
 +    ld al                  ; A = L, para extraer los bits de columna 
 +    and %00011111            ; Nos quedamos con los ultimos 5 bits de L 
 +    ld ca                  ; C = Columna 
 +             ret             ; HL = 010TT000NNNCCCCCb
 </code> </code>
  
- Adaptar esta rutina a alta resolución (''Get_Char_Coordinates_HR(x,y)'') implicaría el multiplicar las coordenadas X e Y por 8, añadiendo el siguiente código inmediatamente antes del RET:+ Adaptar esta rutina a alta resolución (''Get_Char_Coordinates_HR(x,y)'') implicaría el multiplicar las coordenadas X e Y por 8, añadiendo el siguiente código inmediatamente antes del ret:
  
 <code z80> <code z80>
-    SLA C +    sla c 
-    SLA C +    sla c 
-    SLA C              ; C = C*8+    sla c                    ; C = C*8
  
-    SLA B +    sla b 
-    SLA B +    sla b 
-    SLA B              ; B = B*8+    sla b                    ; B = B*8
 </code> </code>
  
Línea 729: Línea 729:
 **Recorrer los 8 scanlines de un bloque** **Recorrer los 8 scanlines de un bloque**
  
- Dada en HL la dirección del primer scanline de un bloque, podemos avanzar a lo largo de los 7 scanlines del mismo bloque sumando "256" a dicha dirección. Como sumar 256 equivale a incrementar la parte alta de la dirección, podemos subir y bajar al scanline anterior y siguiente de los 8 que componen el carácter mediante simples ''DEC H'' e ''INC H'':+ Dada en HL la dirección del primer scanline de un bloque, podemos avanzar a lo largo de los 7 scanlines del mismo bloque sumando "256" a dicha dirección. Como sumar 256 equivale a incrementar la parte alta de la dirección, podemos subir y bajar al scanline anterior y siguiente de los 8 que componen el carácter mediante simples ''dec h'' e ''inc h'':
  
 <code z80> <code z80>
 Scanline_Arriba_HL: Scanline_Arriba_HL:
-  DEC H            ; H = H - 1  (HL = HL-255)+  dec h                      ; H = H - 1  (HL = HL-255)
  
 Scanline_Abajo_HL: Scanline_Abajo_HL:
-  INC H            ; H = H + 1  (HL = HL-255)+  inc h                      ; H = H + 1  (HL = HL-255)
 </code> </code>
  
Línea 752: Línea 752:
 <code z80> <code z80>
 Caracter_Derecha_HL: Caracter_Derecha_HL:
-    INC HL            ; HL = HL + 1+    inc hl                   ; HL = HL + 1
  
 Caracter_Izquierda_HL: Caracter_Izquierda_HL:
-    DEC HL            ; HL = HL - 1+    dec hl                   ; HL = HL - 1
 </code> </code>
  
Línea 774: Línea 774:
  
 <code z80> <code z80>
-    LD AL                     ; Cargamos A en L y le sumamos 32 para +Caracter_Abajo_HL: 
-    ADD A32                   ; incrementar "Bloque dentro del tercio" +    ld al                       ; Cargamos A en L y le sumamos 32 para 
-    LD LA                     ; L = A +    add a%00100000              ; incrementar "Bloque dentro del tercio" (+32) 
-    JR NC, no_ajustar_H_abajob  ; Si esta suma produce acarreo, ajustar +    ld la                       ; L = A 
-    LD AH                     ; la parte alta sumando 8 a H (TT = TT + 1). +    jr nc, no_ajustar_H_abajob    ; Si esta suma produce acarreo, ajustar 
-    ADD A8                    ; Ahora NNN=000b y TT se ha incrementado. +    ld ah                       ; la parte alta sumando 8 a H (TT = TT + 1). 
-    LD HA                     ; H = A+    add a%00001000              ; Ahora NNN=000b y TT se ha incrementado. 
 +    ld ha                       ; H = A
 no_ajustar_H_abajob no_ajustar_H_abajob
-                                ; Ahora HL apunta al bloque de debajo.+                                  ; Ahora HL apunta al bloque de debajo.
 </code> </code>
  
Línea 788: Línea 789:
  
 <code z80> <code z80>
-    LD A, L                       ; Cargamos L en A 
-    AND 224                       ; A = A AND 11100000b 
-    JR NZ, no_ajustar_h_arribab   ; Si no es cero, no retrocedemos tercio 
-    LD A, H                       ; Si es cero, ajustamos tercio (-1) 
-    SUB 8                         ; Decrementamos TT 
-    LD H, A 
-no_ajustar_h_arribab: 
-    LD A, L                       ; Decrementar NNN 
-    SUB 32 
-    LD L, A                       ; NNN = NNN-1 
-</code> 
- 
- En forma de rutina: 
- 
-<code z80> 
-Caracter_Abajo_HL: 
-    LD A, L                     ; Cargamos A en L y le sumamos 32 para 
-    ADD A, 32                   ; incrementar "Bloque dentro del tercio" 
-    LD L, A                     ; L = A 
-    RET NC                      ; Si esta suma no produce acarreo, fin 
-    LD A, H                     ; la parte alta sumando 8 a H (TT = TT + 1). 
-    ADD A, 8                    ; Ahora NNN=000b y TT se ha incrementado. 
-    LD H, A                     ; H = A 
-    RET 
- 
 Caracter_Arriba_HL: Caracter_Arriba_HL:
-    LD A                      ; Cargamos L en A +    ld a                      ; Cargamos L en A 
-    AND 224                       ; A = A AND 11100000b +    and %11100000                 ; A = A and 11100000b 
-    JR NZ, nofix_h_arribab        ; Si no es cero, no retrocedemos tercio +    jr nz, nofix_h_arribab        ; Si no es cero, no retrocedemos tercio 
-    LD A                      ; Si es cero, ajustamos tercio (-1) +    ld a                      ; Si es cero, ajustamos tercio (-1) 
-    SUB 8                         ; Decrementamos TT +    sub %00001000                 ; Decrementamos TT 
-    LD HA+    ld ha
 nofix_h_arribab: nofix_h_arribab:
-    LD A                      ; Decrementar NNN +    ld a                      ; Decrementar NNN 
-    SUB 32 +    sub 32 
-    LD L                      ; NNN = NNN-1 +    ld l                      ; NNN = NNN-1 
-    RET+    ret
 </code> </code>
  
Línea 914: Línea 890:
 \\  \\ 
  
- No obstante, recordemos que esta dirección de memoria obtenida hace referencia a 8 píxeles, por lo que necesitamos obtener además la información del número de bit con el que se corresponde nuestro pixel, que podemos extraer del resto de la división entre 8 de la coordenada X (P = X AND 7).+ No obstante, recordemos que esta dirección de memoria obtenida hace referencia a 8 píxeles, por lo que necesitamos obtener además la información del número de bit con el que se corresponde nuestro pixel, que podemos extraer del resto de la división entre 8 de la coordenada X (P = X and %00000111).
  
  La rutina resultante es similar a la vista en baja resolución con la descomposición de la coordenada Y en el "número de scanline" (0-7) y la "fila dentro del tercio (0-7)":  La rutina resultante es similar a la vista en baja resolución con la descomposición de la coordenada Y en el "número de scanline" (0-7) y la "fila dentro del tercio (0-7)":
Línea 930: Línea 906:
  
     ; Calculo de la parte alta de la direccion:     ; Calculo de la parte alta de la direccion:
-    LD AB +    ld ab 
-    AND 7                       ; A = 00000SSSb +    and %00000111            ; A = 00000SSSb 
-    LD HA                     ; Lo guardamos en H +    ld ha                  ; Lo guardamos en H 
-    LD AB                     ; Recuperamos de nuevo Y +    ld ab                  ; Recuperamos de nuevo Y 
-    RRA +    rra 
-    RRA +    rra 
-    RRA                         ; Rotamos para asi obtener el tercio +    rra                      ; Rotamos para asi obtener el tercio 
-    AND 24                      ; con un AND 00011000b -> 000TT000b +    and %00011000            ; con un and 00011000b -> 000TT000b 
-    OR H                        ; H = H OR A = 00000SSSb OR 000TT000b +    or h                     ; H = H or a = 00000SSSb or 000TT000b 
-    OR 64                       ; Mezclamos H con 01000000b (vram) +    or %01000000             ; Mezclamos H con 01000000b (vram) 
-    LD HA                     ; Establecemos el "H" definitivo+    ld ha                  ; Establecemos el "H" definitivo
  
     ; Calculo de la parte baja de la direccion:     ; Calculo de la parte baja de la direccion:
-    LD AC                     ; A = coordenada X +    ld ac                  ; A = coordenada X 
-    RRA +    rra 
-    RRA +    rra 
-    RRA                         ; Rotamos para obtener CCCCCb +    rra                      ; Rotamos para obtener CCCCCb 
-    AND 31                      ; A = A AND 31 = 000CCCCCb +    and %00011111            ; A = A and 31 = 000CCCCCb 
-    LD LA                     ; L = 000CCCCCb +    ld la                  ; L = 000CCCCCb 
-    LD AB                     ; Recuperamos de nuevo Y +    ld ab                  ; Recuperamos de nuevo Y 
-    RLA                         ; Rotamos para obtener NNN +    rla                      ; Rotamos para obtener NNN 
-    RLA +    rla 
-    AND 224                     ; A = A AND 11100000b +    and %11100000            ; A = A and 11100000b 
-    OR L                        ; L = NNNCCCCC +    or l                     ; L = NNNCCCCC 
-    LD LA                     ; Establecemos el "L" definitivo+    ld la                  ; Establecemos el "L" definitivo
  
     ; Finalmente, calcular posicion relativa del pixel:     ; Finalmente, calcular posicion relativa del pixel:
-    LD AC                      ; Recuperamos la coordenada X +    ld ac                  ; Recuperamos la coordenada X 
-    AND 7                        AND 00000111 para obtener pixel +    and %00000111            and 00000111 para obtener pixel 
-                                 ; A = 00000PPP +                             ; A = 00000PPP 
-    RET+    ret
 </code> </code>
  
- Esta rutina de 118 t-estados nos devuelve el valor de la dirección calculado en HL y la posición relativa del pixel dentro del byte:+ Esta rutina de 128 t-estados nos devuelve el valor de la dirección calculado en HL y la posición relativa del pixel dentro del byte:
  
 |< 50% >| |< 50% >|
 ^ Valor de A ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ ^ Valor de A ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^
-| Posición del pixel\\ desde la izquierda | +7 | +6 | +5 | +4 | +3 | +2 | +1 | +0 |+| Posición del pixel\\ desde la izquierda | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
 | Posición del pixel\\ dentro del byte (Bit) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | Posición del pixel\\ dentro del byte (Bit) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
  
Línea 976: Línea 952:
  Por otra parte, si necesitamos activar (PLOT, bit=1), desactivar (UNPLOT, b=0) o testear el estado del pixel (x,y), podremos utilizar este valor "**posición del pixel**" para generar una **máscara de pixel**.  Por otra parte, si necesitamos activar (PLOT, bit=1), desactivar (UNPLOT, b=0) o testear el estado del pixel (x,y), podremos utilizar este valor "**posición del pixel**" para generar una **máscara de pixel**.
  
 + Si queremos convertir la //posición del pixel// en una //máscara de pixel// (por ejemplo, convertir ''A=6'' en el bit 6 activo (''A=%01000000''), podemos hacerlo con un bucle:
 +
 +<code z80>
 +    and %00000111               ; and 00000111 para obtener pixel
 +                                ; A = 00000PPP, y además setear ZF si es 0
 +    ;--- Nuevo código ---
 +    
 +    ld b, a                     ; Poner en B el numero de pixel
 +    ld a, %10000000             ; Activar sólo el bit 7 de A
 +    jr z, getpixoff_norotate    ; Si el ''and %00000111' dice que A == 0
 +                                ; entonces ya no necesitamos rotar
 +getpixoff_loop:
 +    rra                         ; Rotar A a la derecha B veces
 +    djnz getpixoff_lop
 +getpixoff_norotate:
 +                                ; Ahora A es una máscara de pixel
 +    ;--- Fin nuevo código ---
 +
 +    ret
 +</code>
  
 \\  \\ 
Línea 1010: Línea 1006:
  
 <code z80> <code z80>
-    LD BA         ; Cargamos A (posicion de pixel) en B +    ld ba                  ; Cargamos A (posicion de pixel) en B 
-    INC B           ; Incrementamos B (para pasadas del bucle) +    inc b                    ; Incrementamos B (para pasadas del bucle) 
-    XOR A           ; A = 0 +    xor a                    ; A = 0 
-    SCF             ; Set Carry Flag (A=0, CF=1)+    scf                      ; Set Carry Flag (A=0, CF=1)
 pix_rotate_bit: pix_rotate_bit:
-    RRA             ; Rotamos A a la derecha B veces +    rra                      ; Rotamos A a la derecha B veces 
-    DJNZ pix_rotate_bit+    djnz pix_rotate_bit
 </code> </code>
  
Línea 1022: Línea 1018:
  
 \\  \\ 
-{{ :cursos:ensamblador:rra.png | Instrucción RRA }}+{{ :cursos:ensamblador:rra.png | Instrucción rra }}
 \\  \\ 
  
Línea 1036: Línea 1032:
 ;-------------------------------------------------------- ;--------------------------------------------------------
 Relative_to_Mask: Relative_to_Mask:
-    LD BA         ; Cargamos A (posicion de pixel) en B +    ld ba                  ; Cargamos A (posicion de pixel) en B 
-    INC B           ; Incrementamos B (para pasadas del bucle) +    inc b                    ; Incrementamos B (para pasadas del bucle) 
-    XOR A           ; A = 0 +    xor a                    ; A = 0 
-    SCF             ; Set Carry Flag (A=0, CF=1)+    scf                      ; Set Carry Flag (A=0, CF=1)
 pix_rotate_bit: pix_rotate_bit:
-    RRA             ; Rotamos A a la derecha B veces +    rra                      ; Rotamos A a la derecha B veces 
-    DJNZ pix_rotate_bit +    djnz pix_rotate_bit 
-    RET+    ret
 </code> </code>
  
Línea 1051: Línea 1047:
 ; Activar el pixel apuntado por HL usando la máscara A ; Activar el pixel apuntado por HL usando la máscara A
 Plot_Pixel_HL: Plot_Pixel_HL:
-    OR (HL+    or (hl
-    LD (HL), A +    ld (hl), a 
-    RET+    ret
  
 ; Desactivar el pixel apuntado por HL usando la máscara A ; Desactivar el pixel apuntado por HL usando la máscara A
 Unplot_Pixel_HL: Unplot_Pixel_HL:
-    CPL +    cpl 
-    AND (HL+    and (hl
-    LD (HL), A +    ld (hl), a 
-    RET+    ret
  
 ; Testear el pixel apuntado por HL usando la máscara A ; Testear el pixel apuntado por HL usando la máscara A
 Test_Pixel_HL: Test_Pixel_HL:
-    AND (HL+    and (hl
-    RET+    ret
 </code> </code>
  
Línea 1077: Línea 1073:
 </code> </code>
  
- Si ejecutaramos un simple ''LD (HL), A'', el resultado de la operación eliminaría los 2 píxeles activos que ya teníamos en memoria:+ Si ejecutaramos un simple ''ld (hl), a'', el resultado de la operación eliminaría los 2 píxeles activos que ya teníamos en memoria:
  
 <code> <code>
 Pixeles activos en (16384) = 10000001 Pixeles activos en (16384) = 10000001
 Máscara de pixel A         = 00010000 Máscara de pixel A         = 00010000
-OPERACION (HL)=A           LD (HL), A+OPERACION (HL)=A           ld (hl), a
 Resultado en (16384)       = 00010000 Resultado en (16384)       = 00010000
 </code> </code>
Línea 1091: Línea 1087:
 Pixeles activos en (16384) = 10000001 Pixeles activos en (16384) = 10000001
 Máscara de pixel A         = 00010000 Máscara de pixel A         = 00010000
-OPERACION A = A OR (HL)    = OR (HL)+OPERACION A = A or (hl)    = or (hl)
 Resultado en A             = 10010001 Resultado en A             = 10010001
-OPERACION (HL)=A           LD (HL), A+OPERACION (HL)=A           ld (hl), a
 Resultado en (16384)       = 10010001 Resultado en (16384)       = 10010001
 </code> </code>
  
- Si en lugar de un ''OR'' hubieramos complementado A (''CPL A'') y hubieramos hecho un ''AND'', habríamos puesto a 0 el bit (y por tanto el pixel):+ Si en lugar de un ''OR'' hubieramos complementado A (''cpl A'') y hubieramos hecho un ''AND'', habríamos puesto a 0 el bit (y por tanto el pixel):
  
 <code> <code>
 Pixeles activos en (16384) = 10000001 Pixeles activos en (16384) = 10000001
 Máscara de pixel A         = 00010000 Máscara de pixel A         = 00010000
-OPERACION A = CPL(A)       = 11101111 +OPERACION A = cpl(A)       = 11101111 
-OPERACION A = A OR (HL)    = AND (HL)+OPERACION A = A or (hl)    = and (hl)
 Resultado en A             = 10000001 Resultado en A             = 10000001
-OPERACION (HL)=A           LD (HL), A+OPERACION (HL)=A           ld (hl), a
 Resultado en (16384)       = 10000001 Resultado en (16384)       = 10000001
 </code> </code>
Línea 1112: Línea 1108:
  
 <code z80> <code z80>
-  LD C, 127                   ; X = 127 +  ld c, 127                  ; X = 127 
-  LD B, 95                    ; Y = 95 +  ld b, 95                   ; Y = 95 
-  CALL Get_Pixel_Offset_HR    ; Calculamos HL y A +  call Get_Pixel_Offset_HR   ; Calculamos HL y A 
-  OR (HL                    ; OR de A y (HL) +  or (hl                   ; OR de A y (HL) 
-  LD (HL), A                  ; Activamos pixel+  ld (hl), a                 ; Activamos pixel
 </code> </code>
  
Línea 1131: Línea 1127:
 ==== La rutina de la ROM PIXEL-ADDRESS ==== ==== La rutina de la ROM PIXEL-ADDRESS ====
  
- Curiosamente, los usuarios de Spectrum tenemos disponible en la memoria ROM una rutina parecida, llamada ''PIXEL-ADDRESS'' (o ''PIXEL-ADD''), utilizada por las rutinas ''POINT'' y ''PLOT'' de la ROM (y de BASIC). La rutina está ubicada en $22AA y su código es el siguiente:+ Curiosamente, los usuarios de Spectrum tenemos disponible en la memoria ROM una rutina parecida, llamada ''PIXEL-ADDRESS'' (o ''PIXEL-ADD''), utilizada por las rutinas ''POINT'' y ''PLOT'' de la ROM (y de BASIC). La rutina está ubicada en $22aa y su código es el siguiente:
  
 <code z80> <code z80>
Línea 1144: Línea 1140:
 ; OUT: HL = address, A = pixel relative position in (HL) ; OUT: HL = address, A = pixel relative position in (HL)
  
-$22AA PIXEL-ADD +$22aa PIXEL-ADD 
-    LD    A,$AF               ; Test that the y co-ordinate (in +    ld    a,$af               ; Test that the y co-ordinate (in 
-    SUB                     ; B) is not greater than 175. +    sub                     ; B) is not greater than 175. 
-    JP    C,24F9,REPORT-B +    jp    c,24F9,REPORT-B 
-    LD    B,                ; B now contains 175 minus y.+    ld    b,                ; B now contains 175 minus y.
  
-$22B1 PIXEL_ADDRESS_B:        ; Entramos aqui para saltarnos la limitacion+$22b1 PIXEL_ADDRESS_B:        ; Entramos aqui para saltarnos la limitacion
                               ; hacia las 2 ultimas lineas de pantalla.                               ; hacia las 2 ultimas lineas de pantalla.
  
-    AND                     ; A holds b7b6b5b4b3b2b1b0, +    and                     ; A holds b7b6b5b4b3b2b1b0, 
-    RRA                       ; the bite of B. And now+    rra                       ; the bite of B. And now
                               ; 0b7b6b5b4b3b2b1.                               ; 0b7b6b5b4b3b2b1.
-    SCF +    scf 
-    RRA                       ; Now 10b7b6b5b4b3b2. +    rra                       ; Now 10b7b6b5b4b3b2. 
-    AND   A +    and   a 
-    RRA                       ; Now 010b7b6b5b4b3. +    rra                       ; Now 010b7b6b5b4b3. 
-    XOR   B +    xor   b 
-    AND   $F8                 ; Finally 010b7b6b2b1b0, so that +    and   $f8                 ; Finally 010b7b6b2b1b0, so that 
-    XOR                     ; H becomes 64 + 8*INT (B/64) + +    xor                     ; H becomes 64 + 8*INT (B/64) + 
-    LD    H,                ; B (mod 8), the high byte of the +    ld    h,                ; B (mod 8), the high byte of the 
-    LD    A,                ; pixel address. C contains X. +    ld    a,                ; pixel address. C contains X. 
-    RLCA                      ; A starts as c7c6c5c4c3c2c1c0. +    rlca                      ; A starts as c7c6c5c4c3c2c1c0. 
-    RLCA +    rlca 
-    RLCA                      ; And is now c2c1c0c7c6c5c4c3. +    rlca                      ; And is now c2c1c0c7c6c5c4c3. 
-    XOR   B +    xor   b 
-    AND   $C7 +    and   $c7 
-    XOR                     ; Now c2c1b5b4b3c5c4c3. +    xor                     ; Now c2c1b5b4b3c5c4c3. 
-    RLCA +    rlca 
-    RLCA                      ; Finally b5b4b3c7c6c5c4c3, so +    rlca                      ; Finally b5b4b3c7c6c5c4c3, so 
-    LD    L,                ; that L becomes 32*INT (B(mod +    ld    l,                ; that L becomes 32*INT (B(mod 
-    LD    A,                ; 64)/8) + INT(x/8), the low byte. +    ld    a,                ; 64)/8) + INT(x/8), the low byte. 
-    AND   $07                 ; A holds x(mod 8): so the pixel +    and   $07                 ; A holds x(mod 8): so the pixel 
-    RET                       ; is bit (A - 7) within the byte.+    ret                       ; is bit (A - 7) within the byte.
 </code> </code>
  
- Esta rutina tiene una serie de ventajas: Entrando por $22B1 tenemos 23 instrucciones (107 t-estados) que realizan el cálculo de la dirección de memoria además de la posición del pixel dentro del byte al que apunta dicha dirección. La rutina está ubicada en ROM, por lo que ahorramos esta pequeña porción de espacio en nuestro programa. Además, no usa la pila, no usa registros adicionales a B, C, HL y A, y no altera los valores de B y C durante el cálculo.+ Esta rutina tiene una serie de ventajas: Entrando por $22b1 tenemos 23 instrucciones (107 t-estados) que realizan el cálculo de la dirección de memoria además de la posición del pixel dentro del byte al que apunta dicha dirección. La rutina está ubicada en ROM, por lo que ahorramos esta pequeña porción de espacio en nuestro programa. Además, no usa la pila, no usa registros adicionales a B, C, HL y A, y no altera los valores de B y C durante el cálculo.
  
- Nótese que aunque la rutina está ubicada en $22AA y se entra con los valores (x,y) en C y B, el principio de la rutina está diseñado para evitar que ''PLOT'' y ''POINT'' puedan acceder a las 2 últimas filas (16 últimos píxeles) de la pantalla. Para saltarnos esta limitación entramos saltando con un ''CALL'' a $22B1 con la coordenada X en el registro C y la coordenada Y en los registros A y B:+ Nótese que aunque la rutina está ubicada en $22aa y se entra con los valores (x,y) en C y B, el principio de la rutina está diseñado para evitar que ''PLOT'' y ''POINT'' puedan acceder a las 2 últimas filas (16 últimos píxeles) de la pantalla. Para saltarnos esta limitación entramos saltando con un ''call'' a $22b1 con la coordenada X en el registro C y la coordenada Y en los registros A y B:
  
 <code z80> <code z80>
-    LD A, (coord_x) +    ld a, (coord_x) 
-    LD CA +    ld ca 
-    LD A, (coord_y) +    ld a, (coord_y) 
-    LD BA +    ld ba 
-    CALL $22B1+    call $22b1
 </code> </code>
  
Línea 1199: Línea 1195:
     ORG 50000     ORG 50000
  
-PIXEL_ADDRESS EQU $22B1+PIXEL_ADDRESS EQU $22b1
  
 entrada: entrada:
  
     ; Imprimimos un solo pixel en (0,0)     ; Imprimimos un solo pixel en (0,0)
-    LD C, 0                ; X = 0 +    ld c, 0                  ; X = 0 
-    LD B, 0                ; Y = 0 +    ld b, 0                  ; Y = 0 
-    LD AB                ; A = Y = 0 +    ld ab                  ; A = Y = 0 
-    CALL PIXEL_ADDRESS     ; HL = direccion (0,0) +    call PIXEL_ADDRESS       ; HL = direccion (0,0) 
-    LD A, 128              ; A = 10000000b (1 pixel). +    ld a, 128                ; A = 10000000b (1 pixel). 
-    LD (HL), A             ; Imprimimos el pixel+    ld (hl), a               ; Imprimimos el pixel
  
     ; Imprimimos 8 pixeles en (255,191)     ; Imprimimos 8 pixeles en (255,191)
-    LD C, 255              ; X = 255 +    ld c, 255                ; X = 255 
-    LD B, 191              ; Y = 191 +    ld b, 191                ; Y = 191 
-    LD AB                ; A = Y = 191 +    ld ab                  ; A = Y = 191 
-    CALL PIXEL_ADDRESS +    call PIXEL_ADDRESS 
-    LD A, 255              ; A = 11111111b (8 pixeles) +    ld a, 255                ; A = 11111111b (8 pixeles) 
-    LD (HL), A+    ld (hl), a
  
     ; Imprimimos 4 pixeles en el centro de la pantalla     ; Imprimimos 4 pixeles en el centro de la pantalla
-    LD C, 127              ; X = 127 +    ld c, 127                ; X = 127 
-    LD B, 95               ; Y = 95 +    ld b, 95                 ; Y = 95 
-    LD AB                ; A = Y = 95 +    ld ab                  ; A = Y = 95 
-    CALL PIXEL_ADDRESS +    call PIXEL_ADDRESS 
-    LD A170              ; A = 10101010b (4 pixeles) +    ld a%10101010          ; A = 10101010b (4 pixeles) 
-    LD (HL), A+    ld (hl), a
  
-loop:                      ; Bucle para no volver a BASIC y que +loop:                        ; Bucle para no volver a BASIC y que 
-    JR loop                ; no se borren la 2 ultimas lineas+    jr loop                  ; no se borren la 2 ultimas lineas
  
     END 50000     END 50000
Línea 1239: Línea 1235:
 \\  \\ 
  
- Nótese que la rutina de la ROM nos devuelve en A la posición relativa del pixel cuyas coordenadas hemos proporcionado, por lo que podemos convertir A en una **máscara de pixel** a la salida de la rutina encapsulando ''PIXEL-ADDRESS'' en una rutina "propia" que haga ambas operaciones, a cambio de 2 instrucciones extras (un ''CALL'' y un ''RET'' adicionales):+ Nótese que la rutina de la ROM nos devuelve en A la posición relativa del pixel cuyas coordenadas hemos proporcionado, por lo que podemos convertir A en una **máscara de pixel** a la salida de la rutina encapsulando ''PIXEL-ADDRESS'' en una rutina "propia" que haga ambas operaciones, a cambio de 2 instrucciones extras (un ''call'' y un ''RET'' adicionales):
  
 <code z80> <code z80>
-PIXEL_ADDRESS EQU $22B1+PIXEL_ADDRESS EQU $22b1
  
 ;---------------------------------------------------------- ;----------------------------------------------------------
Línea 1250: Línea 1246:
 ;---------------------------------------------------------- ;----------------------------------------------------------
 PIXEL_ADDRESS_MASK: PIXEL_ADDRESS_MASK:
-    CALL PIXEL_ADDRESS   ; Llamamos a la rutina de la ROM +    call PIXEL_ADDRESS       ; Llamamos a la rutina de la ROM 
-    LD BA              ; Cargamos A (posicion de pixel) en B +    ld ba                  ; Cargamos A (posicion de pixel) en B 
-    INC B                ; Incrementamos B (para pasadas del bucle) +    inc b                    ; Incrementamos B (para pasadas del bucle) 
-    XOR A                ; A = 0 +    xor a                    ; A = 0 
-    SCF                  ; Set Carry Flag (A=0, CF=1)+    scf                      ; Set Carry Flag (A=0, CF=1)
 pix_rotate_bit: pix_rotate_bit:
-    RRA                  ; Rotamos A a la derecha B veces +    rra                      ; Rotamos A a la derecha B veces 
-    DJNZ pix_rotate_bit +    djnz pix_rotate_bit 
-    RET+    ret
 </code> </code>
  
Línea 1274: Línea 1270:
 <code> <code>
 DIRECCION_DESTINO  = Tabla_Offsets_Linea[Y] + (X/8) DIRECCION_DESTINO  = Tabla_Offsets_Linea[Y] + (X/8)
-PIXEL_EN_DIRECCION = Resto(X/8) = X AND 7+PIXEL_EN_DIRECCION = Resto(X/8) = X AND %00000111
 </code> </code>
  
Línea 1318: Línea 1314:
     DW $4060, $4160, $4260, $4360, $4460, $4560, $4660, $4760     DW $4060, $4160, $4260, $4360, $4460, $4560, $4660, $4760
     DW $4080, $4180, $4280, $4380, $4480, $4580, $4680, $4780     DW $4080, $4180, $4280, $4380, $4480, $4580, $4680, $4780
-    DW $40A0, $41A0, $42A0, $43A0, $44A0, $45A0, $46A0, $47A0 +    DW $40a0, $41a0, $42a0, $43a0, $44a0, $45a0, $46a0, $47a0 
-    DW $40C0, $41C0, $42C0, $43C0, $44C0, $45C0, $46C0, $47C0 +    DW $40c0, $41c0, $42c0, $43c0, $44c0, $45c0, $46c0, $47c0 
-    DW $40E0, $41E0, $42E0, $43E0, $44E0, $45E0, $46E0, $47E0 +    DW $40e0, $41e0, $42e0, $43e0, $44e0, $45e0, $46e0, $47e0 
-    DW $4800, $4900, $4A00, $4B00, $4C00, $4D00, $4E00, $4F00 +    DW $4800, $4900, $4a00, $4b00, $4c00, $4d00, $4e00, $4f00 
-    DW $4820, $4920, $4A20, $4B20, $4C20, $4D20, $4E20, $4F20 +    DW $4820, $4920, $4a20, $4b20, $4c20, $4d20, $4e20, $4f20 
-    DW $4840, $4940, $4A40, $4B40, $4C40, $4D40, $4E40, $4F40 +    DW $4840, $4940, $4a40, $4b40, $4c40, $4d40, $4e40, $4f40 
-    DW $4860, $4960, $4A60, $4B60, $4C60, $4D60, $4E60, $4F60 +    DW $4860, $4960, $4a60, $4b60, $4c60, $4d60, $4e60, $4f60 
-    DW $4880, $4980, $4A80, $4B80, $4C80, $4D80, $4E80, $4F80 +    DW $4880, $4980, $4a80, $4b80, $4c80, $4d80, $4e80, $4f80 
-    DW $48A0, $49A0, $4AA0, $4BA0, $4CA0, $4DA0, $4EA0, $4FA0 +    DW $48a0, $49a0, $4aa0, $4ba0, $4ca0, $4da0, $4ea0, $4fa0 
-    DW $48C0, $49C0, $4AC0, $4BC0, $4CC0, $4DC0, $4EC0, $4FC0 +    DW $48c0, $49c0, $4ac0, $4bc0, $4cc0, $4dc0, $4ec0, $4fc0 
-    DW $48E0, $49E0, $4AE0, $4BE0, $4CE0, $4DE0, $4EE0, $4FE0+    DW $48e0, $49e0, $4ae0, $4be0, $4ce0, $4de0, $4ee0, $4fe0
     DW $5000, $5100, $5200, $5300, $5400, $5500, $5600, $5700     DW $5000, $5100, $5200, $5300, $5400, $5500, $5600, $5700
     DW $5020, $5120, $5220, $5320, $5420, $5520, $5620, $5720     DW $5020, $5120, $5220, $5320, $5420, $5520, $5620, $5720
Línea 1334: Línea 1330:
     DW $5060, $5160, $5260, $5360, $5460, $5560, $5660, $5760     DW $5060, $5160, $5260, $5360, $5460, $5560, $5660, $5760
     DW $5080, $5180, $5280, $5380, $5480, $5580, $5680, $5780     DW $5080, $5180, $5280, $5380, $5480, $5580, $5680, $5780
-    DW $50A0, $51A0, $52A0, $53A0, $54A0, $55A0, $56A0, $57A0 +    DW $50a0, $51a0, $52a0, $53a0, $54a0, $55a0, $56a0, $57a0 
-    DW $50C0, $51C0, $52C0, $53C0, $54C0, $55C0, $56C0, $57C0 +    DW $50c0, $51c0, $52c0, $53c0, $54c0, $55c0, $56c0, $57c0 
-    DW $50E0, $51E0, $52E0, $53E0, $54E0, $55E0, $56E0, $57E0+    DW $50e0, $51e0, $52e0, $53e0, $54e0, $55e0, $56e0, $57e0
 </code> </code>
  
Línea 1370: Línea 1366:
 ;-------------------------------------------------------- ;--------------------------------------------------------
  
-Scanline_Offsets EQU $F900+Scanline_Offsets EQU $f900
  
 Generate_Scanline_Table: Generate_Scanline_Table:
-    LD DE, $4000 +    ld de, $4000 
-    LD HL, Scanline_Offsets +    ld hl, Scanline_Offsets 
-    LD B, 192+    ld b, 192
  
 genscan_loop: genscan_loop:
-    LD (HL), E +    ld (hl), e 
-    INC L +    inc l 
-    LD (HL), D           ; Guardamos en (HL) (tabla) +    ld (hl), d               ; Guardamos en (HL) (tabla) 
-    INC HL               ; el valor de DE (offset)+    inc hl                   ; el valor de DE (offset)
  
     ; Recorremos los scanlines y bloques en un bucle generando las     ; Recorremos los scanlines y bloques en un bucle generando las
     ; sucesivas direccione en DE para almacenarlas en la tabla.     ; sucesivas direccione en DE para almacenarlas en la tabla.
     ; Cuando se cambia de caracter, scanline o tercio, se ajusta:     ; Cuando se cambia de caracter, scanline o tercio, se ajusta:
-    INC D +    inc d 
-    LD AD +    ld ad 
-    AND 7 +    and %00000111 
-    JR NZ, genscan_nextline +    jr nz, genscan_nextline 
-    LD AE +    ld ae 
-    ADD A, 32 +    add a, 32 
-    LD EA +    ld ea 
-    JR C, genscan_nextline +    jr c, genscan_nextline 
-    LD AD +    ld ad 
-    SUB +    sub 
-    LD DA+    ld da
  
 genscan_nextline: genscan_nextline:
-    DJNZ genscan_loop +    djnz genscan_loop 
-    RET+    ret
 </code> </code>
  
Línea 1419: Línea 1415:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Pixel_Offset_LUT_HR: Get_Pixel_Offset_LUT_HR:
-    LD DE, Scanline_Offsets   ; Direccion de nuestra LUT +    ld de, Scanline_Offsets  ; Direccion de nuestra LUT 
-    LD LB                   ; L = Y +    ld lb                  ; L = Y 
-    LD H, 0 +    ld h, 0 
-    ADD HLHL                ; HL = HL * 2 = Y * 2 +    add hlhl               ; HL = HL * 2 = Y * 2 
-    ADD HLDE                ; HL = (Y*2) + ScanLine_Offset +    add hlde               ; HL = (Y*2) + ScanLine_Offset 
-                              ; Ahora Offset = [HL] +                             ; Ahora Offset = [HL] 
-    LD A, (HL               ; Cogemos el valor bajo de la direccion en A +    ld a, (hl              ; Cogemos el valor bajo de la direccion en A 
-    INC L +    inc l 
-    LD H, (HL               ; Cogemos el valor alto de la direccion en H +    ld h, (hl              ; Cogemos el valor alto de la direccion en H 
-    LD LA                   ; HL es ahora Direccion(0,Y) +    ld la                  ; HL es ahora Direccion(0,Y) 
-                              ; Ahora sumamos la X, para lo cual calculamos CCCCC +                             ; Ahora sumamos la X, para lo cual calculamos CCCCC 
-    LD AC                   ; Calculamos columna +    ld ac                  ; Calculamos columna 
-    RRA +    rra 
-    RRA +    rra 
-    RRA                       ; A = A>>3 = ???CCCCCb +    rra                      ; A = A>>3 = ???CCCCCb 
-    AND 31                    ; A = 000CCCCB +    and %00011111            ; A = 000CCCCB 
-    ADD AL                  ; HL = HL + C +    add al                 ; HL = HL + C 
-    LD LA +    ld la 
-    LD AC                   ; Recuperamos la coordenada (X) +    ld ac                  ; Recuperamos la coordenada (X) 
-    AND 7                     ; A = Posicion relativa del pixel +    and %00000111            ; A = Posicion relativa del pixel 
-    RET                       ; HL = direccion destino+    ret                      ; HL = direccion destino
 </code> </code>
  
Línea 1450: Línea 1446:
 entrada: entrada:
  
-    CALL Generate_Scanline_Table +    call Generate_Scanline_Table 
-    LD B, 191+    ld b, 191
  
 loop_draw: loop_draw:
-    PUSH BC                ; Preservamos B (por el bucle)+    push bc                  ; Preservamos B (por el bucle)
  
-    LD C, 127              ; X = 127, Y = B+    ld c, 127                ; X = 127, Y = B
  
-    CALL Get_Pixel_Offset_LUT_HR+    call Get_Pixel_Offset_LUT_HR
  
-    LD A128 +    ld a%10000000          ; 1 pixel en la parte izquierda del byte 
-    LD (HL), A             ; Imprimimos el pixel+    ld (hl), a               ; Imprimimos el pixel
  
-    POP BC +    pop bc 
-    DJNZ loop_draw+    djnz loop_draw
  
-loop:                      ; Bucle para no volver a BASIC y que +loop:                        ; Bucle para no volver a BASIC y que 
-    JR loop                ; no se borren la 2 ultimas lineas+    jr loop                  ; no se borren la 2 ultimas lineas
  
     END 50000     END 50000
Línea 1504: Línea 1500:
 </code> </code>
  
- El paso de una tabla a otra se realizará incrementando o decrementando la parte alta del registro de 16 bits (INC H DEC H), gracias al hecho de que son 2 tablas múltiplos de 256 y consecutivas en memoria.+ El paso de una tabla a otra se realizará incrementando o decrementando la parte alta del registro de 16 bits (inc h dec h), gracias al hecho de que son 2 tablas múltiplos de 256 y consecutivas en memoria.
  
  Veamos primero la rutina para generar la tabla separando las partes altas y bajas y alineando ambas a una dirección múltiplo de 256:  Veamos primero la rutina para generar la tabla separando las partes altas y bajas y alineando ambas a una dirección múltiplo de 256:
Línea 1524: Línea 1520:
  
 Generate_Scanline_Table_Aligned: Generate_Scanline_Table_Aligned:
-    LD DE, $4000 +    ld de, $4000 
-    LD HL, Scanline_Offsets +    ld hl, Scanline_Offsets 
-    LD B, 192+    ld b, 192
  
 genscan_loop: genscan_loop:
-    LD (HL), E        ; Escribimos parte baja +    ld (hl), e               ; Escribimos parte baja 
-    INC H             ; Saltamos a tabla de partes altas +    inc h                    ; Saltamos a tabla de partes altas 
-    LD (HL), D        ; Escribimos parte alta +    ld (hl), d               ; Escribimos parte alta 
-    DEC H             ; Volvemos a tabla de partes bajas +    dec h                    ; Volvemos a tabla de partes bajas 
-    INC L             ; Siguiente valor+    inc l                    ; Siguiente valor
  
     ; Recorremos los scanlines y bloques en un bucle generando las     ; Recorremos los scanlines y bloques en un bucle generando las
     ; sucesivas direccione en DE para almacenarlas en la tabla.     ; sucesivas direccione en DE para almacenarlas en la tabla.
     ; Cuando se cambia de caracter, scanline o tercio, se ajusta:     ; Cuando se cambia de caracter, scanline o tercio, se ajusta:
-    INC D +    inc d 
-    LD AD +    ld ad 
-    AND 7 +    and %00000111 
-    JR NZ, genscan_nextline +    jr nz, genscan_nextline 
-    LD AE +    ld ae 
-    ADD A, 32 +    add a, 32 
-    LD EA +    ld ea 
-    JR C, genscan_nextline +    jr c, genscan_nextline 
-    LD AD +    ld ad 
-    SUB +    sub 
-    LD DA+    ld da
  
 genscan_nextline: genscan_nextline:
-    DJNZ genscan_loop +    djnz genscan_loop 
-    RET+    ret
 </code> </code>
  
Línea 1571: Línea 1567:
  
 <code> <code>
-; Macro de alineacion para PASMO +    ; Macro de alineacion para PASMO 
-align   macro value+    align   macro value
        if $ mod value        if $ mod value
        ds value - ($ mod value)        ds value - ($ mod value)
Línea 1578: Línea 1574:
        endm        endm
  
-align 256+    align 256
  
 Scanline_Offsets: Scanline_Offsets:
Línea 1585: Línea 1581:
     DB $20, $20, $20, $20, $40, $40, $40, $40, $40, $40, $40, $40     DB $20, $20, $20, $20, $40, $40, $40, $40, $40, $40, $40, $40
     DB $60, $60, $60, $60, $60, $60, $60, $60, $80, $80, $80, $80     DB $60, $60, $60, $60, $60, $60, $60, $60, $80, $80, $80, $80
-    DB $80, $80, $80, $80, $A0, $A0, $A0, $A0, $A0, $A0, $A0, $A0 +    DB $80, $80, $80, $80, $a0, $a0, $a0, $a0, $a0, $a0, $a0, $a0 
-    DB $C0, $C0, $C0, $C0, $C0, $C0, $C0, $C0, $E0, $E0, $E0, $E0 +    DB $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0, $e0, $e0, $e0, $e0 
-    DB $E0, $E0, $E0, $E0, $00, $00, $00, $00, $00, $00, $00, $00+    DB $e0, $e0, $e0, $e0, $00, $00, $00, $00, $00, $00, $00, $00
     DB $20, $20, $20, $20, $20, $20, $20, $20, $40, $40, $40, $40     DB $20, $20, $20, $20, $20, $20, $20, $20, $40, $40, $40, $40
     DB $40, $40, $40, $40, $60, $60, $60, $60, $60, $60, $60, $60     DB $40, $40, $40, $40, $60, $60, $60, $60, $60, $60, $60, $60
-    DB $80, $80, $80, $80, $80, $80, $80, $80, $A0, $A0, $A0, $A0 +    DB $80, $80, $80, $80, $80, $80, $80, $80, $a0, $a0, $a0, $a0 
-    DB $A0, $A0, $A0, $A0, $C0, $C0, $C0, $C0, $C0, $C0, $C0, $C0 +    DB $a0, $a0, $a0, $a0, $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 
-    DB $E0, $E0, $E0, $E0, $E0, $E0, $E0, $E0, $00, $00, $00, $00+    DB $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0, $00, $00, $00, $00
     DB $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $20, $20     DB $00, $00, $00, $00, $20, $20, $20, $20, $20, $20, $20, $20
     DB $40, $40, $40, $40, $40, $40, $40, $40, $60, $60, $60, $60     DB $40, $40, $40, $40, $40, $40, $40, $40, $60, $60, $60, $60
     DB $60, $60, $60, $60, $80, $80, $80, $80, $80, $80, $80, $80     DB $60, $60, $60, $60, $80, $80, $80, $80, $80, $80, $80, $80
-    DB $A0, $A0, $A0, $A0, $A0, $A0, $A0, $A0, $C0, $C0, $C0, $C0 +    DB $a0, $a0, $a0, $a0, $a0, $a0, $a0, $a0, $c0, $c0, $c0, $c0 
-    DB $C0, $C0, $C0, $C0, $E0, $E0, $E0, $E0, $E0, $E0, $E0, $E0+    DB $c0, $c0, $c0, $c0, $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0
  
 Free_64_Bytes: Free_64_Bytes:
Línea 1611: Línea 1607:
     DB $44, $45, $46, $47, $40, $41, $42, $43, $44, $45, $46, $47     DB $44, $45, $46, $47, $40, $41, $42, $43, $44, $45, $46, $47
     DB $40, $41, $42, $43, $44, $45, $46, $47, $40, $41, $42, $43     DB $40, $41, $42, $43, $44, $45, $46, $47, $40, $41, $42, $43
-    DB $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F +    DB $44, $45, $46, $47, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f 
-    DB $48, $49, $4A, $4B, $4C, $4D, $4E, $4F, $48, $49, $4A, $4B +    DB $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $48, $49, $4a, $4b 
-    DB $4C, $4D, $4E, $4F, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F +    DB $4c, $4d, $4e, $4f, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f 
-    DB $48, $49, $4A, $4B, $4C, $4D, $4E, $4F, $48, $49, $4A, $4B +    DB $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $48, $49, $4a, $4b 
-    DB $4C, $4D, $4E, $4F, $48, $49, $4A, $4B, $4C, $4D, $4E, $4F +    DB $4c, $4d, $4e, $4f, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f 
-    DB $48, $49, $4A, $4B, $4C, $4D, $4E, $4F, $50, $51, $52, $53+    DB $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $50, $51, $52, $53
     DB $54, $55, $56, $57, $50, $51, $52, $53, $54, $55, $56, $57     DB $54, $55, $56, $57, $50, $51, $52, $53, $54, $55, $56, $57
     DB $50, $51, $52, $53, $54, $55, $56, $57, $50, $51, $52, $53     DB $50, $51, $52, $53, $54, $55, $56, $57, $50, $51, $52, $53
Línea 1635: Línea 1631:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Pixel_Offset_LUT_2: Get_Pixel_Offset_LUT_2:
-    LD AC                     ; Ponemos en A la X +    ld ac                       ; Ponemos en A la X 
-    RRA +    rra 
-    RRA +    rra 
-    RRA                         ; A = ???CCCCC +    rra                           ; A = ???CCCCC 
-    AND 31                      ; A = 000CCCCCb +    and %00011111                 ; A = 000CCCCCb 
-    LD LB                     ; B = coordenada Y +    ld lb                       ; B = coordenada Y 
-    LD H, Scanline_Offsets/256  ; Parte alta de la dir de tabla +    ld h, Scanline_Offsets/256    ; Parte alta de la dir de tabla 
-    ADD A, (HL                ; A = columna + tabla_baja[linea] +    add a, (hl                  ; A = columna + tabla_baja[linea] 
-    INC H                       ; saltamos a la siguiente tabla +    inc h                         ; saltamos a la siguiente tabla 
-    LD H, (HL                 ; cargamos en H la parte alta +    ld h, (hl                   ; cargamos en H la parte alta 
-    LD LA                     ; cargamos en L la parte baja +    ld la                       ; cargamos en L la parte baja 
-    LD AC                     ; Recuperamos la coordenada (X) +    ld ac                       ; Recuperamos la coordenada (X) 
-    AND 7                       ; A = Posicion relativa del pixel +    and %00000111                 ; A = Posicion relativa del pixel 
-    RET+    ret
 </code> </code>
  
Línea 1696: Línea 1692:
  
 Pixel_Izquierda_HL_Mask: Pixel_Izquierda_HL_Mask:
-    RLC A            ; Rotamos A a la izquierda +    rlc a                    ; Rotamos A a la izquierda 
-    RET NC           ; Si no se activa el carry flag, volvemos +    ret nc                   ; Si no se activa el carry flag, volvemos 
-    DEC L            ; Si se activa, hemos pasado de 10000000b +    dec l                    ; Si se activa, hemos pasado de 10000000b 
-    RET              ; a 00000001b y ya podemos alterar HL+    ret                      ; a 00000001b y ya podemos alterar HL
  
 Pixel_Derecha_HL_Mask: Pixel_Derecha_HL_Mask:
-    RRC A            ; Rotamos A a la derecha +    rrc a                    ; Rotamos A a la derecha 
-    RET NC           ; Si no se activa el carry flag, volvemos +    ret nc                   ; Si no se activa el carry flag, volvemos 
-    INC L            ; Si se activa, hemos pasado de 00000001b +    inc l                    ; Si se activa, hemos pasado de 00000001b 
-    RET              ; a 10000000b y ya podemos alterar HL+    ret                      ; a 10000000b y ya podemos alterar HL
 </code> </code>
  
  Son apenas 4 instrucciones, lo que resulta en un cálculo significativamente más rápido que volver a llamar a la rutina de coordenación original.  Son apenas 4 instrucciones, lo que resulta en un cálculo significativamente más rápido que volver a llamar a la rutina de coordenación original.
  
- Nótese cómo en lugar de utilizar ''DEC HL'' o ''INC HL'' (6 t-estados), realizamos un ''DEC L'' o ''INC L'' (4 t-estados), ya que dentro de un mismo scanline de pantalla no hay posibilidad de, moviendo a derecha o izquierda, variar el valor del byte alto de la dirección (siempre y cuando no excedamos los límites de la pantalla por la izquierda o por la derecha). De esta forma ahorramos 2 valiosos ciclos de reloj en una operación que suele realizarse en el bucle más interno de las rutinas de impresión de sprites.+ Nótese cómo en lugar de utilizar ''dec hl'' o ''inc hl'' (6 t-estados), realizamos un ''dec l'' o ''inc l'' (4 t-estados), ya que dentro de un mismo scanline de pantalla no hay posibilidad de, moviendo a derecha o izquierda, variar el valor del byte alto de la dirección (siempre y cuando no excedamos los límites de la pantalla por la izquierda o por la derecha). De esta forma ahorramos 2 valiosos ciclos de reloj en una operación que suele realizarse en el bucle más interno de las rutinas de impresión de sprites.
  
  Si en lugar de una máscara de pixel tenemos en A la posición relativa (0-7), podemos utilizar el siguiente código:  Si en lugar de una máscara de pixel tenemos en A la posición relativa (0-7), podemos utilizar el siguiente código:
Línea 1719: Línea 1715:
  
 Pixel_Derecha_HL_Rel: Pixel_Derecha_HL_Rel:
-    INC A            ; Incrementamos A +    inc a                    ; Incrementamos A 
-    AND 7            ; Si A=8 -> A=0 +    and %00000111            ; Si A=8 -> A=0 
-    RET NZ           ; Si no es cero, hemos acabado +    ret nz                   ; Si no es cero, hemos acabado 
-    INC L            ; Si se activa, hemos pasado al byte +    inc l                    ; Si se activa, hemos pasado al byte 
-    RET              ; siguiente -> alterar HL+    ret                      ; siguiente -> alterar HL
  
 Pixel_Izquierda_HL_Rel: Pixel_Izquierda_HL_Rel:
-    DEC A            ; Decrementamos A +    dec a                    ; Decrementamos A 
-    RET P            ; Si no hay overflow (A de 0 a 255), fin +    ret p                    ; Si no hay overflow (A de 0 a 255), fin 
-    AND 7            ; 11111111b -> 00000111b +    and %00000111            ; 11111111b -> 00000111b 
-    DEC L            ; Hemos pasado al byte siguiente -> +    dec l                    ; Hemos pasado al byte siguiente -> 
-    RET              ; alteramos HL+    ret                      ; alteramos HL
 </code> </code>
  
Línea 1751: Línea 1747:
 <code z80> <code z80>
 ; Avanzamos HL 1 scanline: ; Avanzamos HL 1 scanline:
-    INC H                       ; Incrementamos HL en 256 (siguiente scanline) +    inc h                    ; Incrementamos HL en 256 (siguiente scanline) 
-    LD AH                     ; Cargamos H en A +    ld ah                  ; Cargamos H en A 
-    AND 7                       ; Si despues del INC H los 3 bits son 0, +    and %00000111            ; Si despues del inc h los 3 bits son 0, 
-                                ; es porque era 111b y ahora 1000b. +                             ; es porque era 111b y ahora 1000b. 
-    JR NZ, nofix_abajop         ; Si no es cero, hemos acabado (solo INC H). +    jr nz, nofix_abajop      ; Si no es cero, hemos acabado (solo inc h). 
-    LD AL                     ; Es cero, hemos pasado del scanline 7 de un +    ld al                  ; Es cero, hemos pasado del scanline 7 de un 
-                                ; caracter al 0 del siguiente: ajustar NNN +                             ; caracter al 0 del siguiente: ajustar NNN 
-    ADD A32                   ; Ajustamos NNN (caracter dentro de tercio += 1) +    add a%00100000         ; Ajustamos NNN (caracter dentro de tercio += 1) 
-    LD LA                     ; Ahora hacemos la comprobacion de salto de tercio +    ld la                  ; Ahora hacemos la comprobacion de salto de tercio 
-    JR C, nofix_abajop          ; Si esta suma produce acarreo, habria que ajustar +    jr c, nofix_abajop       ; Si esta suma produce acarreo, habria que ajustar 
-                                ; tercio, pero ya lo hizo el INC H (111b -> 1000b) +                             ; tercio, pero ya lo hizo el inc h (111b -> 1000b) 
-    LD AH                     ; Si no produce acarreo, no hay que ajustar +    ld ah                  ; Si no produce acarreo, no hay que ajustar 
-    SUB 8                       ; tercio, por lo que restamos el bit TT que sumo +    sub %00001000            ; tercio, por lo que restamos el bit TT que sumo 
-    LD HA                     ; el INC H inicial.+    ld ha                  ; el inc h inicial.
  
 nofix_abajop: nofix_abajop:
Línea 1774: Línea 1770:
  
 <code z80> <code z80>
-    LD AH +    ld ah 
-    AND 7                       ; Comprobamos scanline +    and %00000111            ; Comprobamos scanline 
-    JR Z, Anterior_SL_DEC       ; Si es cero, hay salto de caracter +    jr z, Anterior_SL_DEC    ; Si es cero, hay salto de caracter 
-    DEC H                       ; No es cero, basta HL = HL - 256 +    dec h                    ; No es cero, basta HL = HL - 256 
-    RET                         ; Hemos acabado (solo INC H). +    ret                      ; Hemos acabado (solo inc h). 
-Anterior_SL_DEC:               ; Hay que ir de caracter 000b a 111b +Anterior_SL_DEC:             ; Hay que ir de caracter 000b a 111b 
-    DEC H                       ; Decrementamos H +    dec h                    ; Decrementamos H 
-    LD AL                     ; Ajustamos NNN (caracter en tercio -=1) +    ld al                  ; Ajustamos NNN (caracter en tercio -=1) 
-    SUB 32 +    sub %00100000            ; -32 
-    LD LA +    ld la 
-    RET C                       ; Si se produjo carry, no hay que ajustar +    ret c                    ; Si se produjo carry, no hay que ajustar 
-    LD AH                     ; Se produjo carry, ajustamos el tercio +    ld ah                  ; Se produjo carry, ajustamos el tercio 
-    ADD A8                    ; por el DEC H inicial. +    add a%00001000         ; por el dec h inicial. (+8) 
-    LD HA+    ld ha
 </code> </code>
  
Línea 1805: Línea 1801:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Siguiente_Scanline_HL: Siguiente_Scanline_HL:
-    INC H +    inc h 
-    LD AH +    ld ah 
-    AND 7 +    and %00000111 
-    RET NZ +    ret nz 
-    LD AL +    ld al 
-    ADD A, 32 +    add a%00100000         ; +32 
-    LD LA +    ld la 
-    RET C +    ret c 
-    LD AH +    ld ah 
-    SUB +    sub %00001000            ; -
-    LD HA +    ld ha 
-    RET             ; Devolvemos en HL el valor ajustado+    ret                      ; Devolvemos en HL el valor ajustado
 </code> </code>
  
  
- La rutina para retroceder al scanline superior es de similar factura, con una pequeña reorganización del código para evitar el salto con ''JR'':+ La rutina para retroceder al scanline superior es de similar factura, con una pequeña reorganización del código para evitar el salto con ''jr'':
  
  
Línea 1834: Línea 1830:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Anterior_Scanline_HL: Anterior_Scanline_HL:
-    LD AH +    ld ah 
-    DEC H +    dec h 
-    AND 7 +    and %00000111 
-    RET NZ +    ret nz 
-    LD A+    ld a, %00001000          ; 
-    ADD AH +    add ah 
-    LD HA +    ld ha 
-    LD AL +    ld al 
-    SUB 32 +    sub %00100000            ; -32 
-    LD LA +    ld la 
-    RET NC +    ret nc 
-    LD AH +    ld ah 
-    SUB +    sub %00001000            ; -
-    LD HA +    ld ha 
-    RET             ; Devolvemos en HL el valor ajustado+    ret                      ; Devolvemos en HL el valor ajustado
 </code> </code>
  
-La rutina ''Siguiente_Scanline_HL'' será especialmente útil en el desarrollo de rutinas de impresión de Sprites, aunque lo normal es que incluyamos el código "inline" dentro de dichas rutinas, para ahorrar los ciclos de reloj usandos en un CALL+RET.+La rutina ''Siguiente_Scanline_HL'' será especialmente útil en el desarrollo de rutinas de impresión de Sprites, aunque lo normal es que incluyamos el código "inline" dentro de dichas rutinas, para ahorrar los ciclos de reloj usandos en un call+ret.
  
  
Línea 1872: Línea 1868:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Attr_Offset_From_Image: Attr_Offset_From_Image:
-    LD AH +    ld ah 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    AND 3 +    and %00000011 
-    OR $58 +    or %01011000 
-    LD DA +    ld da 
-    LD EL +    ld el 
-    RET+    ret
 </code> </code>
  
Línea 1893: Línea 1889:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Image_Offset_From_Attr: Image_Offset_From_Attr:
-    LD AH +    ld ah 
-    AND 3 +    and %00000011 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    RLCA +    rlca 
-    OR $40 +    or %01000000 
-    LD DA +    ld da 
-    LD EL +    ld el 
-    RET+    ret
 </code> </code>
  
Línea 1916: Línea 1912:
 ;------------------------------------------------------------- ;-------------------------------------------------------------
 Get_Char_Data: Get_Char_Data:
-    LD AB +    ld ab 
-    AND $18 +    and %00011000 
-    LD HA +    ld ha 
-    SET 6, H +    set 6, h 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    OR $58 +    or %01011000 
-    LD DA +    ld da 
-    LD AB +    ld ab 
-    AND 7 +    and %00000111 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    RRCA +    rrca 
-    ADD AC +    add ac 
-    LD LA +    ld la 
-    LD EA +    ld ea 
-    LD A, (DE+    ld a, (de
-    RET+    ret
 </code> </code>
  
  Llamando a la anterior rutina con unas coordenadas (c,f) en C y B obtenemos la dirección de memoria de imagen (HL) y de atributo (DE) de dicho carácter, así como el valor del atributo en sí mismo (A).  Llamando a la anterior rutina con unas coordenadas (c,f) en C y B obtenemos la dirección de memoria de imagen (HL) y de atributo (DE) de dicho carácter, así como el valor del atributo en sí mismo (A).
 +
 +\\ 
 +===== Optimizaciones para Get_Pixel_Offset_HR =====
 +
 + En ocasiones se puede reescribir una rutina de otra forma para ser ligeramente más eficiente, y las rutinas relacionadas con los gráficos (tanto "dibujar" gráficos como calcular la posición de dibujado) es una firma candidata a optimizarla todo lo posible.
 +
 +\\ //Dean Belfield//, en su página //L Break Into Program// nos proporciona la siguiente rutina optimizada para obtener la dirección de memoria de un pixel dadas su coordenadas (x,y) que requiere 117 t-estados, a costa de no devolvernos la posición relativa del pixel:
 +
 +\\ 
 +<code z80>
 +; Get screen address - by Dean Belfield
 +;
 +;  B = Y pixel position
 +;  C = X pixel position
 +;  Returns address in HL
 +Get_Pixel_Address:
 +    ld a, b                  ; Calculate Y2,Y1,Y0
 +    and %00000111            ; Mask out unwanted bits
 +    or %01000000             ; Set base address of screen
 +    ld h, a                  ; Store in H
 +    ld a, b                  ; Calculate Y7,Y6
 +    rra                      ; Shift to position
 +    rra
 +    rra
 +    and %00011000            ; Mask out unwanted bits
 +    or h                     ; OR with Y2,Y1,Y0
 +    ld h, a                  ; Store in H
 +    ld a, b                  ; Calculate Y5,Y4,Y3
 +    rla                      ; Shift to position
 +    rla
 +    and %11100000            ; Mask out unwanted bits
 +    ld l, a                  ; Store in L
 +    ld a, c                  ; Calculate X4,X3,X2,X1,X0
 +    rra                      ; Shift into position
 +    rra
 +    rra
 +    and %00011111            ; Mask out unwanted bits
 +    or l                     ; OR with Y5,Y4,Y3
 +    ld l, a                  ; Store in L
 +    ret
 +</code>
 +
 +Finalmente, //David Black// en su web //Overtaken by events// nos ofrece la siguiente rutina de 105 t-estados y 26 bytes:
 +
 +\\ 
 +<code z80>
 +; Get screen address - by David Black
 +;  B = Y pixel position
 +;  C = X pixel position
 +; Returns address in HL
 +Get_Screen_Address:
 +    ld a,b                  ; Work on the upper byte of the address
 +    and %00000111                ; a = Y2 Y1 y0
 +    or %01000000                 ; first three bits are always 010
 +    ld h,a                  ; store in h
 +    ld a,b                  ; get bits Y7, Y6
 +    rra                  ; move them into place
 +    rra
 +    rra
 +    and %00011000                ; mask off
 +    or h                  ; a = 0 1 0 Y7 Y6 Y2 Y1 Y0
 +    ld h,a                  ; calculation of h is now complete
 +    ld a,b                  ; get y
 +    rla
 +    rla
 +    and %11100000                ; a = y5 y4 y3 0 0 0 0 0
 +    ld l,a                  ; store in l
 +    ld a,c
 +    and %00011111                ; a = X4 X3 X2 X1
 +    or l                  ; a = Y5 Y4 Y3 X4 X3 X2 X1
 +    ld l,a                  ; calculation of l is complete
 +    ret
 +</code>
 +
 +Utilizando tablas, en esta misma web podemos ver las siguientes 2 aproximaciones de //Patrick Prendergast// en base a organizar los datos en memoria alineándolos de una forma que "desperdiciamos" memoria a cambio de que las rutinas sean más rápidas por cómo están alineados esos datos:
 +
 +<code z80>
 +; Store the LUT table in the format "y5 y4 y3 y7 y6 y2 y1 y0"
 +; Lower 5 bits where you need them for y and upper 3 bits to mask
 +; out to OR with X (which are replaced with 010 anyway).
 +; This way you'd only need 192 bytes for the table, which could be
 +; page-aligned for speed. You'd be looking at 69 cycles por request
 +; and 16 + 192 for the code + table.
 +;
 +; By Patrick Prendergast.
 +
 +; b = y, c = x
 +getScreenAddress:
 +    ld h,tbl >> 8
 +    ld l,b
 +    ld h,(hl)
 +    ld a,%11100000
 +    and h
 +    or c
 +    ld l,a
 +    ld a,%00011111
 +    and h
 +    or %01000000
 +    ld h,a
 +    ret
 +
 +tbl: ; y5 y4 y3 y7 y6 y2 y1 y0
 +    .db 0,1,2,3,4,5,6,7,32,33...
 +    
 +
 +; Option 2: if you are willing to [potentially] sacrifice
 +; some space for speed, you can divide the table so that
 +; you have the low and high bytes of your address list in
 +; 2 independent tables and have them both page aligned -
 +; with the low byte first in memory.
 +; This would completely remove to need to calc y*2 to get
 +; to your table offset.
 +; This would require 64 bytes of padding after the 1st table
 +; (due to both tables being page aligned) meaning you would
 +; need 448 bytes all up. That being said the 64 bytes of
 +; padding space is not needed so you can include any other
 +; data you might need there so it's not wasted.
 +; Then you would only need 47 cycles to lookup your address!
 +;
 +; By Patrick Prendergast.
 +
 +; b = y, c = x
 +getScreenAddress:
 +    ld h,tblLow >> 8
 +    ld l,b
 +    ld a,(hl)
 +    inc h
 +    ld h,(hl)
 +    or c
 +    ld l,a
 +    ret
 +
 +    ALIGN 256
 +tblLow: ; (ADDR & 0xFF)
 +    .db 0,0,0,0,0,0,0,0,32,32,32...
 +
 +    ALIGN 256
 +tblHigh: ; (ADDR >> 8)
 +    .db 64,65,66,67,68,69,70,71,64,65,66...
 +</code>
 +
 +Estas rutinas son realmente rápidas, teniendo la segunda un coste de sólo 47 t-estados por cálculo de dirección, a costa de ocupar más espacio por separar la parte alta y la parte baja de la tabla precalculada, y alinearlas en memoria en un múltiplo de 256 para evitar cálculos.
  
 \\  \\ 
Línea 1956: Línea 2094:
   * [[http://www.worldofspectrum.org/faq/reference/z80reference.htm|Z80 Reference de WOS]].   * [[http://www.worldofspectrum.org/faq/reference/z80reference.htm|Z80 Reference de WOS]].
   * [[http://www.speccy.org/trastero/cosas/Fichas/fichas.htm|Microfichas de CM de MicroHobby]].   * [[http://www.speccy.org/trastero/cosas/Fichas/fichas.htm|Microfichas de CM de MicroHobby]].
 +  * [[https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout-part-three/|Overtaken by Events - the screen layout (III)]].
  
 \\  \\ 
 **[ [[.:indice|⬉]] | [[.:gfx1_vram|⬅]] | [[.:gfx3_sprites_lowres|➡]] ]** **[ [[.:indice|⬉]] | [[.:gfx1_vram|⬅]] | [[.:gfx3_sprites_lowres|➡]] ]**
  
  • cursos/ensamblador/gfx2_direccionamiento.1705143596.txt.gz
  • Última modificación: 13-01-2024 10:59
  • por sromero