Kana DS

Learning Japanese writing on the Nintendo DS

22 January, 2007

Rudolph Steady Go!

Este fin de semana terminé el juego para Nintendo DS que comenté en una entrada anterior. Es un pequeño homenaje a Osu! Tatakae! Ouendan! del estudio iNiS, y lo he presentado a una competición de juegos navideños para NDS organizada por DrunkenCoders.com.

Para los neófitos: Un juego musical en el que hay que pulsar ciertos elementos visuales al ritmo de la canción de fondo.

¿Para qué me ha servido esto? ¿No hubiese sido mejor pasar a trabajar en Kana DS directamente?

Hacer un pequeño juego con LibNDS y DevkitPRO me ha servido para:
  • Familiarizarme con el entorno de desarrollo
  • Aprender a programar la Nintendo DS
  • Construir funciones y clases básicas que luego reutilizaré
  • Detectar las limitaciones más serias de las librerías
  • Solventar varios problemas técnicos que hubiesen resultado frustrantes más adelante en el desarrollo.
  • Tener un juego *finalizado* más a mis espaldas. Por muy pequeño que sea, siempre se aprende algo con cada proyecto terminado.

A mí personalmente me suele asustar enfrentarme a un proyecto grande sin conocer demasiado las herramientas con las que voy a trabajar antes. Sé que siempre te acabas topando con limitaciones o "known-bugs" que no conocías, llegando a callejones sin salida. En este caso apenas tenía elección, ya que debía elegir entre LibNDS y PALib, y ésta última dependía de varias herramientas para Windows -y yo trabajo en Mac OS X.

Y ya que estamos con el tema de librerías... aquí va un briconsejo:

Cuando os encontréis en la situación de elegir una API/librería para realizar un proyecto os aconsejo que tengais sólo en cuenta las características actuales que ofrecen. Centráos en que lo que ofrecen ahora, y no en lo que sus responsables piensan añadir durante los próximos meses. Mi experiencia me dice que las nuevas 'features' tardan en llegar, y a veces, nunca lo hacen.

Voy a ser malo y señalar directamente con el dedo un ejemplo:

Hace ya tres años que se anunció el motor para juegos Truevision3D 6.5. Aun no está disponible. Sólo se puede acceder a él mediante una "Beta" de pago. ¿Pagar por una librería en desarrollo e inestable? No gracias. Yo quiero terminar mis juegos (comerciales o no), no pelearme con el motor o esperar a que se corrija la característica "x".

Volviendo al tema.. podeis echar un vistazo a Rudolph Steady Go! en su página.

Rudolph Steady Go!

A mediados de Febrero comenzaré la fase de desarrollo de Kana DS.

10 January, 2007

Arquitectura de Nintendo DS (II)

En el anterior artículo hablé sobre la organización de la memoria, los procesadores ARM9, ARM7 y algunas de sus peculiaridades. Esta vez voy a comentar algunas cosas sobre el DMA.

DMA
El DMA, o 'acceso directo a memoria' permite la lectura y escritura de la memoria principal sin la intervención de la CPU, esto es, con una circuitería dedicada. Las ventajas de usar DMA para transferencias de memoria son varias, pero a nosotros nos interesa especialmente por 1) su rapided y 2) eficiencia. Las operaciones DMA pueden ser en modo síncrono(la CPU permanece bloqueada hasta que la operación termina) o asíncrono. Éste último modo es el utilizado por los SO modernos para permitir p.ej. que podais estar reproduciendo un vídeo y a la vez grabando un CD sin saturar la CPU.

En un PC corriendo Windows o Linux es el propio SO el que gestiona la DMA, siendo totalmente transparente al programador de aplicaciones. Sin embargo, la Nintendo DS no tiene un sistema operativo en sí, sino una colección de rutinas BIOS y un puñado de registros que activan ciertas funciones. Debemos pues gestionar el DMA manualmente :-/

Por suerte Libnds nos provee de varias funciones para hacer uso del hardware DMA de la consola, y así poder hacer transferencias síncronas o asíncronas de manera eficiente. Si miramos en "include/nds/dma.h" podemos ver p.ej. el código de la función dmaCopy:

static inline void dmaCopy(const void * source, void * dest, uint32 size) {
DMA_SRC(3) = (uint32)source;
DMA_DEST(3) = (uint32)dest;
DMA_CR(3) = DMA_COPY_HALFWORDS | (size>>1);
while(DMA_CR(3) & DMA_BUSY);
}

En total tenemos siete (7) funciones para controlar el DMA, siendo sus nombres autoexplicativos:
  • dmaCopyWords
  • dmaCopyHalfWords
  • dmaCopy
  • dmaCopyWordsAsynch
  • dmaCopyHalfWordsAsynch
  • dmaCopyAsynch
  • dmaBusy
Si usamos las funciones -Asynch desde el ARM9 o ARM7, podremos seguir utilizando la CPU mientras la transferencia se realiza en un 'segundo plano'. Esto puede ser útil para aplicaciones que hacen decompresión de audio MP3/OGG o vídeo en tiempo real y que usan un sistema de doble buffer. Otro ejemplo práctico: si tuviésemos que hacer un MMORPG, usaríamos transferencias asíncronas para ir cargando el terreno y objetos segun avanzásemos por el mundo virtual, de manera que el juego no se viese nunca interrumpido por estas cargas.

En el próximo artículo hablaré sobre los modos de vídeo soportados por la consola y sus respectivos planos 2D/3D, poniendo como ejemplo el juego Rudolph Steady Go!

PD: Al igual que el resto de participantes del planet, yo tambien estoy hasta el cuello de prácticas y exámenes :P