Título: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 12:34:52 pm Esto viene de la idea que surgió en este hilo (http://karoshi.auic.es/index.php?topic=2226.msg27184#msg27184)
La cuestión es que es mas rápido escribir una serie de datos iguales usando OUT(n),A en vez de series de OUTI's sin tener en cuenta limitaciones de escritura en VRAM. Esto es un hecho, ahora bien, el manejo de los datos comprimidos o codificados es lo que hará que este sea una método viable o al menos si hay un límite aceptable desde el cual es preferible usar datos RLE. EL programa que adjunto incluye un bitmap en sc3 que se comprime internamente de esta manera tan poco óptima: En cada par de bytes: Byte1: Dato literal Byte2: nº de repeticiones hasta 128 De esta manera el gráfico se comprime un 55% aproximadamente. Queda en un 45% del tamaño original. y lo vuelco a la VRAM de esta manera tan poco elegante y por supuesto tampoco optimizada: Código: RLEDATA_OUT: LD HL,IMAGE_RLE LD A,[HL] INC HL PUSH HL LD L,[HL] LD H,$43 JP [HL] .ORG $4300 REPT 128 OUT [$98],A ENDR POP HL INC HL LD A,[HL] AND A RET Z INC HL PUSH HL LD L,[HL] LD H,$43 JP [HL] frente a: Código: RAWDATA: El resultado se puede ver pulsando la barra espaciadora o dejándola pulsada. Gana RAWDATA!CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S ¿que os parece optimizar el código de manera que sea "rentable" su uso? Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 12:42:39 pm Por cierto, sin tocar nada del código RLEDATA_OUT e incluyendo dos NOP's por cada OUTI, la ventaja es para el primero. Ademas hay que tener en cuenta el menor espacio ocupado. Son dos ventajas! ;D
El dato $00 indica fin del archivo. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 01:46:46 pm Bueno, algo mejor cambiando el orden de los datos por cada par de bytes. (nº rep, dato literal):
Código: RLEDATA_OUT: LD DE,IMAGE_RLE LD A,[DE] LD L,A INC DE LD A,[DE] INC DE LD H,$43 JP [HL] .ORG $4300 REPT 128 OUT [$98],A ENDR LD A,[DE] CP 129 RET Z LD L,A INC DE LD A,[DE] INC DE JP [HL] Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 21 de Enero de 2012, 01:51:16 pm La segunda ROM parece que no funciona bien... Muestra gráficos extraños en vez del avatar de un conocido coder :D
por otro lado, ¿que hace "JP [HL]"? he visto que también esta con los registros de indice. y "REPT 128", ¿que es? ??? No acabo de entender lo que hace RLEDATA_OUT. Puedes poner algún comentario? Justamente estoy interesado en una rutina descompresora RLE a VRAM y sobre todo aprender :D Estoy haciendo una app(win) para tratar gráficos de SC2/4 (creo que puse un comentario en estos foros) y quiero añadirle la opción de comprimir en RLE. saludos! Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 02:00:15 pm Ese @aorante!: No tengas en cuenta la Segunda ROM.
- JP (HL) salta a la dirección indicada por el registro HL. Es un poco confuso al ir entre paréntesis. - REPT X/ ENDR ... Eduardo te vacastigar: " REPITELO CIEN VECES" ;D. Repite X veces lo que hay entre las dos sentencias. - Las rutinas de compresión y descompresión son muy rudimentarias, solo para pruebas. Pero si te interesa te la pasaré una vez esté optimizada. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 21 de Enero de 2012, 02:22:02 pm Ese @aorante!: No tengas en cuenta la Segunda ROM. Ok. Ya he visto la tercera! :)Citar - JP (HL) salta a la dirección indicada por el registro HL. Es un poco confuso al ir entre paréntesis. entiendo, pero al "leer" el codigo es un lio! :o Se me han suicidado 128 neuronas!!! ;D Citar - REPT X/ ENDR ... Eduardo te vacastigar: " REPITELO CIEN VECES" ;D. Repite X veces lo que hay entre las dos sentencias. es que pico rutinas en el SDCC (combino C y ASM), y no tiene tantas facilities como el asMSX... :P Citar - Las rutinas de compresión y descompresión son muy rudimentarias, solo para pruebas. Pero si te interesa te la pasaré una vez esté optimizada. Muchas gracias... :D Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 05:16:17 pm Un poquito mas rápido usando la pila:
Código: RLEDATA_OUT: LD [STACK],SP LD SP,IMAGE_RLE POP BC LD A,C LD L,B LD H,$43 JP [HL] .ORG $4300 REPT 128 OUT [$98],A ENDR POP BC LD A,C LD L,B AND A JP Z,RLEDATA_END JP [HL] RLEDATA_END: LD SP,[STACK] RET Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Mortimer en 21 de Enero de 2012, 07:15:50 pm Muy interesante, veo que mi intuición iba por buen camino :D
Y ya para rizar el rizo, si queremos también la máxima compresión y hay espacio en la ram, quizás se pueda aplicar antes alguna compresión basada en Lempel-Ziv, porque los datos RLE a su vez suelen ser bastantes comprimibles con ese sistema. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 07:45:33 pm Muy interesante, veo que mi intuición iba por buen camino :D Y ya para rizar el rizo, si queremos también la máxima compresión y hay espacio en la ram, quizás se pueda aplicar antes alguna compresión basada en Lempel-Ziv, porque los datos RLE a su vez suelen ser bastantes comprimibles con ese sistema. Si que es muy interesante! :D. Con la última optimización usando la pila, por lo que he visto una compresión del 50% aprox. compensa en espacio y en velocidad. Depende de como estén ordenados los datos puede ser incluso mas rápido que OUTI a secas y por supuesto mas rápido si es OUTI+NOP. La compresión es muy sencilla para permitir la velocidad en la descompresión a VRAM pero si hay grandes areas continuas puede ser bastante efectivo. Os dejo el código por si quieres trastear o aorante quiere mirarlo para su uso: * Hay que añadir un bitmap en screen 3 (&H0600 bytes) Código: .page 1 .ROM .start BOOT .DB "RLE2VDP" VRAMFRM EQU $0000 DATA_PORT EQU $0098 ;PUEDE VARIARSE REG_PORT EQU $0099 ;PUEDE VARIARSE IMAGE_RLE EQU $8800 STACK EQU $87F0 INTVECTAB EQU $FC00 ;TABLA -$101 HOOK EQU $FDFD .INCLUDE "ASM/SYSVAR.ASM" .INCLUDE "ASM/KEYBOARD.ASM" BOOT: EI CALL $0075 DI ;COMPRESION RLE 127 LD HL,IMAGE1 LD DE,IMAGE_RLE COMPRLEBC1: LD BC,$0000 LD A,[HL] AND A JR Z,COMPRLEND COMPRLEBC0: INC HL ;CPI PARA OPTIMIZAR LD C,[HL] BIT 7,B JR Z,COMPRLEJP3 LD B,0 DEC HL JR COMPRLEJP2 COMPRLEJP3: INC B CP C JR Z,COMPRLEBC0 COMPRLEJP2: LD [DE],A ;GUARDA DATO INC DE LD A,B RLCA ;DUPLICA NEG ;NEGATIVO LD [DE],A ;GUARDA Nº REPETICIONES EN NEGATIVO INC DE JR COMPRLEBC1 COMPRLEND: LD [DE],A LD HL,RAWDATA ;CONFIGURA GANCHO INTERRUPCIONES IM2 LD HL,RLEDATA LD [HOOK+1],HL CALL INSTALLISR I_LOOP: JR I_LOOP INSTALLISR: DI LD HL,INTVECTAB LD E,L LD D,H INC DE LD [HL],HOOK>>8 LD BC,256 LDIR LD A,$C3 LD [HOOK],A LD A,INTVECTAB>>8 LD I,A IM 2 EI RET ;________________________________________________ RLEDATA: IN A,[REG_PORT] LD A,44 LD B,7 CALL W_REGVDP LD HL,VRAMFRM CALL INIVPOKE CALL RLEDATA_OUT LD A,11 LD B,7 CALL W_REGVDP ;BARRA ESPACIADORA ;OUT: FLAG C LD C,8 CALL K_GET_LINE RRA JR NC,NO_SPACE1 LD HL,RAWDATA LD [HOOK+1],HL LD A,$C3 LD [HOOK],A NO_SPACE1: EI RETI RLEDATA_OUT: LD [STACK],SP LD SP,IMAGE_RLE POP BC LD A,C LD L,B LD H,$44 JP [HL] .ORG $4400 REPT 128 OUT [DATA_PORT],A ENDR POP BC LD L,B LD A,C AND A JP Z,RLEDATA_END JP [HL] RLEDATA_END: LD SP,[STACK] RET RAWDATA: IN A,[REG_PORT] LD A,44 LD B,7 CALL W_REGVDP LD HL,VRAMFRM CALL INIVPOKE LD HL,IMAGE1 LD C,DATA_PORT CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S CALL REPOUTI256 ;256 OTIR'S LD A,11 LD B,7 CALL W_REGVDP ;BARRA ESPACIADORA ;OUT: FLAG C LD C,8 CALL K_GET_LINE RRA JR NC,NO_SPACE2 LD HL,RLEDATA LD [HOOK+1],HL LD A,$C3 LD [HOOK],A NO_SPACE2: EI RETI REPOUTI256: REPT 256 OUTI ENDR RET W_REGVDP: OUT (REG_PORT),A LD A,B OR 10000000B OUT (REG_PORT),A RET INIVPOKE: LD A,L OUT [REG_PORT],A LD A,H OR 01000000B OUT [REG_PORT],A RET IMAGE1: .INCBIN "IMAGE1.SC3" IMAGE1_OEF: DB 0 Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Dioniso en 21 de Enero de 2012, 08:49:11 pm Yo me quedo con el vuelco "raw".
Si se volcaran 128 veces el valor 1 y 128 veces el valor 0 pues sería un buen método el que planteáis, pero si cada vez que no se repite el valor hay que hacer esto: Código: POP HL INC HL LD A,[HL] AND A RET Z INC HL PUSH HL LD L,[HL] LD H,$43 JP [HL] pues olvidaos ... Tendría que ser una imagen de lo más simple para que medio funcionara. La diferencia entre OUT y OUTI es de 5 t-states, nada más. POP HL ; 10 t-states INC HL ; 6 t-states LD A,[HL] ; 7 t-states AND A ; 4 t-states RET Z ; 11 t-states INC HL ; 6 t-states PUSH HL ; 11 t-states LD L,[HL] ; 7 t-states LD H,$43 ; 7 t-states JP [HL] ; 4 t-states -Esto hace un total de 73 t-states. -Le añadimos un OUT, es decir, 11 t-states. -Son 11 instrucciones por lo que se le habría que añadir 11 t-states más en modo IM1. -Total, 95 s-tates para un valor cada vez que no se repite. RLE = 95 t-states, RAW = 17 (mediante OUTI). Supongo que la imagen debería tener una compresión de casi el 80% para que el método RLE a VRAM fuera mejor que el volcado RAW. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Dioniso en 21 de Enero de 2012, 08:56:23 pm He visto que también lo haríais en modo IM2. Bueno, en ese caso se recortan la rutinas:
RLE = 84 frente a RAW = 16 Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Dioniso en 21 de Enero de 2012, 09:06:36 pm Por qué no me habré leído el post entero ...
Acabo de ver que habéis optimizado la rutina. Ahora sería: POP BC ; 10 t-states LD L,B ; 4 t-states LD A,C ; 4 t-states AND A ; 4 t-states JP Z,RLEDATA_END ; 10 t-states JP [HL] ; 4 t-states más el OUT Lo que en modo IM2 resulta en lo siguiente: RLE = 47, RAW = 16 cuando no se repite el valor RLE = 11, RAW = 16 cuando se repite el valor edito: corregida la gamba del modo IM2 más abajo Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Mortimer en 21 de Enero de 2012, 09:11:16 pm He visto que también lo haríais en modo IM2. Bueno, en ese caso se recortan la rutinas: RLE = 84 frente a RAW = 16 Creo que estás mezclando el modo de interrupción (IM0, IM1 ó IM2) con la velocidad de ejecución debido al ciclo adicional del estado M1 del Z80. Independientemente del modo de interrupción, los retardos introducidos son (Según http://map.grauw.nl/resources/z80instr.php (http://map.grauw.nl/resources/z80instr.php)) Citar Every instruction has 1 additional M1 wait state Instructions starting with a CB, DD, ED, FD, DDCB or DDFD opcode have two additional M1 wait states Por lo que la direrencia entre OUT (n),A y OUTI son 6 ciclos. En cuanto al problema de la sobrecarga si hay pocos datos repetidos, y si queremos complicarnos mucho la vida, podríamos utilizar un bit del byte que indica las repeticiones, para indicar si lo siguiente que viene es un bloque que no merece la pena ser comprimido y volcar con OUTI, o es RLE. En desensamblado añadiría algo de sobrecarga, pero la rutina de compresión ya tendría que ser algo más inteligente para que valorara cuando indicar que lo siguiente es una cadena literal Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Dioniso en 21 de Enero de 2012, 09:23:03 pm Creo que estás mezclando el modo de interrupción (IM0, IM1 ó IM2) con la velocidad de ejecución debido al ciclo adicional del estado M1 del Z80. Ha sido una paja mental mía. Sí ... La edad. :angel: RLE = 54, RAW = 18 cuando no se repite el valor RLE = 12, RAW = 18 cuando se repite el valor Vaya gamba con el IM2 ... Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Iggy Rock en 21 de Enero de 2012, 09:27:27 pm @Dioniso , gracias por echarle un tiento al código. :D
Si, la última optimización mejora bastante los tiempos y permite un mayor rango de archivos candidatos a RLE. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 21 de Enero de 2012, 10:13:19 pm Si, la última optimización mejora bastante los tiempos y permite un mayor rango de archivos candidatos a RLE. supongo que no digo nada nuevo para los que ya lleváis tiempo peleando en estas cosas, pero quizás pueda servir los que no conocen mucho el tema. En el caso de una pantalla de screen2/4, si se usa para volcar un tileset (patrones+colores), o un gráfico, si te curras el orden de los tiles por colores y que estos estén arreglados (el fondo y la tinta seguidos), una compresión RLE solo en los datos de los colores se puede ganar mucho, mientras que utilizarlo en los patrones puede que incluso ocupe más. Los conversores no suelen darte los datos ordenados, y hay que pasar unas horas arreglandolo con la tecnica "handmade" ;D ahí queda eso! :D Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Dioniso en 21 de Enero de 2012, 11:05:36 pm Sí, efectivamente. O cosas como tener el cero y el uno como color negro, sin necesitar transparencias de ningún tipo. Algo como:
$06,$06,$16,$06,$06,$16,$06,$06,$16,$06,$06,$16,$06,$06,$16,$06,$06,$16,$06,$06,$16 serían 28 bytes en RLE y 21 en RAW. Mientras que las TILES se podrían optimizar a: $16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16 y serían 2 bytes en RLE :laugh: Pero quizá no merezca la pena meterse en tanta "optimización" si hablamos de cargar los tres bancos de patrones. La diferencia de velocidad sería despreciable. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 24 de Enero de 2012, 08:56:38 pm una duda...
como funciona el RLE? es correcto lo siguiente? 1er byte - número repeticiones (de 1 a 255). Si es 0 es fin. 2do byte - valor Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Mortimer en 24 de Enero de 2012, 10:12:36 pm Sí, sería correcto, no hay forma 'oficial' de hacerlo, así que verás varias implementaciones con la misma idea básica, y quizás algunos posibles refinamientos como por ejemplo para intentar optimizar el tamaño de los casos sin repetición.
Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: j4mk3 en 24 de Enero de 2012, 11:44:14 pm ...se puede ganar mucho, mientras que utilizarlo en los patrones puede que incluso ocupe más. Los conversores no suelen darte los datos ordenados, y hay que pasar unas horas arreglandolo con la tecnica "handmade" ;D Y lo que costó en el Hans...la de dios y horas con el nMSXTiles. verdad Aorante? :) ...moviendo, girando..cambiando colores. La experiencia fue muy util para que Pentacour refinara la aplicación y pusiera nuevas opciones destinadas a este tipo de faenitas. En Hans Adventure, el volcado a VRAM es directo desde RLE, pero creo q no optimizado. En el gráfico de portada tube que poner 3 parones para entrar en la interrupción y que no parara la música. Así que a groso modo...tardo 3 frames en hacerlo entero. Pero ya digo que no está nada optimizado ni con buffer en Ram ni nada. Interesante Hilo y aquí mi experiencia. ;) Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: theNestruo en 25 de Enero de 2012, 12:25:19 am es correcto lo siguiente? Una variante típica es que algún bit del primer byte te permita alternar entre "vienen n repeticiones" o "vienen n bytes sin repetición" para los fragmentos en los que viene una buena mezcolaina de bytes.1er byte - número repeticiones (de 1 a 255). Si es 0 es fin. 2do byte - valor Ejemplo chorra (considero el primer bit 0 y 1 significando repeticiones y fragmento exacto): Código: 84 10 04 14 6F 3D 41 82 9F 00 se traduciría a:Código: 10 10 10 10 14 6F 3D 41 9F 9F Luego tienes variantes de todo tipo, según las necesidades específicas que tengas... Por ejemplo, puedes hacer repeticiones de bloques ("repetir 7 veces la siguiente secuencia de 4 bytes"). Otro ejemplo: en mi época de GP32, para pintar sprites por software, lo que hice fue un pseudo-RLE en el que si el primer bit era 0 indicaba hueco a saltar y 1 indicaba número de bytes a copiar (es decir, comprimía las repeticiones de bytes transparentes). Ahorraba ir haciendo un if por cada byte y los fragmentos a copiar se volcaban con un memcpy(). Implementar RLE es como cocinar una tortilla: lo básico es el huevo batido; luego cada uno le añade lo que más le guste ;D Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 25 de Enero de 2012, 10:13:55 am Gracias theNestruo!
estoy incluyendo en la tool que estoy programando la compresión de los datos con RLE y la opción primera me parece interesante. Estoy pensando en poner las dos formas: la sencilla que preguntaba (qe va muy bien para los colores) y la que tu dices. Saludos! Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 25 de Enero de 2012, 08:51:48 pm he programado esta rutina para descomprimir RLE a VRAM (1ºB:1-255=repeticion,0=fin ; 2ºB:valor)
Funciona, pero tengo la duda con lo de la escritura a VRAM en los TMS99xx. He puesto 2 "nops", pero no se si sobran o faltan. ¿podéis echarme una mano en este tema? y ¿se puede optimizar? Código: ; descompresor RLE a VRAM unRLE2VR: ; direccion de VRAM (DE) in A,($99) di ld A,E out ($99),A ld A,D add A,$40 out ($99),A ei getCMD: ;mira byte de codigo, 1-255 repeticion ld A,[HL] cp 0 ;si es 0 es fin ret Z ;sale de la funcion inc HL ld B,A ;numero de repeticiones ld A,[HL] ;recoge el valor RLE_bucle: out ($98),A nop nop djnz RLE_bucle inc HL jr getCMD Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: Mortimer en 25 de Enero de 2012, 09:18:58 pm Pues si consideramos que 28 son los mínimos ciclos seguros, te sobraría un NOP en el bucle, porque ya quedaría
Código: RLE_bucle: out ($98),A ; 12 ciclos nop ; 5 djnz RLE_bucle ; 14 si se repite Total 31 Y apurando un pelín más Código: RLE_bucle: OUT ($98),A ; 12 ciclos DEC B ; 5 JP NZ,RLE_bucle ; 11 Total 28! Y en cuanto al resto, cambia CP 0 por AND A y ahorrarás 3 ciclos, y también el JR final, puedes cambiarlo por un JP y ahorras 2 ciclos más por iteración. Título: Re: ¿Es posible que sea mas rápido escribir RLE que RAW en VRAM? Publicado por: aorante en 27 de Enero de 2012, 12:55:27 pm gracias por la ayuda Mortimer!
|