Homebrew [Q] Possible to access DS carts and 3DS carts from the same homebrew app?

LeifEricson

Coming Soon™
OP
Member
Joined
Jun 22, 2012
Messages
234
Trophies
0
Age
27
Location
New York, USA
Website
www.youtube.com
XP
534
Country
United States
Hey all,

I'm working on a sort of interesting project (details to be revealed later) which can interface with not only 3DS game carts, but DS game carts as well. I've managed to implement DS cart functionality successfully using some of TWL Save Tool's code, but it seems that I cannot get both 3DS and DS support working at the same time. I want the user to be able to pick which type of cart at the start of the program.

Is this perhaps because of the rsf file (it's CIA only at the moment), which I've noticed needs a few "TWL" flags to be set for DS compatibility? Or is it just something in my code? (I've tried taking code directly from a few 3DS save managers but although they can read the cartID, any attempt to read data from the cart results in nothing happening, but strangely no errors.)

It's strange considering I'm directly using code from other save managers, the DS reading is working, but not the 3DS reading. I can try taking the rsf from it as well, but this of course would then break DS compatibility.
 
  • Like
Reactions: Drakia

Bedel

The key of the blade
Member
Joined
Oct 28, 2015
Messages
1,384
Trophies
0
XP
2,837
Country
United States
I don't think it is possible, but I don't know that much. Let's just speculate why it'd not work.
Once you use the TWL, it enters in DSi mode (I don't know if this is wright), so the 3DS is no longer ablible to use or read 3DS games. If this is the case, then maybe you should separate the code in more modules. Maybe not use anything from TWL if it's not really needed. I don't know.
I hope this cas be usefull, gl with your job.
 

Slashcash

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
338
Trophies
0
XP
611
Country
Italy
It SHOULD be possible. Probably we can tell you more if you show us the source code!

Of course it should be possible from a cia. The .3dsx won't work unless you boot under a process with can access both save and twl save
 
Last edited by Slashcash,

LeifEricson

Coming Soon™
OP
Member
Joined
Jun 22, 2012
Messages
234
Trophies
0
Age
27
Location
New York, USA
Website
www.youtube.com
XP
534
Country
United States
It SHOULD be possible. Probably we can tell you more if you show us the source code!

Of course it should be possible from a cia. The .3dsx won't work unless you boot under a process with can access both save and twl save

Here's my main as of now. It's pretty sloppy as I didn't implement a sort of proper state management class, but at the moment I'm solely focusing on getting working code before making it look pretty. Main interest should be the cartManager() call, which is almost directly copied from JKSM. It's also not really working as pasted right now but that's because I'm in the middle of switching code from PCHex++ (which I tried just because its filesystem code is pretty cleaned up), but it ended up not working so I'm in the process of going back to using JKSM's code.

EDIT: I also think I should mention that PCHex++'s code was able to read the cartID successfully and has its own error handling which never produced any errors, yet still resulted in an empty array.

Code:
#include <3ds.h>
#include "twl/TWLCard.h"
#include "twl/TWLLoad.h"
#include "jksm/cart.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <unistd.h>
#include <stdio.h>
#include <cstring>
using namespace std;

// Override the default service init/exit functions
extern "C" {
    void __appInit() {
        // Initialize services
        srvInit();
        aptInit();
        gfxInitDefault();
        hidInit();
        fsInit();
        sdmcInit();
        pxiDevInit();
        consoleInit(GFX_TOP, NULL);
    }

    void __appExit() {
        // Exit services
        pxiDevExit();
        sdmcExit();
        fsExit();
        hidExit();
        gfxExit();
        aptExit();
        srvExit();
    }
}

int main() {
    //ENVIROMENT INITIALIZATION
    string gameID = "";
    int game = 0;
    int state = 0;
    bool updateTop = true;
    vector<uint8_t> save(600000);
 
    // State 0 variables
    vector<string> st0choices;
    st0choices.push_back("NDS Pokemon Cartridge");
    st0choices.push_back("3DS Pokemon Cartridge");
    st0choices.push_back("SD Card Save File");
    int st0sel = 0;
 
    //MAIN LOOP
    while( aptMainLoop()) {
        hidScanInput();
        auto keys = hidKeysDown();
     
        if(keys & KEY_START) break;
     
        if(keys & KEY_A) {
            updateTop = true;
            if (state == 0) ++state;
        }
     
        if(keys & KEY_DDOWN) {
            updateTop = true;
            if (state == 0) { if(st0sel < st0choices.size()-1)++st0sel; else st0sel = 0; }
        }
        if(keys & KEY_DUP) {
            updateTop = true;
            if (state == 0) { if(st0sel > 0)--st0sel; else st0sel = st0choices.size()-1; }
        }
     
        if (updateTop) {
            consoleClear();
            updateTop = false;
            // Main menu state
            if (state == 0) {
                cout << "Choose SOURCE game type:\n\n";
                for (int i = 0; i < st0choices.size(); ++i) {
                   if (i == st0sel) cout << "\x1b[47;30m"+st0choices[i]+"\x1b[40;37m" << endl;
                   else cout << st0choices[i] << endl;
                }
            }
            // Save reading state
            else if (state == 1) {
                // NDS cart
                if (st0sel == 0) {
            // Stripped down TWL Tool main(), returns a u8 vector of loaded save and currently works
                    save = twlLoad(gameID);
                    if (gameID.size() == 0) break;
                    updateTop = true;
                    ++state;
                }
                // 3DS cart
                else if (st0sel == 1) {
                    // Stripped down JKSM cartManager(), uses JKSM functions to write save to file, then loads file back into u8 vector, please note that the written output file is 0 bytes and the vector becomes empty. Also note that PCHex++'s functions to read directly to a char buffer were tested and also returned empty arrays.
                    cartManager(save);
                }
                // SD Save
                else if (st0sel == 2) {

                }
            }
            // Debug state
            else if (state == 2) {
                cout << "Game ID: " << gameID << endl;
                if (save.size() > 200) {
                    for (int i = 0; i < 200; ++i) {
                        cout << hex << (int)save[i] << " ";
                    }
                }
                else cout << "Error loading save file!!";
            }
        }
        gfxFlushBuffers();
        gfxSwapBuffers();
        gspWaitForVBlank();
    }
 
 
    //ENVIROMENT CLEANING
    return 0;
}
 
Last edited by LeifEricson,

Joom

 ❤❤❤
Member
Joined
Jan 8, 2016
Messages
6,067
Trophies
1
Location
US
Website
mogbox.net
XP
6,077
Country
United States
No it doesn't.
HE HATH SPOKANE

On a serious note, I kinda figured the same thing; using TWL flags goes into a certain mode that doesn't read 3DS data properly. I was also thinking of a way to hot swap between modes if that were the case, but I guess it's not.

Also, I kinda giggled at the idea of Leif Ericson writing code. Hinga hurga horda.
 
Last edited by Joom,

TuxSH

Well-Known Member
Member
Joined
Oct 19, 2015
Messages
614
Trophies
1
Age
26
XP
1,295
Country
France
Hey all,

I'm working on a sort of interesting project (details to be revealed later) which can interface with not only 3DS game carts, but DS game carts as well. I've managed to implement DS cart functionality successfully using some of TWL Save Tool's code, but it seems that I cannot get both 3DS and DS support working at the same time. I want the user to be able to pick which type of cart at the start of the program.

Is this perhaps because of the rsf file (it's CIA only at the moment), which I've noticed needs a few "TWL" flags to be set for DS compatibility? Or is it just something in my code? (I've tried taking code directly from a few 3DS save managers but although they can read the cartID, any attempt to read data from the cart results in nothing happening, but strangely no errors.)

It's strange considering I'm directly using code from other save managers, the DS reading is working, but not the 3DS reading. I can try taking the rsf from it as well, but this of course would then break DS compatibility.
Try stripping those flags ... ?
 

Slashcash

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
338
Trophies
0
XP
611
Country
Italy
Here's my main as of now. It's pretty sloppy as I didn't implement a sort of proper state management class, but at the moment I'm solely focusing on getting working code before making it look pretty. Main interest should be the cartManager() call, which is almost directly copied from JKSM. It's also not really working as pasted right now but that's because I'm in the middle of switching code from PCHex++ (which I tried just because its filesystem code is pretty cleaned up), but it ended up not working so I'm in the process of going back to using JKSM's code.

EDIT: I also think I should mention that PCHex++'s code was able to read the cartID successfully and has its own error handling which never produced any errors, yet still resulted in an empty array.

Given that your .rsf has all the correct flags uncommented (you could look at PCHex++'s rsf file, but i don't think this is the problem since PCHex++'s code would return an error when opening the save archive) i can't see nothing wrong in the code you posted because it is just gui code.

Would you mind showing the cartManager() function and his signature? There should be something wrong there.

As a side note, i don't think this should be the problem as you seem pretty aware of what you are doing, but just in case, are you possibly doing

Code:
void callManager(std::vector<uint8_t> buffer)

Because if that's the case the reason why you are getting an empty vector is pretty obvious (and it would explain why the nds reading is working instead)

of course the correct signature is:

Code:
void callManager(std::vector<uint8_t> &buffer)

(PS: if you need some help in interpreting PCHex++ filesystem code you can pm me for my skype id)

[EDIT]In all honesty i never tested if having both the twl and the save flag stripped down causes any problem, i would say no but who knows...
 
Last edited by Slashcash,

LeifEricson

Coming Soon™
OP
Member
Joined
Jun 22, 2012
Messages
234
Trophies
0
Age
27
Location
New York, USA
Website
www.youtube.com
XP
534
Country
United States
Given that your .rsf has all the correct flags uncommented (you could look at PCHex++'s rsf file, but i don't think this is the problem since PCHex++'s code would return an error when opening the save archive) i can't see nothing wrong in the code you posted because it is just gui code.

Would you mind showing the cartManager() function and his signature? There should be something wrong there.

As a side note, i don't think this should be the problem as you seem pretty aware of what you are doing, but just in case, are you possibly doing

Code:
void callManager(std::vector<uint8_t> buffer)

Because if that's the case the reason why you are getting an empty vector is pretty obvious (and it would explain why the nds reading is working instead)

(PS: if you need some help in interpreting PCHex++ filesystem code you can pm me for my skype id)

[EDIT]In all honesty i never tested if having both the twl and the save flag stripped down causes any problem, i would say no but who knows...

I PM'd you, I really appreciate it Slashcash. I'll share any code you'd like to see with you over Skype.
 

LeifEricson

Coming Soon™
OP
Member
Joined
Jun 22, 2012
Messages
234
Trophies
0
Age
27
Location
New York, USA
Website
www.youtube.com
XP
534
Country
United States
Given that your .rsf has all the correct flags uncommented (you could look at PCHex++'s rsf file, but i don't think this is the problem since PCHex++'s code would return an error when opening the save archive) i can't see nothing wrong in the code you posted because it is just gui code.

Would you mind showing the cartManager() function and his signature? There should be something wrong there.

As a side note, i don't think this should be the problem as you seem pretty aware of what you are doing, but just in case, are you possibly doing

Code:
void callManager(std::vector<uint8_t> buffer)

Because if that's the case the reason why you are getting an empty vector is pretty obvious (and it would explain why the nds reading is working instead)

of course the correct signature is:

Code:
void callManager(std::vector<uint8_t> &buffer)

(PS: if you need some help in interpreting PCHex++ filesystem code you can pm me for my skype id)

[EDIT]In all honesty i never tested if having both the twl and the save flag stripped down causes any problem, i would say no but who knows...

Quick update, switched back to PCHex++ code, turns out I still get no error codes. Even tried using your .rsf. The code below never enters the errorLoop() function, but instead goes to state 2 which was shown earlier, but complains about an empty save vector. Here's what my relevant snippet looks like now:

Code:
else if (state == 1) {
                // NDS Card
                if (st0sel == 0) {
                    save = twlLoad(gameID); // Stripped down TWL Save Tool's main()
                    if (gameID.size() == 0) { errorLoop("twlLoad", 1); break; }
                }
                // 3DS Card
                else if (st0sel == 1) {
                    // Direct code from PCHex++ (unmodified)
                    int ret = FileSystem::romFsInit();
                    if (ret) { errorLoop("romFsInit", ret); break; }
                    ret = FileSystem::initialize(-1, FileSystem::CART); // This returns 0x113 every time...
                                                                  // (game set to -1 since always uses CART condition)
                    if (ret) { errorLoop("FS::initialize", ret); break; }
                    Savefile test;
                    ret = test.loadSaveFile();
                    if (ret) { errorLoop("loadSaveFile", ret); break; }   
                    save = test.getSaveVector(); // Custom method     
                }
                // SD Save File
                else if (st0sel == 2) {

                }

...

EDIT: Here's the getSaveVector method I added to savefile.cpp:

Code:
std::vector<uint8_t> Savefile::getSaveVector() {
    std::vector<uint8_t> saveVec(sizeof(save));
    memcpy(&saveVec[0], save, sizeof(save));
    return saveVec;
}

--------------------- MERGED ---------------------------

Try stripping those flags ... ?

I tried using PCHex++'s code and its .rsf file directly (which has no TWL flags but all the right "3ds" cart flags) and still no luck.
 
Last edited by LeifEricson, , Reason: Derp'd and realized there's no return codes as of now

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    OctoAori20 @ OctoAori20: Not a lot, just relaxing