Result UnmapProcessMemoryEx(Handle processHandle, void *dst, u32 size)
{
    if(kernelVersion < SYSTEM_VERSION(2, 37, 0)) // < 6.x
        return UnmapProcessMemory(processHandle, dst, size); // equivalent when size <= 64MB

    KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);

    Result res = KProcessHwInfo__UnmapProcessMemory(currentHwInfo, dst, size >> 12);

    invalidateEntireInstructionCache();
    flushEntireDataCache();

    return res;
}
void Player::Init(int argc, char *argv[]) {
	static bool init = false;
	frames = 0;

	if (init) return;

	// Display a nice version string
	std::stringstream header;
	std::string addtl_ver(PLAYER_ADDTL);
	header << "EasyRPG Player " << PLAYER_VERSION;
	if (!addtl_ver.empty())
		header << " " << addtl_ver;
	header << " started";
	Output::Debug(header.str().c_str());

	unsigned int header_width = header.str().length();
	header.str("");
	header << std::setfill('=') << std::setw(header_width) << "=";
	Output::Debug(header.str().c_str());

#ifdef GEKKO
	// Init libfat (Mount SD/USB)
	if (!fatInitDefault()) {
		Output::Error("Couldn't mount any storage medium!");
	}
#elif defined(_3DS)
	// Starting debug console
	gfxInitDefault();
	consoleInit(GFX_BOTTOM, NULL);

	APT_SetAppCpuTimeLimit(30);
	if (osGetKernelVersion() <  SYSTEM_VERSION(2, 48, 3)) khaxInit(); // Executing libkhax just to be sure...
	consoleClear();

	// Check if we already have access to csnd:SND, if not, we will perform a kernel privilege escalation
	Handle csndHandle = 0;
	use_dsp = false;
#ifndef FORCE_DSP
	srvGetServiceHandleDirect(&csndHandle, "csnd:SND");
	if (csndHandle) {
		Output::Debug("csnd:SND has been selected as audio service.");
		svcCloseHandle(csndHandle);
	} else {
		Output::Debug("csnd:SND is unavailable...");
#endif
		srvGetServiceHandleDirect(&csndHandle, "dsp::DSP");
		if (csndHandle) {
			Output::Debug("dsp::DSP has been selected as audio service.");
			use_dsp = true;
			svcCloseHandle(csndHandle);
		} else {
			Output::Error("dsp::DSP is unavailable. Please dump a DSP firmware to use EasyRPG Player. If the problem persists, please report us the issue.");
		}
#ifndef FORCE_DSP
	}
#endif

	fsInit();
	sdmcInit();
#ifndef CITRA3DS_COMPATIBLE
	romfsInit();
#endif

	hidInit();

	// Enable 804 Mhz mode if on N3DS
	bool isN3DS;
	APT_CheckNew3DS(&isN3DS);
	if (isN3DS) {
		osSetSpeedupEnable(true);
	}
#endif

#if (defined(_WIN32) && defined(NDEBUG) && defined(WINVER) && WINVER >= 0x0600)
	InitMiniDumpWriter();
#endif

	srand(time(NULL));

	ParseCommandLine(argc, argv);

#ifdef EMSCRIPTEN
	Output::IgnorePause(true);

	// Create initial directory structure in our private area
	// Retrieve save directory from persistent storage
	EM_ASM(

		FS.mkdir("easyrpg");
		FS.chdir("easyrpg");

		var dirs = ['Backdrop', 'Battle', 'Battle2', 'BattleCharSet', 'BattleWeapon', 'CharSet', 'ChipSet', 'FaceSet', 'Frame', 'GameOver', 'Monster', 'Movie', 'Music', 'Panorama', 'Picture', 'Sound', 'System', 'System2', 'Title', 'Save'];
		dirs.forEach(function(dir) { FS.mkdir(dir) });

		FS.mount(IDBFS, {}, 'Save');

		FS.syncfs(true, function(err) {
		});
	);