Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Foro dedicado a la programación en todo tipo de sistemas clásicos.
Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 20 Jul 2018, 17:49

AjAJjAjaJAJAJ, LD HL, BD, pos no lo habré yo intentado veces... Pero el que más, esto:

Código: Seleccionar todo

LD DE, (HL)


Qué maravilloso sería que existiera esa instrucción... En su lugar hay que hacer tó esto:

Código: Seleccionar todo

LD E, (HL)
INC HL
LD D, (HL)
DEC HL


Aunque sé que había por ahí una paranoia tal que LD HL, (SP) o algo así, pero nunca me ha hecho falta llegar a tal nivel de frikismo, jiji.
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
explorer
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 217
Registrado: 11 May 2014, 17:10
Sistema Favorito: Atari ST
primer_sistema: Atari 800XL/600XL
consola_favorita: Atari 2600
Primera consola: Atari 2600
Ubicación: Valladolid, España
Gracias recibidas: 45 veces
Contactar:

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor explorer » 21 Jul 2018, 00:37

Uto escribió:sjasm tiene un motón de macros incorporadas, para que los torpes no tengamos problemas. A mi me pasó una vez que puse LD HL, BC o algo así, y el tío me lo aceptó y cambió en el código a LD H, B / LD L, C. Lo malo es que me puse a depurar, y me puse a a hacer scroll en el depurador a ver donde estaba el trozo de código que yo quería, y precisamente mi ojo iba buscando el LD HL, BC, y claro no lo veía.

Este tipo de macros empieza a ser muy útil cuando estás programando en ensamblador todo el día, porque acabas cansado de escribir tantas líneas. Hay programadores que tienen docenas y docenas de macros, y agrupadas por niveles.

Hay macros como éstas, que "imitan" instrucciones reales, que reducen el tamaño del código fuente, que ese ensamblador llama "fake instructions".

Otras macros son para hacer operaciones especiales, como inicializar_hardware, limpiar_memoria_video, que a veces son tan extensas que más que macros son llamadas a subrutinas, pero como solo se usan una vez, el programador las pone como macros y así se ahorra toda la parafernalia de poner argumentos, salvar la pila, saltar a la subrutina, regresar, ajustar la pila, etc.

Un ejemplo que suelo usar para 68000:

Para cambiar la paleta de colores, en el Atari ST pongo esto

Código: Seleccionar todo

        Setpalette a0

conteniendo el registro a0 la dirección de memoria donde se define la nueva paleta de colores que se debe usar. ¿A qué es cómodo?

Bueno, naturalmente, Setpalette no es una instrucción del ensamblador del 68000. Es una macro que equivale a esto:

Código: Seleccionar todo

Setpalette      macro
                move.l  \1,-(sp)
                Xbios   6,6
                endm

Que quiere decir que mete el primer argumento (\1) en la pila y luego hace una llamada a la BIOS, más concretamente, la parte Xbios, la función 6. El segundo 6 tiene otro significado que explico a continuación. Es decir... que Xbios es otra macro, que vale esto:

Código: Seleccionar todo

Xbios           macro
                maktrap 14,\1,\2
                endm

Vemos que hay una sentencia llamada maktrap, con tres argumentos. El primero es fijo (14) y luego siguen los dos argumentos pasados antes (los dos 6 de antes). Y... de nuevo... maktrap no es una instrucción de ensamblador para 68000... es otra macro, que vale esto:

Código: Seleccionar todo

maktrap         macro
                move    #\2,-(sp)
                trap    #\1
                suma    \3
                endm

Por fin, ya vemos lenguaje ensamblador... move, trap... Vemos que el primer move mete en la pila el segundo argumento (es el primer 6 de la llamada original). Luego, hace un trap con el primer argumento (el 14, valor fijo), y luego... llama a otra macro, suma, con el tercer argumento (el segundo 6). Esa macro suma tiene este aspecto (no asustarse, por favor):

Código: Seleccionar todo

suma            macro
                ifne    \1
                ifle    \1-8
                addq.l  #\1,sp
                elseif
                lea     \1(sp),sp
                endc
                endc
                endm

Aquí hay varias sentencias que son directivas del ensamblador, para generar código condicional (según lo que ocurra, genera un código u otro). En la primera línea se pregunta si el primer argumento es distinto de 0. Si es así, en la segunda línea se pregunta si el primer argumento es inferior a 8. Si es así, genera la sentencia addq.l, es decir, una suma rápida para ajustar la posición de la pila. Si no es así, genera una sentencia lea con direccionamiento relativo a la pila. Así ajustamos la pila para desplazamientos de 16 bits.

Bueno... en resumen... lo que hace

Código: Seleccionar todo

        Setpalette a0

es equivalente a

Código: Seleccionar todo

                move.l  a0,-(sp)
                move    #6,-(sp)
                trap    #17
                addq.l  #6,sp

¿Demasiado lioso para solo cuatro instrucciones de código máquina? Sí, pero hay que recordar que en un programa pueden aparecer docenas y docenas de estas llamadas. Además, es más claro poner Setpalette ya que es el nombre de la propia función en la documentación de la BIOS.

Perdón, me he enrollado como una persiana :-)

Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 21 Jul 2018, 03:16

No, si está esto harto interesante, vaya. Lo que opino yo de las macros es que sí, pero siempre que sea uno el que se las crea, no que vengan incorporadas en el ensamblador. De toas formas yo no las uso, nu sé por qué nunca me han hecho tanta falta como para tener que definir una macro. Siempre he pogramado en Z80 del Spectrum, quizás en otras CPUs o járgüeres sí que sean más necesarias las macros, nu sé.
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Namek
Amstrad PC 1640
Amstrad PC 1640
Mensajes: 618
Registrado: 11 Jul 2011, 13:13
Gracias dadas: 12 veces
Gracias recibidas: 26 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Namek » 21 Jul 2018, 09:59

Las macros son mas cuestión de comodidad que otra cosa, imaginate tener que escribir un moton de subrutinas que siempre usan una misma secuencia de instrucciones, podrias copiar y pegar esa secuencia todas las veces que quisieras pero eso haria el código más extenso y dificil de leer y podrias sustituir esa serie de instrucciones con una sola palabra, cuando hize mi emulador de Spectrum para Amiga me apañe montones de macros que me ahorraron un monton de tiempo y de código al escribir la emulación de cada instrucción del Z80.

Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 23 Jul 2018, 13:12

Y por curiosidad, la rutina análoga a calcular la dirección VRAM previa, siguiendo el mismo método de pasarme de tercio y al final restablecerlo, sería así:

Código: Seleccionar todo

calc_prev_vram:

dec h
ld a, h
and %111
cp %111
ret nz

ld a, l
sub %00100000
ld l, a
and %11100000
ret z

ld a, h
add a, %1000
ret


Como veis, mover hacia arriba un sprite sería algo más lento que moverlo hacia abajo, por la sencilla razón de que hacia arriba los desbordamientos aterrizan en bits a 1, mientras que hacia abajo los desbordamientos aterrizan en bits a 0, y en Z80 es más rápido detectar ceros que unos.

Esta rutina no la he catado, espero hacerlo en breva.
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 23 Jul 2018, 18:39

Restifico la rutina anterior, me faltó alguna cosilla. Ahora sí está bien:

Código: Seleccionar todo

calc_prev_vram:

dec h
ld a, h
and %111
cp %111
ret nz

ld a, l
sub %00100000
ld l, a
and %11100000
cp %11100000
ret z

ld a, h
add a, %1000
ld h, a

ret



Lo que sí es verdura es que esta rutina sólo se llama una única vez pa mover un gráfico p'arriba, es decir, sólo la tengo que llamar pa ver aonde empiezo a dibujar, y a partir de ahí llamo a la otra, a la calc_next_vram, así que nu hace falta que sea tan tan taaaan rápida.
De toas formas si por curiosidad veis alguna manera más optimizada, dígase

:D
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
explorer
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 217
Registrado: 11 May 2014, 17:10
Sistema Favorito: Atari ST
primer_sistema: Atari 800XL/600XL
consola_favorita: Atari 2600
Primera consola: Atari 2600
Ubicación: Valladolid, España
Gracias recibidas: 45 veces
Contactar:

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor explorer » 23 Jul 2018, 19:01

Humm... me temo que no va a ser tan sencillo.

De todas maneras, la rutina de cálculo de siguiente scanline es para pintar el sprite o gráfico de arriba hacia abajo.

Lo de usarlo para desplazar el sprite... eso solo te servirá para moverlos un scanline cada vez. Para movimientos de más de un scanline, se podría llamar más de una vez, o mejor, realizar una rutina optimizada para esos casos.

El algunas ocasiones... es más rápido tener una rutina que calcule el scanline desde cero cuando haya un cambio de posición, en lugar de calcular diferencias.

Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 23 Jul 2018, 19:28

Bueno, la calc_prev_vram podría servir p.ej. pa cuando una nave que está abajo dispara hacia arriba: voy calculando la VRAM previa, y ahí pongo un puntito (y borro el de más abajo).
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!

Avatar de Usuario
explorer
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 217
Registrado: 11 May 2014, 17:10
Sistema Favorito: Atari ST
primer_sistema: Atari 800XL/600XL
consola_favorita: Atari 2600
Primera consola: Atari 2600
Ubicación: Valladolid, España
Gracias recibidas: 45 veces
Contactar:

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor explorer » 25 Jul 2018, 15:05

O sea... que la "bala" sube 1 pixel por cuadro de animación.

Si, suponemos, que generamos 50 cuadros de animación por segundo, quiere decir que la bala se mueve a 50 píxeles/s.

Atravesar toda la pantalla del Spectrum, tardará... 192 / 50 = 3.84 segundos... una eternidad.

:D

Avatar de Usuario
Bubu
MSX Turbo R
MSX Turbo R
Mensajes: 481
Registrado: 04 Abr 2018, 23:10
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Atari 2600
Primera consola: Nintendo GameBoy
Gracias dadas: 10 veces
Gracias recibidas: 13 veces

Re: Zx Spectrum: Cómo calcular el siguiente scanline en VRAM

Mensajepor Bubu » 25 Jul 2018, 16:33

Yo no he dicho nada de poner la bala en la rutina de interrupción :D
Si algo funciona... ¡¡NO LO TOQUES!! ¡¡NI DE COÑA!!


Volver a “Programación”

¿Quién está conectado?

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