(NDS) Cómo hacer un cartucho de Nintendo DS para que tu homebrew parezca un juego oficial

Flashcard sin etiqueta

Hoy vamos a crear un flashcard de NDS para que parezca un juego original, y así cambiar un poco el tema y dejar los coches a un lado por un momento.

Últimamente estoy haciendo experimentos con mi vieja consola Nintendo DS Lite, la cual por aburrimiento buscando entre mis cosas encontré y empecé a desarrollar un pequeño juego random y a aprender un poco de programación C++ (cosa que aún no he conseguido). También me hacía ilusión hacer una colección de la generación de consolas “DS”: NDS, DSi, 3Ds y New 3Ds (las versiones 2Ds y New 2Ds no las incluyo porque básicamente son 3Ds para pobres sin efecto 3D). Así que conseguí realizar la colección y tengo todas las mencionadas anteriormente gracias a Wallapop, en el momento oportuno y a unos precios realmente buenos, ya que están subiendo como la espuma, especialmente las 3Ds y New 3Ds.

Más adelante os contaré mi batalla con las 3Ds y cómo programar para ellas con el motor gráfico Unity3D y el SDK oficial de Nintendo (compatible para 3Ds y New 3Ds). Hay muy poca información al respecto y quiero compartir mis hitos con vosotros.

Volviendo a la cuestión principal, siempre he querido hacer un juego para NDS y que quedase todo como si fuese un juego sacado por la propia Nintendo, que cuando metas el cartucho y ejecutes el juego, directamente aparezca el juego, y no pasar por el típico menú de las flashcard que todos conocemos. 

Por ejemplo:

Así pues, empecé a buscar una flashcard que fuese de las más baratas de Aliexpress, que no tuviera ningún color especial y ninguna pegatina. Por suerte esta vez, nuestros amigos chinos cumplieron las expectativas, y encontré esto:

Enlace de compra

En aquel momento dudé en qué hacer, pero al final por ese precio decidí realizar el pedido de una tarjeta para probar.

Una vez llegó la tarjeta y abrí el paquete, me encuentro que no viene ninguna caja ni nada más salvo una pequeña bolsa de plástico transparente con una pegatina, la cual contiene un código de barras y pone en chino “R4 flashcard”, en cuyo interior se encontraba la tarjeta tal y como quería, sin nada.

Tal cual llegó, metí la tarjeta en la 3Ds y, para mi ingrata sorpresa, no la reconocía (mi mayor temor). “¡Ya me han timado!” -Pensé. “Bueno, como he pedido también otra R4 con pegatina para probar, pruebo la otra y a ver si al menos la otra funciona.” -Me dije a mi mismo.

Me dispuse a probar la otra tarjeta que me llegó a la par de esta y, nuevamente, tampoco funcionaba.

“¡Vaya timazo!” -Dije en voz alta. “Normal, por el precio que tenían que esperabas… ¡Oh! ¿Y si es cosa del firmware de la flashcard? Leí que Nintendo se puso las pilas a raíz del pirateo masivo de la Nintendo DS, y a partir de la DSi, la consola hacía comprobaciones más severas, y había actualizaciones del firmware de la consola para que las flashcard dejasen de funcionar, al igual que con la 3Ds (que es la que estoy usando). Además, tengo la 3Ds en la última versión del firmware. Voy a probar con la DSi aunque también tenga la última versión de firmware, ya que la última versión para esta consola salió allá por 2012 o así. En la 3Ds salió más recientemente. Imagino que esta tarjeta al menos irá en esa consola… Si va, es posible que tenga que actualizar el firmware de la flashcard como hice en su día en otra tarjetas R4, ya que el anuncio indicaba que era compatible con todas las consolas de la serie DS” -Me autoconvencía para no perder la calma.

“¡Mierda! ¿En serio tampoco va aquí? Pues probaré en la DS” -Yo perdiendo la paciencia…

“¡Estoy flipando! ¡Ni en la DS original tampoco! ¡Menuda mierda! ¡Qué pérdida de tiempo y dinero para nada!” -Dije enfurecido tras probar ambas tarjetas en todas mis consolas y ver que no eran detectadas.

“¡Espera!” -Dijo una voz en mi cabeza mientras una idea se encendía como una bombilla. “¿Y si es porque estas tarjetas funcionan de manera distintas a las otras que tengo? Son una tarjetas chinas de las baratas, posiblemente sean clones. ¿Podría ser que necesitan que les inserte la tarjeta micro SD para que activen el micro interruptor en el slot y así activar la flashcard? ¡Menos mal que pedí 3 tarjetas micro SD! -Yo en mi cabeza.

¡Pues efectivamente! Estas tarjetas chinas necesitan la micro SD puesta en el slot para que las consolas detecten las flashcards. Ambas funcionan si tienen la tarjeta SD puesta. Al probar en todas las consolas, sólo hubo un fallo: La DSi no reconocía la tarjeta sin pegatina, mientras que la R4 con pegatina era reconocida desde la DS a la New 3Ds, la (llamémosla “tarjeta black”) no era reconocida en la DSi, pero en la DS original y en ambas 3Ds sí, con lo cual me resultaba bastante extraño, pero ya me había pasado antes con otra tarjeta R4 que tenía antígua. Este fallo era algo que empezaba a mosquearme.

NOTA: Al final di con la solución con el problema. Consiste en, por algún motivo, no hace buen contacto la flashcard en la lectora de  mi DSi. Quizás sea por algún golpe en la consola o algo, ya que es de 2º mano y parece estar manipulada con anterioridad y le faltan algunos tornillos).

Ya que tanto el anuncio como en la pegatina dentro del sobre ponía R4 para la “tarjeta black”, empecé a probar una lista bastante larga de firmwares para R4, de los cuales ninguno funcionaba. Mientras probaba dicha tarjeta, también probé firmwares para la otra R4 que me llegó, que finalmente encontré su firmware y ahí quedó la cosa.

Desgraciadamente, me tiré como 3h buscando firmwares R4 para la “tarjeta black” y ninguno funcionaba. Algunos decían “Couldn’t find _ds_menu.dat” y otros símplemente se quedaban en “Loading…”. Me fui a la cama ya que era tarde y ya mañana seguiría mi búsqueda, aunque antes de eso, escribí en Reddit a ver si alguien sabía algo acerca de dicha flashcard (a día de hoy sigo esperando respuesta).

Al día siguiente continuó mi búsqueda y no encontraba nada. Probé con el famoso “Twilight Menu++” que funciona prácticamente con todas las flashcards, y también con el YSmenu, y nada de nada.

En un momento de desesperación, me vino a la cabeza buscar: “NDS flashcard with no sticker” (Tarjeta para NDS sin pegatina para los no angloparlantes).

¡En el clavo! Habían más personas con el mismo problema. Lo único es que el color de las placas de  sus flashcards sin etiqueta eran verdes o azules, o rojos con algún texto. En mi caso, mi tarjeta es así:

Sin texto detrás, y de color rojo. No coincidía con ninguna tarjeta de las fotos. Seguí leyendo un post en GBATemp donde estaban otras personas intentando identificar la tarjeta, hasta que uno puso el siguiente enlace:

https://flashcard-archive.ds-homebrew.com/Ace3DS+_R4iLS/

Alternativamente, puedes encontrar el firmware aquí:

Descargar firmware (enlace alternativo)

Me metí dentro de dicho enlace, y me encontré con un firmware para ACE3DS+ R4iLS en un .Zip, un README.TXT y una foto. Abrí la foto para ver si en la foto aparecía la tarjeta y así compararla, y me encontré con esto:

Viendo tremenda violación al Copyright de Nintendo y la calidad de la foto, y la falta de originalidad y edición de la portada, supe de primeras que era una tremenda tarjeta china. ¡Justo lo que buscaba!

Me puse a comparar los bordes de la tarjeta y la forma y parecía coincidir con mi tarjeta. Y aunque se llame “ACE3Ds Plus”, en el enlace y en el README.TXT mencionan algo de R4. No perdemos nada por probar, ¿no?

Pues meto el famoso archivo _ds_menu.dat en la raíz de la micro SD para ver si al menos aparecía algo más que “Loading…” o “Couldn’t find _ds_menu.dat”, sin dar mucha importancia a los archivos de firmware ya presentes del Twilight Menu++. Enciendo mi DS, ejecuto la flashcard y…

“¡Ostias! ¡Se está iniciando el Twilight Menu++!” -Exclamé sorprendido.

Resulta que al tener los archivos del Twilight Menu++ junto al archivo “_ds_menu.dat”, hace que inicie la flashcard. Si quitamos los archivos del Twilight Menu++, la flashcard se iniciará con un menú tipo R4 Wood.

“¡Ya funciona! ¡Al fin! ¡Menuda gente son estos chinos que no saben ni lo que venden! Dicen que es una R4 y esto es una ACE3DS+” -Dije para mí mismo.

Ahora sólo faltaba hacer que el juego se iniciara automáticamente sin pasar por ningún menú. La cosa es que para hacerlo, necesito un “_ds_menu.dat” que en lugar de ejecutar un menú, ejecute mi aplicación directamente, o al menos un menú que pueda programar yo mismo y le diga automáticamente que inicie el archivo que yo quiero.

“¿Y si uso el hb-menu? ¡Es perfecto para lo que quiero! Puedo modificar el código fuente del archivo “_ds_menu.dat” y añadir funciones que se adapten a lo que quiero. Ojalá y sea compatible con esta flashcard.” -Hablando mentalmente conmigo mismo.

Me descargué una copia del código fuente del HB-menu de GitHub, ya tenía Devkitpro NDS instalado en su última versión, sólo tenía que meter la carpeta del hb-menu para empezar a modificar y compilar mi propio “_ds_menu.dat”.

Enlace del Github para descargar hb-menu: https://github.com/devkitPro/nds-hb-menu (versión utilizada para el tutorial: 0.9)

Enlace de descarga del instalador de Devkitpro: https://github.com/devkitPro/installer/releases (versión utilizada para el tutorial: 3.0.3)

Descargad el código fuente de hb-menu:

Tenéis que descomprimir el archivo zip en “C:\devkitpro”. Tiene que quedar algo así como directorio:

“C:\devkitpro\nds-hb-menu\”. Dentro de la carpeta nds-hb-menu deberá estar el código fuente y las carpetas relacionadas, no otra subcarpeta. De no ser así, corregid y ordenad los directorios vosotros mismos de manera manual.

Dentro del directorio “C:\devkitpro\nds-hb-menu\BootStrap\arm9\source\”, encontrarás el archivo “bootstrap.c”, ese archivo lo puedes modificar con la finalidad de eliminar mensajes de cargando o error, cosa que no aparece nunca en un juego oficial. Indico las líneas las cuales puedes eliminar:

Seguidamente vamos a “C:\devkitpro\nds-hb-menu\source\” y abrimos el archivo “main.cpp”:

No os voy a liar explicado que líneas modificar. Borrad todo el código del archivo y pegad lo que os dejo escrito a continuación:

				
					/*-----------------------------------------------------------------
 Copyright (C) 2005 - 2013
	Michael "Chishm" Chisholm
	Dave "WinterMute" Murphy
	Claudio "sverx"

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

------------------------------------------------------------------*/
#include <nds.h>
#include <stdio.h>
#include <fat.h>
#include <sys/stat.h>
#include <limits.h>

#include <string.h>
#include <unistd.h>

#include "args.h"
#include "file_browse.h"
#include "hbmenu_banner.h"
#include "iconTitle.h"
#include "nds_loader_arm9.h"


using namespace std;

//---------------------------------------------------------------------------------
void stop (void) {
//---------------------------------------------------------------------------------
	while (1) {
		swiWaitForVBlank();
	}
}

//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------

	// overwrite reboot stub identifier
	// so tapping power on DSi returns to DSi menu
	extern u64 *fake_heap_end;
	*fake_heap_end = 0;

	iconTitleInit();

	// Subscreen as a console
	videoSetModeSub(MODE_0_2D);
	vramSetBankH(VRAM_H_SUB_BG);
	consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);

	if (!fatInitDefault()) {
		iprintf ("fatinitDefault failed!\n");
		stop();
	}

	keysSetRepeat(25,5);

	vector<string> extensionList = argsGetExtensionList();

	//chdir("/nds");
	chdir("/");

	while(1) {

		string filename = "game.nds"; //browseForFile(extensionList);

		// Construct a command line
		vector<string> argarray;
			// Make a copy of argarray using C strings, for the sake of runNdsFile
			vector<const char*> c_args;
			for (const auto& arg: argarray) {
				c_args.push_back(arg.c_str());
			}

			// Try to run the NDS file with the given arguments
			int err = runNdsFile(c_args[0], c_args.size(), &c_args[0]);
			//iprintf("Start failed. Error %i\n", err);
				argarray.clear();
				
		if (!argsFillArray(filename, argarray)) {
			iprintf("Invalid NDS or arg file selected\n");
		} else {
			iprintf("Running %s with %d parameters\n", argarray[0].c_str(), argarray.size());

			// Make a copy of argarray using C strings, for the sake of runNdsFile
			vector<const char*> c_args;
			for (const auto& arg: argarray) {
				c_args.push_back(arg.c_str());
			}

			// Try to run the NDS file with the given arguments
			int err = runNdsFile(c_args[0], c_args.size(), &c_args[0]);
			iprintf("Start failed. Error %i\n", err);
		}

		argarray.clear();

		while (1) {
			swiWaitForVBlank();
			scanKeys();
			if (!(keysHeld() & KEY_A)) break;
		}

	}

	return 0;
}
				
			

A tener en cuenta:

-El archivo de vuestro juego se debe de llamar “game.nds“, y se debe dejar en el directorio raíz de la micro SD junto a “_ds_menu.dat” y “BOOT.nds” (este último se creará a continuación).

Una vez modificado el código, lo guardáis y cerráis el archivo.

Y por último, debéis entrar en: “C:\devkitpro\nds-hb-menu\gfx\” y sustituid el archivo “hbmenu_banner.png” por esta foto:

Sí, es una foto en negro.

Si por algún casual diese problemas el compilador a la hora de convertir la imagen, cread una imagen en Photoshop con el tamaño 256×192 y le ponéis un fondo en negro. Dirigíos al menú “Imagen–>Modo–>Indexado” y si os pregunta le hacéis clic en “Sí”, “Aceptar”, o similares.

Guardad la foto en formato *.png y con el nombre “hbmenu_banner.png” (muy importante).

Por último, abrid una ventana de línea de comandos de Windows (CMD.exe) y escribid:

				
					cd C:\devkitpro\nds-hb-menu\"
				
			

Y pulsad “Enter”. Seguidamente escribís:

				
					Make
				
			

Y nuevamente pulsad “Enter”. Si habéis instalado correctamente Devkitpro, empezarán un montón de letras como si estuvese cargando algo (está compilando código). Si finalmente se compila correctamente, en “C:\devkitpro\nds-hb-menu\” se habrá creado (entre otros) un archivo llamado “BOOT.nds”, “nds-hb-menu.nds” o algún archivo con extensión “*.nds”. Ese archivo debe llamarse “BOOT.nds”. De no llamarse así, renombrad el archivo y lo copiáis a la raíz de la micro SD de vuestra flashcard.

El siguiente archivo necesario (“_ds_menu.dat”) se encuentra dentro del directorio “C:\devkitpro\nds-hb-menu\BootStrap\ACE3Ds\”. Copiad el archivo y lo pegáis también en la raíz de la tarjeta micro SD.

Por último, copiad vuestro juego a la raíz de la  tarjeta micro SD y renombrad el archivo como “game.nds”. Finalmente, en la raíz de tu tarjeta micro SD debe haber:

  1. _ds_menu.dat
  2. BOOT.nds
  3. game.nds

Extraéis la tarjeta micro SD con seguridad. Insertadla en vuestro cartucho y probad que el juego se ejecuta al instante.

Si no se ejecuta el juego o se bloquea al cargar, posbilente tengas que parchear con DLDI Patcher el archivo “game.nds”.

Enlace de descarga: https://gbatemp.net/download/dlditool-win32-gui.19908/

El parche DLDI para que funcione vuestro juegos está dentro de la carpeta “_rpg” en el archivo “Ace3DS+_R4iLS_Wood_R4_1.62.zip” en https://flashcard-archive.ds-homebrew.com/Ace3DS+_R4iLS/

Próximamente más información

Leave a Reply

Your email address will not be published. Required fields are marked *