Activar un pixel de pantalla con ensamblador

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Responder
Avatar de Usuario
iadvd
rst 0
Mensajes: 39
Registrado: Mar Abr 09, 2019 9:48 am
Ubicación: Tokio, Japon
Contactar:

Activar un pixel de pantalla con ensamblador

Mensaje por iadvd » Lun Jun 03, 2019 3:59 am

Hola a tod@s, tengo una duda de ensamblador, si alguien con experiencia
me puede echar una mano con la duda y tiene un momento para darme pistas de esto
me ayudaría muchísimo:

En un 48k, tengo una pantalla mostrándose en la zona de memoria de pantalla,
ahora dependiendo de unas condiciones, quiero activar un único pixel de la pantalla x,y ,
el paper de dicho pixel es negro y el ink es amarillo (es decir, el paper y el ink
del udg - se dice asi al bloque de pixels verdad?- al que pertenece dicho pixel es así),
lo que quiero es según una condición que pasa en un bucle es poner en ese pixel determinado x,y
el ink activado y por tanto se ve ese pixel amarillo o desactivado y por tanto se ve el paper, es decir negro.

Existe una forma fácil de hacer este set/unset de un solo pixel con ensamblador?

En un principio pensé que no, que me tocara hacer algo como esto:

1. leer el udg que esta en la posición que incluye dicho pixel y meterlo en una variable con LD

2. Para hacer "set" hacer algún tipo de operación OR con otro udg que solo tiene un "1" justo
en el pixel que quiero activar; y si lo quiero desactivar un AND con un udg que tiene todo unos
excepto justo un "0" en la misma posición del pixel.

3. poner de nuevo el udg modificado en la zona de memoria de pantalla a través de la variable del
paso 1 ya modificado otra vez con LD.

Aun así no se como implementarlo. Esto leyendo algunos cursos de ensamblador, y creo que me va a costar
un tiempo ponerme al día y entender el proceso, pero si alguien me puede explicar un código que lo haga
por aquí lo agradecería muchísimo, ya que hace mucho que no toco el ensamblador. Al menos la
estructura básica seria una gran ayuda.Mientras sigo mirando a ver si consigo hacerlo por mi cuenta (en tal caso pondré mi solución por aquí)
:( :(

Saludos y gracias!
:D

Avatar de Usuario
iadvd
rst 0
Mensajes: 39
Registrado: Mar Abr 09, 2019 9:48 am
Ubicación: Tokio, Japon
Contactar:

Re: Activar un pixel de pantalla con ensamblador

Mensaje por iadvd » Lun Jun 03, 2019 4:47 am

Parece que ha avanzado un poquito...

He podido comprender que se leen 8 bits de pantalla de una tacada, asi que si mi
pantalla tiene (creo) 32 bloques de 8 bits de ancho y la altura es de 21*8=168 bits de alto
(tengo que mirarlo bien) entonces si mi (x,y) es uno de los ocho bits -ambos empiezan en indice 0-
del bloque B de la linea de pixels L por ejemplo, entonces quiero leer:

LD HL, 16384+(32*L)+B
LD A, (HL)
AND A, _asm_int
LD (HL), A

_asm_int es una variable en la que tengo el valor 11011111 binario
esto esta mapeando los pixels activos de dicha linea de pixels de pantalla.

Lo he probado y funciona, pero mi calculo de la posicion de pantalla esta mal, sale en otra posicion,
pero lo que es en si la rutina de leer de pantalla y hacer and / or dependiendo de lo que
necesite y volver a color, parece que funciona.

Si alguien sabe bien los calculos de la posicion de un pixel en pantalla a partir de la posicion 16384 de un 48k
se agradece (estoy usando una pantalla de 16 tiles * 8 de ancho de resolucion (creo que es la estandar
que se suele usar)

Gracias de nuevo!
:D

Avatar de Usuario
Nat
Herbert
Mensajes: 95
Registrado: Lun Mar 25, 2019 9:31 am

Re: Activar un pixel de pantalla con ensamblador

Mensaje por Nat » Lun Jun 03, 2019 9:20 am

La memoria de pantalla del ZX Spectrum tiene una organización optimizada para que a la ULA le sea muy sencillo leerla mientras representa su contenido en la TV. En tu código falta que considere los 3 tercios de 2048 bytes que forman la memoria de pantalla, 8 líneas cada uno, y después con un XOR inviertes el valor del pixel que tú quieras.

Si recuerdas cómo se carga una pantalla de presentación, ahí se observa sin problemas la organización real en la memoria.

Imagen

Si X e Y son las coordenadas de un pixel en pantalla, la columna C (C=X/8) en el intervalo [0,32) e Y en [0,192), la dirección calculada en HL tiene este formato:

Imagen

Código: Seleccionar todo

; Get screen address
; 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
y este es un ejemplo de uso:

Código: Seleccionar todo

            org     $8000

            call    FIND_INT2               ; Fetch the coordinates (B=Y, C=X)
            push    BC
            ld      BC,1                    ; Push 1 to FP stack
            call    STACK_BC
            pop     BC

            call    Get_Pixel_Address       ; Get screen address

            ld      A,(HL)
            xor     128                     ; Bit 7 leftmost pixel
            ld      (HL),A
            ret


; Get screen address
; 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

FIND_INT2   equ     $1E99
STACK_BC    equ     $2D2B
que puedes probar con este programa en BASIC:

Código: Seleccionar todo

10 LET x=255
20 LET y=191
30 LET l=(x+256*y)*USR 32768
40 PAUSE 0
50 GO TO 10
Última edición por Nat el Jue Nov 14, 2019 5:26 pm, editado 14 veces en total.
Saludos,
Nat

Avatar de Usuario
iadvd
rst 0
Mensajes: 39
Registrado: Mar Abr 09, 2019 9:48 am
Ubicación: Tokio, Japon
Contactar:

Re: Activar un pixel de pantalla con ensamblador

Mensaje por iadvd » Lun Jun 03, 2019 9:22 am

Fantástico muchas gracias Natohara! :D

Avatar de Usuario
Nat
Herbert
Mensajes: 95
Registrado: Lun Mar 25, 2019 9:31 am

Re: Activar un pixel de pantalla con ensamblador

Mensaje por Nat » Lun Jun 03, 2019 9:56 am

De nada.

En un juego real y en función de la memoria libre, no se usan estos cálculos. En su lugar se recurre a tablas precalculadas de las direcciones de memoria de pantalla para el píxel más a la izquierda de cada línea. Esta otra técnica consume 384 (2x192) bytes de un bloque de 2 páginas (512 bytes) pero es mucho más rápida.
Saludos,
Nat

Avatar de Usuario
Metalbrain
Freddy Hardest
Mensajes: 592
Registrado: Lun May 07, 2007 8:17 am
Ubicación: Sevilla
Contactar:

Re: Activar un pixel de pantalla con ensamblador

Mensaje por Metalbrain » Jue Jun 06, 2019 10:05 am

Hola iadvd,

Para este tema, te aconsejo el curso de ensamblador de Santiago Romero que tenemos en esta misma página. El tema de las direcciones de los gráficos se trata de forma extensa en este capítulo:
https://wiki.speccy.org/cursos/ensambla ... ionamiento
Nat escribió:Si X e Y son las coordenadas de un pixel en pantalla, X en el intervalo [0,192) e Y en [0,256)
Para esa tabla, X en el intervalo [0,31] (porque estamos hablando de caracteres, no pixels) e Y en [0,191]
SevenuP se escribe con u minúscula y P mayúscula.

Avatar de Usuario
Nat
Herbert
Mensajes: 95
Registrado: Lun Mar 25, 2019 9:31 am

Re: Activar un pixel de pantalla con ensamblador

Mensaje por Nat » Jue Jun 06, 2019 1:11 pm

Gracias por la corrección, muy bien visto. La confusión surgió cuando primero puse el código que sí usa píxeles y en una edición posterior la tabla y se me pasó hablar de la transformación sobre el valor de X porque estuve entretenido de más buscando el conversor de GIFs con soporte para vídeos de más de 15 segundos por la dichosa pantalla de presentación.
Saludos,
Nat

Avatar de Usuario
iadvd
rst 0
Mensajes: 39
Registrado: Mar Abr 09, 2019 9:48 am
Ubicación: Tokio, Japon
Contactar:

Re: Activar un pixel de pantalla con ensamblador

Mensaje por iadvd » Jue Jun 20, 2019 3:51 am

Por cierto, que conseguí programarlo y funciona de maravilla! tengo un nuevo juego casi a puntito, y ahí se podrá ver el resultado! saludos y gracias de nuevo a todos por las recomendaciones!
:D :D

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados