Table of Contents

Getting started guide

Welcome to Ekona, a library part of the SceneGate framework that provides support for DS and DSi file formats.

Usage

The project provides the following .NET libraries (NuGet packages in nuget.org). The libraries works on supported versions of .NET: 6.0 and 8.0.

  • SceneGate.Ekona
    • SceneGate.Ekona.Containers.Rom: DS and DSi cartridge (ROM) format.
    • SceneGate.Ekona.Security: hash and encryption algorithms

Quick start

Cartridge file system

Let's start by opening a game (ROM) and accessing to its files. We can virtually unpack the ROM by using the converter Binar2NitroRom. It will create a tree of nodes that we can use to access to the files.

// Create node from file with binary format.
Node game = NodeFactory.FromFile(gameFilePath, FileOpenMode.Read);

// Use the `Binary2NitroRom` converter to convert the binary format
// into node containers (virtual file system tree).
game.TransformWith<Binary2NitroRom>();

// And it's done!
// Now we can access to every game file. For instance, we can export one file
Node gameFile = game.Children["data"].Children["Items.dat"];
gameFile.Stream.WriteTo("dump/items.dat");
Note

The converter will not write any file to the disk. It will create a tree of nodes that points to different parts of the original game file. If it needs to decrypt a file (like arm9i), it will create a new stream on memory.

Now we can quickly modify our file even by code!

// Read the file by converting from binary format into PO (translation format)
Node itemsFile = Navigator.SearchNode(game, "data/Items.dat");
Po items = itemsFile.TransformWith<BinaryItems2Po>().GetFormatAs<Po>();

// Let's modify the first entry
items.Entries[0].Translated = "Hello world!";

// Convert back from PO format into binary (write into a new memory stream)
itemsFile.TransformWith<Po2BinaryItems>();

Finally, to generate a new game (ROM) file we just need one more line of code to use the NitroRom2Binary converter.

game.TransformWith<NitroRom2Binary>();
game.Stream.WriteTo("output/new_game.nds");
Tip

Check-out the cartridge section to learn about the optional parameters of these converters!

Cartridge information

Once we have opened a game, we can access to all the information from its header easily via the system/info node.

Node game = NodeFactory.FromFile(gameFilePath, FileOpenMode.Read)
    .TransformWith<Binary2NitroRom>();

ProgramInfo info = game.Children["system"].Children["info"]
    .GetFormatAs<ProgramInfo>();

Console.WriteLine($"Game title: {info.GameTitle} [{info.GameCode}]");

In a similar way, you can access to the information from the banner like the game title in different languages:

Banner bannerInfo = Navigator.SearchNode(game, "system/banner/info").GetFormatAs<Banner>();
Console.WriteLine($"Japanese title: {bannerInfo.JapaneseTitle}");
Console.WriteLine($"English title: {bannerInfo.EnglishTitle}");

You can also export the game icon. If it's a DSi game, it may even have an animated icon that you can export as GIF!

IndexedPaletteImage icon = Navigator.SearchNode(game, "system/banner/icon")
    .GetFormatAs<IndexedPaletteImage>();

// Using Texim converters, create a PNG image
var converterParameters = new IndexedImageBitmapParams { Palettes = icon };
var bitmapConverter = new IndexedImage2Bitmap(converterParameters);

using BinaryFormat binaryPng = bitmapConverter.Convert(icon);
binaryPng.Stream.WriteTo("dump/icon.png");

// For DSi-enhanced games we can export its animated icon as GIF
if (bannerInfo.SupportAnimatedIcon) {
    var animatedNode = Navigator.SearchNode(game, "system/banner/animated")
        .GetFormatAs<NodeContainerFormat>();

    var animatedImage = new IconAnimation2AnimatedImage().Convert(animatedNode);
    using var binaryGif = new AnimatedFullImage2Gif().Convert(animatedImage);
    binaryGif.Stream.WriteTo("dump/icon.gif");
}