Zalo DS Blog

Sunday, July 19, 2015

3DS Homebrew Tips and Tricks (III)

This is the 3rd post on the series 3DS Homebrew Tips and Tricks
3DS Homebrew Tips and Tricks (I)
3DS Homebrew Tips and Tricks (II)
3DS Homebrew Tips and Tricks (III)

6. Adding sound permissions to 3ds files

Searching on the forums about sound you will find posts saying you cannot have sound using 3ds or 3dsx format (for example take a look af the F.A.Q in the blargsnes site or their wiki). So I spent a few days implementing my sound driver using the cia format that was supposed to be the only one supporting sound

That was hell. Everytime I needed to change anything I had to create the cia, transfer that to the console somehow (microsd management turned out to be the best option), delete the previous cia and install the new one. There wasn't anyway that I was aware of to automatize the whole big process.

Then I found this post clearly stating that the only thing you needed for having sound support in 3ds files is adding ns:s, am:u and csnd:SND service access on your rsf. Take a look here.

With the new ninjhax 2.0 released it seems that sound is also supported now on 3dsx files


It took me a few weeks to catch a random crash (the best of them) on one of the tests I was doing. At the end it turned out it was caused by using GPU_TRIANGLE_FAN somewhere on my code. After replacing that with just GPU_TRIANGLES it never happened again. 

Talking about this on #3dsdev on the irc channel there seemed to be at least one other person having the same issue. Probably there is still something wrong on the ctrulib with them so I would recommend not using them if you can.

8. Using RomFS

RomFS is the file system used by 3ds and cia files to store resources inside the rom itselt. Although there are some tools available for extracting it from dumped roms and then putting it back, the ctrulib doesn't have support for it yet.

I thought it would be great if I could distribute my apps without any external dependencies so I took a look into it. 

There are two ways to include a romfs into your builds:
 - The first is creating it with an external tool (like RomFS Builder) then using the -romfs option when calling makerom.
 - The second hasn't been fully implemented (according to 3dbrew) but it worked for my particular case. On the rsf file you should add
  # Specifies the root path of the file system to include in the ROM.
  RootPath                : "../bin/romfs"
The rootpath is relative to your makefile's location

With any of these options you will have a rom that includes a file system with the resources. Now, how do you get access to them? Take a look at the code I posted on this thread.

This code only gives you access to the romfs. Now because we don't have support for this filesystem we have two options:
- Implement it
- User another known Filesystem

I went for the second one. Since I worked a lot with .zip files when I ported the engine to Android I decided to use the same thing here. So basically, my filesystem is a zip file containing all my resoures placed inside a romfs.

Since this zip is the only file available on my romfs I just do a search of the string "PK" from the beginning of the romfs and there is my zip file located. Hacky, but works pretty well

9. Painting steps: clean, render, transfer and swap

As I said before my starting point was the gpu example. If you spend some time trying to understand how it works you'll soon realize this is what happens after the GPUCMD_Finalize() command:

- GPUCMD_FlushAndRun is called and the command list is processed making the rendering
- GX_SetDisplayTransfer is called after that and the content of the framebuffer is trasnferred to the specified LCD framebuffer
- GX_SetMemoryFill is called, cleaning the color and depth buffer
- gfxSwapBuffersGpu is finally called, swapping buffers (because the ctrulib by default uses double buffer)

This process happens for a single render, if you are using the 3D effect it will happen twice, once for each screen (I am just simplifying it)

So basically: we render the current frame, transfer it to the proper LCD, clean the frame and then do the double buffer swap. Anything strange here? We are cleaning the screen for the next frame before the next frame actually happens, and that's a bad idea because:
- At some points on my code I was changing the clear color and that was delayed one frame. 
- At some points on my code I wasn't interested on cleaning the color buffer for a specific frame and it was being cleaned in advance

This is actually easy to fix if you move that call to GX_SetMemoryFill to the beginning (before calling GPUCMD_FlushAndRun). Don't forget to move also the call to gspWaitForPSC0, and ensure that you actually want to clear the current color buffer or depth buffer.

10. Improving the 3D steresocopic effect

Another problem that I found with the gpu example is that no matter how you place the 3D slider on the console it is very hard to the get the feelling of 3d. Taking  a look at the code I found these calculations being done for each eye:

mtx44 m; 
translateMatrix((float*)m, interaxial*0.5f, 0.0f, 0.0f); 

what this is doing is adding a translation to the whole render process for each eye. So basically moving the camera to the left for the left eye and to the right to the right eye. It just doesn't work well. I changed it into this

mtx44 m; 
rotateMatrixY((float*)m, -slider * 0.06f, false);

which rotates the camera instead of displacing it for each eye. This works way more better :)

And that's it. I have concluded these series of posts. I just hope anything I had been writing these days will be useful for someone and I would like to see more homebrews released on this amazing console. Specially games.

Happy coding!

Saturday, July 18, 2015

3DS Homebrew Tips and Tricks (II)

This is the 2nd post on the series 3DS Homebrew Tips and Tricks
3DS Homebrew Tips and Tricks (I)
3DS Homebrew Tips and Tricks (II)
3DS Homebrew Tips and Tricks (III)

3. Application Icon, banner and RSF

If you are going to distribute your creations on cia or 3ds format then you are going to need a banner and an icon. For this I am using bannertool  cerated by Steveice10. You can find a compiled version of it on this thread

- Icons: you create icons using this:

bannertool makesmdh -s $(APP_TITLE) -l $(APP_DESCRIPTION) -p $(APP_AUTHOR) -i icon.png -o icon.smdh

where icon.png should be a 48x48 image. You can define AP_TITLE APP_DESCRIPTION and APP_AUTHOR somewhere else in your makefile, like this

APP_TITLE := "Jumping Jack" 
APP_AUTHOR := "Zalo" 
APP_DESCRIPTION  := "My very first game for the 3DS"

Icons should alse be distributed with your 3dsx file so the homebrew launcher can display information about your homebrew

- Banners: you create banners using this

bannertool  makebanner -i banner.png -a audio.wav -o banner.bin  

where banner.png is a  256x128 image (you can use transparency) and audio.wav I am not sure but I am always using 16 bits, 44100 Hz and stereo for them

- RSF: this files are configurations files for your project. You need a different one depending if you are going to build a cia or a 3ds. There are two good examples on Rinnegatamante's Lua Player Plus for 3DS. Here is the rsf for 3ds with audio support (see point 6) and the rsf for cia files. You only need to edit the BasicInfo and TitleInfo usually. For the TitleInfo you are gonna need a UniqueId. It is recommented to use and ID between 0xF8000 -0xFFFFF or 0xFF000 - 0xFF3FF which is used for Evaulations and Prototypes, ensuring you won't have a collision with a released app. To ensure you don't collide with another homebrew take a look at this post

The banner, the icon and the rsf are required for makerom to create your 3ds using the command

makerom -f cci -o $(PROJECT_NAME).3ds -rsf gw_workaround.rsf -target d -exefslogo -elf $(PROJECT_NAME)_stripped.elf -icon icon.bin -banner banner.bin

or to create your cias using the next one

makerom -f cia -o $(PROJECT_NAME).cia -rsf cia.rsf -target t -exefslogo -elf $(PROJECT_NAME)_stripped.elf -icon icon.bin -banner banner.bin 

[Update: take a look at the 3DSHomebrewTemplate created by Steveice10, those are probably the best makefiles around]

4. Pica Texture Format

Textures are optimized on the 3DS GPU in a special format optimized for cache called Pica Texture Format. This means that in order to use it with the GPU_SetTexture  function, first you need to convert it (either on real time or preprocessing it first)
It took me a while to get the code working for this (as you can see on this thread). But yeah, you just need to copy the code I posted there (actually I forgot to do it and I just did it now)

5. Sideways framebuffer

The framebuffer on the 3ds screens is sideways. Meaning it really goes like this:
In other words, what you really have is an screensize of 240x400, so if you don't do anything special this is what you'll get:
Usually you don't want this (not in the 3DS specially, because if you rotate the console you cannot have the 3D effect working). You need to do three things

- Everywhere in your code where you need the screen size, use 400x240 (which is what we want)

- When you set the viewport size make sure you swap the params. In other words, call

      GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),(u32*)osConvertVirtToPhys((u32)gpuOut), y, x, h * 2, w);

- You need to premultiply your projection matrix by this one

      float mtx_projection_tmp0[16] =
       0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
       0.0f, 0.0f, 0.5f, -0.5f,
       0.0f, 0.0f, 0.0f, 1.0f

which basically swaps the x and y axis and also converts z from [-1, 1] to [-1, 0] because those are the viewport coordinates for the 3DS.

Now you can use the typical functions for creating a projection matrix, ortho, oblique... this is important if you are working on a cross platform environment. Creating a particlar case for a specific platform is a bit annoying and will cause you problems

Friday, July 17, 2015

3DS Homebrew Tips and Tricks (I)

So, as I said on my previous post I am gonna start a series of posts talking about some things that might be useful for those of you intereseted on developing for this machine. For me this is just a hobby and I cannot dedicate 100% of my time, just 1 hour a day and a little bit more during the weekends, so being stuck on something is a bit frustrating.

I have spent much more time stuck on some stuff and searching on forums than actually coding. Hoping that this will help you I have made a compilation of the things that would had saved me a lot of time if I had knew how they were before.

This is the 1st post on the series 3DS Homebrew Tips and Tricks

1. 3dsx, Cia and 3ds

These are the 3 formats that you can compile your programs into.

- 3dsx this is the format that the ctrulib (which is the SDK for homebrew in 3DS) supports officially. If you are gonna release something you should distribute it under this format. You need to execute the Homebrew Launcher to use it. You need to execute ninjhax for that. The problem is, some of us cannot do this, either because we don't have Cubic Ninja or because we have updated our emunands beyond 9.2 and now it doens't work anymore (take a look at this post)

- Cia this is the format that you use for stuff that needs to be installed in the console (as channels). Some people doesn't like it because it has been used a lot for piracy (way more than for homebrew). You need to use a CFW (Custom Firmware) and then a CFW installer in order to use it. You don't need a flaschcard for this but your console needs to be on 4.5 firmware

- 3ds this file is the oficial format supported by nintendo. You need a flashcard for this and that's why some people doesn't like it.

As I said the makefiles that come with the ctrulib only support building for 3dsx. If you want to create your own makefiles supporting those formats you can take a look at the ones used in GameYob. You still need to take a look at how to create banners, icons and sounds but I will cover that on the 3rd point.

2. Setting up a good Developement environment

I am not going to cover here how to get started with 3ds homebrew. You can take a look at my previous post here. In sort you need to download devkitpro and from there devkitARM. I don't recommend installing ctrulib from devkitpro. The version that comes with it doesn't include examples and it is hardly up to date. Your best option is getting ctrulib from github and compiling it yourself. You need to be careful because then you are gonna be working with a library that is not stable but you can always take a look at the changes and see what's going on. I usually update it once a month unless there is an important update.

Take some time compiling and running the examples. If one of them doesn't work take a look at the last time it was updated and try again with a branch created on that day. If you are planing to do 3d games the best start point for you is the gpu example.
Once you reach the point when you have compiled and executed some examples and played with them a bit using programmers notepad (or any other text editor you want) you might start considering using another IDE a bit more powerful

The one that I am using is Visual Studio 2010 but what I am gonna post here should be very similar in any other version.
 - Create a makefile project

 - Linking it to our Makefile
 Go to Project properties and configure it like this:
    - Build command line: 
    - Clean commands: 
                            make clean
    - Rebuild command line: 
                            make clean 

you can now close visual studio go where you have created this project and copy it into the folder of the example you want to compile. After that if you open it and compile, it will run the makefile and create a 3dsx as expected. Rebuild and clean will also be working as usual

- Adding intellisense
Add the next paths into the Include Search Path
 - C:\devkitPro\devkitARM\arm-none-eabi\include
 - C:\devkitPro\devkitARM\include
 - C:\devkitPro\libctru_git\libctru\include
where C:\devkitPro is the folder in your harddrive where you have installed devkitpro
Now code completion should be working as well as going to function declaratinos.

 - Creating a external tool for copying contents into the console
   - In yout makefile add a target called install similar to this:
                  cp ../bin/$(PROJECT_NAME).3ds g:/
                     @echo Done 

   - Go to Tools/External Tools
   - Add a new Tool called Install like this
   - Now Create a New Toolbar called Homebrew (Tools/Customize/New...)
   - Go the Commands tab and select the toolbar created. Press Add Command and in Tools search select External Command 7 (yeah.. this is a bit ughhh... but it works)
You should now see your new ToolBar located in the Toolbars and a the button Install on it
Now when you compile you just need to put the SD on your computer, press Install, wait for the message "Done" and put it back on your console to execute

This is very useful if you have a flashcard and you work with the 3ds format. Actually this is the fastest way to work. Compilation times are big and you need to reduce it the maximum posible (bear in mind that sometimes you just change the value of one var and recompile and you need to see the results as soon as posible). This is how I usually work
- I run the latest build on my 3ds and see that something doesn't work
- I take a look at the code, detect what's happening and make some changes. Then press F7 to compile
- While compiling I stop the build on the 3ds (by pressing the home menu and then closing the app)
- I take out the flashcard form the console, then the micro SD inside it and put it on my laptop
- By that time the compilation has finished so I jsut press Install
- I wait for the "Done" message, take out the micro SD from my laptop, and plug it in on the flashcard
- I put the flashcard on the console, select the rom and run it

This is usually about 20 seconds, which is not bad. And it is actually faster than sending the build via FTP (because you need to launch the client on the console for that, then send it form your computer, then close it... and it fails a lot). 

It is even worst if you work with cias, because you need to install them on the internal SD and you cannot remove the SD while on emunad (the console freezes). You can again send the content via wifi (using the tool from nintendo is the best way, see this post) but it takes too much time.

Again, this is up to you, but for applications that are big I highly recommend getting a flashcard and working with 3ds files directly.

Wednesday, July 15, 2015

Jumping Jack for 3DS

Time for some releases!

As some of you know I have spent the last few months doing  some coding for the 3DS. I have finally finished the porting of my little engine so it is now time for some posts talking about the experience and some things I wish I had knew before I started doing this. I am gonna be doing this during this week and the next one

But first. I want to release my first homebrew on this console: Jumping Jack 3DS. This is basically a port of the same game I released a few years ago for the Wii
I already wrote a post about it here

And here is the link if you wanna give it a try

DOWNLOAD: Jumping Jack 3DS

UPDATE: this is now working for ninjahx 2.0