[Modo Radastaniano] - Sprites transparentes sin máscara

Software para o relacionado con el core ZX Spectrum / Software for or related to the ZX Spectrum core
Responder
Avatar de Usuario
Radastan
Mensajes: 386
Registrado: 05 Oct 2015, 14:39

[Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Radastan » 19 Nov 2015, 15:31

Vamos a ver, partimos de esta sencilla rutina:

Código: Seleccionar todo

// ___________________________________________
// Posiciona un Sprite de 8x8 a color
// ___________________________________________

void put_sprite_x8 (unsigned char *posicion, unsigned int x, unsigned int y)
{
	// -------------------------------------------
	// RUTINA DE IMPRESION DE UN SPRITE 8x8 PIXELS
	// EN CUALQUIER POSICION DE BYTES (cada byte dos pixels horizontales)
	// ENTRADAS:
	// D será la posición del cursor vertical en pixels
	// E será la posición del cursor horizontal en parejas de pixels
	// HL es la posición de memoria donde tenemos el sprite
	// SALIDAS: se escribe en el mapa de pantalla
	// ADVERTENCIAS: no comprueba límites de pantalla
	// -------------------------------------------
	#asm
		ld hl,2		; Pasamos la variable de entrada al acumulador
		add hl,sp
		ld d, (hl)	; D es el valor Y
		inc hl
		inc hl
		ld e, (hl)	; E es el valor X
		inc hl
		inc hl
		ld a, (hl)
	    	inc hl
	    	ld h, (hl)
	    	ld l, a		; HL es el puntero al sprite
	
		ld a, d		; recuperamos el valor vertical
		rrca
	        rrca		; rotamos para dejar su valor en múltiplos de 64 (linea, de dos en dos pixels)
		and 192		; borramos el resto de bits por si las moscas
		or e		; sumamos el valor horizontal
		ld e, a		; e preparado
		ld a, d		; cargamos el valor vertical
		rrca
		rrca		; rotamos para quedarnos con los bits altos
		and 63		; borramos el resto de bits
		or 64		; nos posicionamos a partir de 16384 (16384=64+0 en dos bytes)
		ld d, a		; d preparado, ya tenemos la posición en pantalla
	
		ld b,8		; Indicamos que vamos a pintar 8 líneas
		.draw		; dibujamos 8 pixels (4 bytes)
		ld c,4		; Indicamos que vamos a pintar 4 pares de pixels
		ldi
		ldi
		ldi
		ldi
		ld a,e
		add a,60	; incrementamos una línea y retornamos los pixels dibujados
		ld e,a
		jr nc, sigue
		inc d		; incrementamos D si sale acarrero al incrementar E en 64 bytes
		.sigue
		djnz, draw
	
		ret
	
	#endasm
}
La idea es que cuando detecte un pixel cero (0000xxxx ó xxxx0000 en binario) respete el pixel que hubiera anteriormente en pantalla. Es evidente que al tener que hacer alguna operación vamos a perder rapidez, pero tampoco es algo crítico porque no vamos a querer 32 sprites simultáneos en pantalla ni nada por el estilo (para animar fondos ya tenemos la rutina de arriba).

Lo que he pensado es en recuperar el byte de pantalla antes de "machacarlo" y hacer un par de operaciones con él:
- AND con valor 240, otro con 15 (para separar el tratamiento del primer y el segundo pixel) con cada byte del sprite
- Si el valor obtenido después de cada AND no es cero se dibuja el pixel, en caso contrario se salta el dibujado.

La parte que hay que modificar es esta:

Código: Seleccionar todo

		ld b,8		; Indicamos que vamos a pintar 8 líneas
		.draw		; dibujamos 8 pixels (4 bytes)
		ld c,4		; Indicamos que vamos a pintar 4 pares de pixels
		ldi
		ldi
		ldi
		ldi
		ld a,e
		add a,60	; incrementamos una línea y retornamos los pixels dibujados
		ld e,a
		jr nc, sigue
		inc d		; incrementamos D si sale acarrero al incrementar E en 64 bytes
		.sigue
		djnz, draw
Le daré vueltas y os contaré el progreso. Se aceptan sugerencias (sin usar máscara, evidentemente).

Avatar de Usuario
Haplo
Mensajes: 366
Registrado: 05 Oct 2015, 13:51
Ubicación: Ciudad Real

Re: [Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Haplo » 19 Nov 2015, 21:34

Si te fijas, lo q planteas es básicamente un "descompresor", es algo que investigué un poco pero que deseché enseguida por lo lento que era para este ámbito de aplicación. De todas maneras le echaré un ojete a lo que pides aunque me haga cruces por los ciclos de reloj :)

Avatar de Usuario
Hark0
Mensajes: 683
Registrado: 27 Sep 2015, 00:31
Ubicación: Cornellà de Llobregat - BCN
Contactar:

Re: [Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Hark0 » 20 Nov 2015, 10:45

Haplo escribió:Si te fijas, lo q planteas es básicamente un "descompresor", es algo que investigué un poco pero que deseché enseguida por lo lento que era para este ámbito de aplicación. De todas maneras le echaré un ojete a lo que pides aunque me haga cruces por los ciclos de reloj :)
Suelta tu source secreto... :boingg:
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.

Avatar de Usuario
Radastan
Mensajes: 386
Registrado: 05 Oct 2015, 14:39

Re: [Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Radastan » 15 Dic 2015, 09:28

Como en ensamblador parece un buen jaleo voy a crearla antes en C y así partimos de algo más sencillo de manejar e incluso ya utilizable.

Una rutina de sprites de 8x8 pixels es tal que así en C:

Código: Seleccionar todo

void put_msprite_x8 (unsigned char *sprite, unsigned int x, unsigned int y)
{
	unsigned int xx;
	unsigned int yy=8;
	unsigned char *pantalla;

	pantalla=16384+x+y*64;
	while (yy>0)
	{
		xx=4;
		while (xx>0)
		{
			*pantalla=*sprite;
			sprite++;
			pantalla++;
			xx--;
		}
		yy--;
		pantalla=pantalla+60;
	}
}
Ahora voy a modificarla para que en función del valor de cada byte dibuje o no cada pixel, para lo cual habrá que leer de la pantalla para hacer una mezcla. Después evolucionaré la rutina para que devuelva a un sprite de buffer lo que había en pantalla y así podamos restaurar luego lo que había de una forma sencilla.

Avatar de Usuario
Radastan
Mensajes: 386
Registrado: 05 Oct 2015, 14:39

Re: [Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Radastan » 15 Dic 2015, 10:22

Una primera rutina, que seguramente no sea muy optimizada, es esta:

Código: Seleccionar todo

// ___________________________________________
// Posiciona un Sprite de 8x8 a color con máscara
// ___________________________________________

void put_msprite_x8 (unsigned char *posicion, unsigned int x, unsigned int y)
{
	// -------------------------------------------
	// RUTINA DE IMPRESION DE UN SPRITE 8x8 PIXELS CON MÁSCARA (color 0 paleta)
	// EN CUALQUIER POSICION DE BYTES (cada byte dos pixels horizontales)
	// ENTRADAS:
	// D será la posición del cursor vertical en pixels
	// E será la posición del cursor horizontal en parejas de pixels
	// HL es la posición de memoria donde tenemos el sprite
	// SALIDAS: se escribe en el mapa de pantalla
	// ADVERTENCIAS: no comprueba límites de pantalla
	// -------------------------------------------
	unsigned int xx;
	unsigned int yy=8;
	unsigned char *pantalla=16384+x+y*64;
	unsigned int buffer;
	unsigned int dibuja;

	while (yy>0)
	{
		xx=4;
		while (xx>0)
		{
			buffer=*posicion;
			dibuja = 10*((buffer&15)>0)+((buffer&240)>0);
			switch(dibuja)
			{
				case 0: dibuja = *pantalla; break;
				case 1: dibuja = (buffer&240)+((*pantalla)&15); break;
				case 10: dibuja = (buffer&15)+((*pantalla)&240); break;
				case 11: dibuja = buffer; break;
			}
			*pantalla=dibuja;
			posicion++;
			pantalla++;
			xx--;
		}
		yy--;
		pantalla=pantalla+60;
	}
}
Con esto usamos el color 0 de la paleta como máscara y dibujamos un bonito sprite en pantalla con su transparencia.

Reto conseguido. :okidoki;

EDITADO: He metido unos paréntesis que me faltaban, ahora ya va bien
Última edición por Radastan el 15 Dic 2015, 13:05, editado 3 veces en total.

Avatar de Usuario
Hark0
Mensajes: 683
Registrado: 27 Sep 2015, 00:31
Ubicación: Cornellà de Llobregat - BCN
Contactar:

Re: [Modo Radastaniano] - Sprites transparentes sin máscara

Mensaje por Hark0 » 15 Dic 2015, 10:31

:gracias!: :gracias!: :gracias!:
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.

Responder