Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions 3ds/include/archive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ namespace Archive {
FS_Archive sdmc(void);

Result save(FS_Archive* archive, FS_MediaType mediatype, u32 lowid, u32 highid);
Result rawSave(FSPXI_Archive* archive, FS_MediaType mediatype, u32 lowid, u32 highid);
Result extdata(FS_Archive* archive, u32 extdata);
bool accessible(FS_MediaType mediatype, u32 lowid, u32 highid); // save
bool accessibleRaw(FS_MediaType mediatype, u32 lowid, u32 highid); // raw save
bool accessible(u32 extdata); // extdata
bool setPlayCoins(void);
}
Expand Down
43 changes: 43 additions & 0 deletions 3ds/include/csvc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* This paricular file is licensed under the following terms: */

/*
* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable
* for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it
* and redistribute it freely, subject to the following restrictions:
*
* The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
*
* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
* This notice may not be removed or altered from any source distribution.
*/

/* This file was modified from https://github.com/AuroraWright/Luma3DS to only have svcControlService */

#pragma once

#include <3ds/types.h>

/// Operations for svcControlService
enum ServiceOp
{
SERVICEOP_STEAL_CLIENT_SESSION = 0, ///< Steal a client session given a service or global port name
SERVICEOP_GET_NAME, ///< Get the name of a service or global port given a client or session handle
};

inline Handle FsPxiHandle;

extern "C"
{
/**
* @brief Performs actions related to services or global handles.
* @param op The operation to perform, see @ref ServiceOp.
*
* Examples:
* svcControlService(SERVICEOP_GET_NAME, (char [12])outName, (Handle)clientOrSessionHandle);
* svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, (Handle *)&outHandle, (const char *)name);
*/
Result svcControlService(ServiceOp op, ...);
}
9 changes: 7 additions & 2 deletions 3ds/include/fsstream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@

#include <3ds.h>
#include <string>
#include <variant>

using MultiHandle = std::variant<FSPXI_File, Handle>;

class FSStream {
public:
FSStream(FS_Archive archive, const std::u16string& path, u32 flags);
FSStream(FS_Archive archive, const std::u16string& path, u32 flags, u32 size);
~FSStream(void){};
FSStream(FSPXI_Archive archive, u32 flags);
FSStream(FSPXI_Archive archive, u32 flags, u32 size);
~FSStream(){};

Result close(void);
bool eof(void);
Expand All @@ -47,7 +52,7 @@ class FSStream {
u32 write(const void* buf, u32 size);

private:
Handle mHandle;
MultiHandle mHandle;
u32 mSize;
u32 mOffset;
Result mResult;
Expand Down
1 change: 1 addition & 0 deletions 3ds/include/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace io {

Result copyDirectory(FS_Archive srcArch, FS_Archive dstArch, const std::u16string& srcPath, const std::u16string& dstPath);
void copyFile(FS_Archive srcArch, FS_Archive dstArch, const std::u16string& srcPath, const std::u16string& dstPath);
Result copyPxiSaveFile(FSPXI_Archive pxiArch, FS_Archive regularArch, const std::u16string& path, bool fromPxi);
Result createDirectory(FS_Archive archive, const std::u16string& path);
void deleteBackupFolder(const std::u16string& path);
Result deleteFolderRecursively(FS_Archive arch, const std::u16string& path);
Expand Down
6 changes: 4 additions & 2 deletions 3ds/include/title.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Title {
~Title(void);

bool accessibleSave(void);
bool isGBAVC(void);
bool accessibleExtdata(void);
FS_CardType cardType(void);
std::vector<std::u16string> extdata(void);
Expand All @@ -64,8 +65,8 @@ class Title {
bool isActivityLog(void);
void load(void);
bool load(u64 id, FS_MediaType mediaType, FS_CardType cardType);
void load(u64 id, u8* productCode, bool accessibleSave, bool accessibleExtdata, std::u16string shortDescription, std::u16string longDescription,
std::u16string savePath, std::u16string extdataPath, FS_MediaType media, FS_CardType cardType, CardType card);
void load(u64 id, u8* productCode, bool accessibleSave, bool saveIsGBA, bool accessibleExtdata, std::u16string shortDescription,
std::u16string longDescription, std::u16string savePath, std::u16string extdataPath, FS_MediaType media, FS_CardType cardType, CardType card);
std::string longDescription(void);
std::u16string getLongDescription(void);
u32 lowId(void);
Expand Down Expand Up @@ -96,6 +97,7 @@ class Title {
std::vector<std::u16string> mExtdata;
std::vector<std::u16string> mFullExtdataPaths;
u64 mId;
bool mGBA;
FS_MediaType mMedia;
FS_CardType mCard;
CardType mCardType;
Expand Down
30 changes: 28 additions & 2 deletions 3ds/source/archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/

#include "archive.hpp"
#include "fsstream.hpp"
#include "csvc.hpp"

static FS_Archive mSdmc;
static Mode_t mMode = MODE_SAVE;
Expand All @@ -41,7 +43,9 @@ void Archive::mode(Mode_t v)

Result Archive::init(void)
{
return FSUSER_OpenArchive(&mSdmc, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
Result res = FSUSER_OpenArchive(&mSdmc, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
if(R_FAILED(res)) return res;
return svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, &FsPxiHandle, "PxiFS0");
}

void Archive::exit(void)
Expand All @@ -67,6 +71,12 @@ Result Archive::save(FS_Archive* archive, FS_MediaType mediatype, u32 lowid, u32
return 0;
}

Result Archive::rawSave(FSPXI_Archive* archive, FS_MediaType mediatype, u32 lowid, u32 highid)
{
const u32 path[4] = {lowid, highid, mediatype, 1};
return FSPXI_OpenArchive(FsPxiHandle, archive, ARCHIVE_SAVEDATA_AND_CONTENT, {PATH_BINARY, 16, path});
}

Result Archive::extdata(FS_Archive* archive, u32 ext)
{
const u32 path[3] = {MEDIATYPE_SD, ext, 0};
Expand All @@ -84,6 +94,22 @@ bool Archive::accessible(FS_MediaType mediatype, u32 lowid, u32 highid)
return false;
}

bool Archive::accessibleRaw(FS_MediaType mediatype, u32 lowid, u32 highid)
{
FSPXI_Archive archive;
Result res = rawSave(&archive, mediatype, lowid, highid);
if (R_SUCCEEDED(res)) {
FSStream file(archive, FS_OPEN_READ);
if(file.good())
{
file.close();
FSPXI_CloseArchive(FsPxiHandle, archive);
return true;
}
}
return false;
}

bool Archive::accessible(u32 ext)
{
FS_Archive archive;
Expand Down Expand Up @@ -118,4 +144,4 @@ bool Archive::setPlayCoins(void)
FSUSER_CloseArchive(archive);
}
return false;
}
}
36 changes: 36 additions & 0 deletions 3ds/source/csvc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@ This paricular file is licensed under the following terms:

@ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable
@ for any damages arising from the use of this software.
@
@ Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it
@ and redistribute it freely, subject to the following restrictions:
@
@ The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
@ If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
@
@ Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
@ This notice may not be removed or altered from any source distribution.

@ This file was modified from https://github.com/AuroraWright/Luma3DS to only have svcControlService

.arm
.balign 4

.macro SVC_BEGIN name
.section .text.\name, "ax", %progbits
.global \name
.type \name, %function
.align 2
.cfi_startproc
\name:
.endm

.macro SVC_END
.cfi_endproc
.endm

SVC_BEGIN svcControlService
svc 0xB0
bx lr
SVC_END
97 changes: 90 additions & 7 deletions 3ds/source/fsstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,19 @@
*/

#include "fsstream.hpp"
#include "csvc.hpp"

FSStream::FSStream(FS_Archive archive, const std::u16string& path, u32 flags)
{
mGood = false;
mSize = 0;
mOffset = 0;
Handle hnd;

mResult = FSUSER_OpenFile(&mHandle, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
mResult = FSUSER_OpenFile(&hnd, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
if (R_SUCCEEDED(mResult)) {
FSFILE_GetSize(mHandle, (u64*)&mSize);
FSFILE_GetSize(hnd, (u64*)&mSize);
mHandle = hnd;
mGood = true;
}
}
Expand All @@ -44,12 +47,13 @@ FSStream::FSStream(FS_Archive archive, const std::u16string& path, u32 flags, u3
mGood = false;
mSize = size;
mOffset = 0;
Handle hnd;

mResult = FSUSER_OpenFile(&mHandle, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
mResult = FSUSER_OpenFile(&hnd, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
if (R_FAILED(mResult)) {
mResult = FSUSER_CreateFile(archive, fsMakePath(PATH_UTF16, path.data()), 0, mSize);
if (R_SUCCEEDED(mResult)) {
mResult = FSUSER_OpenFile(&mHandle, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
mResult = FSUSER_OpenFile(&hnd, archive, fsMakePath(PATH_UTF16, path.data()), flags, 0);
if (R_SUCCEEDED(mResult)) {
mGood = true;
}
Expand All @@ -58,11 +62,58 @@ FSStream::FSStream(FS_Archive archive, const std::u16string& path, u32 flags, u3
else {
mGood = true;
}

mHandle = hnd;
}

static const u32 pxi_path[5] = {
1,
1,
3,
0,
0
};
FSStream::FSStream(FSPXI_Archive archive, u32 flags)
{
mGood = false;
mSize = 0;
mOffset = 0;
FSPXI_File hnd;

mResult = FSPXI_OpenFile(FsPxiHandle, &hnd, archive, {PATH_BINARY, 20, pxi_path}, flags, 0);
if(R_SUCCEEDED(mResult))
{
FSPXI_GetFileSize(FsPxiHandle, hnd, (u64*)&mSize);
mHandle = hnd;
mGood = true;
}
}

FSStream::FSStream(FSPXI_Archive archive, u32 flags, u32 size)
{
mGood = false;
mSize = size;
mOffset = 0;
FSPXI_File hnd;

mResult = FSPXI_OpenFile(FsPxiHandle, &hnd, archive, {PATH_BINARY, 20, pxi_path}, flags, 0);
if(R_SUCCEEDED(mResult))
{
mHandle = hnd;
mGood = true;
}
}

Result FSStream::close(void)
{
mResult = FSFILE_Close(mHandle);
if(mHandle.index() == 0)
{
mResult = FSPXI_CloseFile(FsPxiHandle, std::get<0>(mHandle));
}
else
{
mResult = FSFILE_Close(std::get<1>(mHandle));
}
return mResult;
}

Expand All @@ -81,10 +132,26 @@ u32 FSStream::size(void)
return mSize;
}

using ReadFunction = Result(*)(MultiHandle, u32*, u64, void*, u32);
u32 FSStream::read(void* buf, u32 sz)
{
u32 rd = 0;
mResult = FSFILE_Read(mHandle, &rd, mOffset, buf, sz);
ReadFunction calling = nullptr;

if(mHandle.index() == 0)
{
calling = [](MultiHandle hnd, u32* readAmount, u64 off, void* b, u32 s) -> Result {
return FSPXI_ReadFile(FsPxiHandle, std::get<0>(hnd), readAmount, off, b, s);
};
}
else
{
calling = [](MultiHandle hnd, u32* readAmount, u64 off, void* b, u32 s) -> Result {
return FSFILE_Read(std::get<1>(hnd), readAmount, off, b, s);
};
}

mResult = calling(mHandle, &rd, mOffset, buf, sz);
if (R_FAILED(mResult)) {
if (rd > sz) {
rd = sz;
Expand All @@ -94,10 +161,26 @@ u32 FSStream::read(void* buf, u32 sz)
return rd;
}

using WriteFunction = Result(*)(MultiHandle, u32*, u64, const void*, u32);
u32 FSStream::write(const void* buf, u32 sz)
{
u32 wt = 0;
mResult = FSFILE_Write(mHandle, &wt, mOffset, buf, sz, FS_WRITE_FLUSH);
WriteFunction calling = nullptr;

if(mHandle.index() == 0)
{
calling = [](MultiHandle hnd, u32* readAmount, u64 off, const void* b, u32 s) -> Result {
return FSPXI_WriteFile(FsPxiHandle, std::get<0>(hnd), readAmount, off, b, s, FS_WRITE_FLUSH);
};
}
else
{
calling = [](MultiHandle hnd, u32* readAmount, u64 off, const void* b, u32 s) -> Result {
return FSFILE_Write(std::get<1>(hnd), readAmount, off, b, s, FS_WRITE_FLUSH);
};
}

mResult = calling(mHandle, &wt, mOffset, buf, sz);
mOffset += wt;
return wt;
}
Expand Down
Loading