Rutina para dibujar un Sprite en pantalla.

Programando el Amstrad en Ensamblador.
Reglas del Foro
Debido a que hay varios temas pidiendo ayuda para programar en ensamblador máquinas distintas al Amstrad CPC, con micro distinto al Z80 y que incluso dependen del sistema operativo, nos vemos en la necesidad de poner por escrito que estos posts son bienvenidos pero que no es el lugar adecuado ya que por estos lares nos dedicamos más al ensamblador del Z80, un microprocesador de 8 bits que tuvo su gran auge en ordenadores y consolas de los años 80.

De todas formas, esto no quita que alguien que sepa del asunto pueda postear alguna respuesta pero es más fácil encontrar foros dedicados a programar en ensamblador en Windows o MS-DOS que ayudarán más que nosotros:
http://www.lawebdelprogramador.com/news ... nsamblador
Avatar de Usuario
Mochilote
Keeper of The Forum
Keeper of The Forum
Mensajes: 903
Registrado: Sab 08 Oct , 2005 4:26 pm
Contactar:

Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "piec

Mensajepor Mochilote » Jue 16 Mar , 2006 10:24 am

Cierto, Mochilote, se cambia el valor del salto entre líneas, pero no es como una variable ya que accede directamente al código. Por eso digo que modifica el código. De esta misma forma se puede "reescribir" el código modificando cualquier cosa.
Yo una variable la actualizaría así:
ld hl,valor
ld (variable),hl
Pero es cierto que es más lento que machacar el valor en el código.
Cierto cierto, si razón llevas desde el principio, sólo que 'cambiar el codigo fuente' sonaba muy raro y por eso lo desrrollaba más :D en resumen: "LD (ademas_linea+1),HL" machaca el &800 por el valor de HL :shock:
Bueno, a lo que iba. La rutina de T&J es incompleta. Le he encontrado dos errores. Por un lado, el manejo de HL y DE no era bueno y por otro, el número de salto de línea tpc estaba bien calculado. Os pongo el código arreglado, comentado y con un ejemplo en modo 1.
Luego lo probaré (en casa), ¿se supone que es mas rapida que la original?¿has contado ciclos?

saludos.

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

RE: Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "

Mensajepor Artaburu » Jue 16 Mar , 2006 10:43 am

Todavía no he contado ciclos pero al usar LDI en vez de ld a,(hl) ld (de),a inc hl, inc de, dec bc ahí se gana una pizca.

loop_ancho_2
ld A,(DE) ; 2
ld (hl),a ; 2
inc de ; 1
inc hl ; 1
djnz loop_ancho_2 ; 3,2

Este bucle ejecutaría 9*(ancho-1)+8 ciclos


loop_ancho_2
LDI ;4
DEC A ;1
JR NZ,loop_ancho_2 ;(true)3,(false)2

Este bucle ejecutaría 8*(ancho-1)+7 ciclos, es mejor que el anterior

Por lo menos esta parte y la del salto de línea son mejores asi que me las apunto.
Salu2,
Arta

Avatar de Usuario
Mochilote
Keeper of The Forum
Keeper of The Forum
Mensajes: 903
Registrado: Sab 08 Oct , 2005 4:26 pm
Contactar:

Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "piec

Mensajepor Mochilote » Jue 16 Mar , 2006 6:56 pm

Bueno, a lo que iba. La rutina de T&J es incompleta. Le he encontrado dos errores. Por un lado, el manejo de HL y DE no era bueno y por otro, el número de salto de línea tpc estaba bien calculado. Os pongo el código arreglado, comentado y con un ejemplo en modo 1.
Ya la he probado y funciona perfectamente, habrá que estudiarla detenidamente :lol: He de decir que llevo un rato con cara de bobo hasta que he encontrado que en esta segunda los parametros de entrada a la función HL y DE van al reves que en la tuya original :o

Saludos.

Avatar de Usuario
MiguelSky
Lord of Short Time
Lord of Short Time
Mensajes: 6969
Registrado: Sab 08 Oct , 2005 2:02 am
Contactar:

Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "piec

Mensajepor MiguelSky » Jue 16 Mar , 2006 7:18 pm

Yo una variable la actualizaría así:
ld hl,valor
ld (variable),hl
"LD (ademas_linea+1),HL" machaca el &800 por el valor de HL
Gracias chicos, eso es lo que me parecía, pero se me hacía un poco duro que el programa se automodificase y encima en tan temprana linea :) Es más claro el "método arta" pero yendo a lo práctico el segundo es una buena treta ;)

tom&jerry
Lechoncillo
Lechoncillo
Mensajes: 5
Registrado: Mar 14 Mar , 2006 8:23 pm

Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "piec

Mensajepor tom&jerry » Jue 16 Mar , 2006 9:08 pm

Hola !

Soy desolado por los "bugs". My reputacion ha fracassa :-)
Hay une ultima error en la rutina..

bla bla...
LD A,C
CPL
INC A
LD C,A
add HL,BC ; = HL - C

; INC HL no sirve de nada ahora

LD (ademas_linea+1),HL
bla bla...

Sorry for this ugly spanish... I suppose I should improve it reading this forum. Continue to support CPC, it's really a great computer :-)

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

RE: Re: RE: Re: RE: Re: RE: Re: Se puede mejorar esta "

Mensajepor Artaburu » Jue 16 Mar , 2006 9:35 pm

Ok Tom&Jeey, no problem. Se te entiende bien y es un honor que te pases por aquí.
Salu2,
Arta

Avatar de Usuario
Mode 2
I am The Forum
I am The Forum
Mensajes: 2068
Registrado: Lun 10 Oct , 2005 8:01 pm
Ubicación: Sevilla, años 80.
Contactar:

Mensajepor Mode 2 » Lun 05 Jun , 2006 11:17 pm

Suprime de esta última los comentarios
; dibujar en pantalla el sprite
; Entradas bc: Alto Ancho
; de: origen (sprite)
; hl: destino (pantalla)
; Se alteran hl, bc, de, af
ya que parece que el Ensamblador no los entiende y da error al compilar.
Hola MiguelSky!

He estado compilando el código y el problema de los comentarios al parecer está en la utilización de : dentro de éstos.

Un saludo.

Por cierto Arta, por favor sigue colgando rutinas y trucos de programación que ésto engancha. Iluminanos, artista!!

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

Mensajepor Artaburu » Mar 06 Jun , 2006 9:02 am

Suprime de esta última los comentarios
; dibujar en pantalla el sprite
; Entradas bc: Alto Ancho
; de: origen (sprite)
; hl: destino (pantalla)
; Se alteran hl, bc, de, af
ya que parece que el Ensamblador no los entiende y da error al compilar.
Hola MiguelSky!

He estado compilando el código y el problema de los comentarios al parecer está en la utilización de : dentro de éstos.

Un saludo.

Por cierto Arta, por favor sigue colgando rutinas y trucos de programación que ésto engancha. Iluminanos, artista!!
Si estás compilando con WinApe no se pueden tener dos puntos ":" en los comentarios ya que es como un salto de línea.

Seguiré con rutinillas, no te preocupes ;) Gracias!
Salu2,
Arta

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

Mensajepor Artaburu » Mié 14 Jun , 2006 11:32 am

Estoy haciendo unas pruebas para meter sprites en pantalla usando máscaras.
Partiendo de la máscara de un sprite (mask) y del fondo dibujado en la pantalla (&C000) se generan dos bloques de datos. Uno, el fondo enmascarado que ha hecho un AND entre cada byte de mask y de pantalla y que se guarda en destino_fondo_enmascarado y otro que simplemente copia la pantalla sin alterarla en buffer_sp. buffer_sp se actualiza usando IX y destino_fondo_enmascarado usando BC. Espero que os pueda ser de utilidad y si veis algo que se pueda optimizar, avisadme, please. Yo tb la actualizaré si la mejoro (esta es la primera versión)

Código: Seleccionar todo

org &4000

;relleno la máscara con &FF para que actúe dejando pasar todo.
ld de,mask+1
ld hl,mask
ld bc,400
ld (hl),&ff
ldir

;relleno toda la pantalla con un valor cualquiera para probar
ld de,&c000+1
ld hl,&c000
ld bc,16383
ld (hl),5
ldir


DI
LD HL,#C9FB ; Desactivo las interrupciones
LD (#0038),HL ; Establecemos el manejador de interrupciones
IM 1 ; Modo 1 de interrupciones (La CPU saltará a #0038 cuando ocurra una interrupción)
EI



;leer pantalla y hacer un AND con la mascara
; llamada a la rutina
; hl tiene pantalla
; de tiene mascara
; bc dimensiones y destino. Con las dimensiones inciales se automodifica el código
; ix guarda buffer de pantalla
;
; las etiquetas que empiezan por _a_ indican dónde hay que modificar el código cuando se cambien los parámetros.
; el ancho y alto se modifican en la rutina, en destino_enmascarado hay que modificarlo antes de llamarla.

LD BC,destino_fondo_enmascarado
LD HL,_a_destino_fondo_enmascarado+1
LD (HL),C
INC HL
ld (HL),B

LD IX,buffer_sp
LD HL,pos_pantalla
LD DE,mask
ld BC,&1010 ; alto/ancho del sprite


rutina_enmascaramiento

LD A,B
LD (_a_alto+1),A
LD A,C
LD (_a_ancho+1),A


_a_destino_fondo_enmascarado
ld bc,destino_fondo_enmascarado ;destino

_a_alto
LD A,0

bucle_alto_mask
PUSH AF ;cuidado con las interrupciones
_a_ancho
LD A,0 ;se pone el ancho
bucle_ancho_mask
EX AF,AF' ; uso A' como contador de ancho
LD A,(DE) ; se lee el byte de pantalla
LD (IX+0),A ; se guarda info de pantalla original
AND (HL) ; se enmascara
LD (BC),A ; se guarda en temporal de fondo y máscara.
INC DE
INC BC
INC HL
INC IX
EX AF,AF' ; restablezco el contador
DEC A
JP NZ,bucle_ancho_mask

; se incrementa la pantalla para cambiar de línea
PUSH BC
LD A,H
ADD &08
LD H,A
SUB &C0
JP NC,sig_linea_pantalla
LD BC,&C050
ADD HL,BC
sig_linea_pantalla

POP BC

POP AF
DEC A
JP NZ,bucle_alto_mask
RET




buffer_sp EQU &5000
mask EQU &5500
destino_fondo_enmascarado EQU &6000
pos_pantalla EQU &c000
Salu2,
Arta

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

Mensajepor Artaburu » Mié 28 Jun , 2006 10:20 am

Sigo con pruebas de rendimiento en dibujado de pantalla. El siguiente código bastante mejor para sprites anchotes ya que la parte que dibuja el ancho usa la pila y aunque emplea más ciclos, dibuja de 2 en 2 bytes. Quiero mejorar la parte del alto pq es tan lenta como la original, si se os ocurre algo soy todo orejas.

Código: Seleccionar todo

org &4000

ld (pila),sp ; se guarda posic actual de la pila


_origen_pila_sprite ;(posc pantalla-ancho*2)
ld hl,&d0ff
ld sp,hl ; se actualiza la pila



_origen_datos_sprite
ld hl,datos
ld a,40
bucle_alto_pila


ld (cont),a ;4


_ancho_sprite

ld b,5 ;mitad del ancho del sprite (ancho real/2) ;2

bucle_ancho_pila
ld d,(hl) ;2
inc HL ;1
ld e,(hl) ;2
INC HL ;1
push DE ;3
djnz bucle_ancho_pila ;3
;TOTAL bucle ancho 12 ciclos para 2 bytes (peor caso)


; se debe actualizar la pila a nueva posicion salto línea
ex de,hl ;1
ld h,0 ;2
ld l,h ;1
add hl,sp ;3


ld A,H ;1
add &08 ;2
ld H,A ;1
sub &C0 ;2

jp nc,sig_linea_pila ;3
ld bc,&c050 ;3
add HL,BC ;3
sig_linea_pila


;se suma a HL el ancho del sprite
ld bc,10 ;3
add hl,bc ;3
ld sp,hl ;2

ex de,hl ;1
ld a,(cont) ;3
dec a ;1
jp nz, bucle_alto_pila ;3


;TOTAL bucle alto 38 ciclos (peor caso)

;
ld sp,(pila) ;se restaura posicion inicial de la pila
ret
pila dw 0
cont db 0

datos

db &00,&00,&80,&00,&00,&00,&00,&00,&00,&00
db &00,&00,&48,&30,&00,&00,&00,&00,&00,&00
db &00,&00,&06,&70,&00,&00,&00,&00,&00,&00
db &00,&00,&12,&C0,&10,&00,&00,&00,&00,&00
db &00,&80,&09,&42,&F0,&00,&00,&00,&00,&00
db &00,&C0,&04,&C1,&F0,&30,&00,&00,&00,&00
db &00,&20,&0A,&E0,&F0,&70,&00,&00,&00,&00
db &00,&60,&04,&F0,&F0,&F0,&00,&00,&80,&F0
db &00,&B0,&02,&F8,&F7,&F7,&10,&00,&60,&80
db &00,&70,&84,&FC,&FC,&F9,&10,&00,&30,&C0
db &00,&30,&80,&F5,&E8,&D0,&10,&80,&10,&A0
db &80,&00,&80,&F7,&C8,&90,&10,&00,&10,&58
db &80,&00,&C0,&FF,&F8,&F0,&00,&00,&A0,&A4
db &00,&10,&A0,&FE,&FF,&F6,&00,&00,&52,&52
db &80,&90,&00,&FE,&F7,&F7,&00,&80,&85,&21
db &40,&C0,&30,&FE,&FF,&F3,&00,&48,&80,&10
db &40,&80,&C0,&FC,&F1,&F0,&30,&24,&00,&00
db &40,&00,&00,&CC,&73,&50,&60,&12,&00,&00
db &40,&10,&00,&F8,&F7,&70,&E4,&01,&00,&00
db &C0,&10,&00,&E0,&F0,&30,&78,&10,&00,&00
db &80,&20,&80,&60,&00,&90,&F6,&10,&00,&00
db &80,&10,&40,&C0,&20,&F0,&FD,&10,&00,&00
db &00,&30,&20,&F0,&E0,&10,&DA,&10,&00,&00
db &00,&70,&C0,&FA,&3C,&90,&E7,&00,&00,&00
db &00,&D2,&E8,&FF,&B4,&10,&00,&00,&00,&00
db &00,&96,&EC,&FB,&79,&10,&00,&00,&00,&00
db &00,&B4,&F0,&F5,&96,&30,&80,&30,&00,&00
db &00,&1E,&D2,&F3,&4B,&70,&60,&20,&00,&00
db &00,&38,&A5,&70,&B4,&C3,&B0,&50,&00,&00
db &00,&34,&4B,&30,&E0,&70,&C0,&70,&00,&00
db &00,&68,&86,&21,&00,&90,&F0,&70,&00,&00
db &00,&C0,&78,&21,&80,&E0,&F0,&30,&00,&00
db &00,&80,&4B,&21,&00,&F0,&70,&00,&00,&00
db &00,&80,&F0,&70,&00,&F0,&10,&00,&00,&00
db &00,&C0,&80,&F0,&00,&00,&00,&00,&00,&00
db &00,&60,&E0,&B0,&00,&00,&00,&00,&00,&00
db &00,&D0,&F0,&D0,&00,&00,&00,&00,&00,&00
db &00,&30,&00,&20,&00,&00,&00,&00,&00,&00
db &00,&E0,&F0,&10,&00,&00,&00,&00,&00,&00
Salu2,
Arta

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

Mensajepor Artaburu » Mié 28 Jun , 2006 6:24 pm

Esta rutina según mis pruebas es un 30% más rápida que la de Tom&Jerry. Mochilote, ¿puedes hacer tu la misma prueba que hiciste con las otras dos rutinas? Yo he probado este código frente al de T&J sin el cálculo previo que hace para escribir en linea_además. La nueva me da una tasa &11D y la de T&J &174. He dibujado 100 veces un sprite de 10*40 en ambos casos y el número es la diferencia de HL entre la primera y la segunda ejecución de TIME_PLEASE (rutina del firm. que dice el tiempo transcurrido desde el reset del CPC)

Luego he modificado una tontería en la de T&J:

Cambio el siguiente código:
LD A,C
loop_ancho_2
LDI
DEC A
JR NZ,loop_ancho_2

por:
ld b,0 ;1
loop_ancho_2zz
LDIR

y la rutina da una tasa de &115. Con lo cual, por ahora es la más rápida. Tengo que hacer las pruebas usando la pila para ver si se mejora esta tasa.



Importante: Esta rutina requiere indicar un par de parámetros calculados previamente, los veréis en el código. Lo más rápido sería tener una tabla (son función del ancho del sprite) y de este modo se gana bastante velocidad, lo mismo para la de T&J, si se escribe el valor en (ademas_linea+1) sin calcularlo, se gana algo de tiempo (aunque pequeño comparado con el de los bucles)

Código: Seleccionar todo

imp_sp_normalxs ; dibujar en pantalla el sprite
; Entradas bc-> Alto Ancho
; de-> origen
; hl-> destino
; Se alteran hl, bc, de, af

loop_alto_2xs
push bc ;3
ld b,0 ;1

loop_ancho_2xs
ldir ;5
ex de,hl ;1
ld a,h ;1
cp &f7 ;2
jp m,menor ;3

ld bc,&C846 ;3 COMPLEMENTO A 2 DE (&37B0+ANCHO) PRECALCULADO O DE UNA TABLA
ADD hl,bc ;3
ex de,hl ;1
pop BC ;3
djnz loop_alto_2xs ;3
ret

menor
LD BC,&07F6 ;3 (&0800-ANCHO)&07F6 PRECALCULADO O DE UNA TABLA
ADD HL,BC ;3
ex de,hl ;1
pop BC ;3
djnz loop_alto_2xs ;3
ret


Codigo T&J

Código: Seleccionar todo

imp_sprite
loop_alto_2
push bc
ld b,0 ;1
;loop_ancho_2
LDIR
ex de,hl ;voy a operar con la linea de pantalla DE, así que cambio a HL

ademas_linea ;siguiente línea
LD BC,&07f6
ADD HL,BC
jp nc,sig_linea_2 ;si no desborda va a la siguiente linea

ld bc,&c050
add HL,BC

sig_linea_2
ex de,hl ;recupero HL y DE en su sitio
pop BC
djnz loop_alto_2
ret
Salu2,
Arta

Avatar de Usuario
Mochilote
Keeper of The Forum
Keeper of The Forum
Mensajes: 903
Registrado: Sab 08 Oct , 2005 4:26 pm
Contactar:

Mensajepor Mochilote » Jue 29 Jun , 2006 7:12 am

Esta rutina según mis pruebas es un 30% más rápida que la de Tom&Jerry. Mochilote, ¿puedes hacer tu la misma prueba que hiciste con las otras dos rutinas?
No tengo apenas tiempo tio, pero te he dejado en el hilo en el que hablé de medir tiempos las instrucciones para que puedas hacer la medida tu mismo, cuando las tengas comentanos a ver si ha mejorado la cosa,

Este es el hilo http://www.amstrad-esp.com/index.php?na ... opic&t=227

Saludos.

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

Mensajepor Artaburu » Sab 01 Jul , 2006 12:03 pm

Muchas gracias, Mochilote. El lunes me pongo a ello.
al final he depurado un poco más el código y usando algún LDI para el tamaño mínimo se gana velocidad:

Código: Seleccionar todo

imp_sp_normal
; C, ancho-> actualizar (_ancho_sprite_zz+1)
; B, alto
; HL, origen
; DE, destino
ld a,b
loop_alto_2zz

_ancho_sprite_zz
ld bc,&000a
loop_ancho_2zz
LDI
LDIR

ex de,hl ;voy a operar con la linea de pantalla DE, así que cambio a HL
ademas_linea ;siguiente línea
LD BC,&07f6 ;salto linea menos ancho
ADD HL,BC
jp nc,sig_linea_2zz ;si no desborda va a la siguiente linea

ld bc,&c050
add HL,BC

sig_linea_2zz
ex de,hl ;recupero HL y DE en su sitio
dec a
jp nz,loop_alto_2zz
ret
Salu2,
Arta

tecnoxarxa
Me voy lanzando
Me voy lanzando
Mensajes: 52
Registrado: Mar 20 Jun , 2006 4:01 pm

Re: Rutina para dibujar un Sprite en pantalla.

Mensajepor tecnoxarxa » Dom 10 Sep , 2006 11:52 pm

No es por chinchar, pero es muy lenta!!!!!!!!!!!
La siguiente rutina dibuja un sprite en pantalla. Es la rutina que uso yo para dibujar, creo que es bastante rápida pero si alguien tiene alguna mejor, le agradecería que la posteara. O si alguien modifica esta para mejor, pues también.
VIVA GNU/LINUX LA GPL Y EL SOFTWARE LIBRE !!!
QUIERES UN PAQUETE DE OFIMATICA DE CALIDAD ?
http://www.openoffice.org

QUIERES UN SISTEMA ESTABLE, SEGURO Y ALTAMENTE OPTIMIZABLE PARA TU ORDENADOR ?
http://www.gentoo.org

Avatar de Usuario
Artaburu
Trasteador
Trasteador
Mensajes: 8419
Registrado: Vie 07 Oct , 2005 6:18 pm
Ubicación: En tu pantalla

RE: Re: Rutina para dibujar un Sprite en pantalla.

Mensajepor Artaburu » Lun 11 Sep , 2006 8:01 am

No, si ya se que no es por chinchar, pero pon una más rápida, anda.
Salu2,
Arta


¿Quién está conectado?

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


La Comunidad Española
ESP Soft, juegos para tu CPC Foro de Amstrad CPC Todos los juegos para CPC en un CD Web dedicada al Amstrad CPC (utilidades) Información útil para el CPC (talleres) Selección de juegos de Amstrad CPC Mundo CPC Pree Play then any Key CPC Basic