Skip to content

Instantly share code, notes, and snippets.

@Epicpkmn11
Last active April 21, 2022 21:28
Show Gist options
  • Save Epicpkmn11/c35ad7fa4dad571737172d54b688974c to your computer and use it in GitHub Desktop.
Save Epicpkmn11/c35ad7fa4dad571737172d54b688974c to your computer and use it in GitHub Desktop.
bannerpng.c - Extracts the icon from a DS(i) ROM to a PNG, see bannergif.py for a better extractor capable of extracting animated icons but in Python
/* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to <http://unlicense.org/>
*/
/* To build:
* gcc bannerpng.c lodepng.c -o bannerpng
* https://lodev.org/lodepng/
*/
#include "lodepng.h"
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
/**
* @param input path to the DS ROM
* @param output path to write to
* @return true if successful
*/
bool bannergif(const char *input, const char *output) {
FILE *rom = fopen(input, "rb");
if(!rom)
return false;
// Seek to banner
fseek(rom, 0x68, SEEK_SET);
uint32_t bannerOfs;
fread(&bannerOfs, sizeof(uint32_t), 1, rom);
fseek(rom, bannerOfs, SEEK_SET);
// Load banner data
uint8_t palette[0x10][4]; // 16 colors RGBA
uint8_t bitmap[32 * 32 * 4]; // 32×32 RGBA
// Read palette
fseek(rom, bannerOfs + 0x220, SEEK_SET);
for(int i = 0; i < 0x10; i++) {
uint16_t color;
fread(&color, sizeof(uint16_t), 1, rom);
palette[i][0] = lroundf((color & 0x1F) * 255.0f / 31.0f);
palette[i][1] = lroundf(((color >> 5) & 0x1F) * 255.0f / 31.0f);
palette[i][2] = lroundf(((color >> 10) & 0x1F) * 255.0f / 31.0f);
palette[i][3] = i == 0 ? 0x00 : 0xFF;
}
// Read bitmap
fseek(rom, bannerOfs + 0x20, SEEK_SET);
for(int ty = 0; ty < 4; ty++) {
for(int tx = 0; tx < 4; tx++) {
for(int y = 0; y < 8; y++) {
for(int x = 0; x < 4; x++) {
uint8_t byte = fgetc(rom);
memcpy(bitmap + ((ty * 8 + y) * 32 * 4) + (tx * 8 + x * 2) * 4, palette[byte & 0xF], 4);
memcpy(bitmap + ((ty * 8 + y) * 32 * 4) + (tx * 8 + x * 2) * 4 + 4, palette[byte >> 4], 4);
}
}
}
}
fclose(rom);
lodepng_encode32_file(output, bitmap, 32, 32);
return true;
}
int main(int argc, char **argv) {
if(argc < 3) {
printf("Usage: %s input.nds output.png\n", argv[0]);
return 1;
}
bool success = bannergif(argv[1], argv[2]);
return success ? 0 : 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment