Exomizer 2, rutinas actualizadas
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
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
- Metalbrain
- Forero habitual
- Mensajes: 151
- Registrado: Mar 30 Oct , 2007 1:45 pm
- Ubicación: Sevilla
Exomizer 2, rutinas actualizadas
Veo que no hay un hilo dedicado a Exomizer, así que aprovechando que hay novedades, pues lo creo ahora:
Señoras y señores, con ustedes el método de compresión que vence con claridad tanto al de aPLib como al de pucrunch: exomizer 2.
https://bitbucket.org/magli143/exomizer/wiki/Home
Como no había descompresor para Z80, lo porté yo, y además hice un optimizador que coge la salida del exomizer, le quita 2 bits inútiles y le reordena los bits para que se puedan leer un poco más rápido con el Z80. Hace escasos días Antonio Villena ha optimizado los descompresores de forma que ahora son más rápidos, y de paso les ha recortado unos cuantos bytes.
Los tamaños de los descompresores varían entre 163-187 bytes. La rutina descompresora necesita una tabla de 156 bytes, que puede ser desechada tras la descompresión, así que si la ponemos en un buffer no debería suponer ningún gasto extra. De registros alternativos solo utiliza el AF'.
http://www.speccy.org/metalbrain/exo_v4.zip
En la carpeta /normal están las versiones que funcionan directamente con la salida que genera exomizer al hacer:
exomizer raw -o salida entrada
En /optimized están las que funcionan con la salida optimizada, la cual se genera haciendo:
exomizer raw -o temporal entrada
exoopt temporal salida
exoopt es el optimizador, el ejecutable Windows está presente en optimized/bin y su código fuente para otros sistemas en optimized/src
Las rutinas _simple necesitan que la tabla esté alineada a un múltiplo de 256, y no soportan cadenas de literales, que suele ser raro que aparezcan y además se pueden desactivar con la opción -c de exomizer.
Señoras y señores, con ustedes el método de compresión que vence con claridad tanto al de aPLib como al de pucrunch: exomizer 2.
https://bitbucket.org/magli143/exomizer/wiki/Home
Como no había descompresor para Z80, lo porté yo, y además hice un optimizador que coge la salida del exomizer, le quita 2 bits inútiles y le reordena los bits para que se puedan leer un poco más rápido con el Z80. Hace escasos días Antonio Villena ha optimizado los descompresores de forma que ahora son más rápidos, y de paso les ha recortado unos cuantos bytes.
Los tamaños de los descompresores varían entre 163-187 bytes. La rutina descompresora necesita una tabla de 156 bytes, que puede ser desechada tras la descompresión, así que si la ponemos en un buffer no debería suponer ningún gasto extra. De registros alternativos solo utiliza el AF'.
http://www.speccy.org/metalbrain/exo_v4.zip
En la carpeta /normal están las versiones que funcionan directamente con la salida que genera exomizer al hacer:
exomizer raw -o salida entrada
En /optimized están las que funcionan con la salida optimizada, la cual se genera haciendo:
exomizer raw -o temporal entrada
exoopt temporal salida
exoopt es el optimizador, el ejecutable Windows está presente en optimized/bin y su código fuente para otros sistemas en optimized/src
Las rutinas _simple necesitan que la tabla esté alineada a un múltiplo de 256, y no soportan cadenas de literales, que suele ser raro que aparezcan y además se pueden desactivar con la opción -c de exomizer.
Re: Exomizer 2, rutinas actualizadas
Yo me lo guardo y, a partir de ahora, será mi compresor de cabecera para CPC. ¡Muchas gracias por compartirlo!
Salu2,
Arta
Arta
Re: Exomizer 2, rutinas actualizadas
Estupendo. Si no me falla la memoria, yo venía usando la versión 2. Voy a comprobarlo y descargo esta otra.
Saludos,
gg.
gg.
- Metalbrain
- Forero habitual
- Mensajes: 151
- Registrado: Mar 30 Oct , 2007 1:45 pm
- Ubicación: Sevilla
Re: Exomizer 2, rutinas actualizadas
Ops!
Metí la pata al volver a meter los comentarios en el código nuevo, incluyendo en la rutina normal (no simple) una línea de la versión antigua que jode toda la descompresión. Ya está corregido, os lo podeis volver a bajar en el mismo enlace:
http://www.speccy.org/metalbrain/exo_v4.zip
Metí la pata al volver a meter los comentarios en el código nuevo, incluyendo en la rutina normal (no simple) una línea de la versión antigua que jode toda la descompresión. Ya está corregido, os lo podeis volver a bajar en el mismo enlace:
http://www.speccy.org/metalbrain/exo_v4.zip
Re: Exomizer 2, rutinas actualizadas
Hola!
Tenía ganas de estudiar este proyecto y por fin he tenido tiempo. La verdad es que estoy alucinando por partida doble: por la inventiva de Magnus y por las rutinas creadas por Metalbrain y optimizaciones posteriores de Antonio.
El caso es que, a pesar de la dificultad, he logrado encontrar una pequeña mejora de 1 byte en la rutina descompresora. Estoy usando la óptima simple pero imagino que se podrá aplicar a las otras (no lo he mirado).
Consiste en cortar la primera línea de la subrutina exo_getpair (ld iyl, c) y pegarla justo antes del primer call exo_getpair , y por otro lado sustituir el código:por este otro:
Ahora estoy tratando de optimizar el código:
con la idea de eliminar las otras dos instrucciones ex af, af' (ya se que se pueden sustituir por push af y pop af) y lograr un ahorro adicional de dos bytes correspondientes al di y ei necesarios al llamar a la subrutina y evitar asi mensajes como el de la cpcwiki:
Un saludo
Tenía ganas de estudiar este proyecto y por fin he tenido tiempo. La verdad es que estoy alucinando por partida doble: por la inventiva de Magnus y por las rutinas creadas por Metalbrain y optimizaciones posteriores de Antonio.
El caso es que, a pesar de la dificultad, he logrado encontrar una pequeña mejora de 1 byte en la rutina descompresora. Estoy usando la óptima simple pero imagino que se podrá aplicar a las otras (no lo he mirado).
Consiste en cortar la primera línea de la subrutina exo_getpair (ld iyl, c) y pegarla justo antes del primer call exo_getpair , y por otro lado sustituir el código:
Código: Seleccionar todo
ex af, af'
ld a, e
add a, c
ld c, a
ex af, af'
Código: Seleccionar todo
ld iyl,e
add iy,bc
Código: Seleccionar todo
ex af, af'
ld a, b
sub 4
and 15
jr nz, exo_node1
ld de, 1 ;DE=b2
exo_node1: ld c, 16
ex af, af'
Exomizer can sometimes fail to decompress files correctly for no apparent reason, causing the CPC to crash. Unfortunately there is no known way to overcome this problem, other than to use a different compressor.
Un saludo
Re: Exomizer 2, rutinas actualizadas
Bueno, me ha costado más de la cuenta pero por fin he dado con ello:
He aprovechado el registro c, que al tener el valor 16 me viene genial para usarlo como inicializador del contador ixl, y de esta manera logro que ocupe el mismo número de bytes que la rutina original (pero gana velocidad, aunque no sea importante en este caso). Lo verdaderamente importante es el ahorro "externo" de 2 bytes (DI-EI) al no tener que depender ya del registro A' de modo que ya es compatible 100% con el Amstrad CPC sin tener que añadir código antes de la llamada
Un saludo.
Código: Seleccionar todo
ld ixl, 1
exo_initbits: ld c, 16
dec ixl
jr nz, exo_get4bits
ld de, 1
ld ixl,c
Un saludo.
Re: Exomizer 2, rutinas actualizadas
Great news! Porque así, efectivamente no desactivaríamos las interrupciones y podríamos reproducir música durante la descompresión. Me lo apunto para cambiarlo en las librerías para C, con tu permiso, claro
Salu2,
Arta
Arta
Re: Exomizer 2, rutinas actualizadas
Hombreeeeee, Arta! tú no tienes que pedir permiso para nada, faltaría más!Great news! Porque así, efectivamente no desactivaríamos las interrupciones y podríamos reproducir música durante la descompresión. Me lo apunto para cambiarlo en las librerías para C, con tu permiso, claro
¿Cuál es la rutina que has metido en tu librería? ¿la deexo_simple.asm de la carpeta optimized? si no es ésta asegúrate de que las modificaciones son compatibles...
Un saludo.
Re: Exomizer 2, rutinas actualizadas
Otra optimización, aunque sea un adorno más que otra cosa:
La instrucción inc iy se puede sustituir por inc iyl para tardar 104 ciclos menos en generar el buffer (en el cpc puede que no haya ahorro alguno)
Y por otro lado una modificación de posición:
La instrucción ld de, 512+48 es mejor que esté situada justo después del djnz. De esta manera se le gana 10 ciclos cada vez que la longitud sea superior a 255 (si, un caso raro pero posible)
Un saludo.
Código: Seleccionar todo
ld (iy+52), e
ld (iy+104), d ;base[i]=b2
add hl, de
ex de, hl
inc iy
pop hl
djnz exo_initbits
Y por otro lado una modificación de posición:
Código: Seleccionar todo
ld de, 512+48 ;1?
inc b
djnz exo_dontgo
dec c
Un saludo.
Re: Exomizer 2, rutinas actualizadas
Y oooooooootra importante optimización, esta vez por parte del maestro Antonio Villena:
por este otro:
Con esto ganamos 1 byte más, todo un logro teniendo en cuenta lo optimizado que ya estaba
Un saludo.
Código: Seleccionar todo
ld ixl, 1
exo_initbits: dec ixl
ld c, 16
jr NZ, exo_get4bits
ld de, 1 ;DE=b2
ld ixl,c
Código: Seleccionar todo
cp a
defb &C2
exo_initbits: dec ixl
ld c, 16
jr NZ, exo_get4bits
ld de, 1 ;DE=b2
ld ixl,c
Un saludo.
Re: Exomizer 2, rutinas actualizadas
Es increíble que todavía se pueda seguir optimizando. Casi te sabrás de memoria el código
Salu2,
Arta
Arta
-
- Forero habitual
- Mensajes: 115
- Registrado: Mar 26 Abr , 2011 9:25 pm
Re: Exomizer 2, rutinas actualizadas
Todo el mérito es de Urusergi. A parte de que ya no empleamos el registro AF' y es unos cuantos ciclos más rápida, la rutina ha pasado de 163 bytes a 160 (la optimizada simple, las otras también reducen 3 bytes cada una). Me dejé atrás otro byte que era evidente, el código final sería este:
Si me estás leyendo, Metalbrain, actualiza tus rutinas y dale un aviso a Magnus. Que no se te olvide poner a Urusergi en los créditos.
Código: Seleccionar todo
ld iy, exo_mapbasebits
ld a, 128
ld b, 52
push de
cp a
exo_initbits:
ld c, 16
jr nz, exo_get4bits
ld de, 1
ld ixl, c
exo_get4bits:
call exo_getbit
rl c
jr nc, exo_get4bits
ld (iy+0), c ;bits[i]=b1
push hl
ld hl, 1
defb 210 ;3 bytes nop (JP NC)
exo_setbit:
add hl, hl
dec c
jr nz, exo_setbit
exo_one:
ld (iy+52), e
ld (iy+104), d ;base[i]=b2
add hl, de
ex de, hl
inc iyl
pop hl
dec ixl
djnz exo_initbits
pop de
exo_literalcopy:
ldi
exo_mainloop:
call exo_getbit ;literal?
jr c, exo_literalcopy
ld c, 255
exo_getindex:
inc c
call exo_getbit
jr nc, exo_getindex
bit 4, c
ret nz
push de
ld iyl, c
call exo_getpair
push bc
pop ix
inc b
djnz exo_dontgo
ld de, 512+48 ;1?
dec c
jr z, exo_goforit
dec c ;2?
exo_dontgo:
ld de, 1024+32
jr z, exo_goforit
ld e, 16
exo_goforit:
call exo_getbits
ld iyl, e
add iy, bc
call exo_getpair ;bc=offset
pop de ;de=destination
push hl
ld h, d
ld l, e
sbc hl, bc ;hl=origin
push ix
pop bc ;bc=lenght
ldir
pop hl ;Keep HL, DE is updated
jr exo_mainloop ;Next!
exo_getpair:
ld d, (iy+0)
call exo_getbits
push hl
ld l, (iy+52)
ld h, (iy+104)
add hl, bc ;Always clear C flag
ld b, h
ld c, l
pop hl
ret
exo_getbits:
ld bc, 0 ;get D bits in BC
exo_gettingbits:
dec d
ret m
call exo_getbit
rl c
rl b
jr exo_gettingbits
exo_getbit:
add a, a
ret nz
ld a, (hl)
inc hl
adc a, a
ret
-
- Forero habitual
- Mensajes: 115
- Registrado: Mar 26 Abr , 2011 9:25 pm
Re: Exomizer 2, rutinas actualizadas
Se añaden 2 mejoras. Por un lado Urusergi ha conseguido mejorar casi un 20% la velocidad de la rutina con un pequeño cambio que sólo implica 2 bytes más de código.
por esto otro:
La rutina simple optimizada ahora ocupa 161 bytes (159 bytes si no te parece bien la versión rápida) y sería ésta:
Por otro lado he conseguido optimizar 1 byte, cambiando ésto:Se trata de sustituir todos los call exo_getbit por:
add a,a
call z,exo_getbit
Y en la subrutina, como te imaginarás, hay que eliminar el add a,a y el ret nz
Código: Seleccionar todo
pop de ;de=destination
push hl
ld h, d
ld l, e
Código: Seleccionar todo
ex (sp), hl
ld d, h
ld e, l
Código: Seleccionar todo
ld iy, exo_mapbasebits
ld a, 128
ld b, 52
push de
cp a
exo_initbits:
ld c, 16
jr nz, exo_get4bits
ld de, 1
ld ixl, c
exo_get4bits:
add a, a
call z, exo_getbit
rl c
jr nc, exo_get4bits
ld (iy+0), c ;bits[i]=b1
push hl
ld hl, 1
defb 210 ;3 bytes nop (JP NC)
exo_setbit:
add hl, hl
dec c
jr nz, exo_setbit
exo_one:
ld (iy+52), e
ld (iy+104), d ;base[i]=b2
add hl, de
ex de, hl
inc iyl
pop hl
dec ixl
djnz exo_initbits
pop de
exo_literalcopy:
ldi
exo_mainloop:
add a, a
call z, exo_getbit ;literal?
jr c, exo_literalcopy
ld c, 255
exo_getindex:
inc c
add a, a
call z, exo_getbit
jr nc, exo_getindex
bit 4, c
ret nz
push de
ld iyl, c
call exo_getpair
push bc
pop ix
inc b
djnz exo_dontgo
ld de, 512+48 ;1?
dec c
jr z, exo_goforit
dec c ;2?
exo_dontgo:
ld de, 1024+32
jr z, exo_goforit
ld e, 16
exo_goforit:
call exo_getbits
ld iyl, e
add iy, bc
call exo_getpair ;bc=offset
ex (sp), hl
ld d, h
ld e, l
sbc hl, bc ;hl=origin
push ix
pop bc ;bc=lenght
ldir
pop hl ;Keep HL, DE is updated
jr exo_mainloop ;Next!
exo_getpair:
ld d, (iy+0)
call exo_getbits
push hl
ld l, (iy+52)
ld h, (iy+104)
add hl, bc ;Always clear C flag
ld b, h
ld c, l
pop hl
ret
exo_getbits:
ld bc, 0 ;get D bits in BC
exo_gettingbits:
dec d
ret m
add a, a
call z, exo_getbit
rl c
rl b
jr exo_gettingbits
exo_getbit:
ld a, (hl)
inc hl
adc a, a
ret
Re: Exomizer 2, rutinas actualizadas
Se añaden 2 mejoras. Por un lado Urusergi ha conseguido mejorar casi un 20% la velocidad de la rutina con un pequeño cambio que sólo implica 2 bytes más de código.
Salu2,
Arta
Arta
¿Quién está conectado?
Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro
La Comunidad Española |