From 85e8da6fc8579c313649d12494f58b654b439326 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Mon, 31 Mar 2014 22:23:55 -0400
Subject: [PATCH] added ELF loading support to loader.cpp

---
 src/core/src/loader.cpp | 178 +++++++++++++++++++++++++---------------
 1 file changed, 111 insertions(+), 67 deletions(-)

diff --git a/src/core/src/loader.cpp b/src/core/src/loader.cpp
index 994ce85e94..7e7eb91613 100644
--- a/src/core/src/loader.cpp
+++ b/src/core/src/loader.cpp
@@ -26,35 +26,67 @@
 #include "loader.h"
 #include "system.h"
 #include "file_sys/directory_file_system.h"
+#include "elf/elf_reader.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 /// Loads an extracted CXI from a directory
 bool LoadDirectory_CXI(std::string &filename) {
-	std::string full_path = filename;
-	std::string path, file, extension;
-	SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
+    std::string full_path = filename;
+    std::string path, file, extension;
+    SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
 #if EMU_PLATFORM == PLATFORM_WINDOWS
-	path = ReplaceAll(path, "/", "\\");
+    path = ReplaceAll(path, "/", "\\");
 #endif
-	DirectoryFileSystem *fs = new DirectoryFileSystem(&System::g_ctr_file_system, path);
-	System::g_ctr_file_system.Mount("fs:", fs);
+    DirectoryFileSystem *fs = new DirectoryFileSystem(&System::g_ctr_file_system, path);
+    System::g_ctr_file_system.Mount("fs:", fs);
 
-	std::string final_name = "fs:/" + file + extension;
-	File::IOFile f(filename, "rb");
+    std::string final_name = "fs:/" + file + extension;
+    File::IOFile f(filename, "rb");
 
-	if (f.IsOpen()) {
-		// TODO(ShizZy): read here to memory....
-	}
-	ERROR_LOG(TIME, "Unimplemented function!");
-	return true;
+    if (f.IsOpen()) {
+        // TODO(ShizZy): read here to memory....
+    }
+    ERROR_LOG(TIME, "Unimplemented function!");
+    return true;
+}
+
+/// Loads a CTR ELF file
+bool Load_ELF(std::string &filename) {
+    std::string full_path = filename;
+    std::string path, file, extension;
+    SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
+#if EMU_PLATFORM == PLATFORM_WINDOWS
+    path = ReplaceAll(path, "/", "\\");
+#endif
+    File::IOFile f(filename, "rb");
+
+    if (f.IsOpen()) {
+        u64 size = f.GetSize();
+        u8* buffer = new u8[size];
+        ElfReader* elf_reader = NULL;
+
+        f.ReadBytes(buffer, size);
+
+        elf_reader = new ElfReader(buffer);
+        elf_reader->LoadInto(0x00100000);
+
+        delete[] buffer;
+        delete elf_reader;
+    }
+    else {
+        return false;
+    }
+    f.Close();
+
+    return true;
 }
 
 namespace Loader {
 
 bool IsBootableDirectory() {
-	ERROR_LOG(TIME, "Unimplemented function!");
-	return true;
+    ERROR_LOG(TIME, "Unimplemented function!");
+    return true;
 }
 
 /**
@@ -64,28 +96,36 @@ bool IsBootableDirectory() {
  * @return FileType of file
  */
 FileType IdentifyFile(std::string &filename) {
-	if (filename.size() == 0) {
-		ERROR_LOG(LOADER, "invalid filename %s", filename.c_str());
-		return FILETYPE_ERROR;
-	}
-	std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : "";
-	
-	if (File::IsDirectory(filename)) {
-		if (IsBootableDirectory()) {
-			return FILETYPE_DIRECTORY_CXI;
-		} else {
-			return FILETYPE_NORMAL_DIRECTORY;
-		}
-	} else if (!strcasecmp(extension.c_str(),".zip")) {
-		return FILETYPE_ARCHIVE_ZIP;
-	} else if (!strcasecmp(extension.c_str(),".rar")) {
-		return FILETYPE_ARCHIVE_RAR;
-	} else if (!strcasecmp(extension.c_str(),".r00")) {
-		return FILETYPE_ARCHIVE_RAR;
-	} else if (!strcasecmp(extension.c_str(),".r01")) {
-		return FILETYPE_ARCHIVE_RAR;
-	}
-	return FILETYPE_UNKNOWN;
+    if (filename.size() == 0) {
+        ERROR_LOG(LOADER, "invalid filename %s", filename.c_str());
+        return FILETYPE_ERROR;
+    }
+    std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : "";
+
+    if (File::IsDirectory(filename)) {
+        if (IsBootableDirectory()) {
+            return FILETYPE_DIRECTORY_CXI;
+        }
+        else {
+            return FILETYPE_NORMAL_DIRECTORY;
+        }
+    }
+    else if (!strcasecmp(extension.c_str(), ".elf")) {
+        return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p
+    }
+    else if (!strcasecmp(extension.c_str(), ".zip")) {
+        return FILETYPE_ARCHIVE_ZIP;
+    }
+    else if (!strcasecmp(extension.c_str(), ".rar")) {
+        return FILETYPE_ARCHIVE_RAR;
+    }
+    else if (!strcasecmp(extension.c_str(), ".r00")) {
+        return FILETYPE_ARCHIVE_RAR;
+    }
+    else if (!strcasecmp(extension.c_str(), ".r01")) {
+        return FILETYPE_ARCHIVE_RAR;
+    }
+    return FILETYPE_UNKNOWN;
 }
 
 /**
@@ -95,48 +135,52 @@ FileType IdentifyFile(std::string &filename) {
  * @return True on success, otherwise false
  */
 bool LoadFile(std::string &filename, std::string *error_string) {
-	INFO_LOG(LOADER,"Identifying file...");
-	// Note that this can modify filename!
-	switch (IdentifyFile(filename)) {
+    INFO_LOG(LOADER, "Identifying file...");
 
-	case FILETYPE_DIRECTORY_CXI:
-		return LoadDirectory_CXI(filename);
+    // Note that this can modify filename!
+    switch (IdentifyFile(filename)) {
 
-	case FILETYPE_ERROR:
-		ERROR_LOG(LOADER, "Could not read file");
-		*error_string = "Error reading file";
-		break;
+    case FILETYPE_CTR_ELF:
+        return Load_ELF(filename);
 
-	case FILETYPE_ARCHIVE_RAR:
+    case FILETYPE_DIRECTORY_CXI:
+        return LoadDirectory_CXI(filename);
+
+    case FILETYPE_ERROR:
+        ERROR_LOG(LOADER, "Could not read file");
+        *error_string = "Error reading file";
+        break;
+
+    case FILETYPE_ARCHIVE_RAR:
 #ifdef WIN32
-		*error_string = "RAR file detected (Require WINRAR)";
+        *error_string = "RAR file detected (Require WINRAR)";
 #else
-		*error_string = "RAR file detected (Require UnRAR)";
+        *error_string = "RAR file detected (Require UnRAR)";
 #endif
-		break;
+        break;
 
-	case FILETYPE_ARCHIVE_ZIP:
+    case FILETYPE_ARCHIVE_ZIP:
 #ifdef WIN32
-		*error_string = "ZIP file detected (Require WINRAR)";
+        *error_string = "ZIP file detected (Require WINRAR)";
 #else
-		*error_string = "ZIP file detected (Require UnRAR)";
+        *error_string = "ZIP file detected (Require UnRAR)";
 #endif
-		break;
+        break;
 
-	case FILETYPE_NORMAL_DIRECTORY:
-		ERROR_LOG(LOADER, "Just a directory.");
-		*error_string = "Just a directory.";
-		break;
+    case FILETYPE_NORMAL_DIRECTORY:
+        ERROR_LOG(LOADER, "Just a directory.");
+        *error_string = "Just a directory.";
+        break;
 
-	case FILETYPE_UNKNOWN_BIN:
-	case FILETYPE_UNKNOWN_ELF:
-	case FILETYPE_UNKNOWN:
-	default:
-		ERROR_LOG(LOADER, "Failed to identify file");
-		*error_string = "Failed to identify file";
-		break;
-	}
-	return false;
+    case FILETYPE_UNKNOWN_BIN:
+    case FILETYPE_UNKNOWN_ELF:
+    case FILETYPE_UNKNOWN:
+    default:
+        ERROR_LOG(LOADER, "Failed to identify file");
+        *error_string = "Failed to identify file";
+        break;
+    }
+    return false;
 }
 
 } // namespace
\ No newline at end of file