diff --git a/.gitignore b/.gitignore index c6127b3..a3a7781 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ modules.order Module.symvers Mkfile.old dkms.conf +.* +core +nsemu diff --git a/Makefile b/Makefile index b236ea3..56c491d 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ CXX := g++ SRC_FILES := $(wildcard *.cpp) OBJ_FILES := $(SRC_FILES:.cpp=.o) -CXX_FLAGS := -Iinclude +CXX_FLAGS := -std=c++11 -Iinclude LD_FLAGS := -llz4 all: nsemu nsemu: $(OBJ_FILES) - $(CXX) -o nsemu $(LD_FLAGS) $(OBJ_FILES) + $(CXX) -o nsemu $(OBJ_FILES) $(LD_FLAGS) %.o: %.cpp $(CXX) $(CXX_FLAGS) -c -g -o $@ $< clean: diff --git a/NintendoObject.cpp b/NintendoObject.cpp index 03f598d..adf8c2d 100644 --- a/NintendoObject.cpp +++ b/NintendoObject.cpp @@ -1,13 +1,19 @@ +/* nsemu - LGPL - Copyright 2017 rkx1209 */ + #include "Nsemu.hpp" #include NintendoObject::NintendoObject(string path) { - fp.open(path, ios::in | ios::binary); + fp.open(path.c_str(), ios::in | ios::binary); fp.seekg(0, ios_base::end); length = (uint32_t) fp.tellg(); fp.seekg(0); } +NintendoObject::~NintendoObject() { + fp.close(); +} + char *decompress(ifstream &fp, uint32_t offset, uint32_t csize, uint32_t usize) { fp.seekg(offset); char *buf = new char[csize]; @@ -18,10 +24,29 @@ char *decompress(ifstream &fp, uint32_t offset, uint32_t csize, uint32_t usize) return obuf; } -int Nso::load (Nsemu *nsemu, uint64_t *base) { +int Nso::load (Nsemu *nsemu, uint64_t base) { + NsoHeader hdr; + fp.read((char *) &hdr, sizeof(NsoHeader)); + if (hdr.magic != host_order32("NSO0")) + return 0; + uint32_t size = hdr.dataLoc + hdr.dataSize + hdr.bssSize; + if (size & 0xfff) + size = (size & ~0xfff) + 0x1000; + char *text = decompress(fp, hdr.textOff, hdr.rdataOff - hdr.textOff, hdr.textSize); + bindump ((uint8_t*)text, 105); + delete[] text; + char *rdata = decompress(fp, hdr.rdataOff, hdr.dataOff - hdr.rdataOff, hdr.rdataSize); + + delete[] rdata; + + char *data = decompress(fp, hdr.dataOff, length - hdr.dataOff, hdr.dataSize); + + delete[] data; + + return size; } -int Nro::load (Nsemu *nsemu, uint64_t *base) { - +int Nro::load (Nsemu *nsemu, uint64_t base) { + } diff --git a/Nsemu.cpp b/Nsemu.cpp index e69de29..7de9e2c 100644 --- a/Nsemu.cpp +++ b/Nsemu.cpp @@ -0,0 +1,3 @@ +/* nsemu - LGPL - Copyright 2017 rkx1209 */ +#include "Nsemu.hpp" +Nsemu *Nsemu::inst = nullptr; diff --git a/Util.cpp b/Util.cpp new file mode 100644 index 0000000..472d4a4 --- /dev/null +++ b/Util.cpp @@ -0,0 +1 @@ +/* nsemu - LGPL - Copyright 2017 rkx1209 */ diff --git a/include/NintendoObject.hpp b/include/NintendoObject.hpp index 8c4c3e8..a29e290 100644 --- a/include/NintendoObject.hpp +++ b/include/NintendoObject.hpp @@ -5,8 +5,8 @@ class Nsemu; class NintendoObject { public: NintendoObject(std::string path); - ~NintendoObject() {} - virtual int load (Nsemu *nsemu, uint64_t *base) = 0; + ~NintendoObject(); + virtual int load (Nsemu *nsemu, uint64_t base) = 0; protected: std::ifstream fp; uint32_t length; @@ -15,7 +15,7 @@ protected: class Nso : NintendoObject { public: Nso(std::string path) : NintendoObject(path) {} - int load (Nsemu *nsemu, uint64_t *base); + int load (Nsemu *nsemu, uint64_t base); }; typedef struct { @@ -29,7 +29,7 @@ typedef struct { class Nro : NintendoObject { public: Nro(std::string path) : NintendoObject(path) {} - int load (Nsemu *nsemu, uint64_t *base); + int load (Nsemu *nsemu, uint64_t base); }; #endif diff --git a/include/Nsemu.hpp b/include/Nsemu.hpp index af16ecc..5a97b9e 100644 --- a/include/Nsemu.hpp +++ b/include/Nsemu.hpp @@ -4,16 +4,44 @@ #include #include #include +#include #include #include #include #include using namespace std; +#include "Util.hpp" #include "NintendoObject.hpp" +/* Global NSEMU singleton class .*/ class Nsemu { +private: + Nsemu() = default; + ~Nsemu() = default; + + static Nsemu *inst; public: - Nsemu(); + Nsemu(const Nsemu&) = delete; + Nsemu& operator=(const Nsemu&) = delete; + Nsemu(Nsemu&&) = delete; + Nsemu& operator=(Nsemu&&) = delete; + + static Nsemu* get_instance() { + return inst; + } + + static void create() { + if ( !inst ) { + inst = new Nsemu; + } + } + + static void destroy() { + if ( inst ) { + delete inst; + inst= nullptr; + } + } }; #endif diff --git a/include/Util.hpp b/include/Util.hpp new file mode 100644 index 0000000..5430cbb --- /dev/null +++ b/include/Util.hpp @@ -0,0 +1,46 @@ +#ifndef _UTIL_HPP +#define _UTIL_HPP + +#include +#include + +#define LINE_BREAK 15 + +enum RunLevel{ + RUN_LEVEL_RELEASE = 0, + RUN_LEVEL_DEBUG, +}; + +static RunLevel curlevel = RUN_LEVEL_DEBUG; + +static void util_print(RunLevel level, const char *format, ...) { + if (curlevel >= level) { + va_list va; + va_start (va, format); + vprintf (format, va); + va_end (va); + } +} + +#define debug_print(format, ...) util_print (RUN_LEVEL_DEBUG, format, ##__VA_ARGS__) +#define print(format, ...) util_print (RUN_LEVEL_RELEASE, format, ##__VA_ARGS__) + +inline void bindump(uint8_t *ptr, size_t size) { + int i = 0; + while (i < size) { + debug_print ("%02x", ptr[i]); + if ((i + 1) % LINE_BREAK == 0) + debug_print ("\n"); + else + debug_print (" "); + i++; + } + if (i % LINE_BREAK != 0) + debug_print ("\n"); +} + +inline int32_t host_order32(const char *b) { + return ((b[3]) << 24) | ((b[2]) << 16) | ((b[1]) << 8) | (b[0]); +} + +#endif diff --git a/main.cpp b/main.cpp index 1f6cc7f..ff6b809 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,4 @@ +/* nsemu - LGPL - Copyright 2017 rkx1209 */ #include "Nsemu.hpp" #include "optionparser.h" using namespace std; @@ -42,13 +43,20 @@ struct Arg: public option::Arg enum optionIndex { UNKNOWN, HELP }; const option::Descriptor usage[] = { - {UNKNOWN, 0, "", "",Arg::None, "USAGE: nsemu [options] \n\n" + {UNKNOWN, 0, "", "",Arg::None, "USAGE: nsemu [options] \n\n" "Options:" }, {HELP, 0,"","help",Arg::None, " --help \tUnsurprisingly, print this message." }, {0,0,nullptr,nullptr,nullptr,nullptr} }; +static void load_nso(Nsemu *nsemu, string path, uint64_t addr) { + Nso nso(path); + nso.load(nsemu, addr); +} + int main(int argc, char **argv) { + Nsemu::create(); + Nsemu *nsemu = Nsemu::get_instance(); argc -= argc > 0; argv += argc > 0; @@ -79,6 +87,9 @@ int main(int argc, char **argv) { } #endif } - + string nso_path = parse.nonOption(0); + debug_print ("NSO path=%s\n", nso_path.c_str()); + load_nso(nsemu, nso_path, 0x1000); + Nsemu::destroy(); return 0; }