Solucionado - Problemas compresión de mapas al pasar a 128K

For all things Churrera. ¿Estás haciendo un juego? ¿quieres proponer un cambio? ¿tienes alguna duda? ¡Cuéntanoslo!

Moderador: na_th_an

Avatar de Usuario
na_th_an
Mensajes: 26413
Registrado: Vie, 09 Ene 2009, 12:18

Re: Solucionado - Problemas compresión de mapas al pasar a 128K

Mensajepor na_th_an » Mar, 11 Mar 2014, 08:26

La idea es dejar el mapa comprimido en la RAM extra, y modificar el procedimiento de obtener una pantalla para que la pille directamente de ahí.

Se me ocurre que hagas lo siguiente:

1.- El mapa comprimido tal y como sale de las utilidades de Antonio no lo puedes comprimir más, además, como bien él dice, sería mala idea.
2.- Ahora bien, ese .bin lo puedes colocar en la lista de archivos que colocar en RAM extra, utilizando el librarian.
3.- Con esto consigues que el binario del mapa comprimido con las utilidades de Antonio esté en una página de RAM y una dirección fija. Estos valores los puedes sacar directamente de la estructura que se crea en librarian.h: la página será resources [res].ramPage y la dirección de inicio será resources [res].ramOffset.
4.- Cada vez que queramos obtener una nueva pantalla, habría que:
a) desactivar las interrupciones.
b) Cambiar a la página resources [res].ramPage
c) Descomprimir la pantalla.
d) Poner la página 0 de nuevo
e) habilitar las interrupciones.

5.- Efectivamente, habría que quitar
$this->bbcode_second_pass_code('', '.map BINARY "mapa_comprimido.bin" <--- y esta otra')

6.- Pero te conviene tener esto:
$this->bbcode_second_pass_code('', 'extern unsigned int map_address [0];
extern unsigned int map_fin [0];
#asm
._map_address defw 0
._map_fin defw 0
#endasm')

7.- Y cambiar el descompresor para que mire ahí la dirección:
Esto:
$this->bbcode_second_pass_code('', 'ld de, map <----- Esta línea
ld hl, fin-1')

Cambiarlo por esto (atención, la puedo estar cagando):
$this->bbcode_second_pass_code('', 'ld hl, (_map_address)
ex de, hl
ld hl, (_map_fin)')

8.- Y antes de empezar el nivel, hay que establecer el valor de esas dos variables. La primera dice el principio del mapa compilado, y la segunda dice donde acaba. Necesitamos siempre que haya un recurso más después del mapa para poder calcularlo así:
$this->bbcode_second_pass_code('', 'map_address [0] = resources [n].ramOffset;
map_fin [0] = resources [n + 1].ramOffset - 1;')

donde n es el número de recurso donde está el mapa.

9.- Así, antes de llamar al descompresor para obtener la pantalla actual, como dijimos antes, haríamos:

$this->bbcode_second_pass_code('', 'asm_number [0] = resources [n].ramPage
#asm
; Deshabilitar interrupciones
di
; Cambiar de página
ld a, (_asm_number)
ld b, a
call SetRAMBank
#endasm

// AQUÍ LLAMARÍAMOS AL DESCOMPRESOR

#asm
; Poner RAM 0 de nuevo
ld b, 0
call SetRAMBank
; Habilitar interrupciones
ei
#endasm')

Más o menos esta es la idea (es posible que haya metido alguna gamba ;) ). Supongo que Antonio nos podrá ayudar más.
Como diría Rorshach: "Urm..."
Avatar de Usuario
elborra
Mensajes: 209
Registrado: Dom, 12 Ene 2014, 14:37

Re: Solucionado - Problemas compresión de mapas al pasar a 128K

Mensajepor elborra » Mar, 11 Mar 2014, 10:58

Pues en cuanto pueda le hecho un vistazo a todo esto.

Lo de comprimir 2 veces ya se que es contraproducente. Pretendía ir paso a paso y lo primero era conseguir cambiar la rutina de antonio para que "buscara" el mapa en una determinada dirección de memoria; por lo que de momento me daba igual recomprimir el fichero con apack para las pruebas, más adelante me dedicaría a evitar apack, aunque sorprendentemente el fichero recomprimido con apack ocupaba 17 bytes menos o_O. Aún así no es mi intención dejar esa doble compresión.

Gracias una vez más. Os ire comentando los progresos.
Avatar de Usuario
elborra
Mensajes: 209
Registrado: Dom, 12 Ene 2014, 14:37

Re: Solucionado - Problemas compresión de mapas al pasar a 128K

Mensajepor elborra » Mar, 11 Mar 2014, 13:58

Ummm. hay un par de cosas que no acabo de entender muy bien. A ver si antonio se pasa y comenta. Recordar que de ensamblador poquito entiendo...

Por lo que yo entiendo la función de antonio de descomprimir mapa necesitaba 2 cosas:
    - la pantalla que se quiere descomprimir
    - el binario comprimido
aparte dentro de la propia función usa
    - dirección del inicio del mapa comprimido
    - dirección final del mapa comprimido

La descompresión, por lo que entiendo, se hace de atrás hacia alante. Estas dos direcciones antonio las resuelve con ¿etiquetas? ya que el propio mapa binario se incluye dentro de la funcion descomprimir_map. Pego la función completa (que bien vendría un tag spoiler en el foro para no saturar el post :P)
$this->bbcode_second_pass_code('', 'void __FASTCALL__ descomprimir_map ( unsigned char pantalla) {
#asm
ld a, l
and a
ld b, h
ld c, h
ld de, map ; elborra: dirección final? o al revés
ld hl, fin-1 ; elborra: dirección inicio? o al revés
desc1: sbc hl, bc
ex de, hl
ld c, (hl)
ex de, hl
inc de
dec a
jp p, desc1
ld de, DMAP_BUFFER+SCR_W*SCR_H-1
ld b, $80 ; marker bit
desc2: ld a, 256 / 2^DMAP_BITSYMB
desc3: call gbit3 ; load DMAP_BITSYMB bits (literal)
jr nc, desc3
#if (DMAP_BITHALF==1)
#if (DMAP_BITSYMB==1)
rrca
jr nc, desc4
xor a
call gbit3
inc a
#else
rrca ; half bit implementation (ie 48 tiles)
call c, gbit1
#endif
#else
and a
#endif
desc4: ld (de), a ; write literal
desc5: dec e ; test end of file (map is always 150 bytes)
ret z
call gbit3 ; read one bit
rra
jr nc, desc2 ; test if literal or sequence
push de ; if sequence put de in stack
ld a, 1 ; determine number of bits used for length
desc6: call nc, gbit3 ; (Elias gamma coding)
and a
call gbit3
rra
jr nc, desc6 ; check end marker
inc a ; adjust length
ld c, a ; save lenth to c
xor a
ld de, SCR_W
call gbit3 ; get two bits
call gbit3
jr z, desc9 ; 00 = 1
dec a
call gbit3
jr z, descb ; 010 = 15
bit 2, a
jr nz, desc7
#if (SCR_W>15)
call gbit3 ; [011, 100, 101] xx = from 2 to 13
dec a
call gbit3
jr desca
desc7: call gbit3 ; [110, 111] xxxxxx = from 14-15, 17-142
jr nc, desc7
cp SCR_W-14
sbc a, -14
#else
#if (SCR_W==15)
add a, $7c ; [011, 100, 101] xx = from 2 to 13
dec e
desc7: dec e ; [110, 111] xxxxxx = 14 and from 16 to 142
desc8: call gbit3
jr nc, desc8
jr z, descb
add a, e
#else
call gbit3 ; [011, 100, 101] xx = from 2 to 11 and from 13 to 14
call gbit3
cp SCR_W+2
sbc a, 2
jr desc9
desc7: call gbit3 ; [110, 111] xxxxxx = from 15 to 142
jr nc, desc7
add a, 14
#endif
#endif
desc9: inc a
desca: ld e, a
descb: ld a, b ; save b (byte reading) on a
ld b, d ; b= 0 because lddr moves bc bytes
ex (sp), hl ; store source, restore destination
ex de, hl ; HL = destination + offset + 1
add hl, de ; DE = destination
lddr
pop hl ; restore source address (compressed data)
ld b, a ; restore b register
inc e ; prepare test of end of file
jr desc5 ; jump to main loop
#if (DMAP_BITHALF==1 && DMAP_BITSYMB>1)
gbit1: sub $80 - (2^(DMAP_BITSYMB-2))
defb $da ; second part of half bit implementation
#endif
gbit2: ld b, (hl) ; load another group of 8 bits
dec hl
gbit3: rl b ; get next bit
jr z, gbit2 ; no more bits left?
adc a, a ; put bit in a
ret
.map BINARY "mapa_comprimido.bin" ;<-- elborra: etiqueta?
.fin ;<-- el borra: etiqueta?
#endasm
}')Por lo que entiendo con .map BINARY "mapa_comprimido.bin" lo que sucede es que "por donde vaya el compilador" crea una referencia (etiqueta?) llamada map y "copia" el binario del mapa_comprimido. A continuación crea otra referencia llamada fin que identificará el siguiente byte después del mapa binario. Así cuando mete en el registro DE la dirección de map y en HL la dirección de fin-1 (es decir el último byte del mapa) ya lo tiene todo listo para la descompresión.

$this->bbcode_second_pass_quote('na_th_an', '4').- Cada vez que queramos obtener una nueva pantalla, habría que:
a) desactivar las interrupciones.
b) Cambiar a la página resources [res].ramPage
c) Descomprimir la pantalla.
d) Poner la página 0 de nuevo
e) habilitar las interrupciones.
Yo lo que pretendo es que el mapa en memoria extra se copie y mantenga en memoria principal (en una estructura reservada) hasta que se cambie de nivel. No necesito (ni debería) estar copiando el mapa continuamente a cada pantalla.

Por un momento olvidaros que el mapa está comprimido previamente con tmxcompress y lo único que quiero hacer es copiar un recurso que esta en memoria extra a memoria principal donde yo quiera, lo cual, sino me equivoco es precisamente lo que hace get_resource, que a fin de cuentas es usar unpack_RAMn con los datos de librarian.h. Así si mi recurso es el 27 y quiero descomprimirlo a partir del byte 32000 del binario principal sólo tendría que hacer:$this->bbcode_second_pass_code('', 'get_resource(27, 32000)')Está claro que yo no quiero descomprimirlo en 32000 sino en esa estructura que habiamos reservado anteriormente. Así si en alguna parte del código hemos escrito por ejemplo$this->bbcode_second_pass_code('', 'unsigned char mimapa[2000]')al poner$this->bbcode_second_pass_code('', 'get_resource(27, (unsigned int) (mimapa))')tendría teóricamente el mapa donde quiero.

Así lo único que quedaría es como referenciar en la utilidad de antonio las direcciones map y fin-1 con las nuevas direcciones que hagan referencia al inicio de mimapa[] y su final (que esto si se haría más o menos como me explicas) Yo es que me confundo en asm con los
.algo
._algo
(algo)
(_algo)
y las correspondencias en c.

Sorry por el tocho post