/*
      Sound Demo
*/

/*                 */
/* Include headers */
/*                 */
#include <shinobi.h>

#include "..\include\onmempcm.h"
#include "..\include\sndutls.h"

/* defines */
#define MAX_OF_FX       4 
#define MAX_OF_FX_OUT   2
#define MAX_OF_FUNCTION 5
#define MAX_OF_TRACK    11

/*                   */
/* Declare Prototype */
/*                   */
void UserVBlankIn( void );
void SoundInit( void );
void SoundMain( PDS_PERIPHERAL * );
void setpan( Sint8 *, Sint8 );
void main( void );

/*                   */
/* Global Varibables */
/*                   */
SDMIDI midi_handle1;
SDMIDI midi_handle2;
SDSHOT shot_handle;
mpHn   *pcm_handle;

Sint32 track[ 99 ];
Sint32 numoftrack;

Uint8 *msg[] = { "Stop", "Play" };

/*                 */
/* Function Define */
/*                 */
void UserVBlankIn() {
  /* Call Sound Server */
  sdSysServer();
}

void MidiManager( PDS_PERIPHERAL *pad ) {
  SDS_MIDI_STAT midi_status;
  Sint32 stat1, stat2;

  sdMidiGetStat( midi_handle1, &midi_status );
  if ( midi_status.m_Flg & SDD_PORT_FLG_PLAY ) {
    stat1 = 0;
  } else {
    stat1 = 1;
  }
  sdMidiGetStat( midi_handle2, &midi_status );
  if ( midi_status.m_Flg & SDD_PORT_FLG_PLAY ) {
    stat2 = 0;
  } else {
    stat2 = 1;
  }

  if ( pad->press & PDD_DGT_TA ) {
    if ( stat1 == 0 ) {
      sdMidiStop( midi_handle1 );
    } else {
      /* Sequence play */
      sdMidiPlay( midi_handle1, 0, 0, 0 );
      sdSndSetFxPrg( 0, 0 );
    }
  }
  if ( pad->press & PDD_DGT_TB ) {
    if ( stat2 == 0 ) {
      sdMidiStop( midi_handle2 ); 
    } else {
      sdMidiPlay( midi_handle2, 0, 1, 0 );
      sdSndSetFxPrg( 1, 0 );
    }
  }
  njPrint( NJM_LOCATION( 5, 6 ), "A     : %s Sequence A", msg[ stat1 ] );
  njPrint( NJM_LOCATION( 5, 7 ), "B     : %s Sequence B", msg[ stat2 ] );
}

void ShotManager( PDS_PERIPHERAL *pad ) {
  SDS_SHOT_STAT shot_status;
  Sint32 stat;
  static Sint32 num;

  sdShotGetStat( shot_handle, &shot_status );
  if ( shot_status.m_Flg & SDD_PORT_FLG_PLAY ) {
    stat = 0;
  } else {
    stat = 1;
  }

  if ( pad->press & PDD_DGT_TA ) {
    sdShotGetStat( shot_handle, &shot_status );
    if ( shot_status.m_Flg & SDD_PORT_FLG_PLAY ) {
      sdShotStop( shot_handle );
    } else {
      /* Sequence play */
      sdShotPlay( shot_handle, 0, num, 0 );
    }
  }
  if ( pad->press & PDD_DGT_KR ) {
    if ( ++num > 3 ) num = 3;
  }
  if ( pad->press & PDD_DGT_KL ) {
    if ( --num < 0 ) num = 0;
  }
  njPrint( NJM_LOCATION( 5, 6 ), "Left/Right: Change Music" );
  njPrint( NJM_LOCATION( 5, 7 ), "A         : %s One Shot #%d", msg[ stat ], num );
}

void PCMManager( PDS_PERIPHERAL *pad ) {
  Sint32 play_stat, i;
  static Sint32 loop_stat = 0;
  Uint8 *loop[] = { "Valid", "Invalid" };

  i = mpGetStat( pcm_handle );
  if ( i == MP_STAT_PLAY ) {
    play_stat = 0;
  } else {
    play_stat = 1;
  }

  if ( pad->press & PDD_DGT_TA ) {
    if ( i == MP_STAT_PLAY ) {
      mpStop( pcm_handle );
    } else {
      mpPlay( pcm_handle, 0 );
    }
  }
  if ( pad->press & PDD_DGT_ST ) {
    if ( loop_stat == 0 ) {
      mpSetLoop( pcm_handle, true );
      loop_stat = 1;
    } else {
      mpSetLoop( pcm_handle, false );
      loop_stat = 0;
    }
  }

  njPrint( NJM_LOCATION( 5, 7 ), "A    : %s PCM Steam (On Memory)", msg[ play_stat ] );
  njPrint( NJM_LOCATION( 5, 8 ), "START: %s Loop point", loop[ loop_stat ] );
}

void GDDAManager( PDS_PERIPHERAL *pad ) {
  static Sint32 tr = 0;
  Sint32        st;

  if ( gdFsGetDrvStat() == GDD_DRVSTAT_PLAY ) {
    st = 0;
  } else {
    st = 1;
  }

  if ( pad->press & PDD_DGT_KR ) {
    if ( ++tr > ( numoftrack - 1 ) ) tr = numoftrack - 1;
  }
  if ( pad->press & PDD_DGT_KL ) {
    if ( --tr < 0 ) tr = 0;
  }
  if ( pad->press & PDD_DGT_TA ) {
    if ( st == 1 ) {
      gdFsDaPlay( track[ tr ], track[ tr ], 0 );
      sdGddaSetVol( 0x70, 0x70 );
    } else {
      gdFsDaStop();
      sdGddaSetVol( 0, 0 );
    }
  }
  njPrint( NJM_LOCATION( 5, 6 ), "Left/Right: Change DA Track number" );
  njPrint( NJM_LOCATION( 5, 7 ), "A:          %s Digital Audio Track %d", msg[ st ], track[ tr ] );
  
}

void FXManager( PDS_PERIPHERAL *pad ) {
  Sint8 fx_module;
  Sint8 fx_out;
  static Uint32 module = 0;
  static Uint32 out = 0;

  sdSndGetFxPrg( &fx_module );
  sdSndGetFxOut( &fx_out );

  if ( pad->press & PDD_DGT_KR ) {
    module = ( module + 1 + MAX_OF_FX ) % MAX_OF_FX;
  }
  if ( pad->press & PDD_DGT_KL ) {
    module = ( module - 1 + MAX_OF_FX ) % MAX_OF_FX;
  }
  if ( pad->press & PDD_DGT_TR ) {
    out = ( out + 1 + MAX_OF_FX ) % MAX_OF_FX_OUT;
  }
  if ( pad->press & PDD_DGT_TL ) {
    out = ( out - 1 + MAX_OF_FX ) % MAX_OF_FX_OUT;
  }
  if ( pad->press & PDD_DGT_ST ) {
    sdSndSetFxPrg( module, out );
  }
  if ( pad->press & PDD_DGT_TA ) {
    sdSndSetFxPrg( module, out );
  }
  if ( pad->press & PDD_DGT_TB ) {
    sdSndSetFxOut( out );
  }
  if ( pad->press & PDD_DGT_TX ) {
    sdSndClearFxPrg();
  }

  njPrint( NJM_LOCATION( 5, 6 ), "Left/Right: Change FX Program No." );
  njPrint( NJM_LOCATION( 5, 7 ), "L/R:        Change FX Out No." );
  njPrint( NJM_LOCATION( 5, 8 ), "START:      Set FX Program and Out" ); 
  njPrint( NJM_LOCATION( 5, 9 ), "A:          Set FX Programi #%d", module ); 
  njPrint( NJM_LOCATION( 5, 10 ), "B:          Set FX Out #%d", out ); 
  njPrint( NJM_LOCATION( 5, 11 ), "X:          Reset FX" ); 
  njPrint( NJM_LOCATION( 5, 13 ), "Now FX Program:%d, FX Out %d", fx_module, fx_out );
}

void SndInit( void ) {
  Uint32 buf[] = { 0, 1 };
  char   *file[] = { "SAMPLE_L.P08", "SAMPLE_R.P08" };
  Sint32 temp[ 102 ], i, j;

  SoundInitialize( "MANATEE.DRV", "DEMO.MLT" );
  sdMidiOpenPort( &midi_handle1 );
  sdMidiOpenPort( &midi_handle2 );
  sdShotOpenPort( &shot_handle );
  mpInit();
  pcm_handle = mpOpen( file, 2 );
  mpSetPort( pcm_handle, buf, 2 );
  mpSetPrm( pcm_handle, 44100, 8 );
  mpSetLoopStart( pcm_handle, 824000 );
  mpSetFx( pcm_handle, 0, 90, 90 );

  if ( gdFsGetToc( 1, ( void * )temp ) != GDD_ERR_OK ) {
    return;
  }
  i = ( ( temp[ 100 ] & 0x00ff0000 ) >> 16 );

  numoftrack = 0;
  for ( j = 2 ; j < i ; ++j ) {
    if ( ( buf[ j ] & 0xc0000000 ) == 0 ) {
      track[ numoftrack++ ] = j + 1;
    }
  }


}

void SoundMain( PDS_PERIPHERAL *pad ) {
  static Sint8  num = 0;
  static Uint8  base = 0;
  SDS_MIDI_STAT midi_status;

  switch ( base ) {
  case 0:
    MidiManager( pad );
    break;
  case 1:
    ShotManager( pad );
    break;
  case 2:
    PCMManager( pad );
    break;
  case 3:
    GDDAManager( pad );
    break;
  case 4:
    FXManager( pad );
    break;
  }

  if ( pad->press & PDD_DGT_KU ) {
    base = --base % MAX_OF_FUNCTION;
  }
  if ( pad->press & PDD_DGT_KD ) {
    base = ++base % MAX_OF_FUNCTION;
  }

  njPrintC( NJM_LOCATION( 5, 15 + base ), ">" );
}
 
void main(void)
{
  PDS_PERIPHERAL *pad;
  GDFS           sys;
  Sint32         cnt = 0;

  /* Initialize System */
  njSetBorderColor( 0x00000000 );
#ifdef VGA
  sbInitSystem( NJD_RESOLUTION_VGA, NJD_FRAMEBUFFER_MODE_RGB565, 1 );
#else
  sbInitSystem( NJD_RESOLUTION_640x480_NTSCI, NJD_FRAMEBUFFER_MODE_RGB565, 1 );
#endif

  njInitVertexBuffer( 50000, 0, 50000, 0, 0 );
  njInitPrint( NULL, 0, NJD_TEXFMT_ARGB_1555 );
  njSetBackColor( 0x00000000, 0x00000000, 0x000000FF );
  njPrintSize( 12 );
  SndInit();
  sys = gdFsGetSysHn();

  njSetVSyncFunction( UserVBlankIn );
  /* Request for update drive status register */
  gdFsReqDrvStat();

  while ( 1 ) {
    pad = pdGetPeripheral( PDD_PORT_A0 );
    njPrintC( NJM_LOCATION( 5, 3 ), "-- Sound Total Demo --" );
    njPrintC( NJM_LOCATION( 5, 5 ), "Up/Down   : Select Function" );
    njPrintC( NJM_LOCATION( 7, 15 ), "MIDI" );
    njPrintC( NJM_LOCATION( 7, 16 ), "One Shot" );
    njPrintC( NJM_LOCATION( 7, 17 ), "PCM Stream" );
    njPrintC( NJM_LOCATION( 7, 18 ), "GDDA" );
    njPrintC( NJM_LOCATION( 7, 19 ), "FX" );
    SoundDrvStat( 5, 21 );
    SoundLibVer( 5, 22 );
    SoundDrvVer( 5, 23 );
    if ( cnt == 0 ) {
      /* Wait for finish before system request */
      while( gdFsGetStat( sys ) != GDD_STAT_COMPLETE );
    }
    SoundMain( pad );
    if ( cnt == 1 ) {
      /* Request for update drive status register */
      gdFsReqDrvStat();
    }
    mpTask();
    cnt = ( cnt + 1 ) % 2;
    njWaitVSync();
  }
}

/******************************* end of file *******************************/
