neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

plugin.cpp (4083B)


      1 #include "version.hpp"
      2 #include "vita_plugin/cpk.hpp"
      3 
      4 #include <libshit/except.hpp>
      5 #include <libshit/memory_utils.hpp>
      6 #include <libshit/options.hpp>
      7 #include <libshit/vita_fixup.h>
      8 
      9 #include <fstream>
     10 #include <memory>
     11 #include <psp2/appmgr.h>
     12 #include <psp2/io/dirent.h>
     13 #include <psp2/kernel/modulemgr.h>
     14 #include <psp2/kernel/processmgr.h>
     15 #include <unistd.h>
     16 #include <vector>
     17 
     18 #define LIBSHIT_LOG_NAME "tai"
     19 #include <libshit/logger_helper.hpp>
     20 
     21 namespace Neptools::VitaPlugin
     22 {
     23 
     24   static void Uncaught()
     25   {
     26     printf("Terminate handler\n");
     27     printf("Caught: %s\n", Libshit::ExceptionToString(false).c_str());
     28 
     29     abort();
     30   }
     31 
     32   static bool CheckPath(const char* buf, const char*& out)
     33   {
     34     SceIoStat stat;
     35     auto ret = sceIoGetstat(buf, &stat);
     36     if (ret == 0 && SCE_S_ISDIR(stat.st_mode))
     37     {
     38       out = buf;
     39       return true;
     40     }
     41     return false;
     42   }
     43 
     44   static void my_strlcpy(char* dst, const char* str, size_t n)
     45   {
     46     while (--n && (*dst++ = *str++));
     47     *dst = 0;
     48   }
     49 
     50   static int FindDir(char* out_base_fname, char* out_data_fname, char* out_cache_fname)
     51   {
     52     char log_buf[32];
     53     log_buf[0] = 0;
     54 
     55     char buf[] = "____:neptools/_________";
     56     constexpr size_t off = sizeof("____:neptools/")-1;
     57     int ret = sceAppMgrAppParamGetString(sceKernelGetProcessId(), 12, buf+off, 10);
     58     if (ret < 0) return ret; // can't log anything here...
     59 
     60     // same order as repatch
     61     const char* base_path = nullptr;
     62     bool cache_td = false;
     63     for (const auto& x : {"ux0", "uma0", "imc0", "grw0", "xmc0"})
     64     {
     65       size_t len = strlen(x);
     66       memcpy(buf + 4 - len, x, len);
     67       if (CheckPath(buf + 4 - len, base_path))
     68       {
     69         my_strlcpy(log_buf, base_path, buf+off+1-base_path);
     70         break;
     71       }
     72     }
     73     if (!base_path && CheckPath("app0:neptools", base_path)) cache_td = true;
     74     if (!base_path) return -1;
     75     my_strlcpy(out_data_fname, base_path, 32);
     76 
     77     // check for ioplus bug
     78     if (!cache_td)
     79     {
     80       ret = sceIoDopen(base_path);
     81       if (ret >= 0) sceIoDclose(ret);
     82       else cache_td = true;
     83     }
     84 
     85     char td_buf[16];
     86     if (cache_td)
     87     {
     88       ret = sceAppMgrWorkDirMount(0xc9, td_buf);
     89       if (ret < 0) return ret;
     90     }
     91     if (!log_buf[0]) strcpy(log_buf, td_buf);
     92 
     93     if (cache_td)
     94     {
     95       strcpy(out_cache_fname, td_buf);
     96       strcat(out_cache_fname, "neptools_cache");
     97     }
     98     else
     99     {
    100       my_strlcpy(out_cache_fname, base_path, strlen(base_path) - 9 + 1);
    101       strcat(out_cache_fname, "cache");
    102     }
    103 
    104     strcpy(out_base_fname, log_buf);
    105     auto pos = log_buf + strlen(log_buf);
    106     strcpy(pos, "log_out.txt");
    107     freopen(log_buf, "w", stdout);
    108     strcpy(pos, "log_err.txt");
    109     freopen(log_buf, "w", stderr);
    110 
    111     return 0;
    112   }
    113 
    114   extern "C" int _start() __attribute__ ((weak, alias ("module_start")));
    115 
    116   extern "C" int module_start(SceSize, const void*);
    117   extern "C" int module_start(SceSize, const void*)
    118   {
    119     char base_fname[32], data_fname[32], cache_fname[32];
    120     if (FindDir(base_fname, data_fname, cache_fname) < 0)
    121       return SCE_KERNEL_START_FAILED;
    122 
    123     std::set_terminate(Uncaught);
    124 
    125     LibshitInitVita();
    126 
    127     std::vector<std::string> argv;
    128     {
    129       strcat(base_fname, "/command_line.txt");
    130       std::ifstream is{base_fname};
    131       while (is.good())
    132       {
    133         std::string s;
    134         std::getline(is, s);
    135         if (!s.empty()) argv.push_back(std::move(s));
    136       }
    137     }
    138 
    139     int argc = argv.size() + 1;
    140 
    141     auto cargv = Libshit::MakeUnique<const char*[]>(
    142       argc + 2, Libshit::uninitialized);
    143     cargv[0] = "";
    144     for (int i = 1; i < argc; ++i) cargv[i] = argv[i-1].c_str();
    145     cargv[argc+1] = nullptr;
    146 
    147     auto& pars = Libshit::OptionParser::GetGlobal();
    148     pars.SetVersion("NepTools vita plugin v" NEPTOOLS_VERSION);
    149     pars.SetUsage("[--options]");
    150     pars.FailOnNonArg();
    151 
    152     try { pars.Run(argc, cargv.get()); }
    153     catch (const Libshit::Exit& e) { _exit(!e.success); }
    154 
    155     INF << pars.GetVersion() << " initializing..." << std::endl;
    156     Init(data_fname, cache_fname);
    157 
    158     return SCE_KERNEL_START_SUCCESS;
    159   }
    160 
    161 }