Rutina decompresora exomizer mejorada

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Dom Ene 01, 2012 8:35 pm

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
Imagen

Avatar de Usuario
climacus
Sabreman
Mensajes: 411
Registrado: Mar Ago 25, 2009 1:46 pm

Re: Rutina decompresora exomizer mejorada

Mensaje por climacus » Dom Ene 01, 2012 10:36 pm

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
Todos mis juegos en formato físico
http://www.matranet.net/boutique/zx/zx.php

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Dom Ene 01, 2012 11:01 pm

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
Imagen

Avatar de Usuario
climacus
Sabreman
Mensajes: 411
Registrado: Mar Ago 25, 2009 1:46 pm

Re: Rutina decompresora exomizer mejorada

Mensaje por climacus » Lun Ene 02, 2012 9:10 am

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.
Todos mis juegos en formato físico
http://www.matranet.net/boutique/zx/zx.php

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Lun Ene 02, 2012 10:40 am

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
Imagen

Avatar de Usuario
climacus
Sabreman
Mensajes: 411
Registrado: Mar Ago 25, 2009 1:46 pm

Re: Rutina decompresora exomizer mejorada

Mensaje por climacus » Lun Ene 02, 2012 11:13 am

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" :wink: . 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
Todos mis juegos en formato físico
http://www.matranet.net/boutique/zx/zx.php

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Lun Ene 02, 2012 1:13 pm

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" :wink: . 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.
Imagen

Avatar de Usuario
climacus
Sabreman
Mensajes: 411
Registrado: Mar Ago 25, 2009 1:46 pm

Re: Rutina decompresora exomizer mejorada

Mensaje por climacus » Lun Ene 02, 2012 3:03 pm

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
Todos mis juegos en formato físico
http://www.matranet.net/boutique/zx/zx.php

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Lun Ene 02, 2012 7:27 pm

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
Imagen

Avatar de Usuario
Metalbrain
Freddy Hardest
Mensajes: 592
Registrado: Lun May 07, 2007 8:17 am
Ubicación: Sevilla
Contactar:

Re: Rutina decompresora exomizer mejorada

Mensaje por Metalbrain » Sab Ene 14, 2012 4:48 pm

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.
SevenuP se escribe con u minúscula y P mayúscula.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Sab Ene 14, 2012 8:12 pm

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:

Código: Seleccionar todo

  ex af,af
  ld a, e
  add a, c
  ld e, a
  ex af,af


y se puede hacer (funciona porque uno de los sumandos nunca vale cero):

Código: Seleccionar todo

1 inc e
  dec c
  jr nz, 1


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.
Imagen

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Sobre notación oficial

Mensaje por antoniovillena » Dom Ene 15, 2012 10:49 am

En cuanto a la notación oficial, la correcta es ésta para los opcodes desde 80 hasta BF:

Código: Seleccionar todo

  ADD A,B
  ADC A,B
  SUB B
  SBC A,B
  AND B
  XOR B
  OR B
  CP B


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:

Código: Seleccionar todo

  ADD B


Es incorrecto, pero el ensamblador intuye correctamente lo que el programador quería escribir. En cambio:

Código: Seleccionar todo

  XOR A,B


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:

Código: Seleccionar todo

  XOR A
  XOR B


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.

Código: Seleccionar todo

  PUSH HL,DE
  LD HL,1
  LD DE,1
  ADD HL,DE
  POP DE,HL
Imagen

Avatar de Usuario
Metalbrain
Freddy Hardest
Mensajes: 592
Registrado: Lun May 07, 2007 8:17 am
Ubicación: Sevilla
Contactar:

Re: Sobre notación oficial

Mensaje por Metalbrain » Dom Ene 15, 2012 1:38 pm

antoniovillena escribió:En cuanto a la notación oficial, la correcta es ésta para los opcodes desde 80 hasta BF:

Código: Seleccionar todo

  ADD A,B
  ADC A,B
  SUB B
  SBC A,B
  AND B
  XOR B
  OR B
  CP B


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)...
SevenuP se escribe con u minúscula y P mayúscula.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Sobre notación oficial

Mensaje por antoniovillena » Dom Ene 15, 2012 2:57 pm

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).
Imagen

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Rutina decompresora exomizer mejorada

Mensaje por antoniovillena » Lun Ene 16, 2012 8:06 pm

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:

Código: Seleccionar todo

      ld    iy, exo_mapbasebits
      ld    a, (hl)
      ld    b, 52
      push  de


invirtiendo también el orden en la rutina getbit:

Código: Seleccionar todo

exo_getbit:
      srl   a
      ret   nz
      inc   hl
      ld    a, (hl)
      rra
      ret


en el caso de la rutina optimizada, el cambio sería así:

Código: Seleccionar todo

      ld    iy, exo_mapbasebits
      ld    a, 128
      ld    b, 52


por esto:

Código: Seleccionar todo

      ld    iy, exo_mapbasebits
      ld    a, (hl)
      ld    b, 52


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).
Imagen

Responder

¿Quién está conectado?

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