Homebrew Homebrew Development

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
To be honest it's the first time that I mess with homebrew development, so I don't have a clue about how to help you.

Anyways your fopen() workaround worked, but after implementing more things (without touching the fopen() call!) it started freezing again.
L+R+Down+B in this case doesn't even work, forcing me to reboot the console. But after a hour trying to discover what I did wrong, the function was too big (I think that this caused it)
Then I chopped it into 3 parts (read file, put into ram and parse) and set the first one to chaincall until end. This fixed my issue.
It is unlikely that the function was too big - as in to much code. It would be more likely that you were using too much stack space. Local variables and sometimes parameters are stored on the the stack. The default stack on the 3ds with libctru is only 32k. So it is easy to use too much.
 

Metab

Well-Known Member
Member
Joined
Mar 23, 2013
Messages
155
Trophies
0
Age
27
Location
Where dat ass is
XP
289
Country
Have a separate function that draws your menu, add a call to printf with "\x1b[2J" at the beginning to clear the screen.
Also, instead of drawing the menu every frame, just draw it when something has changed and it won't be all flickery.
Yeah im re-writing my menu at the moment in a very similar format
 

Slashcash

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
338
Trophies
0
XP
611
Country
Italy
It is unlikely that the function was too big - as in to much code. It would be more likely that you were using too much stack space. Local variables and sometimes parameters are stored on the the stack. The default stack on the 3ds with libctru is only 32k. So it is easy to use too much.

Knowing this limit would have saved me A LOT of trouble when trying to debug a crash. I was allocating a 64k array and the program kept crashing. I allocated the 64k on heap and the crash solved and i filed it under: "well it now works but i don't know why"

Better late than never
 

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
Knowing this limit would have saved me A LOT of trouble when trying to debug a crash. I was allocating a 64k array and the program kept crashing. I allocated the 64k on heap and the crash solved and i filed it under: "well it now works but i don't know why"

Better late than never
It is also possible to change the stack sizes for your project. Define a global u32 __stacksize__=64*1024; would change it to 64k. I have set it as high as 1 MB. Of course this does reduce the available heap size.
 

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,564
Country
Chile
Define a global u32 __stacksize__=64*1024; would change it to 64k.

are you sure? I mean I dont want to be "that guy" but this u8 is 1 byte and u32 is 4, so ..


main.h
Code:
extern u8 buffer_test[64*1024];
extern u32 buffer_test2[64*1024];

main.c
Code:
u8 buffer_test[64*1024];
u32 buffer_test2[64*1024];

compiled and reserved size for each: (from map file)

9ll8uv.jpg


so buffer_test is 64k
but buffer_test2 is 64k*4 = 256k
 
  • Like
Reactions: Metab

MasterFeizz

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
1,098
Trophies
1
Age
29
XP
3,710
Country
United States
are you sure? I mean I dont want to be "that guy" but this u8 is 1 byte and u32 is 4, so ..


main.h
Code:
extern u8 buffer_test[64*1024];
extern u32 buffer_test2[64*1024];

main.c
Code:
u8 buffer_test[64*1024];
u32 buffer_test2[64*1024];

compiled and reserved size for each: (from map file)

9ll8uv.jpg


so buffer_test is 64k
but buffer_test2 is 64k*4 = 256k

__stacksize__ is not an array of said size...
 

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
ah well this screen was from devkitarm (libnds), same as map (ARM9 being int 32 bit). But still, i am curious now
You are comparing two separate environments - nds and 3ds - completely different. plus you are comparing the definition of the stack (nds) with the definition of the size of the stack (3ds). In ctrulib __stacksize__ is a weakly define u32 that contains the size of the stack to create during initialization. The weak definition means if you create it in your code it will be used instead of the value in ctrulib. It needs to be defined at global scope and needs to use C naming not C++ or it will not match.
For the nds the stack needs to be created at a fixed hardware address location with a static size.
 
  • Like
Reactions: MasterFeizz

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,564
Country
Chile
You are comparing two separate environments - nds and 3ds - completely different. plus you are comparing the definition of the stack (nds) with the definition of the size of the stack (3ds). In ctrulib __stacksize__ is a weakly define u32 that contains the size of the stack to create during initialization. The weak definition means if you create it in your code it will be used instead of the value in ctrulib. It needs to be defined at global scope and needs to use C naming not C++ or it will not match.
.

Of course I am aware of the differences between overriding with a __weak attribute, different data/code paths, the linker sections, the relocated code and the code sections. But still, as a weakly define i am seeing 64*4*1024 (u32) which is NOT 64k as stack. This made me double check this against a map file what would've been the final stack size. Now I didnt know ctrulib can override stack size like this (and I dont think I could really care for now), but if I ever see u32 __something__ [64*1024] I will know it will be a multiple of sizeof(u32),

edit: nope it was u32 __weak_symbol__ = 64*1024; I am wrong here.

For the nds the stack needs to be created at a fixed hardware address location with a static size

Yeah no, you do know (nds) CP15's can move the base address/size (DTCM) ? And that is perfectly configurable through linker. Size must be fixed, but definitely you can move base address (c9, c1,0)

mpu_setup.s (google )
Code:
@---------------------------------------------------------------------------------
@ Protection Unit Setup added by Sasq
@---------------------------------------------------------------------------------
   @ Disable cache
   mov   r0, #0
   mcr   p15, 0, r0, c7, c5, 0     @ Instruction cache
   mcr   p15, 0, r0, c7, c6, 0     @ Data cache

   @ Wait for write buffer to empty
   mcr   p15, 0, r0, c7, c10, 4

   ldr   r0, =__dtcm_start
   orr   r0,r0,#0x0a
   mcr   p15, 0, r0, c9, c1,0     @ DTCM base = __dtcm_start, size = 16 KB

   mov   r0,#0x20
   mcr   p15, 0, r0, c9, c1,1     @ ITCM base = 0 , size = 32 MB
 
Last edited by Coto,

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
Of course I am aware of the differences between overriding with a __weak attribute, different data/code paths, the linker sections, the relocated code and the code sections. But still, as a weakly define i am seeing 64*4*1024 (u32) which is NOT 64k as stack. This made me double check this against a map file what would've been the final stack size. Now I didnt know ctrulib can override stack size like this (and I dont think I could really care for now), but if I ever see u32 __something__ [64*1024] I will know it will be a multiple of sizeof(u32),

edit: nope it was u32 __weak_symbol__ = 64*1024; I am wrong here.



Yeah no, you do know (nds) CP15's can move the base address/size (DTCM) ? And that is perfectly configurable through linker. Size must be fixed, but definitely you can move base address (c9, c1,0)

mpu_setup.s (google )
Code:
@---------------------------------------------------------------------------------
@ Protection Unit Setup added by Sasq
@---------------------------------------------------------------------------------
   @ Disable cache
   mov   r0, #0
   mcr   p15, 0, r0, c7, c5, 0     @ Instruction cache
   mcr   p15, 0, r0, c7, c6, 0     @ Data cache

   @ Wait for write buffer to empty
   mcr   p15, 0, r0, c7, c10, 4

   ldr   r0, =__dtcm_start
   orr   r0,r0,#0x0a
   mcr   p15, 0, r0, c9, c1,0     @ DTCM base = __dtcm_start, size = 16 KB

   mov   r0,#0x20
   mcr   p15, 0, r0, c9, c1,1     @ ITCM base = 0 , size = 32 MB
Perhaps I should have been more clear that I meant libnds rather than just nds. As you said the base address is specified in the linker script which also places the stack relative to that location and size. The distinction did not seem necessary in the context of distinguishing between u32 vs a u32 array. Also the code you referenced does not do what you think it does - an easy mistake to make in your over-zealous attempt to prove me wrong. In any case I hope you found/proved what you needed.
 

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
Perhaps it is you who need to understand how to set up tcm base addresses through a co processor call.. Except nds has a protection unit https://books.google.cl/books?id=qbfi3tJJhPEC&pg=PA117&lpg=PA117&dq=c9+c1+0+arm&source=bl&ots=YB3jPtlCrg&sig=HTCCfA5gAOvd6KajPvXnmJXR2G4&hl=es&sa=X&redir_esc=y#v=onepage&q=c9 c1 0 arm&f=false
So you mapped some memory address ranges. Weren't we talking about stack size and where it is located? I am not sure why you are asking questions if you already think you have all of the answers.
 

MRJPGames

Pretty great guy
Member
Joined
Aug 17, 2013
Messages
1,199
Trophies
1
Location
The Netherlands
Website
fizazy.com
XP
1,674
Country
Netherlands
So I have a dsp related issue (probably not dsp's fault but mine). The problem is that if I play the sound effect frequently (around 3 sounds including background music) there starts to be a very annoying cracking noise. I don't know what's causing it, it's probably my code that handles the sfx because of my very lacking understanding of how dsp works.

Here are the source files for the sound effects:

AudioFX.h:
Code:
#ifndef AudioFX_H
#define AudioFX_H
#define channel_range 10 //usually only ~4 are needed, just for testing

    #include <3ds.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    class AudioFX{
        public:
            AudioFX();
            void setChannel(int var1);
            bool initSfx(const char* name);
            void play();
            int fullChns();
            int getChannelRange();
        private:
            int channel[channel_range];
            ndspWaveBuf waveBuf;
    };

#endif

AudioFX.cpp:
Code:
#include "AudioFX.h"

AudioFX::AudioFX(){
}

void AudioFX::setChannel(int var1){
    for (int i=0; i<channel_range; i++){
        ndspChnWaveBufClear(channel[i]);
        channel[i]=var1+i;
    }
}

bool AudioFX::initSfx(const char* name){
    u32 sampleRate;
    u32 dataSize;
    u16 channels;
    u16 bitsPerSample;
    FILE* fp = fopen(name, "rb");
  
    if(!fp){
        //Could not open file
        return 0;
    }
    char signature[4];
  
    fread(signature, 1, 4, fp);
  
    if( signature[0] != 'R' &&
        signature[1] != 'I' &&
        signature[2] != 'F' &&
        signature[3] != 'F'){
        //Wrong file format
        fclose(fp);
        return 0;
    }
    fseek(fp, 22, SEEK_SET);
    fread(&channels, 2, 1, fp);
    fseek(fp, 24, SEEK_SET);
    fread(&sampleRate, 4, 1, fp);
    fseek(fp, 34, SEEK_SET);
    fread(&bitsPerSample, 2, 1, fp);
    fseek(fp,46,SEEK_END);
    dataSize = ftell(fp);
  
    if(dataSize == 0 || (channels != 1 && channels != 2) ||
        (bitsPerSample != 8 && bitsPerSample != 16))
    {
        //Corrupted file
        fclose(fp);
        return 0;
    }
  
    // Allocating and reading samples
    u8* data = (u8*)linearAlloc(dataSize);
  
    if(!data)
    {
        fclose(fp);
        return 0;
    }
  
    fseek(fp, 44, SEEK_SET);
    fread(data, 1, dataSize, fp);
    fclose(fp);
  
    // Find the right format
    u16 ndspFormat;
  
    if(bitsPerSample == 8)
    {
        ndspFormat = (channels == 1) ?
            NDSP_FORMAT_MONO_PCM8 :
            NDSP_FORMAT_STEREO_PCM8;
    }
    else
    {
        ndspFormat = (channels == 1) ?
            NDSP_FORMAT_MONO_PCM16 :
            NDSP_FORMAT_STEREO_PCM16;
    }
  
    for (int i=0; i<channel_range; i++){
        ndspChnReset(channel[i]);
        ndspChnSetInterp(channel[i], NDSP_INTERP_NONE);
        ndspChnSetRate(channel[i], (float)sampleRate);
        ndspChnSetFormat(channel[i], ndspFormat);
    }
  
    // Create wav buffer
    memset(&waveBuf, 0, sizeof(waveBuf));
  
    waveBuf.data_vaddr = (const void*)data;
    waveBuf.nsamples = dataSize / (bitsPerSample >> 3);
    waveBuf.looping = false; // Loop enabled
    waveBuf.status = NDSP_WBUF_FREE;
    DSP_FlushDataCache(data, dataSize);
    return 1;
}

void AudioFX::play(){
    for (int i=0; i<channel_range; i++){
        if (!ndspChnIsPlaying(channel[i])){
            ndspChnWaveBufClear(channel[i]);
            ndspChnWaveBufAdd(channel[i], &waveBuf);
            break;
        }
    }
}

int AudioFX::fullChns(){
    int ret=0;
    for (int i=0; i<channel_range; i++){
        if (ndspChnIsPlaying(channel[i])){
            ret+=1;
        }
    }
    return ret;
}

int AudioFX::getChannelRange(){
    return channel_range;
}
 

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,029
Country
United States
So I have a dsp related issue (probably not dsp's fault but mine). The problem is that if I play the sound effect frequently (around 3 sounds including background music) there starts to be a very annoying cracking noise. I don't know what's causing it, it's probably my code that handles the sfx because of my very lacking understanding of how dsp works.

Here are the source files for the sound effects:

AudioFX.h:
Code:
#ifndef AudioFX_H
#define AudioFX_H
#define channel_range 10 //usually only ~4 are needed, just for testing

    #include <3ds.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    class AudioFX{
        public:
            AudioFX();
            void setChannel(int var1);
            bool initSfx(const char* name);
            void play();
            int fullChns();
            int getChannelRange();
        private:
            int channel[channel_range];
            ndspWaveBuf waveBuf;
    };

#endif

AudioFX.cpp:
Code:
#include "AudioFX.h"

AudioFX::AudioFX(){
}

void AudioFX::setChannel(int var1){
    for (int i=0; i<channel_range; i++){
        ndspChnWaveBufClear(channel[i]);
        channel[i]=var1+i;
    }
}

bool AudioFX::initSfx(const char* name){
    u32 sampleRate;
    u32 dataSize;
    u16 channels;
    u16 bitsPerSample;
    FILE* fp = fopen(name, "rb");
 
    if(!fp){
        //Could not open file
        return 0;
    }
    char signature[4];
 
    fread(signature, 1, 4, fp);
 
    if( signature[0] != 'R' &&
        signature[1] != 'I' &&
        signature[2] != 'F' &&
        signature[3] != 'F'){
        //Wrong file format
        fclose(fp);
        return 0;
    }
    fseek(fp, 22, SEEK_SET);
    fread(&channels, 2, 1, fp);
    fseek(fp, 24, SEEK_SET);
    fread(&sampleRate, 4, 1, fp);
    fseek(fp, 34, SEEK_SET);
    fread(&bitsPerSample, 2, 1, fp);
    fseek(fp,46,SEEK_END);
    dataSize = ftell(fp);
 
    if(dataSize == 0 || (channels != 1 && channels != 2) ||
        (bitsPerSample != 8 && bitsPerSample != 16))
    {
        //Corrupted file
        fclose(fp);
        return 0;
    }
 
    // Allocating and reading samples
    u8* data = (u8*)linearAlloc(dataSize);
 
    if(!data)
    {
        fclose(fp);
        return 0;
    }
 
    fseek(fp, 44, SEEK_SET);
    fread(data, 1, dataSize, fp);
    fclose(fp);
 
    // Find the right format
    u16 ndspFormat;
 
    if(bitsPerSample == 8)
    {
        ndspFormat = (channels == 1) ?
            NDSP_FORMAT_MONO_PCM8 :
            NDSP_FORMAT_STEREO_PCM8;
    }
    else
    {
        ndspFormat = (channels == 1) ?
            NDSP_FORMAT_MONO_PCM16 :
            NDSP_FORMAT_STEREO_PCM16;
    }
 
    for (int i=0; i<channel_range; i++){
        ndspChnReset(channel[i]);
        ndspChnSetInterp(channel[i], NDSP_INTERP_NONE);
        ndspChnSetRate(channel[i], (float)sampleRate);
        ndspChnSetFormat(channel[i], ndspFormat);
    }
 
    // Create wav buffer
    memset(&waveBuf, 0, sizeof(waveBuf));
 
    waveBuf.data_vaddr = (const void*)data;
    waveBuf.nsamples = dataSize / (bitsPerSample >> 3);
    waveBuf.looping = false; // Loop enabled
    waveBuf.status = NDSP_WBUF_FREE;
    DSP_FlushDataCache(data, dataSize);
    return 1;
}

void AudioFX::play(){
    for (int i=0; i<channel_range; i++){
        if (!ndspChnIsPlaying(channel[i])){
            ndspChnWaveBufClear(channel[i]);
            ndspChnWaveBufAdd(channel[i], &waveBuf);
            break;
        }
    }
}

int AudioFX::fullChns(){
    int ret=0;
    for (int i=0; i<channel_range; i++){
        if (ndspChnIsPlaying(channel[i])){
            ret+=1;
        }
    }
    return ret;
}

int AudioFX::getChannelRange(){
    return channel_range;
}
Why are you resetting all channels in initSfx?
Another issue is that if you are starting new sounds close together quickly - for instance multiple sounds are started per frame then you can run into issues with this approach. The current nds implementation runs a thread in the background to update the status of each channel. I suspect the issue is that you are stopping a sound just as it is starting. If you try to start a channel and immediately check to see if it is playing the it will return false. You can either keep track of the play time your self ( and will know when it should finish) or you can keep track of the channel you start on last time and start with the next channel.
 
  • Like
Reactions: MRJPGames

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    LeoTCK @ LeoTCK: hmm