Homebrew [Release] Homebrew Launcher with grid layout

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Oh I think I get it now: You select the title in the HB Launcher and then that opens up SVDT and tells it to manage the save data for that title. So I just put my DKCR-3D cart in, opened SVDT, selected the cart, and then it brought up SVDT pointing at the DKCR-3D title so I can back up the save data. Is that all it's supposed to do? And what was somebody else referring to when they said that suloku's launcher passes the title directly?
 

pdapanda

Well-Known Member
Member
Joined
Nov 19, 2014
Messages
730
Trophies
0
Age
32
XP
1,184
Country
Switzerland
Well, there will always be some wares not compatible with svdt, it's nomal. And that's not the problem of the menu. I think the only issue is the icon won't show up when you are targeting a title
 
Last edited by pdapanda,

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Ok thanks. Well I've just tested it on my menu and it does work if you press left and right on the D-Pad. There is a duplicate icon on the bottom screen, but if you press left and right you can select the title you want, and press A to launch SVDT pointed to that target. So it does seem to work, it just doesn't display the icons in a grid.

I will need to spend some time extracting the grid rendering code from the menu and putting it into a more generalised set of functions in a separate c file. If I can abstract the functions sufficiently then I should be able to reuse them to put the SVDT icons in a grid as well.

Other than the layout looking right, is there actually a problem using SVDT in the grid launcher?
 

pdapanda

Well-Known Member
Member
Joined
Nov 19, 2014
Messages
730
Trophies
0
Age
32
XP
1,184
Country
Switzerland
svdt will allow us to save the whole directory of savefile to sd card with the title name.however, the default memu can't get the names of 3dswares/download titles. soluke solved the problem in his modition.
also, sdvt will auto duplicate your savefile under sd:/sdvt when boots up
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Oh I see. Thank you. So why were people saying it doesn't work? I understand they want it to look better and auto-detect the title, but to say it doesn't work is not accurate at all.
 

pdapanda

Well-Known Member
Member
Joined
Nov 19, 2014
Messages
730
Trophies
0
Age
32
XP
1,184
Country
Switzerland
[QOTE="mashers, post: 5700401, member: 366855"]Oh I see. Thank you. So why were people saying it doesn't work? I understand they want it to look better and auto-detect the title, but to say it doesn't work is not accurate at all.[/QUOTE]
I dunno either
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Ok guys, I've had a look at suloku's code for his launcher and seen how he managed to pass the title to SVDT. It's an ingenious solution actually, which was easy to integrate into my code. So the grid launcher now passes the title correctly to SVDT in the same way as suloku's launcher. Note that this version is not uploaded yet as I need to finish the fonts (nearly there).

@suloku
Thanks for finding the solution to this. I have credited you in the source for the parts I used, and will be sure to credit you in the readme when I release the source.
 

suloku

Well-Known Member
Member
Joined
Apr 28, 2008
Messages
883
Trophies
1
XP
877
Country
Great news mashers, glad to see the font engine is almost there.

About passing the title to svdt, it would be better to use arguments, since hbl can start apps with argument support, but there's some kind of bug (even in the vanilla source) that makes argument passing not work correctly when launching apps under a certain title, like svdt requires.
 
Last edited by suloku,

ChaosRipple

Well-Known Member
Member
Joined
Oct 1, 2015
Messages
272
Trophies
0
Age
29
XP
183
Country
United States
One thing that is kind of bugging me is the sharp corners of the settings buttons. I suggest making them rounded corners so that it's a little more consistent with the rest of the GUI. Another suggestion is to change those buttons to checkboxes. Other than that, amazing work! XD
 

bunny365

Well-Known Member
Member
Joined
Aug 26, 2013
Messages
241
Trophies
0
XP
217
Country
United States
Oh I think I get it now: You select the title in the HB Launcher and then that opens up SVDT and tells it to manage the save data for that title. So I just put my DKCR-3D cart in, opened SVDT, selected the cart, and then it brought up SVDT pointing at the DKCR-3D title so I can back up the save data. Is that all it's supposed to do? And what was somebody else referring to when they said that suloku's launcher passes the title directly?
It's also not really a convenience thing. Some HB apps rely on that feature of the Homebrew Launcher, including the (unofficial) OoT3Dhax installer.

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

Also, I think the RFL should have a gamecard border behind it, like on the HOME Menu, and a blank gray icon instead of the RFL icon when there's no game inserted, also like on the HOME Menu.
 

Shadowtrance

Well-Known Member
Member
Joined
May 9, 2014
Messages
2,493
Trophies
0
Location
Hervey Bay, Queensland
XP
1,807
Country
Folder option isn't working for me at all.
I've got a folder on the root of my sd called RetroArch.hbfolder with all the retroarch emulators in there in their sub folders and i have no option to change folder.
Tried with ninjhax 1.1 (cubic ninja) and ninjhax 2.1 (browserhax_fright). No joy. :(


Edit: Nevermind, thought i had the latest boot.3dsx on my sdcard... apparently i didn't. lol
 
Last edited by Shadowtrance,

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Great news mashers, glad to see the font engine is almost there.
Thanks buddy!

About passing the title to svdt, it would be better to use arguments, since hbl can start apps with argument support, but there's some kind of bug (even in the vanilla source) that makes argument passing not work correctly when launching apps under a certain title, like svdt requires.
Is it the HBL or SVDT? In any case, as long as it works I don't mind that the argument is sent by storing it in a file.

Thank you mate! That's great! Is it possible for my name on that site to link to my profile here on GBATemp? I tried to register on 3Dbrew but the captcha is ridiculous and would require me to install SHA1SUM on my Mac which itself requires Macports which won't install on OS X 10.11 :wacko:

One thing that is kind of bugging me is the sharp corners of the settings buttons. I suggest making them rounded corners so that it's a little more consistent with the rest of the GUI. Another suggestion is to change those buttons to checkboxes. Other than that, amazing work! XD
Thanks bud. Yes I intend to make the button corners rounded. Currently they are just drawn as rectangles. I quite like the way they highlight to green when selected, but I do understand that a check mark would be more appealing to most. I do intend to do this, but it's not a priority right now.

Also, I think the RFL should have a gamecard border behind it, like on the HOME Menu, and a blank gray icon instead of the RFL icon when there's no game inserted, also like on the HOME Menu.
Nice idea. I'll look into it. Shouldn't be too hard to do.[/QUOTE]
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,084
Country
Just a quick update guys. I've spent the last two days tearing my hear out to get word wrapping working. It's finally done! I can now draw text using my custom font format and pass it a maximum width and maximum number of lines. The function then splits the text up into words, wraps them at the end of each line, and finally truncates the final word with ellipses ('...') if it won't fit.

I can't even begin to tell you how complicated this was to get right, both from the point of view of working out the logic behind it (how to work out when we need to wrap to the next line, how to work out if the next word will fit, how to work out if the next word will fit when truncated to its minimum length with ellipses.....) before even starting on the massive, arduous headfuck that is working with strings in C.

I did try doing it in C++ which was much easier to code, but got bitten by the C++ vectors bug again, which caused the launcher to hang on startup. So I had to write it with two dimensional plain C char arrays which is so unbelievably hard after getting used to proper arrays. I thought I would share the code for this function as it was quite a feat to get it working. There are a couple of helper functions I wrote which are referred to here which I haven't posted - they do things like calculating the pixel width of the string, truncating the string to fit within a specified width etc.

Code:
void MADrawTextWrap(gfxScreen_t screen, gfx3dSide_t side, int cursorx, int cursory, char * text, MAFont * font, int red, int green, int blue, int maxWidth, int maxLines) {
    
    //If no maximum width was specified, just draw the text
    if (maxWidth < 1) {
        MADrawText(screen, side, cursorx, cursory, text, font, red, green, blue);
        return;
    }
    
    if (maxLines == 1) {
        truncateTextToFitMaxWidth(text, maxWidth, font, false);
        MADrawText(screen, side, cursorx, cursory, text, font, red, green, blue);
        return;
    }
    
    //Store initial cursor position in case we need to go down a line
    int initialy = cursory;
    
    /*
          ---------------------------------  To do: get this from the font  ---------------------------------
     */
    int lineHeight = 20;
    
    //Start from line 1
    int currentline = 1;
    
    int maxWords = 128;
    int maxWordLen = 64;
    
    char words[maxWords][maxWordLen];
    memset(words, 0, maxWords*maxWordLen);
    
    int numWords = 0;
    
    int numChars = strlen(text);
    int currentWordStartPosition = 0;
    int i=0;
    
    /*
     This was originally added for testing the output of the sentence splitting function below.
     It is no longer used or even referred to beyond its declaration here and copying one character to it.
     I have no idea why, but if this is removed the text wrapping goes all fucked.
     I should probably try to figure it out, but I would rather have text wrapping working than
        save 1k of memory, and I don't really have the time to figure it out.
     */
    char out[1024];
    strcpy(out, "|");
    
    while (i < numChars) {
        char c[1];
        memset(c, 0, 1);
        strncpy(c, &text[i], 1);
        
        //We have reached the end of a word
        if (charIsWordBreak(c)) {
            
            //Now scan until the beginning of the next word or the end of the string
            while (true) {
                //Go to the next character
                i++;
                
                //If we have reached the end of the string, stop scanning
                if (i >= numChars) {
                    break;
                }
                
                //If we have not reached the end of the string, get the next character
                char c2[1];
                memset(c2, 0, 1);
                strncpy(c2, &text[i], 1);
                
                //If we have reached a non word break character, stop scanning
                if (!charIsWordBreak(c2)) {
                    break;
                }
            }
            
            //Get the index of the character and store it as current word end position
            int currentWordEndPosition = i;
            
            //Calculate the length of the current word
            int currentWordLength = currentWordEndPosition - currentWordStartPosition;
            
            char currentWord[maxWordLen];
            memset(currentWord, 0, maxWordLen);
            strncpy(currentWord, &text[currentWordStartPosition], currentWordLength);
            
            //Copy the word to the words array
            strncpy(words[numWords], currentWord, maxWordLen);
            
            //Prepare to start scanning the next word
            numWords++;
            currentWordStartPosition = i;
        }
        
        //We have not yet reached the end of a word
        else {
            //Go to the next character
            i++;
            
            //Last word - this is pretty much the same code as above, so needs to be abstracted to a function to save repetition (later!)
            if (i >= numChars) {
                //Get the index of the character and store it as current word end position
                int currentWordEndPosition = i;
                
                //Calculate the length of the current word
                int currentWordLength = currentWordEndPosition - currentWordStartPosition;
                
                char currentWord[maxWordLen];
                memset(currentWord, 0, maxWordLen);
                strncpy(currentWord, &text[currentWordStartPosition], currentWordLength);
                
                strncpy(words[numWords], currentWord, maxWordLen);

                numWords++;
            }
        }
    }
    
    for (i=0; i < numWords; i++) {
        //Copy the current word from the array
        char currentWord[maxWordLen];
        memset(currentWord, 0, maxWordLen);
        strncpy(currentWord, words[i], maxWordLen);
        
        //Calculate the width of the word about to be drawn
        int currentWordWidth = MATextWidthInPixels(currentWord, font);
        
        //Work out how much space is left on the current line
        int availableWidthForCurrentWord = maxWidth - (cursory - initialy);
        
        //If there are more words to draw after this one
        if (i < numWords-1) {
            //Copy the next word from the array
            char nextWord[maxWordLen]; // = new char[sNextWord.length() + 1];
            memset(nextWord, 0, maxWordLen);
            strncpy(nextWord, words[i+1], maxWordLen);
            
            //Calculate the width of the next word
            int nextWordWidth = MATextWidthInPixels(nextWord, font);
            
            //Calculate space available for the next word
            int availableWidthForNextWord = availableWidthForCurrentWord - currentWordWidth;
            
            //If the next word will fit on this line
            if (nextWordWidth <= availableWidthForNextWord) {
                //Draw the current word and move the cursor along ready to draw the next word on the next cycle of the loop
                MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                cursory += currentWordWidth;
            }
            
            //If the next word will not fit on this line
            else {
                //If there is no restriction on the number of lines, or if we have not yet reached the last line
                if (maxLines < 1 || currentline < maxLines) {
                    MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                    cursory = initialy;
                    cursorx -= lineHeight;
                    currentline++;
                }
                
                //If there are no more lines left
                else {
                    //Create the minimum truncated version of the next word (its first letter plus ellipses)
                    char minimumTruncatedNextWord[5];
                    memset(minimumTruncatedNextWord, 0, 5);
                    strncpy(minimumTruncatedNextWord, nextWord, 1);
                    strcat(minimumTruncatedNextWord, "...");
                    
                    //Get the width of the minimum truncated next word
                    int minimumTruncatedNextWordWidth = MATextWidthInPixels(minimumTruncatedNextWord, font);
                    
                    //If the minimum truncated next word will fit
                    if (minimumTruncatedNextWordWidth <= availableWidthForNextWord) {
                        //Draw the current word
                        MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                        cursory += currentWordWidth;
                        
                        //Truncate the next word so it will fit on the line with ellipses
                        truncateTextToFitMaxWidth(nextWord, availableWidthForNextWord, font, false);
                        
                        //Draw the next word
                        MADrawText(screen, side, cursorx, cursory, nextWord, font, red, green, blue);
                        
                        //Break since there's no space for any more words
                        break;
                    }
                    
                    //Even the minimum truncated next word won't fit on this line, and there isn't a line available below for it to go on.
                    else {
                        //Truncate the current word and add ellipses
                        truncateTextToFitMaxWidth(currentWord, availableWidthForCurrentWord, font, true);
                        
                        //Draw the truncated current word
                        MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                        
                        //Break, since there's not space for any more words
                        break;
                    }
                }
            }
        }
        
        //This is the last word
        else {
            //If the last word fits, just draw it and we're done
            if (currentWordWidth <= availableWidthForCurrentWord) {
                MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                /*
                 DONE
                 */
            }
            
            //The last word doesn't fit on the current line
            else {
                //If there is no restriction on the number of lines, or if we still have lines available
                if (maxLines < 1 || currentline < maxLines) {
                    //Move the cursor to the beginning of the next line
                    cursory = initialy;
                    cursorx -= lineHeight;

                    //Truncate the last word if necessary
                    if (availableWidthForCurrentWord > maxWidth) {
                        truncateTextToFitMaxWidth(currentWord, availableWidthForCurrentWord, font, false);
                    }
                    
                    //Draw the last word
                    MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                    
                    /*
                     DONE
                     */
                }
                
                //There are no more lines available. Truncate the final word and display it
                else {
                    truncateTextToFitMaxWidth(currentWord, availableWidthForCurrentWord, font, false);
                    MADrawText(screen, side, cursorx, cursory, currentWord, font, red, green, blue);
                    
                    /*
                     DONE
                     */
                }
            }
        }
    }
}


As you can see this is a pretty meaty function. I still need to deal with newline characters within strings as currently they are ignored when drawing the text. This will add yet another layer of complexity!

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

@mashers are you going to update this with smeas new release when he releases it? :)
I didn't know he was working on one. Is it a new launcher?
 

Tjessx

Well-Known Member
Member
Joined
Dec 3, 2014
Messages
1,160
Trophies
0
Age
27
XP
952
Country
Belgium
then there is also this "devs will be happy to hear that the next release should also give them more memory to play with ! hopefully 64MB more on n3ds, 16MB on old."
Sleep mode and power button works too
 
  • Like
Reactions: fmkid and bunny365

suloku

Well-Known Member
Member
Joined
Apr 28, 2008
Messages
883
Trophies
1
XP
877
Country
It's still not in github, but the new version of hbl will also come with a new payload with many new and great features (in-game screenshots!)

The argument passing bug is a problem outside HBL, smea is already aware of it, but yesterday I got pointed out that a function exists and is documented to get the running title ID, then I implemented it on ctrulib and well, it works, so next svdt version will auto-get the current title, no need for title selector or anything.

Also, fincs is working on dsp sound, which he stated will render current sound in ctrulib obsolete, so better wait for that to implement sound.
 
Last edited by suloku,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    HiradeGirl @ HiradeGirl: What.