Página 3 de 6
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 01:01
por antoniovillena
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
')
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 01:09
por antoniovillena
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.
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 01:12
por radastan
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.
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 16:37
por antoniovillena
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.
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 22:45
por radastan
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?
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 23:30
por antoniovillena
$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.
Re: Pintando sprites de 16x16 en ensamblador
Publicado: Sab, 07 Dic 2013, 23:57
por radastan
$this->bbcode_second_pass_quote('antoniovillena', '
')Puedes currarte una rutina con un tamaño variable de sprites, asà lo tengo hecho yo en el otro hilo.
Ya, pero eso es a toda luces ineficiente. Significa usar otro registro, hacer push/pop con él, etc. La rutina pierde una velocidad que en tamaños grandes de sprite es precisamente más importante, veo más lógico una rutina para cada tamaño, tampoco pretendo hace una docena (16x16, 24x24, y 48x48).
Otra cosa es el uso de megatiles, que es algo que debemos comentar aparte porque es algo que siempre he visto muy interesante y que tengo bastante desarrollado en papel.