maxmod icon indicating copy to clipboard operation
maxmod copied to clipboard

Occasional crash on GBA when using mmInit

Open StraDaMa opened this issue 4 years ago • 0 comments

The crash can be replicated by simply taking the basic_sound example and changing the call to mmInitDefault to mmInit. For the code below, I'm using the GBA example given here: https://maxmod.devkitpro.org/ref/functions/mmInit.html

...
// Mixing buffer (globals should go in IWRAM)
// Mixing buffer SHOULD be in IWRAM, otherwise the CPU load
// will _drastially_ increase
u8 myMixingBuffer[ MM_MIXLEN_16KHZ ] __attribute((aligned(4)));

void maxmodInit( void )
{
    irqSet( IRQ_VBLANK, mmVBlank );

    u8* myData;
    mm_gba_system mySystem;
 
    // allocate data for channel buffers & wave buffer (malloc'd data goes to EWRAM)
    // Use the SIZEOF definitions to calculate how many bytes to reserve
    myData = (u8*)malloc( 8 * (MM_SIZEOF_MODCH
                               +MM_SIZEOF_ACTCH
                               +MM_SIZEOF_MIXCH)
                               +MM_MIXLEN_16KHZ );
    
    // setup system info
    // 16KHz software mixing rate, select from mm_mixmode
    mySystem.mixing_mode       = MM_MIX_16KHZ;

    // number of module/mixing channels
    // higher numbers offer better polyphony at the expense
    // of more memory and/or CPU usage.
    mySystem.mod_channel_count = 8;
    mySystem.mix_channel_count = 8;
    
    // Assign memory blocks to pointers
    mySystem.module_channels   = (mm_addr)(myData+0);
    mySystem.active_channels   = (mm_addr)(myData+(8*MM_SIZEOF_MODCH));
    mySystem.mixing_channels   = (mm_addr)(myData+(8*(MM_SIZEOF_MODCH
	                                             +MM_SIZEOF_ACTCH)));
    mySystem.mixing_memory     = (mm_addr)myMixingBuffer;
    mySystem.wave_memory       = (mm_addr)(myData+(8*(MM_SIZEOF_MODCH
                                                     +MM_SIZEOF_ACTCH
                                                     +MM_SIZEOF_MIXCH)));
    // Pass soundbank address
    mySystem.soundbank         = (mm_addr)soundbank_bin;

    // Initialize Maxmod
    mmInit( &mySystem );
}

int main() {

	irqInit();

	// Maxmod requires the vblank interrupt to reset sound DMA.
	// Link the VBlank interrupt to mmVBlank, and enable it. 
	irqSet( IRQ_VBLANK, mmVBlank );
	irqEnable(IRQ_VBLANK);

	consoleDemoInit();

	// ansi escape sequence to clear screen and home cursor
	// /x1b[line;columnH
	iprintf("\x1b[2J");

	// initialise maxmod with soundbank and 8 channels
    //mmInitDefault( (mm_addr)soundbank_bin, 8 );
	maxmodInit();
...

The reason for the crash is because for mySystem.mixing_mode = MM_MIX_16KHZ; the compiler generates code that sets the mixing mode as a byte. But, when mmMixerInit is called the mixing_mode is read as word ldr r1, [r0,#MM_GBA_SYSTEM_MODE] Because there's padding between mixing_mode and mod_channel_count any bytes that were already on the stack get read as part of the mixing mode. Besides remembering to zero the mm_gba_system struct before using it, this could probably just be fixed by just changing the ldr to a ldrb in mmMixerInit

StraDaMa avatar Jul 31 '20 00:07 StraDaMa