Add NSO binary loader

This commit is contained in:
rkx1209 2017-11-14 21:23:42 +09:00
parent 186bc1ed5f
commit aa4cd7ac53
9 changed files with 130 additions and 13 deletions

3
.gitignore vendored
View file

@ -50,3 +50,6 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf
.*
core
nsemu

View file

@ -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:

View file

@ -1,13 +1,19 @@
/* nsemu - LGPL - Copyright 2017 rkx1209<rkx1209dev@gmail.com> */
#include "Nsemu.hpp"
#include <lz4.h>
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) {
}

View file

@ -0,0 +1,3 @@
/* nsemu - LGPL - Copyright 2017 rkx1209<rkx1209dev@gmail.com> */
#include "Nsemu.hpp"
Nsemu *Nsemu::inst = nullptr;

1
Util.cpp Normal file
View file

@ -0,0 +1 @@
/* nsemu - LGPL - Copyright 2017 rkx1209<rkx1209dev@gmail.com> */

View file

@ -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

View file

@ -4,16 +4,44 @@
#include <stdint.h>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
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

46
include/Util.hpp Normal file
View file

@ -0,0 +1,46 @@
#ifndef _UTIL_HPP
#define _UTIL_HPP
#include <stdio.h>
#include <stdarg.h>
#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

View file

@ -1,3 +1,4 @@
/* nsemu - LGPL - Copyright 2017 rkx1209<rkx1209dev@gmail.com> */
#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] <nro-binary>\n\n"
{UNKNOWN, 0, "", "",Arg::None, "USAGE: nsemu [options] <nso-binary>\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;
}