Pintando sprites de 16x16 en ensamblador

Chit chat general. Habla con los MojonTwins y con los amigos de los MojonTwins. Reza a Vah-ka. Delinque. Aviso: está PROHIBIDO tirarse peos fuerte. Si les cortas el pescuezo, vale.

Moderador: na_th_an

antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor antoniovillena » Sab, 07 Dic 2013, 01:01

Ten cuidado con la instrucción LDI, puesto que decrementa BC y en algún caso te puede decrementar B y alterarte el bucle, se puede arreglar con esto:

$this->bbcode_second_pass_code('', '
.draw
inc bc
inc bc
ldi
ldi
dec de
dec de
inc d
djnz draw
ret
')

Pero vamos que si quieres velocidad punta olvídate del call y del contador b y haz loop unrolling (desenrollado de bucle):

$this->bbcode_second_pass_code('', '
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
ldi
ldi
dec de
dec de
inc d
')
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor antoniovillena » Sab, 07 Dic 2013, 01:09

Me da 1155 ciclos aplicando loop unrolling. Por cierto antes calculaba mal los ciclos por byte porque dividía entre 32, hay que dividir entre 36 puesto que también pintas los atributos. Serían 32 ciclos/byte.
Avatar de Usuario
radastan
Mensajes: 692
Registrado: Vie, 20 Ago 2010, 12:54
Contactar:

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor radastan » Sab, 07 Dic 2013, 01:12

Lo he resuelto con un cómodo "ld c,255" antes del primer CALL. En total se realizan 36 LDI's, así que no tengo que preocuparme.

Y si, se que duplicando código gano velocidad, pero también pierdo tamaño. Ahora mismo ya he ganado bastante, creo que lo puedo dejar por bueno, me ha quedado una rutina sencilla de usar y que ocupa poquito, que es lo que buscaba.

Es que la idea que tengo con esta librería es poder hacer juegos para Cartucho IF2 en el futuro, es decir no usar la ROM para absolutamente nada. Y al ser de 16K los cartuchos el espacio es oro.

PD: Y que divertidos son estos hilos de optimizaciones de código, aparte de didácticos.

PD2: Buenas noches y gracias Antonio.
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor antoniovillena » Sab, 07 Dic 2013, 16:37

Te dejo el último código que tengo de tu rutina sólo a modo de curiosidad (ya que para el tutorial vas a emplear la versión más corta).

$this->bbcode_second_pass_code('', '
void put_sprite_x16 (unsigned char *posicion, unsigned char x, unsigned char y)
{
#asm
ld (fin+1), sp
pop bc
pop bc
pop de
pop hl
ld a, c
and 7
rrca
rrca
rrca
and $e0
or e
ld e, a
ex af, af
ld a, c
and $18
or $40
ld d, a
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
ex de, hl
ld bc, $f91e
add hl, bc
ex de, hl
ldi
ldi
dec de
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
dec e
dec e
inc d
ldi
ldi
rra
rra
rra
and 3
or $58
ld d, a
ex af, af
ld e, a
ldi
ldi
ld a, e
add a, 30
ld e, a
ldi
ldi
fin: ld sp, 0
ret
#endasm
}
')

Aparte del loop unrolling he eliminado los 2 push de / pop de y he cambiado la forma en la que se leen los parámetros. Salen 989 ciclos, unos 27 ciclos/byte. Si lo pruebas asegúrate de que estén deshabilitadas las interrupciones.
Avatar de Usuario
radastan
Mensajes: 692
Registrado: Vie, 20 Ago 2010, 12:54
Contactar:

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor radastan » Sab, 07 Dic 2013, 22:45

Lo que vamos a hacer es dejar tu rutina para la "librería optimizada", así la gente podrá usar la que más le convenga.

Seguiré usando la mía por una razón, voy a desarrollarla para hacer otra de 24x24 pixels y es más sencillo trabajar con el loop de la parte de impresión de pixels. Quiero una librería con varias rutinas que permitan no tener que ceñirte a los clásicos 16x16, así habrá más libertad.

Es más, necesito mayor tamaño de sprite porque uno de mis próximos juegos trabaja con sprites a color bastante grandes (no va a ser a lo Popeye, pero si igual de colorido).

EDITADO:

La he probado y no funciona, se te debe haber traspapelado alguna línea.

EDITADO 2:

Vale, he quita la primera línea y lo que hay desde la etiqueta "fin" inclusive y así si va.

¿Para qué demonios tocas el par de registros SP?
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: Pintando sprites de 16x16 en ensamblador

Mensajepor antoniovillena » Sab, 07 Dic 2013, 23:30

$this->bbcode_second_pass_quote('radastan', '')Para qué demonios tocas el par de registros SP?


Es para extraer datos de la pila más rápido. Si te das cuenta hay varios POPs al principio, es un poco más rápido que con LD X,(HL), el problema es que hay que equilibrar la pila, por eso se necesita la primera y la última línea (salva y restaura el contenido de SP).

El error que te da es por un efecto colateral en tu código, deberías tener las interrupciones deshabilitadas porque no las usas (poner un DI al comienzo). Aparecen cosas raras porque se produce una interrupción mientras se leen los parámetros con POP, la interrupción corrompe los valores que hay en la pila.

Puedes currarte una rutina con un tamaño variable de sprites, así lo tengo hecho yo en el otro hilo. Procura que no haya mucho overhead de velocidad entre esta rutina y una de tamaño fijo. En los sprites grandes suele haber muchos huecos (lugares en lo que la máscara es 11111111, es decir no se pinta nada), si te buscas la forma de evitarlos ganarías bastante en velocidad.