📄 msm5205.c
字号:
/**************************************************************//* MSM5205 (DARIUS ADPCM chip) control *//**************************************************************/#include "raine.h"#include "sasound.h"#include "msm5205.h"#ifdef RAINE_DEBUG#include "debug.h"#endifstatic struct MSM5205buffer_interface *intf;typedef struct M5205_SAMPLE{ UINT32 len; // length (in samples?) INT16 *data; // sample data (16 bit?)} M5205_SAMPLE;struct msm5205buffer_chip{ int sample_rate; int now_reqcode; struct M5205_SAMPLE *samp; int stream; int req_len; INT16 *req_buf; int req_vol; int offset, add; INT16 *decode_area;};struct msm5205buffer_chip *MSM5205buffer_chip = NULL;static int chip_num = 0;static int emu_rate, buf_len;static int sample_len;#define UPDATE_SHIFT (8)static INLINE int aLimit( int val, int max, int min ){ if ( val > max ) val = max; else if ( val < min ) val = min; return val;}/**************************************************//* decode control *//**************************************************/static int ad_sample;static int ad_index;static int ad_index_table[8] = { -1, -1, -1, -1, 2, 4, 6, 8};static int ad_offset_table[49]= { 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0029, 0x002d, 0x0032, 0x0037, 0x003c, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006b, 0x0076, 0x0082, 0x008f, 0x009d, 0x00ad, 0x00be, 0x00d1, 0x00e6, 0x00fd, 0x0117, 0x0133, 0x0151, 0x0173, 0x0198, 0x01c1, 0x01ee, 0x0220, 0x0256, 0x0292, 0x02d4, 0x031c, 0x036c, 0x03c3, 0x0424, 0x048e, 0x0502, 0x0583, 0x0610};static void ad_decode(int ad_code){ int ad_base; int ad_offset; ad_base = ad_offset_table[ad_index]; ad_offset = ad_base/8; if( ad_code&0x01 ) ad_offset += ad_base>>2; if( ad_code&0x02 ) ad_offset += ad_base>>1; if( ad_code&0x04 ) ad_offset += ad_base; if( ad_code&0x08 ) ad_offset = 0 - ad_offset; ad_sample = aLimit( ad_sample + ad_offset, 2047, -2048 ); ad_index = aLimit( ad_index + ad_index_table[ad_code&7], 48, 0 );}/**************************************************//* rom decode *//**************************************************/static unsigned int err_table;static int decode_table_count;static unsigned int *decode_table;static int decode_area_size;static INT16 *decode_area;void MSM5205_decode( int i, struct M5205_SAMPLE *samp, UINT8 *rom, UINT32 romsize, UINT32 start, UINT32 stop ){ INT16 *ad_data; /**** table initial ****/ samp->len = 0; samp->data = NULL; /*************************************************/ if( stop >= romsize ) stop = romsize;#ifdef RAINE_DEBUG print_debug( "Now decode No.%d %08x-%08x\n", i, start, stop );#endif if((start<romsize) && (stop<romsize)){ // Add Antiriad (Kick Off needs it) if( (start < stop) && !(start == 0x00808080 || start == 0x00080808 || stop == 0x00808080 || stop == 0x00080808) ){ /**** low limit address check ****/ if( start < err_table ) err_table = start; samp->len = (stop - start)*2; /* get length (1byte = 2 data) */ /**** new decode routine ****/ { int count, j; count = decode_table_count; for( j = 0; j < count; j++ ){#if 0 if( start == *(decode_table + j*3) && stop <= *(decode_table + j*3 + 1) ){#ifdef RAINE_DEBUG print_debug( "Get decode table (%08x - %08x) [%08x-%08x]\n", start, stop, *(decode_table + j*3), *(decode_table + j*3 + 1) );#endif samp->data = (void *)(*(decode_table + j*3 + 2)|0x80000000); return; }#else if( start >= *(decode_table + j*3) && stop <= *(decode_table + j*3 + 1) ){#ifdef RAINE_DEBUG print_debug( "Get decode table (%08x - %08x) [%08x-%08x]\n", start, stop, *(decode_table + j*3), *(decode_table + j*3 + 1) );#endif samp->data = (void *)((*(decode_table + j*3 + 2) + (start - *(decode_table + j*3))*2)|0x80000000 ); return; }#endif } /**** decode start ****/ *(decode_table + count*3) = start; *(decode_table + count*3 + 1) = stop; *(decode_table + count*3 + 2) = decode_area_size; decode_table_count++;#ifdef RAINE_DEBUG print_debug( "New decode Address (%02x:%08x - %08x)\n", count, *(decode_table + count*3), *(decode_table + count*3 + 1) );#endif decode_area = realloc( decode_area, (decode_area_size + samp->len) * sizeof(INT16) ); ad_data = (INT16 *)(decode_area + decode_area_size); samp->data = (void *)(decode_area_size|0x80000000); /* rom offset */ decode_area_size += samp->len; rom += start; ad_sample = 0; /* work init */ ad_index = 0; /* work init */ for( start = 0; start < samp->len/2; start++ ){ ad_decode( (*rom)>>4 ); *ad_data++ = (INT16)(ad_sample<<4); ad_decode( (*rom)&0x0f ); *ad_data++ = (INT16)(ad_sample<<4); rom++; } } } }}/**************************************************//* sh start *//**************************************************/int MSM5205buffer_sh_start( struct MSM5205buffer_interface *interface ){ int num; int i; char buf[2][40]; const char *name[2]; struct msm5205buffer_chip *mp; int rate = audio_sample_rate; intf = interface; chip_num = intf->num; sample_len = rate / 60; emu_rate = sample_len * 60; if( chip_num > MSM5205BF_MAX ) return 1; if( (MSM5205buffer_chip = (struct msm5205buffer_chip *)malloc( sizeof(struct msm5205buffer_chip) * chip_num )) == NULL ) return 1; for( num = 0; num < chip_num; num++ ){ mp = MSM5205buffer_chip + num; mp->now_reqcode = -1; mp->sample_rate = intf->sample_rate[num]; mp->req_len = 0; mp->req_vol = 0xff; mp->add = (int)(((float)mp->sample_rate / (float)rate)*(1<<UPDATE_SHIFT)); if( intf->updatemode == MSM5205_MONO ){ sprintf( buf[0], "MSM5205 Monaural" ); mp->stream = stream_init( buf[0], emu_rate, 16, num, MSM5205buffer_UpdateOne ); // Antiriad: fix param num saSetPan( mp->stream, 0x80 ); saSetVolume( mp->stream, intf->volume[num] ); } else{ name[0] = buf[0]; name[1] = buf[1]; sprintf( buf[0], "MSM5205 Stereo Left" ); sprintf( buf[1], "MSM5205 Stereo Right" ); mp->stream = stream_init_multi( 2, name, emu_rate, 16, num, MSM5205buffer_Stereo_UpdateOne ); // Antiriad: fix param num saSetPan( mp->stream, 0x00 ); saSetPan( mp->stream+1, 0xff ); saSetVolume( mp->stream, intf->volume[num] ); saSetVolume( mp->stream+1, intf->volume[num] ); } mp->samp = (M5205_SAMPLE *)malloc( sizeof(M5205_SAMPLE) * intf->listsize[num] ); decode_table = malloc( (sizeof(unsigned int) * intf->listsize[num] * 3) ); if( mp->samp != NULL && decode_table != NULL ){ decode_table_count = 0; decode_area = NULL; decode_area_size = 0; for( i = 0; i < intf->listsize[num]; i++ ){ *(decode_table + i*3) = 0xffffffff; *(decode_table + i*3 + 1) = 0xffffffff; *(decode_table + i*3 + 2) = 0x00000000; } for( i = 0; i < intf->listsize[num]; i++ ) MSM5205_decode( i, mp->samp + i, intf->rom[num], intf->romsize[num], (intf->list[num] + i)->start, (intf->list[num] + i)->end ); if( decode_area != NULL ){ mp->decode_area = decode_area; /* stock work */ for( i = 0; i < intf->listsize[num]; i++ ){ if( ((unsigned int)(mp->samp + i)->data)&0x80000000 ) (mp->samp + i)->data = decode_area + (((unsigned int)(mp->samp + i)->data)&0x7fffffff); /**** 0x8xxxxxxx is use flag ****/ } } else{ mp->decode_area = NULL; } /**** end of decode ****/ free( decode_table ); } } return 0;}/**************************************************//**************************************************/void MSM5205buffer_sh_stop( void ){ int i; struct msm5205buffer_chip *mp; if( MSM5205buffer_chip == NULL ) return; for( i = 0; i < chip_num; i++ ){ mp = MSM5205buffer_chip + i; if(mp->samp != NULL) free(mp->samp); // Antiriad 06-04-99 if(mp->decode_area != NULL) free(mp->decode_area); } if(MSM5205buffer_chip != NULL) free(MSM5205buffer_chip); // Antiriad 06-04-99 MSM5205buffer_chip = NULL; chip_num = 0;}/**************************************************//* sh update *//**************************************************/void MSM5205buffer_UpdateOne( int num, void *buffer, int length ){ int i, addr, bf_len; INT16 *sp =NULL, *dsp = NULL; struct msm5205buffer_chip *mp; if( num >= chip_num ) return; // Antiriad: replace > with >= mp = MSM5205buffer_chip + num; sp = (INT16 *)buffer; dsp = mp->req_buf; buf_len = length * 2; bf_len = length; if( mp->now_reqcode == -1 ){ memset( buffer, 0, buf_len ); } else{ for( i = 0; i < bf_len; i++ ){ addr = mp->offset>>UPDATE_SHIFT; if( addr >= mp->req_len ){ memset( sp, 0, (bf_len - i)*2 ); mp->now_reqcode = -1; /* end ADPCM */ break; } *sp++ = *(dsp + addr); mp->offset += mp->add; } }}/**************************************************//* sh update *//**************************************************/void MSM5205buffer_Stereo_UpdateOne( int num, void **buffer, int length ){ int i, addr, bf_len; INT16 *sp = NULL, *sp2 = NULL, *dsp = NULL; int lv, rv; struct msm5205buffer_chip *mp; if( num >= chip_num ) return; // Antiriad: replace > with >= mp = MSM5205buffer_chip + num; lv = mp->req_vol&0xf0; rv = (mp->req_vol&0x0f)<<4; buf_len = length * 2; sp = (INT16 *)buffer[0]; sp2 = (INT16 *)buffer[1]; dsp = mp->req_buf; bf_len = buf_len / 2; if( mp->now_reqcode == -1 ){ memset( sp, 0, bf_len*sizeof(short) ); memset( sp2, 0, bf_len*sizeof(short) ); } else{ for( i = 0; i < bf_len; i++ ){ addr = mp->offset>>UPDATE_SHIFT; if( addr >= mp->req_len ){ memset( sp, 0, (bf_len - i)*2 ); memset( sp2, 0, (bf_len - i)*2 ); mp->now_reqcode = -1; /* end ADPCM */ break; } *sp++ = (((int)*(dsp + addr)) * lv)>>8; *sp2++ = (((int)*(dsp + addr)) * rv)>>8; mp->offset += mp->add; } }}/**************************************************//* ADPCM request *//**************************************************/void MSM5205buffer_request( int num, int code ){ struct msm5205buffer_chip *mp; if( num >= chip_num ) return; // Antiriad: replace > with >= mp = MSM5205buffer_chip + num; if(! mp->samp ) return; // Antiriad ??-??-99 mp->now_reqcode = code; mp->req_buf = mp->samp[code].data; mp->req_len = mp->samp[code].len; mp->offset = 0;}/**************************************************//* ADPCM pan request *//**************************************************/void MSM5205buffer_setpan( int num, int data ){ struct msm5205buffer_chip *mp; if( num >= chip_num ) return; // Antiriad: replace > with >= mp = MSM5205buffer_chip + num; mp->req_vol = data;}/**************** end of file ****************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -