Programación #2: Memoria dinámica en splib2

Hoy toca comentario. Tengo uno muy jugoso (amigos, ha aparecido una beta de Tomb Raider 2 para PSX ¡¡y yo la tengo!!), pero como no sé si tendré tiempo de elaborarlo, pongo esto que es más rápido y lo considero muy interesante para los que están usando z88dk+splib2 para hacer sus juegos.

9547418uz71.gif

Se trata de un tema que yo tuve que currarme un poco a cabezazos, entre la parca documentación y las explicaciones del propio Albrecht, y que resulta realmente indispensable para poder sacar el máximo partido a esta biblioteca: comprender cómo gestiona la memoria. 48K son pocos, y hay que aprovechar hasta el último byte. Comprendiendo qué estructuras maneja splib2 en memoria tendremos más herramientas para saber dónde colocar cosas para apretujar todo al máximo y que no tengamos problemas de ningún tipo. En próximos capítulos, explicaremos cómo usar la paginación para poder acceder a los 128K, pero para ello es muy importante tener claros los conceptos que vamos a explicar en este breve articulín.

La biblioteca de juegos splib2 coloca muchos tiestos en la parte superior de la memoria. Estos tiestos son estructuras y buffers necesarios para su funcionamiento. Como seguramente sabréis, splib2 proporciona una solución software que funciona de forma muy parecida a los modos gráficos orientados a tiles y sprites (por hardware) de las consolas de 8 y 16 bits y algunos ordenadores como el MSX. Tenemos una rejilla de carácteres, cada uno contiene uno de 256 tiles, y los sprites se mueven sobre ellos. Un movimiento de sprites causa una invalidación de los tiles que afecta (sobre los que se mueve), y en la próxima actualización de la pantalla (activada de forma asíncrona, llamando manualmente a sp_UpdateAll) se redibujarán en VRAM esas casillas. Esto elimina todo posible parpadeo y minimiza (aunque no elimina) el tearing.

Estas estructuras ocupan, como hemos dicho, unos 4Kb y medio en la parte superior de la memoria. En concreto, esto es lo que crea la splib2 cuando llamamos a su función de inicialización:

61440 - 61696 IM 2 Interrupt Vector Table (optional)
61697 - 61936 Free (240 bytes)
61937 - 61948 Generic Interrupt Service Routine @ 0xf1f1 (optional)
61949 - 61951 Free (3 bytes)
61952 - 65535 Horizontal Rotation Tables (optional)

Todo programa en C necesita una pila, donde hará espacio para las variables locales de las funciones, donde almacenará los valores de sus parámetros y donde irá guardando las direcciones de retorno de las mismas. Si no vamos a usar paginación, y por cuestión de orden, la pila la vamos a colocar justo por debajo de estas estructuras de memoria, o sea, justo bajo 61140. Esto es lo que hace la siguiente directiva del compilador, que colocaremos en todos nuestros programas:

#pragma output STACKPTR=61440

La pila crecerá hacia abajo y ocupará un máximo de 512 bytes. ¿Qué significa esto? Pues que tenemos para nosotros hasta la dirección 61440-512 = 60928.

Esto sólo es cierto si no vamos a usar sprites, pero los sprites llevan asociadas unas estructuras en memoria donde se almacenan datos como su posición, su gráfico y su máscara, etcétera. Los sprites necesitan uno de estos bloques (que ocupan 14 bytes cada uno) por cada trozo de 8×8 píxels que lo componga. Por ejemplo, un sprite de 16×16 píxels necesitará nueve bloques, ya que emplea nueve trozos de 8×8 píxels.

Es muy importante, por tanto, calcular exactamente el número de bloques que vamos a necesitar, sobre todo cuando tenemos que apretar la memoria. En splib2, tenemos que indicar una dirección de inicio que indicará a partir de dónde tomará memoria la biblioteca para crear estos bloques. Si estamos cortos de memoria, lo suyo es reservar ese espacio para que ocupe los bytes justos y colocarlo justo por debajo de la pila. Esto es lo que se consigue con esta linea:

sp_AddMemory(0, 60, 14, MEM_FREE);

Esta linea lo que hace es reservar 60 bloques de 14 bytes a partir de la dirección MEM_FREE. Lo que suele liar a los programadores que se acercan por primera vez a splib2 es dónde colocar ese MEM_FREE. Pues es muy sencillo, lo mejor es hacer que MEM_FREE sea 60928num_bloques*14. Así estamos colocando el área de memoria para los sprites justo debajo de la pila, maximizando el área de RAM contigua que necesitamos para meter todo nuestro código y nuestros datos.

Por tanto, es importante que:

  1. Sepamos cuántos bloques necesitamos como máximo. Lo bueno a la hora de calcular esto es que si ponemos menos de la cuenta lo veremos enseguida: o se nos cuelga el juego o nos salen gráficos divertidos en los sprites. Tampoco es tan complicado, si vamos a tener por ejemplo 4 sprites de 16×16 píxels (como en Infinity) necesitaremos 4 * 9 = 36 bloques. El número de bloques lo vemos fácil: son el número de bloques de 8×8 de gráficos ó de máscara que necesitamos para un sprite. Si un sprite ocupa efectivamente 4 bloques (16×16 píxels) sabemos que necesitamos una fila y una columna más por el tema de las rotaciones, por lo que realmente ocupará 9 bloques. También lo podemos ver fácilmente por el número de celdas de carácter que pueda ocupar el sprite no estando alineado a coordenada de carácter (sus dos coordenadas x, y no son ninguna múltiplo de 8).
  2. Coloquemos estos bloques (con sp_AddMemory) lo más arriba posible (en nuestro caso, justo debajo de la mínima posición de memoria que la pila ocupará) .

Dicho esto, me despido. Intentaré tener listo el review que prometía para hoy. Ya sé que yo soy muy friki de TR y que a la mayoría de la gente le dará igual esto, pero para mí, encontrar una beta temprana de TR2, es todo un hallazgo🙂

4 Responses to Programación #2: Memoria dinámica en splib2

  1. sromero dice:

    Interesantísimo artículo, a los usuarios de Z88DK y SPLIB2 sólo nos queda esto, hacer un poco de espeleología en las fuentes y la documentación para desenmarañar un poco algunas de las cosas más “sucias” de SPLIB.

    Hay bastante cosas poco (o mal, o nada) explicadas y por suerte entre unos y otros se va sacando esta información tan útil.

    Gracias por este articulillo y por compartirlo🙂

  2. anjuel dice:

    Mira, no he entendido na, pero como estás tu para solucionarme la papeleta…😀

    ¿te acuerdas que uwol lo iba a programar yo? Pues eso… pon un joseluis en tu vida!😆

  3. na_th_an dice:

    @Santi: Gracias por tu comentario, me alegro que encuentres esto útil. A ver si entre todos conseguimos que haya más desarrolladores🙂
    @Anju: Joajoajoa – eres un mandangas. El próximo lo vas a programar tú, o si no Wanfri y yo nos iremos a mañolandia a cogerte de las orejas😀

  4. anjuel dice:

    Pues ya me camelaré al Ben!😆

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: