Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 150 additions & 15 deletions src/universal/injector.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,142 @@
#include <stdlib.h>
#include <string.h>

// On the 3DS, fopen on a folder returns NULL, so a path we cannot open as a
// file is treated as a directory to navigate into.
int is_directory(char* path)
{
FILE* file = fopen(path, "rb");
if (file)
{
fclose(file);
return 0;
}
return 1;
}

// Returns a pointer to the last path component (the part after the final '/').
char* base_name(char* path)
{
int last = -1;
for (int i = 0; path[i] != '\0'; i++)
{
if (path[i] == '/')
{
last = i;
}
}
return path + last + 1;
}

// Trims the last path component in place, moving one level up.
void path_up(char* path)
{
int last = -1;
for (int i = 0; path[i] != '\0'; i++)
{
if (path[i] == '/')
{
last = i;
}
}
if (last > 0)
{
path[last] = '\0';
}
}

int main(int argc, char** argv)
{
unsigned char version = *argv[0];
struct directory* injectables = read_directory("/3ds/PKSM/inject");
unsigned char version = *argv[0];

if (injectables->count == 0)
char path[768];
strcpy(path, "/3ds/PKSM/inject");

struct directory* root = read_directory(path);
int rootCount = root->count;
delete_directory(root);

if (rootCount == 0)
{
delete_directory(injectables);
gui_warn("There are no files in \'/3ds/PKSM/inject\'!\nPlace Wonder Card or Pokemon files there");
return 0;
}

int chosen = gui_menu_20x2("Choose a file to inject", injectables->count, injectables->files);
// Browse starting from the inject folder, descending into folders until a
// file is chosen. chosenFile ends up holding the path of the picked file.
char chosenFile[768];
chosenFile[0] = '\0';

while (chosenFile[0] == '\0')
{
struct directory* dir = read_directory(path);
int atRoot = !strcmp(path, "/3ds/PKSM/inject");

// First entry navigates up (or cancels at the root), the rest are the
// folder contents shown by name.
int total = dir->count + 1;
char** labels = malloc(total * sizeof(char*));
if (!labels)
{
delete_directory(dir);
gui_warn("Out of memory.");
return 0;
}
if (atRoot)
{
labels[0] = "[ Cancel ]";
}
else
{
labels[0] = "[ .. ]";
}
for (int i = 0; i < dir->count; i++)
{
labels[i + 1] = base_name(dir->files[i]);
}

int chosen = gui_menu_20x2("Choose a file to inject.\nSelect a folder to open it.", total, labels);
free(labels);

if (chosen <= 0)
{
delete_directory(dir);
if (atRoot)
{
return 0;
}
path_up(path);
continue;
}

if (strlen(dir->files[chosen - 1]) >= 768)
{
gui_warn("Path is too long to open.");
delete_directory(dir);
continue;
}

if (is_directory(dir->files[chosen - 1]))
{
strcpy(path, dir->files[chosen - 1]);
delete_directory(dir);
continue;
}

strcpy(chosenFile, dir->files[chosen - 1]);
delete_directory(dir);
}

char* extension = NULL;
if (strlen(injectables->files[chosen]) > 3)
if (strlen(chosenFile) > 3)
{
if (injectables->files[chosen][strlen(injectables->files[chosen]) - 4] == '.')
if (chosenFile[strlen(chosenFile) - 4] == '.')
{
extension = injectables->files[chosen] + strlen(injectables->files[chosen]) - 3;
extension = chosenFile + strlen(chosenFile) - 3;
}
else if (strlen(injectables->files[chosen]) > 7 &&
injectables->files[chosen][strlen(injectables->files[chosen]) - 8] == '.')
else if (strlen(chosenFile) > 7 && chosenFile[strlen(chosenFile) - 8] == '.')
{
extension = injectables->files[chosen] + strlen(injectables->files[chosen]) - 7;
extension = chosenFile + strlen(chosenFile) - 7;
}
}

Expand All @@ -37,11 +149,22 @@ int main(int argc, char** argv)
!strcasecmp(extension, "wc7") || !strcasecmp(extension, "wc7full") ||
!strcasecmp(extension, "wb7") || !strcasecmp(extension, "wb7full")))
{
FILE* file = fopen(injectables->files[chosen], "rb");
FILE* file = fopen(chosenFile, "rb");
if (!file)
{
gui_warn("Could not open the selected file.");
return 0;
}
fseek(file, 0, SEEK_END);
int size = ftell(file);
fseek(file, 0, SEEK_SET);
char* data = malloc(size);
if (!data)
{
fclose(file);
gui_warn("Out of memory.");
return 0;
}
fread(data, 1, size, file);
fclose(file);

Expand Down Expand Up @@ -92,12 +215,25 @@ int main(int argc, char** argv)
if (!gui_boxes(&fromStorage, &box, &slot, 0))
{
bool ekx = true;
FILE* file = fopen(injectables->files[chosen], "rb");
FILE* file = fopen(chosenFile, "rb");
if (!file)
{
gui_warn("Could not open the selected file.");
sav_box_encrypt();
return 0;
}
fseek(file, 0, SEEK_END);
int size = ftell(file);
fseek(file, 0, SEEK_SET);
char* data = malloc(size);
fread(data, size, size, file);
if (!data)
{
fclose(file);
gui_warn("Out of memory.");
sav_box_encrypt();
return 0;
}
fread(data, 1, size, file);
fclose(file);

enum Generation gen;
Expand Down Expand Up @@ -172,6 +308,5 @@ int main(int argc, char** argv)
gui_warn("Extension not recognized!");
}

delete_directory(injectables);
return 0;
}