Working on a 3DS Port

I assume you already know, but the log writer in output.cpp writes to the project path if the save path is not set.

My 3DS has no custom firmware at all. I can’t launch CIAs.

(carstene1ns was faster but I already wrote all that text :P):

Yes the Player writes into the project directory when no save path is specified.

There are multiple ways to solve this: When a CIA can pass command line arguments you can use “–save-path” to point to a different writable location. Save path is not perfectly named, this is for write operations in general, the logfile will also appear there.

If CLI arguments are not possible you have to change the “GetSavePath” function in main_data.cpp.

[quote=“Ghabry”]My 3DS has no custom firmware at all. I can’t launch CIAs.

(carstene1ns was faster but I already wrote all that text :P):

Yes the Player writes into the project directory when no save path is specified.

There are multiple ways to solve this: When a CIA can pass command line arguments you can use “–save-path” to point to a different writable location. Save path is not perfectly named, this is for write operations in general, the logfile will also appear there.

If CLI arguments are not possible you have to change the “GetSavePath” function in main_data.cpp.[/quote]

Yeah i noticed that but i thought what i’ve already changed SavePath (or not?): github.com/Rinnegatamante/easyr … pp#L80-L90
EDIT: ihaveamac tested romFs also in a 3DSX and it resulted in a system crash.

Yep, this seems ok.
However, one thing to note is: a game does not need to have a Map0001.lmu file. The editor supports shuffling maps around.
A better file to check for is IMHO the map tree or database, because they always exist (RPG_RT.lmt/ldb).

Just a random guess, but is the sd filesystem initialized when the romfs is used?
For example, if we boot up from SD on Wii, we do not have access to the USB drive(s) before mounting.

Yes, filesystems are both mounted.

The problem on trying to fix romFs is that Citra apparently doesn’t support it making debugging quite difficult :frowning:

github.com/citra-emu/citra/issues/1412

I’m quite sure the problem is in ctrulib itself since the same code works fine for sdmc. I’ve pushed the modifications to the repository if you want to take a look. ( github.com/Rinnegatamante/easyr … 3b595b1383 )

EDIT: Simply increasing BGM buffer size looks like partially solved the audiostream speed on csnd apparently but there still are problems with 120-150% pitched 44100 hz musics (strangely more problems are in 120% O.o): github.com/Rinnegatamante/easyr … a09264b441

I was thinking to add a simple samplerate limiter to 44100/48000 HZ as max value to BGM_Pitch, since i find really hard to let 3DS work on higher samplerates without any problem. What do you think about it?

EDIT2: I’m quite sure mutex are not working as intended (or something strange is happening with csnd) since depending on when you call BGM_Pitch, audio streaming could or not broke (even with low samplerates). Experienced the same problems even with LightLocks :confused:
At least LightLocks fixed dsp::DSP wrapper, now it works with BGM_Pitch <.< Also with the samplerate limiter at 48k HZ, BGM_Pitch works PERFECTLY on dsp.

Finally solved all the issued with BGM_Pitch on both csnd:SND and dsp::DSP. Now both play good with the samplerate limiter at 48k hz. Looks like csnd:SND is pretty slow to apply cmds modifications. That’s what was causing problems. A sleepThread did the trick :stuck_out_tongue: github.com/Rinnegatamante/easyr … 1f89699a7f

Tested a bit more for romFs issue, this code doesn’t crash so i really don’t know where could be the problem in easyrpg. If you have some idea…

[code]int main()
{
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
sdmcInit();
Result rc = romfsInit();
if (rc)
printf(“romfsInit: %08lX\n”, rc);
else
{
printf(“romfs Init Successful!\n”);
DIR* a = opendir(“romfs:/”); // opendir on romfs:/
if (a != NULL){
printf(“success! 1\n”);
closedir(a);
}else printf(“failure… 1\n”);
a = opendir(“romfs:/test_dir/”); // opendir on an existent folder
if (a != NULL){
printf(“success! 2\n”);
closedir(a);
}else printf(“failure… 2\n”);
FILE* b = fopen(“romfs:/file.txt”,“r”); // fopen on existent file
if (b != NULL){
printf(“success! 3\n”);
fclose(b);
}else printf(“failure… 3\n”);
b = fopen(“romfs:/test_dir/file.txt”,“r”); // fopen on existent subfile
if (b != NULL){
printf(“success! 4\n”);
fclose(b);
}else printf(“failure… 4\n”);
b = fopen(“romfs:/test_dir/files.txt”,“r”); // fopen on non-existent subfile
if (b != NULL){
printf(“success! 5\n”);
fclose(b);
}else printf(“failure… 5\n”);
b = fopen(“romfs:/test_dir/”,“r”); // fopen on existent directory
if (b != NULL){
printf(“success! 6\n”);
fclose(b);
}else printf(“failure… 6\n”);
a = opendir(“romfs:/test_dir/files.txt”); // opendir on non-existent subfile
if (a != NULL){
printf(“success! 7\n”);
closedir(a);
}else printf(“failure… 7\n”);
b = fopen(“romfs:/”,“r”); // fopen on romfs:/
if (b != NULL){
printf(“success! 8\n”);
fclose(b);
}else printf(“failure… 8\n”);
///////////////////
a = opendir(“sdmc:/”); // opendir on sdmc:/
if (a != NULL){
printf(“success! 1\n”);
closedir(a);
}else printf(“failure… 1\n”);
a = opendir(“sdmc:/test_dir/”); // opendir on an existent folder
if (a != NULL){
printf(“success! 2\n”);
closedir(a);
}else printf(“failure… 2\n”);
b = fopen(“sdmc:/file.txt”,“r”); // fopen on existent file
if (b != NULL){
printf(“success! 3\n”);
fclose(b);
}else printf(“failure… 3\n”);
b = fopen(“sdmc:/test_dir/file.txt”,“r”); // fopen on existent subfile
if (b != NULL){
printf(“success! 4\n”);
fclose(b);
}else printf(“failure… 4\n”);
b = fopen(“sdmc:/test_dir/files.txt”,“r”); // fopen on non-existent subfile
if (b != NULL){
printf(“success! 5\n”);
fclose(b);
}else printf(“failure… 5\n”);
b = fopen(“sdmc:/test_dir/”,“r”); // fopen on existent directory
if (b != NULL){
printf(“success! 6\n”);
fclose(b);
}else printf(“failure… 6\n”);
a = opendir(“sdmc:/test_dir/files.txt”); // opendir on non-existent subfile
if (a != NULL){
printf(“success! 7\n”);
closedir(a);
}else printf(“failure… 7\n”);
b = fopen(“sdmc:/”,“r”); // fopen on sdmc:/
if (b != NULL){
printf(“success! 8\n”);
fclose(b);
}else printf(“failure… 8\n”);
b = fopen(“sdmc:/”,“r”); // fopen on sdmc:/
}

// Main loop
while (aptMainLoop())
{
	gspWaitForVBlank();
	hidScanInput();

	u32 kDown = hidKeysDown();
	if (kDown & KEY_START)
		break; // break in order to return to hbmenu
}

romfsExit();
gfxExit();
return 0;

}[/code]

EDIT: I’ve re-enabled the debug console and finally i found something interesting that probably causes the crash:

Found where’s the problem, easyrpg checks for romfs://Charset and not romfs:/Charset resulting in a Exists = false. This will bring to an assertion failed and to a system crash.

EDIT: Finally fixed, now CIA build works perfectly! Probably there are better way to patch the problem, i opted for the shittiest one, i know :stuck_out_tongue: If @Ghabry or @carstene1ns can take a look at it and properly correct it, it could be very good :stuck_out_tongue:

romfs:// should still work because this says “/” on romfs. Under Linux doing “///tmp” would still open “/tmp”. Well, whatever.

Up to date (jenkins managed) toolchains are now available under
easy-rpg.org/jenkins/view/Toolc … ain.tar.gz

Includes ctrulib, sf2dlib and khax.

This doesn’t include liblcf because liblcf is often recompiled due to Player:
easy-rpg.org/jenkins/job/liblcf … 3ds.tar.gz

Just extract both archives in the same folder.

Using your ctrulib+sf2dlib+libkhax resulted in a black screen right after libkhax execution. All three libraries are bigger then mine and final 3dsx seems to be a lot smaller (200 KBs)

Excellent, thanks for confirming that the libs are broken.

Could you upload your ctrulib+sf2dlib+libkhax directories? (all source files + Makefile) and the compiled libraries? Have to compare them to figure out what I’m doing wrong.

My compilation steps (ripped out of the buildscript):

git clone https://github.com/smealum/ctrulib.git 

git clone https://github.com/xerpi/sf2dlib.git 

git clone https://github.com/Rinnegatamante/lpp-3ds_libraries.git 

cd ctrulib/libctru/
make clean
make
cp -r include/* ../../include/
cp -r lib/* ../../lib/
cd ../..

cd sf2dlib/libsf2d/
make clean
make
cp -r include/* ../../include/
cp -r lib/* ../../lib/
cd ../..

cd lpp-3ds_libraries/source_libkhax/
make clean
make
cp *.h ../../include/
cp -r lib/* ../../lib/
cd ../..

And here is the khax makefile: github.com/EasyRPG/buildscripts … le_libkhax

For libctru i used latest commit on smea’s repo.
For sf2dlib i used this: github.com/Rinnegatamante/lpp-3 … ce_libsf2d
For libkhax, it seems to work fine since it was the only thing i got printed on screen <.< Anyway i use also this: github.com/Rinnegatamante/lpp-3 … ce_libkhax but without svchax things.

How am I supposed to create a working library from your repository? Your Makefile compiles nothing for me (I’m compiling on Linux btw so I had to fix that C:\ aemstro line) except an empty “generic_lib.a” and the other directories don’t contain a Makefile.

EDIT:
And which Version of sf2dlib is your repo based on. When I diff it with upstream the Code is totally different.

[quote=“Ghabry”]How am I supposed to create a working library from your repository? Your Makefile compiles nothing for me (I’m compiling on Linux btw so I had to fix that C:\ aemstro line) except an empty “generic_lib.a” and the other directories don’t contain a Makefile.

EDIT:
And which Version of sf2dlib is your repo based on. When I diff it with upstream the Code is totally different.[/quote]

You must edit in Makefile this line: github.com/Rinnegatamante/lpp-3 … kefile#L21

With the dir you want to compile.
You also should place a working libctru repo in libctru folder (atm it uses a modified libctru since lpp-3ds needs some modifications for DSP service, so you can replace libctru folder with smea cloned repo).
Also you should change mfloat-abi to hard.

As for libsf2d, it’s basically latest commit but with some slight changes for example here (since lpp-3ds (and easyrpg too) initiliazes gfx for console usage before sf2dlib init): github.com/Rinnegatamante/lpp-3 … .c#L59-L62

Nope is still not working. But I havn’t tried it with your Player repository yet, maybe I broke something again while merging the upstream code.

But at least the debug console does not dissapear anymore after initializing sf2dlib.

These are some hashes values for my generated 3dsx file if it could be helpful:

Filesize is: 5.162.332 bytes

Every compilation changes the hash because the binaries contain timestamps.

Most useful for me would be when you could upload your libctru.a, libsf2d.a and libkhax.a.
When it also crashes with your libs I can be sure that it is a problem with my branch.

[quote=“Ghabry”]Every compilation changes the hash because the binaries contain timestamps.

Most useful for me would be when you could upload your libctru.a, libsf2d.a and libkhax.a.
When it also crashes with your libs I can be sure that it is a problem with my branch.[/quote]

Here you are: rinnegatamante.it/lib.rar

About the path issue (double slashes): It really depends on the underlying kernel and filesystem.
For example under linux and other Unices it works to write …/this//lower and it will still find it from the upper folder, because it resolves the path correctly (using realpath() and friends).
I also encountered this problem when testing the gamebrowser code (it adds another slash to the game folder path btw.).
What we could do is add some sanitze_path() function, that strips additional separators (slash or backslash, depending on platform), but a better idea would be to check for a separator in the last place of the game directory and add it, if necessary. Then all folders can be added without additional separators (from the game browser and even the filefinder).