📄 taitosnd.c
字号:
/******************************************************************************//* *//* TAITO SOUND SYSTEMS (C) 1986-1996 TAITO CORPORATION *//* *//******************************************************************************//*answer of hiroshi-----------------YM30?? series is Serial DAC convertor. FM chip output is Serial DAC.This DAC input to YM30??. It change to Analog data.Antiriad: Thanks!!Changes-------17-02-99:- Reduce volume of YM2151 emulation.11-02-99:- z80 emulator and banking was changed some days ago...- added tc0140syt_reset() calls.18-01-99:- tc0140syt emulation is moved to tc140syt.c/h.14-01-99:- Merge changes from Hiroshi source (M6295 bank, ym2151: reg -> reg2151).09-01-99:- Add debug message if 68000 sends data before z80 has read the current data.27-12-98:- Add Hiroshi changes (Volume and Panning).- What is YM3016? Is this the chip for panning/volume control?17-12-98:- Added latest Hiro-Shi changes.- Removed YM2610_Frame(), no longer needed.- Removed Z80 debug as there is already Z80 bad read/write/io routines in mz80help.c.16-12-98:- Added YM2203 (Taito B-System). Used by Master of Weapons etc...*/#include "gameinc.h"#include "taitosnd.h"#include "fm.h"#ifdef RAINE_DEBUG#include "debug.h"#endif#include "sasound.h" // sample support routinesstatic UINT8 *ROMBANK=NULL; // Pointer to start of z80 rom bank datastatic UINT8 *BANKLIST[8]; // Pointers to start of each bank (0-7)static int curr_bank;/************************************************************/// YM2151 Handler// --------------static int reg2151;UINT16 YM2151ReadZ80(UINT16 offset){#if 0 if( (offset&0x01) ){ return YM2151_status_port_0_r(0); } else return 0;#else static int ta=0; ta^=255; return(ta); #endif}UINT16 YM2151ReadZ80_Timer(UINT16 offset){#if 1 if( (offset&0x01) ){ return YM2151_status_port_0_r(0); } else return 0;#else static int ta=0; ta^=255; return(ta); #endif}void YM2151WriteZ80(UINT16 offset, UINT8 data){ if((offset&1)==0){ reg2151=data; } else{ YM2151_register_port_0_w(offset,reg2151); // It's faster to wait for the data like this!! YM2151_data_port_0_w(offset,data); }}// Banking via YM2151 - TAITOvoid YM2151TaitoWriteZ80(UINT16 offset, UINT8 data){ if((offset&1)==0){ reg2151=data; } else{ if(reg2151==0x1B){ TaitoSoundSetBank(offset, (UINT8) ((data>>6)&3) ); } YM2151_register_port_0_w(offset,reg2151); // It's faster to wait for the data like this!! YM2151_data_port_0_w(offset,data); }}/************************************************************/// YM2203A Handler// ---------------UINT16 YM2203AReadZ80(UINT16 offset){ #if 0 if((offset&1)==0){ return YM2203_status_port_0_r(0); } else{ return YM2203_read_port_0_r(0); } #else static int ta=0; ta^=255; return(ta); #endif}void YM2203AWriteZ80(UINT16 offset, UINT8 data){ static int reg; if((offset&1)==0){ reg=data; } else{ YM2203_control_port_0_w(offset,reg); YM2203_write_port_0_w(offset,data); }}// Banking via YM2203 - TAITOvoid YM2203ATaitoWriteZ80(UINT16 offset, UINT8 data){ static int reg; if((offset&1)==0){ reg=data; } else{ if(reg==0x0E){ TaitoSoundSetBank(offset, (UINT8) (data&3) ); } YM2203_control_port_0_w(offset,reg); YM2203_write_port_0_w(offset,data); }}// YM2203A Handler// ---------------UINT16 YM2203BReadZ80(UINT16 offset){ #if 0 if((offset&1)==0){ return YM2203_status_port_1_r(0); } else{ return YM2203_read_port_1_r(0); } #else // Cadash and Rainbow Extra only work with this code>>> static int ta=0; ta^=255; return(ta); #endif}void YM2203BWriteZ80(UINT16 offset, UINT8 data){ static int reg; if((offset&1)==0){ reg=data; } else{ YM2203_control_port_1_w(offset,reg); YM2203_write_port_1_w(offset,data); }}/************************************************************ Taito Z80+YM2610 Interface -------------------------- For 99% of Taito sound Z80s using a YM2610************************************************************/// YM2610 Handler// --------------UINT16 YM2610ReadZ80(UINT16 offset){#if 1 switch(offset&3){ case 0x00: return(YM2610_status_port_0_A_r(offset)); case 0x01: return(YM2610_read_port_0_r(offset)); case 0x02: return(YM2610_status_port_0_B_r(offset)); default: return(YM2610_read_port_0_r(offset)); }#else static int ta=0; ta^=255; return(ta); #endif}UINT16 YM2610ReadZ80SP(UINT16 offset){ // Speed patch static int ta = 0; switch(offset&3){ case 0x00: ta ^= 0x03; return YM2610_status_port_0_A_r(offset) | ta; //return(YM2610_status_port_0_A_r(offset)); case 0x02: return(YM2610_status_port_0_B_r(offset)); break; default: return(YM2610_read_port_0_r(offset)); break; }}void YM2610WriteZ80(UINT16 offset, UINT8 data){ switch(offset&3){ case 0x00: YM2610_control_port_0_A_w(offset,data); break; case 0x01: YM2610_data_port_0_A_w(offset,data); break; case 0x02: YM2610_control_port_0_B_w(offset,data); break; default: YM2610_data_port_0_B_w(offset,data); break; }}static int taitoym2610pan[4];void Pan2610WriteZ80(UINT16 offset, UINT8 data){ int vol, pan, cen; taitoym2610pan[offset&0x03] = data&0x00ff; if( !(offset&0x02) ){ /**** channel 0 (YM3016 Left channel) ****/ if( taitoym2610pan[0] > taitoym2610pan[1] ) pan = taitoym2610pan[0]; else pan = taitoym2610pan[1]; vol = (taitoym2610pan[0] + taitoym2610pan[1]) / 2; if( pan ){ pan = 0x80 + (((0x7f00/pan) * (taitoym2610pan[0] - taitoym2610pan[1]))>>8); cen = pan < 0x80 ? 0x80 - pan : -(0x80 - pan); vol = vol - ((vol * cen)>>(8)); // vol is sometimes 0x1f. It is a bad mapping if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0), vol ); saSetPan( YM2610_get_stream_num(0), pan ); //print_ingame(120,"Make ch0 vol:%02x pan:%02x", vol, pan ); } else{ if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0), vol>>1 ); saSetPan( YM2610_get_stream_num(0), 0x80 ); /* center */ } } else{ /**** channel 1 (YM3016 Right channel) ****/ if( taitoym2610pan[2] > taitoym2610pan[3] ) pan = taitoym2610pan[2]; else pan = taitoym2610pan[3]; vol = (taitoym2610pan[2] + taitoym2610pan[3]) / 2; if( pan ){ pan = 0x80 + (((0x7f00/pan) * (taitoym2610pan[2] - taitoym2610pan[3]))>>8); cen = pan < 0x80 ? 0x80 - pan : -(0x80 - pan); vol = vol - ((vol * cen)>>(8)); if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0)+1, vol ); saSetPan( YM2610_get_stream_num(0)+1, pan ); //print_ingame(120,"Make ch1 vol:%02x pan:%02x", vol, pan ); } else{ if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0)+1, vol>>1 ); saSetPan( YM2610_get_stream_num(0)+1, 0x80 ); /* center */ } }}static int volume_offset;void Pan2610_OffsetVol( int data ){ volume_offset = data;}void Pan2610WriteZ80_OffsetVol(UINT16 offset, UINT8 data){ int vol, pan, cen; taitoym2610pan[offset&0x03] = data&0x00ff; if( !(offset&0x02) ){ /**** channel 0 (YM3016 Left channel) ****/ if( taitoym2610pan[0] > taitoym2610pan[1] ) pan = taitoym2610pan[0]; else pan = taitoym2610pan[1]; vol = ((taitoym2610pan[0] + taitoym2610pan[1]) / 2)<<volume_offset; if( pan ){ pan = 0x80 + (((0x7f00/pan) * (taitoym2610pan[0] - taitoym2610pan[1]))>>8); cen = pan < 0x80 ? 0x80 - pan : -(0x80 - pan); vol = vol - ((vol * cen)>>(8)); if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0), vol ); saSetPan( YM2610_get_stream_num(0), pan ); //print_ingame(120,"Make ch0 vol:%02x pan:%02x", vol, pan ); } else{ if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0), vol>>1 ); saSetPan( YM2610_get_stream_num(0), 0x80 ); /* center */ } } else{ /**** channel 1 (YM3016 Right channel) ****/ if( taitoym2610pan[2] > taitoym2610pan[3] ) pan = taitoym2610pan[2]; else pan = taitoym2610pan[3]; vol = ((taitoym2610pan[2] + taitoym2610pan[3]) / 2)<<volume_offset; if( pan ){ pan = 0x80 + (((0x7f00/pan) * (taitoym2610pan[2] - taitoym2610pan[3]))>>8); cen = pan < 0x80 ? 0x80 - pan : -(0x80 - pan); vol = vol - ((vol * cen)>>(8)); if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0)+1, vol ); saSetPan( YM2610_get_stream_num(0)+1, pan ); //print_ingame(120,"Make ch1 vol:%02x pan:%02x", vol, pan ); } else{ if (vol == 0x1f) vol = 0xff; saSetVolume( YM2610_get_stream_num(0)+1, vol>>1 ); saSetPan( YM2610_get_stream_num(0)+1, 0x80 ); /* center */ } }}static UINT8 TYM = 0x07;UINT16 TaitoYM2610Test(UINT16 offset){ return TYM;}static struct YM2610interface ym2610_interface ={ 1, 8000000, { YM2203_VOL(220,220) }, { 0 }, { 0 }, { 0 }, { 0 }, { NULL }, { 0 }, // hiro-shi { 1 }, // hiro-shi { YM3012_VOL(255,OSD_PAN_LEFT,255,OSD_PAN_RIGHT) },};struct SOUND_INFO taito_ym2610_sound[] ={ { SOUND_YM2610, &ym2610_interface, }, { 0, NULL, },};struct SOUND_INFO taito_ym2610b_sound[] ={ { SOUND_YM2610B, &ym2610_interface, }, { 0, NULL, },};/**** not pan control (lock volume) ****/void Taito2610_Frame(void){ //cpu_execute_cycles(CPU_Z80_0, (4000000/60)*2); // Sound Z80 cpu_execute_cycles(CPU_Z80_0, 6000000/60); // Sound Z80 /*#ifdef RAINE_DEBUG print_debug("Z80PC0:%04x\n",z80pc); #endif*/ cpu_interrupt(CPU_Z80_0, 0x0038); #if 0 // REALLY useless !!! saSetVolume( YM2610_get_stream_num(0), 0xaf ); saSetPan( YM2610_get_stream_num(0), 0x00 ); saSetVolume( YM2610_get_stream_num(0)+1, 0xaf ); saSetPan( YM2610_get_stream_num(0)+1, 0xff );#endif }/**** pan control type (Darius2/NinjaWarriors board. but not use ninjaw.) ****/void Taito2610_FramePan(void){ cpu_execute_cycles(CPU_Z80_0, (4000000/60)*2); // Sound Z80 /*#ifdef RAINE_DEBUG print_debug("Z80PC0:%04x\n",z80pc); #endif*/ cpu_interrupt(CPU_Z80_0, 0x0038);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -