mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Add viewing NDS file info (#102)
* Add viewing NDS file info * Fix breaking SysNAND reads
This commit is contained in:
parent
43f440c9fa
commit
65d65eae41
@ -39,6 +39,7 @@
|
|||||||
#include "driveOperations.h"
|
#include "driveOperations.h"
|
||||||
#include "dumpOperations.h"
|
#include "dumpOperations.h"
|
||||||
#include "hexEditor.h"
|
#include "hexEditor.h"
|
||||||
|
#include "ndsInfo.h"
|
||||||
#include "nitrofs.h"
|
#include "nitrofs.h"
|
||||||
#include "inifile.h"
|
#include "inifile.h"
|
||||||
#include "nds_loader_arm9.h"
|
#include "nds_loader_arm9.h"
|
||||||
@ -225,6 +226,8 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
|||||||
{
|
{
|
||||||
assignedOp[++maxCursors] = FileOperation::mountNitroFS;
|
assignedOp[++maxCursors] = FileOperation::mountNitroFS;
|
||||||
printf(" Mount NitroFS\n");
|
printf(" Mount NitroFS\n");
|
||||||
|
assignedOp[++maxCursors] = FileOperation::ndsInfo;
|
||||||
|
printf(" Show NDS file info\n");
|
||||||
}
|
}
|
||||||
else if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"}))
|
else if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"}))
|
||||||
{
|
{
|
||||||
@ -376,6 +379,9 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
|||||||
currentDrive = 5;
|
currentDrive = 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
} case FileOperation::ndsInfo: {
|
||||||
|
ndsInfo(entry->name.c_str());
|
||||||
|
break;
|
||||||
} case FileOperation::showInfo: {
|
} case FileOperation::showInfo: {
|
||||||
changeFileAttribs(entry);
|
changeFileAttribs(entry);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -45,6 +45,7 @@ enum class FileOperation {
|
|||||||
copyFatOut,
|
copyFatOut,
|
||||||
calculateSHA1,
|
calculateSHA1,
|
||||||
hexEdit,
|
hexEdit,
|
||||||
|
ndsInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool extension(const std::string &filename, const std::vector<std::string> &extensions);
|
bool extension(const std::string &filename, const std::vector<std::string> &extensions);
|
||||||
|
|||||||
@ -152,6 +152,7 @@ int main(int argc, char **argv) {
|
|||||||
// Subscreen as a console
|
// Subscreen as a console
|
||||||
videoSetModeSub(MODE_0_2D);
|
videoSetModeSub(MODE_0_2D);
|
||||||
vramSetBankH(VRAM_H_SUB_BG);
|
vramSetBankH(VRAM_H_SUB_BG);
|
||||||
|
vramSetBankI(VRAM_I_SUB_SPRITE);
|
||||||
consoleInit(&bottomConsoleBG, 1, BgType_Text4bpp, BgSize_T_256x256, 7, 0, false, true);
|
consoleInit(&bottomConsoleBG, 1, BgType_Text4bpp, BgSize_T_256x256, 7, 0, false, true);
|
||||||
consoleInit(&bottomConsole, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);
|
consoleInit(&bottomConsole, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);
|
||||||
|
|
||||||
|
|||||||
134
arm9/source/ndsInfo.cpp
Normal file
134
arm9/source/ndsInfo.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "ndsInfo.h"
|
||||||
|
|
||||||
|
#include "date.h"
|
||||||
|
#include "tonccpy.h"
|
||||||
|
|
||||||
|
#include <nds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern PrintConsole bottomConsole, bottomConsoleBG, topConsole;
|
||||||
|
|
||||||
|
constexpr const char *langNames[8] {
|
||||||
|
"Japanese",
|
||||||
|
"English",
|
||||||
|
"French",
|
||||||
|
"German",
|
||||||
|
"Italian",
|
||||||
|
"Spanish",
|
||||||
|
"Chinese",
|
||||||
|
"Korean"
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void reinitConsoles(void);
|
||||||
|
|
||||||
|
void ndsInfo(const char *path) {
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
if(!file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char headerTitle[0xD] = {0};
|
||||||
|
fread(headerTitle, 1, 0xC, file);
|
||||||
|
|
||||||
|
char tid[5] = {0};
|
||||||
|
fread(tid, 1, 4, file);
|
||||||
|
|
||||||
|
u32 ofs;
|
||||||
|
fseek(file, 0x68, SEEK_SET);
|
||||||
|
fread(&ofs, sizeof(u32), 1, file);
|
||||||
|
fseek(file, ofs, SEEK_SET);
|
||||||
|
|
||||||
|
u16 version;
|
||||||
|
fread(&version, sizeof(u16), 1, file);
|
||||||
|
|
||||||
|
u8 *iconBitmap = new u8[8 * 0x200];
|
||||||
|
u16 *iconPalette = new u16[8 * 0x10];
|
||||||
|
u16 *iconAnimation = new u16[0x40](); // Initialize to 0 for DS icons
|
||||||
|
|
||||||
|
if(version == 0x0103) { // DSi
|
||||||
|
fseek(file, 0x1240 - 2, SEEK_CUR);
|
||||||
|
fread(iconBitmap, 1, 8 * 0x200, file);
|
||||||
|
fread(iconPalette, 2, 8 * 0x10, file);
|
||||||
|
fread(iconAnimation, 2, 0x40, file);
|
||||||
|
|
||||||
|
fseek(file, ofs + 0x240, SEEK_SET);
|
||||||
|
} else { // DS
|
||||||
|
fseek(file, 0x20 - 2, SEEK_CUR);
|
||||||
|
fread(iconBitmap, 1, 0x200, file);
|
||||||
|
fread(iconPalette, 2, 0x10, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int languages = 5 + (version & 0x3);
|
||||||
|
char16_t *titles = new char16_t[languages * 0x80];
|
||||||
|
fread(titles, 2, languages * 0x80, file);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
oamInit(&oamSub, SpriteMapping_Bmp_1D_128, false);
|
||||||
|
|
||||||
|
u16 *iconGfx = oamAllocateGfx(&oamSub, SpriteSize_32x32, SpriteColorFormat_16Color);
|
||||||
|
oamSet(&oamSub, 0, 256 - 36, 4, 0, 0, SpriteSize_32x32, SpriteColorFormat_16Color, iconGfx, -1, false, false, false, false, false);
|
||||||
|
|
||||||
|
tonccpy(iconGfx, iconBitmap, 0x200);
|
||||||
|
tonccpy(SPRITE_PALETTE_SUB, iconPalette, 0x20);
|
||||||
|
|
||||||
|
oamUpdate(&oamSub);
|
||||||
|
|
||||||
|
u16 pressed = 0, held = 0;
|
||||||
|
int animationFrame = 0, frameDelay = 0, lang = 1;
|
||||||
|
while(1) {
|
||||||
|
consoleClear();
|
||||||
|
|
||||||
|
iprintf("Header Title: %s\n", headerTitle);
|
||||||
|
iprintf("Title ID: %s\n", tid);
|
||||||
|
iprintf("Title: (%s)\n ", langNames[lang]);
|
||||||
|
for(int j = 0; j < 0x80 && titles[lang * 0x80 + j]; j++) {
|
||||||
|
if(titles[lang * 0x80 + j] == '\n')
|
||||||
|
iprintf("\n ");
|
||||||
|
else
|
||||||
|
iprintf("%c", titles[lang * 0x80 + j]);
|
||||||
|
}
|
||||||
|
iprintf("\n");
|
||||||
|
|
||||||
|
consoleSelect(&topConsole);
|
||||||
|
do {
|
||||||
|
swiWaitForVBlank();
|
||||||
|
scanKeys();
|
||||||
|
pressed = keysDown();
|
||||||
|
held = keysDownRepeat();
|
||||||
|
iprintf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time
|
||||||
|
if(iconAnimation[animationFrame] && animationFrame < 0x40) {
|
||||||
|
if(frameDelay < (iconAnimation[animationFrame] & 0xFF) - 1) {
|
||||||
|
frameDelay++;
|
||||||
|
} else {
|
||||||
|
frameDelay = 0;
|
||||||
|
if(!iconAnimation[++animationFrame])
|
||||||
|
animationFrame = 0;
|
||||||
|
|
||||||
|
tonccpy(iconGfx, iconBitmap + ((iconAnimation[animationFrame] >> 8) & 7) * 0x200, 0x200);
|
||||||
|
tonccpy(SPRITE_PALETTE_SUB, iconPalette + ((iconAnimation[animationFrame] >> 0xB) & 7) * 0x10, 0x20);
|
||||||
|
oamSetFlip(&oamSub, 0, iconAnimation[animationFrame] & BIT(14), iconAnimation[animationFrame] & BIT(15));
|
||||||
|
oamUpdate(&oamSub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(!held);
|
||||||
|
consoleSelect(&bottomConsole);
|
||||||
|
|
||||||
|
if(held & KEY_UP) {
|
||||||
|
if(lang > 0)
|
||||||
|
lang--;
|
||||||
|
} else if(held & KEY_DOWN) {
|
||||||
|
if(lang < languages - 1)
|
||||||
|
lang++;
|
||||||
|
} else if(pressed & KEY_B) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] iconBitmap;
|
||||||
|
delete[] iconPalette;
|
||||||
|
delete[] iconAnimation;
|
||||||
|
delete[] titles;
|
||||||
|
|
||||||
|
oamFreeGfx(&oamSub, iconGfx);
|
||||||
|
oamDisable(&oamSub);
|
||||||
|
}
|
||||||
6
arm9/source/ndsInfo.h
Normal file
6
arm9/source/ndsInfo.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef NDS_INFO_H
|
||||||
|
#define NDS_INFO_H
|
||||||
|
|
||||||
|
void ndsInfo(const char *path);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue
Block a user