From 5ad1aa8b6821a86527a1afa455516d2d8f2291cd Mon Sep 17 00:00:00 2001
From: Mathieu Vaillancourt <vaillancourtm@gmail.com>
Date: Mon, 21 Apr 2014 23:09:10 -0400
Subject: [PATCH] Add a quick way to load Launcher.dat files

---
 src/core/loader.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++
 src/core/loader.h   | 11 ++++-----
 2 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/src/core/loader.cpp b/src/core/loader.cpp
index 8c6d54a68..7c1dfef61 100644
--- a/src/core/loader.cpp
+++ b/src/core/loader.cpp
@@ -11,6 +11,8 @@
 #include "core/file_sys/directory_file_system.h"
 #include "core/elf/elf_reader.h"
 
+#include "core/mem_map.h"
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
 /// Loads an extracted CXI from a directory
@@ -66,6 +68,52 @@ bool Load_ELF(std::string &filename) {
     return true;
 }
 
+/// Loads a Launcher DAT file
+bool Load_DAT(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];
+
+        f.ReadBytes(buffer, size);
+
+        /**
+        * (mattvail) We shouldn't really support this type of file
+        * but for the sake of making it easier... we'll temporarily/hackishly
+        * allow it. No sense in making a proper reader for this.
+        */
+        u32 entrypoint = 0x080c3ee0; // write to same entrypoint as elf
+        u32 payload_offset = 0x6F4;
+        
+        const u8 *src = &buffer[payload_offset];
+        u8 *dst = Memory::GetPointer(entrypoint);
+        u32 srcSize = size - payload_offset; //just load everything...
+        u32 *s = (u32*)src;
+        u32 *d = (u32*)dst;
+        for (int j = 0; j < (int)(srcSize + 3) / 4; j++)
+        {
+            *d++ = (*s++);
+        }
+        
+        Core::g_app_core->SetPC(entrypoint);
+
+        delete[] buffer;
+    }
+    else {
+        return false;
+    }
+    f.Close();
+
+    return true;
+}
+
 namespace Loader {
 
 bool IsBootableDirectory() {
@@ -97,6 +145,9 @@ FileType IdentifyFile(std::string &filename) {
     else if (!strcasecmp(extension.c_str(), ".elf")) {
         return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p
     }
+    else if (!strcasecmp(extension.c_str(), ".dat")) {
+        return FILETYPE_LAUNCHER_DAT;
+    }
     else if (!strcasecmp(extension.c_str(), ".zip")) {
         return FILETYPE_ARCHIVE_ZIP;
     }
@@ -127,6 +178,9 @@ bool LoadFile(std::string &filename, std::string *error_string) {
     case FILETYPE_CTR_ELF:
         return Load_ELF(filename);
 
+    case FILETYPE_LAUNCHER_DAT:
+        return Load_DAT(filename);
+
     case FILETYPE_DIRECTORY_CXI:
         return LoadDirectory_CXI(filename);
 
diff --git a/src/core/loader.h b/src/core/loader.h
index 3dd8c471d..df30f16c7 100644
--- a/src/core/loader.h
+++ b/src/core/loader.h
@@ -11,12 +11,13 @@
 namespace Loader {
 
 enum FileType {
-	FILETYPE_ERROR,
+    FILETYPE_ERROR,
 
-	FILETYPE_CTR_CCI,
-	FILETYPE_CTR_CIA,
-	FILETYPE_CTR_CXI,
-	FILETYPE_CTR_ELF,
+    FILETYPE_CTR_CCI,
+    FILETYPE_CTR_CIA,
+    FILETYPE_CTR_CXI,
+    FILETYPE_CTR_ELF,
+    FILETYPE_LAUNCHER_DAT,
 
 	FILETYPE_DIRECTORY_CXI,