Página 1 de 2
Rutina decompresora exomizer mejorada
Publicado: Dom Ene 01, 2012 8:35 pm
por antoniovillena
Es la misma rutina que hizo Metalbrain, acepta el mismo stream comprimido y los mismos parámetros de entrada. Ahora es más rápida, ya que no se usa IXH para leer bits. También es 6 bytes más pequeña.
Código: Seleccionar todo
ld iy, exo_mapbasebits
ld a, 128
ld b, 52
push de
exo_initbits:
ex af, af'
ld a, b
sub 4
and 15
jr nz, exo_node1
ld de, 1 ;DE=b2
exo_node1:
ld c, $10
ex af, af'
exo_get4bits:
call exo_getbit
rl c
jr nc, exo_get4bits
ld (iy+0), c ;bits[i]=b1
push hl
ld hl, 1
defb $d2 ;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 iy
pop hl
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
call exo_getpair
push bc
pop ix
ld de, 512+48 ;1?
inc b
djnz exo_dontgo
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
ex af, af'
ld a, e
add c
ld c, a
ex af, af'
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 iyl, c
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
ret nz
ld a, (hl)
inc hl
adc a
ret
Re: Rutina decompresora exomizer mejorada
Publicado: Dom Ene 01, 2012 10:36 pm
por climacus
Muchas gracias por el aporte. Por lo menos a mi me resulta muy útil. Una cosilla, me interesaría una modificación para que la descompresión no fuera "lineal", por ejemplo me interesa tener comprimidas distintas pantallas, pero que me ocupan sólo una parte de la misma. Es decir, a la hora de descomprimir no lo hace a cañón, si no que descomprime x bytes seguidos y el siguiente no va seguido sino que hay que descomprimir otros x justo debajo de los anteriores y así durante y líneas. No sé si me he explicado muy bien, pero bueno
Re: Rutina decompresora exomizer mejorada
Publicado: Dom Ene 01, 2012 11:01 pm
por antoniovillena
climacus escribió:Muchas gracias por el aporte. Por lo menos a mi me resulta muy útil. Una cosilla, me interesaría una modificación para que la descompresión no fuera "lineal", por ejemplo me interesa tener comprimidas distintas pantallas, pero que me ocupan sólo una parte de la misma. Es decir, a la hora de descomprimir no lo hace a cañón, si no que descomprime x bytes seguidos y el siguiente no va seguido sino que hay que descomprimir otros x justo debajo de los anteriores y así durante y líneas. No sé si me he explicado muy bien, pero bueno
Creo que no te he entendido. Si te refieres a tener varios bloques comprimidos en un mismo stream, es sencillo. Por ejemplo, tenemos 2 pantallas y queremos mostrarla una detrás de la otra, sería:
C:\> exomizer raw pantalla1.scr -c -o pantalla1.bin
C:\> exoopt pantalla1.bin pantalla1.out
C:\> exomizer raw pantalla2.scr -c -o pantalla2.bin
C:\> exoopt pantalla2.bin pantalla2.out
Código: Seleccionar todo
ld hl, datos
ld de, $4000
call desexomizer
ld de, $4000
call desexomizer
bucinf jr bucinf
datos incbin pantalla1.out
incbin pantalla2.out
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 9:10 am
por climacus
Definitivamente, me he explicado mal. Me refiero a lo siguiente. En la versión 128k de Retroinvaders uso una serie de fondos de pantalla de juego que son unos planetas. Estos gráficos ocupan 20 columnas por 160 filas. Al descomprimirlo, necesito que se siga ese patrón, osea descomprimir 20 bytes a partir de p.e. #4000 pero el byte 21 no va en #4020 sino en #4100 y así sucesivamente hasta llenar el cuadrado donde va el planeta. Si uso la rutina tal cual, en pantalla aparecerán 3200 bytes seguidos desde #4000 en un cuadro de 32 columnas por 100 filas. Espero haberme explicado.
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 10:40 am
por antoniovillena
climacus escribió:Definitivamente, me he explicado mal. Me refiero a lo siguiente. En la versión 128k de Retroinvaders uso una serie de fondos de pantalla de juego que son unos planetas. Estos gráficos ocupan 20 columnas por 160 filas. Al descomprimirlo, necesito que se siga ese patrón, osea descomprimir 20 bytes a partir de p.e. #4000 pero el byte 21 no va en #4020 sino en #4100 y así sucesivamente hasta llenar el cuadrado donde va el planeta. Si uso la rutina tal cual, en pantalla aparecerán 3200 bytes seguidos desde #4000 en un cuadro de 32 columnas por 100 filas. Espero haberme explicado.
Ahora te he entendido perfectamente. Hay 3 formas de hacer lo que dices:
1. Descomprimir un trozo lineal en una zona fuera de memoria de vídeo y después pasar de ese trozo lineal a memoria de vídeo segmentada. Es lo más fácil.
2. Cambiar el código de exomizer para tener en cuenta los trozos a saltar. Es lo más difícil.
3. En un término intermedio puedes hacer lo siguiente. Comprimir la pantalla en un archivo lo más pequeño posible que abarque el recuadro que quieras mostrar. Rellenas los huecos con bytes aleatorios. No uses siempre la mismos bytes aleatorios porque sino corres peligro de que el compresor halle una secuencia que empiece en zona mostrable y acabe en zona no mostrable. Luego haces un programa que recorra el stream comprimido y detecte los huecos, insertando en ellos un código especial que salte N bytes dados, dejándolos sin escribir. Por supuesto tienes que modificar el descompresor para tener en cuenta esto último.
Saludos, espero haberte ayudado, y feliz 2012
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 11:13 am
por climacus
Muchas gracias.
La fácil no está mal pero supongo que la optimización será menor. La intermedia tiene sus riesgos.
Me preguntaba que ya que tú sabes como va la rutina quizá no te fuera muy complicado hacer la modificación "difícil"
. Yo lo hice con la rutina descompresora publicada en el wiki, pero para ésta, la ingeniería inversa no me da para tanto.
Sea como fuere, muchísimas gracias e igualmente, feliz 2012
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 1:13 pm
por antoniovillena
climacus escribió:Muchas gracias.
La fácil no está mal pero supongo que la optimización será menor. La intermedia tiene sus riesgos.
Me preguntaba que ya que tú sabes como va la rutina quizá no te fuera muy complicado hacer la modificación "difícil"
. Yo lo hice con la rutina descompresora publicada en el wiki, pero para ésta, la ingeniería inversa no me da para tanto.
Sea como fuere, muchísimas gracias e igualmente, feliz 2012
La fácil es la que ofrece mayor compresión, sobre todo porque tienes los datos lineales y contiguos. La pega que tiene es que consume más memoria. En la difícil puedes codificar los offsets de tal forma que parezcan contiguos, pero hacerlos lineales sería muy muy difícil. Además tendrías que familiarizarte con el código compresor de exomizer para meterle mano.
En la solución intermedia (la 3) tiene menos optimización (ocuparían más los datos comprimidos) pero no necesita buffer intermedio y sería la adecuada en caso de que no tengas memoria libre.
Te puedo echar una mano con la solución intermedia. Habría que modificar el código de exoopt (no es muy largo) para que inserte un nuevo token que salte N bytes, y si N es constante, más sencillo todavía.
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 3:03 pm
por climacus
Pues se agradecería. Me parece muy interesante, pero tiene esa pequeña pega de que todas las direcciones de destino tengan que ser correlativas
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 02, 2012 7:27 pm
por antoniovillena
climacus escribió:Pues se agradecería. Me parece muy interesante, pero tiene esa pequeña pega de que todas las direcciones de destino tengan que ser correlativas
Te he escrito un privado
Re: Rutina decompresora exomizer mejorada
Publicado: Sab Ene 14, 2012 4:48 pm
por Metalbrain
antoniovillena escribió:Es la misma rutina que hizo Metalbrain, acepta el mismo stream comprimido y los mismos parámetros de entrada. Ahora es más rápida, ya que no se usa IXH para leer bits. También es 6 bytes más pequeña.
Excelente trabajo. Tan solo una pequeña queja de la notación, creo que es más compatible con todos los ensambladores poner "add a,c" en lugar de "add c", y lo mismo con "add a" y "adc a".
Había una optimización extra no incluida en la v3 (aunque si en el I Need Speed) que ganaba un byte (estaba pillada del MSX-O-mizer), pero tus últimos cambios la cancelan.
antoniovillena, en otro hilo escribió:Échale un vistazo y si te parece bien puedes incluirla en tu web.
Tampoco es que tenga una web dedicada, tengo el archivo "
exo_v3.zip" y supongo que podría hacer un "exo_v4.zip" con las optimizaciones. Para esto habría que incluir las optimizaciones en todas las versiones. Ahora mismo, la que has cambiado es la optimizada simple, ¿no? También sería conveniente hacer las versiones hacia atrás de las rutinas normales (no optimizadas) para mandarselas a Magnus Lind y que las incluya en la siguiente
versión oficial.
Re: Rutina decompresora exomizer mejorada
Publicado: Sab Ene 14, 2012 8:12 pm
por antoniovillena
Metalbrain escribió:Excelente trabajo. Tan solo una pequeña queja de la notación, creo que es más compatible con todos los ensambladores poner "add a,c" en lugar de "add c", y lo mismo con "add a" y "adc a".
Sí, yo también soy más partidario de usar "add a,c" en lugar de "add c". Pero tuve algún problemilla con el sjasmplus en alguna instrucción que no recuerdo. Si escribía "instrucción a,c" el ensamblador lo transformaba en "instrucción a" e "instrucción c", y a partir de ahí usé la forma implícita. Puedes cambiarlo sin problemas.
Metalbrain escribió:Había una optimización extra no incluida en la v3 (aunque si en el I Need Speed) que ganaba un byte (estaba pillada del MSX-O-mizer), pero tus últimos cambios la cancelan.
También hay otra posible optimización de 1 byte pero no merece la pena porque introduce muchos ciclos. Para sumar e y c hago algo como:
y se puede hacer (funciona porque uno de los sumandos nunca vale cero):
Metalbrain escribió:Tampoco es que tenga una web dedicada, tengo el archivo "
exo_v3.zip" y supongo que podría hacer un "exo_v4.zip" con las optimizaciones. Para esto habría que incluir las optimizaciones en todas las versiones. Ahora mismo, la que has cambiado es la optimizada simple, ¿no? También sería conveniente hacer las versiones hacia atrás de las rutinas normales (no optimizadas) para mandarselas a Magnus Lind y que las incluya en la siguiente
versión oficial.
Sí, he tocado sólo la simple. Le echo un vistazo a la rutina normal y te la optimizo también. Te respondo por este hilo.
Edito: He visto que hay 4 rutinas: normal/optimizada y simple/no simple. Haré la modificación en las otras tres.
Sobre notación oficial
Publicado: Dom Ene 15, 2012 10:49 am
por antoniovillena
En cuanto a la notación oficial, la correcta es ésta para los opcodes desde 80 hasta BF:
Como veis las reglas son arbitrarias. Por ejemplo en SUB no hace falta escribir el "A," pero en SBC sí. En cambio en las sumas "ADD y ADC" hay que ponerlo en los dos casos.
Por supuesto que para publicar código hay que hacerlo de la forma correcta, si tu ensamblador es muy estricto no podrás hacerlo de otra forma. Sin embargo el que yo uso (SjAsmPlus) se lo traga todo, por ejemplo:
Es incorrecto, pero el ensamblador intuye correctamente lo que el programador quería escribir. En cambio:
Es incorrecto también, aunque aquí el ensamblador mete la pata (es el programador el responsable realmente) y lo traduce en código máquina al equivalente:
Y es que interpreta que es una forma abreviada para indicar que la misma instrucción se repite con distintos operandos, muy útil por ejemplo en PUSH y POP.
Re: Sobre notación oficial
Publicado: Dom Ene 15, 2012 1:38 pm
por Metalbrain
antoniovillena escribió:En cuanto a la notación oficial, la correcta es ésta para los opcodes desde 80 hasta BF:
Como veis las reglas son arbitrarias. Por ejemplo en SUB no hace falta escribir el "A," pero en SBC sí. En cambio en las sumas "ADD y ADC" hay que ponerlo en los dos casos.
No son tan arbitrarias. Hay que especificar el A, en las instrucciones que también operan en 16 bits (normalmente con HL, aunque con el prefijo correspondiente también valen IX o IY (si no me estoy equivocando)). No hay que especificarlo en las que SIEMPRE se usa A. Existe "SBC HL, DE", pero no "SUB HL,DE", por eso es distinta su notación.
PD: Acabo de comprobarlo, resulta que se puede usar IX o IY con ADD, pero no con ADC ni SBC (ya que estas comienzan con el prefijo ED, y al juntar ambos prefijos se cancelan y no se ejecuta nada)...
Re: Sobre notación oficial
Publicado: Dom Ene 15, 2012 2:57 pm
por antoniovillena
Metalbrain escribió:No son tan arbitrarias. Hay que especificar el A, en las instrucciones que también operan en 16 bits (normalmente con HL, aunque con el prefijo correspondiente también valen IX o IY (si no me estoy equivocando)). No hay que especificarlo en las que SIEMPRE se usa A. Existe "SBC HL, DE", pero no "SUB HL,DE", por eso es distinta su notación.
PD: Acabo de comprobarlo, resulta que se puede usar IX o IY con ADD, pero no con ADC ni SBC (ya que estas comienzan con el prefijo ED, y al juntar ambos prefijos se cancelan y no se ejecuta nada)...
Tienes razón. No había caído en la cuenta que era esa la explicación. Aún así me parece confuso usar notación explícita en unos casos e implícita en otros. Yo hubiera elegido notación explícita siempre (implícita siempre no se puede por los casos IX e IY). Y otro ejemplo de cajón es el de JP (HL). Es un salto directo, no indirecto. ¿A quién se le ocurrió poner los paréntesis ahí?
Lo de que ADD acepte IX/IY y no lo acepte ADC/SBC tiene una explicación sencilla. El 8080 no disponía de ADC/SBC en 16 bits, fue un añadido del Z80. Para mantener la compatibilidad extendieron por el opcode ED, que como dices no permite índices IX e IY. Otras excepciones son las instrucciones "EXX" y "EX DE,HL" que tampoco se ven afectadas por los prefijos índice (DD y FD).
Re: Rutina decompresora exomizer mejorada
Publicado: Lun Ene 16, 2012 8:06 pm
por antoniovillena
Hola Metalbrain
Ya están listas las 4 rutinas descompresoras, las tienes aquí:
http://antoniovillena.es/imagenes_foros/deexo_v4.zip Saludos
Edito: Es posible optimizar otro byte más, aunque no lo recomiendo para no perder compatibilidad hacia atrás.
Se trata de cambiar esto:
Código: Seleccionar todo
ld iy, exo_mapbasebits
ld a, (hl)
inc hl
ld b, 52
push de
por esto otro:
invirtiendo también el orden en la rutina getbit:
en el caso de la rutina optimizada, el cambio sería así:
por esto:
Y lo mismo en la rutina leebit. También habría que cambiar exoopt para meter el marker bit en el primer byte (el primer byte contendría 7 bits).