OK, so your XM player runs mostly fine on his system - except he described a weird white noise in the background. But otherwise, it produced sound.
However, to my test I also added sound effects played on the A, B, and C buttons. The demo has a bouncing face. When he presses any of those buttons to play a sound, the bouncing face thing locks up (so it seems like the entire game hangs at that point).
I'm wondering if the slave CPU just hangs at some point on my audio stuff, and never unlocked the mixer, which would explain the sound effects locking up the main CPU (if the mixer wasn't unlocked it'd just be sitting there waiting for a lock). The real question if that's the case is where it's locking up the slave CPU and why.
I'm going to walk through all of the relevant bits of my audio setup. Maybe you can spot an issue here?
So first, I modified the Mars header:
Code: Select all
.ascii "32X Example " /* module name (16 chars) */
.long 0x00000000 /* version */
.long __text_end-0x02000000 /* Source (in ROM) */
.long 0x00000000 /* Destination (in SDRAM) */
.long __data_size /* Size */
.long mstart /* Master SH2 Jump */
.long sstart /* Slave SH2 Jump */
.long master_vbr /* Master SH2 VBR */
.long slave_vbr /* Slave SH2 VBR */
Then, I added a new entry to the slave vector table:
Code: Select all
.long slav_irq /* Command interupt */
.long slav_irq /* H Blank interupt */
.long slav_irq /* V Blank interupt */
.long slav_irq /* Reset Button */
.long slave_dma1 /* DMA1 TE INT */
Which points to this subroutine:
Code: Select all
! Handles DMA interrupts
slave_dma1:
! save registers
sts.l pr,@-r15
mov.l r0,@-r15
mov.l r1,@-r15
mov.l r2,@-r15
mov.l r3,@-r15
mov.l r4,@-r15
mov.l r5,@-r15
mov.l r6,@-r15
mov.l r7,@-r15
! call C-side slave_dma1_handler() callback
mov.l sd1_handler,r0
jsr @r0
nop
! restore registers
mov.l @r15+,r7
mov.l @r15+,r6
mov.l @r15+,r5
mov.l @r15+,r4
mov.l @r15+,r3
mov.l @r15+,r2
mov.l @r15+,r1
mov.l @r15+,r0
lds.l @r15+,pr
rte
nop
.align 2
sd1_handler:
.long _slave_dma1_handler
That, in turn, points to this C function:
Code: Select all
void slave_dma1_handler(void)
{
static u8 which = 1;
while (MARS_SYS_COMM12 == MIXER_LOCK_MSH2) ; // locked by MSH2
SH2_DMA_CHCR1; // read TE
SH2_DMA_CHCR1 = 0; // clear TE
if (which)
{
// start DMA on first buffer and fill second
SH2_DMA_SAR1 = ((u32)&snd_buffer[0]) | 0x20000000;
SH2_DMA_TCR1 = num_samples; // number longs
SH2_DMA_CHCR1 = 0x18E5; // dest fixed, src incr, size long, ext req, dack mem to dev, dack hi, dack edge, dreq rising edge, cycle-steal, dual addr, intr enabled, clear TE, dma enabled
FillAudioBuffer(&snd_buffer[MAX_NUM_SAMPLES * 2]);
}
else
{
// start DMA on second buffer and fill first
SH2_DMA_SAR1 = ((u32)&snd_buffer[MAX_NUM_SAMPLES * 2]) | 0x20000000;
SH2_DMA_TCR1 = num_samples; // number longs
SH2_DMA_CHCR1 = 0x18E5; // dest fixed, src incr, size long, ext req, dack mem to dev, dack hi, dack edge, dreq rising edge, cycle-steal, dual addr, intr enabled, clear TE, dma enabled
FillAudioBuffer(&snd_buffer[0]);
}
which ^= 1; // flip audio buffer
}
Meanwhile, my slave entry function looks like this:
Code: Select all
void slave(void)
{
// initialize DMA
SH2_DMA_SAR0 = 0;
SH2_DMA_DAR0 = 0;
SH2_DMA_TCR0 = 0;
SH2_DMA_CHCR0 = 0;
SH2_DMA_DRCR0 = 0;
SH2_DMA_SAR1 = 0;
SH2_DMA_DAR1 = 0x20004034; // storing a long here will set left and right
SH2_DMA_TCR1 = 0;
SH2_DMA_CHCR1 = 0;
SH2_DMA_DRCR1 = 0;
SH2_DMA_DMAOR = 1; // enable DMA
SH2_DMA_VCR1 = 72; // set exception vector for DMA channel 1
SH2_INT_IPRA = (SH2_INT_IPRA & 0xF0FF) | 0x0F00; // set DMA INT to priority 15
// initialize audio hardware
InitAudio();
// initialize mixer
MARS_SYS_COMM12 = MIXER_UNLOCKED; // sound subsystem running
FillAudioBuffer(&snd_buffer[0]); // fill first buffer
slave_dma1_handler(); // start DMA
// set up command port so we can do other stuff on the slave SH2 if necessary
SetSH2SR(2);
while (1)
{
if (MARS_SYS_COMM14 == SSH2_WAITING)
continue; // wait for command
// do command in COMM4
switch(MARS_SYS_COMM14)
{
case SSH2_LOADSONG:
{
ssh2_loadSong( MARS_SYS_COMM2 );
}
break;
case SSH2_STOPSONG:
{
ssh2_stopSong();
}
break;
}
// done
MARS_SYS_COMM14 = SSH2_WAITING;
}
}
And then InitAudio does:
Code: Select all
void InitAudio()
{
int i;
for( i = 0; i < ECHOBUFMAX; i++ )
echo_buffer[i] = 0;
// init the sound hardware
MARS_PWM_MONO = 1;
MARS_PWM_MONO = 1;
MARS_PWM_MONO = 1;
if (MARS_VDP_DISPMODE & MARS_NTSC_FORMAT)
MARS_PWM_CYCLE = (((23011361 << 1)/SAMPLE_RATE + 1) >> 1) + 1; // for NTSC clock
else
MARS_PWM_CYCLE = (((22801467 << 1)/SAMPLE_RATE + 1) >> 1) + 1; // for PAL clock
MARS_PWM_CTRL = 0x0185; // TM = 1, RTP, RMD = right, LMD = left
// ramp PWM to center to avoid a click on real hardware
u16 sample = SAMPLE_MIN;
u16 ix;
while( sample < SAMPLE_CENTER )
{
for( ix = 0; ix < (SAMPLE_RATE*2)/(SAMPLE_CENTER-SAMPLE_MIN); ix++ )
{
while( MARS_PWM_MONO & 0x8000 ); // wait until the buffer is not full
MARS_PWM_MONO = sample;
}
sample++;
}
}
Beyond this, I can only imagine it's somehow my song loading or playback routines that are freezing the slave CPU?
I also tried running in Gens/GS release 7. It produces no sound, though neither does your XM player,
despite the release notes claiming that it adds SH2 DMA support for PWM audio. Pressing buttons produces no sound either, but does not hang.