1 /***************************************************************************
2 
3   2608intf.c
4 
5   The YM2608 emulator supports up to 2 chips.
6   Each chip has the following connections:
7   - Status Read / Control Write A
8   - Port Read / Data Write A
9   - Control Write B
10   - Data Write B
11 
12 ***************************************************************************/
13 
14 #include "driver.h"
15 #include "ay8910.h"
16 #include "2608intf.h"
17 #include "fm.h"
18 
19 #ifdef BUILD_YM2608
20 
21 #define YM2608_NUMBUF 2
22 /* use FM.C with stream system */
23 
24 static int stream[MAX_2608];
25 
26 /* Global Interface holder */
27 static const struct YM2608interface *intf;
28 
29 static void *Timer[MAX_2608][2];
30 
31 
32 /* IRQ Handler */
IRQHandler(int n,int irq)33 static void IRQHandler(int n,int irq)
34 {
35 	if(intf->handler[n]) intf->handler[n](irq);
36 }
37 
38 /* Timer overflow callback from timer.c */
timer_callback_2608(int param)39 static void timer_callback_2608(int param)
40 {
41 	int n=param&0x7f;
42 	int c=param>>7;
43 
44 	YM2608TimerOver(n,c);
45 }
46 
47 /* TimerHandler from fm.c */
TimerHandler(int n,int c,int count,double stepTime)48 static void TimerHandler(int n,int c,int count,double stepTime)
49 {
50 	if( count == 0 )
51 	{	/* Reset FM Timer */
52 		timer_enable(Timer[n][c], 0);
53 	}
54 	else
55 	{	/* Start FM Timer */
56 		double timeSec = (double)count * stepTime;
57 		if (!timer_enable(Timer[n][c], 1))
58 			timer_adjust(Timer[n][c], timeSec, (c<<7)|n, 0);
59 	}
60 }
61 
FMTimerInit(void)62 static void FMTimerInit( void )
63 {
64 	int i;
65 
66 	for( i = 0 ; i < MAX_2608 ; i++ )
67 	{
68 		Timer[i][0] = timer_alloc(timer_callback_2608);
69 		Timer[i][1] = timer_alloc(timer_callback_2608);
70 	}
71 }
72 
73 /* update request from fm.c */
YM2608UpdateRequest(int chip)74 void YM2608UpdateRequest(int chip)
75 {
76 	stream_update(stream[chip],100);
77 }
78 
YM2608_sh_start(const struct MachineSound * msound)79 int YM2608_sh_start(const struct MachineSound *msound)
80 {
81 	int i,j;
82 	int rate = Machine->sample_rate;
83 	char buf[YM2608_NUMBUF][40];
84 	const char *name[YM2608_NUMBUF];
85 	int mixed_vol,vol[YM2608_NUMBUF];
86 	void *pcmbufa[YM2608_NUMBUF];
87 	int  pcmsizea[YM2608_NUMBUF];
88 
89 
90 	intf = msound->sound_interface;
91 	if( intf->num > MAX_2608 ) return 1;
92 
93 	if (AY8910_sh_start_ym(msound)) return 1;
94 
95 	/* Timer Handler set */
96 	FMTimerInit();
97 
98 	/* stream system initialize */
99 	for (i = 0;i < intf->num;i++)
100 	{
101 		/* stream setup */
102 		mixed_vol = intf->volumeFM[i];
103 		/* stream setup */
104 		for (j = 0 ; j < YM2608_NUMBUF ; j++)
105 		{
106 			name[j]=buf[j];
107 			vol[j] = mixed_vol & 0xffff;
108 			mixed_vol>>=16;
109 			sprintf(buf[j],"%s #%d Ch%d",sound_name(msound),i,j+1);
110 		}
111 		stream[i] = stream_init_multi(YM2608_NUMBUF,name,vol,rate,i,YM2608UpdateOne);
112 		/* setup adpcm buffers */
113 		pcmbufa[i]  = (void *)(memory_region(intf->pcmrom[i]));
114 		pcmsizea[i] = memory_region_length(intf->pcmrom[i]);
115 	}
116 
117 
118 	/* initialize YM2608 */
119 	if (YM2608Init(intf->num,intf->baseclock,rate,
120 		           pcmbufa,pcmsizea,
121 		           TimerHandler,IRQHandler) == 0)
122 		return 0;
123 
124 	/* error */
125 	return 1;
126 }
127 
128 /************************************************/
129 /* Sound Hardware Stop							*/
130 /************************************************/
YM2608_sh_stop(void)131 void YM2608_sh_stop(void)
132 {
133 	YM2608Shutdown();
134 	AY8910_sh_stop_ym();
135 }
136 /* reset */
YM2608_sh_reset(void)137 void YM2608_sh_reset(void)
138 {
139 	int i;
140 
141 	for (i = 0;i < intf->num;i++)
142 		YM2608ResetChip(i);
143 }
144 
145 /************************************************/
146 /* Status Read for YM2608 - Chip 0				*/
147 /************************************************/
READ_HANDLER(YM2608_status_port_0_A_r)148 READ_HANDLER( YM2608_status_port_0_A_r )
149 {
150 /*logerror("PC %04x: 2608 S0A=%02X\n",activecpu_get_pc(),YM2608Read(0,0));*/
151 	return YM2608Read(0,0);
152 }
153 
READ_HANDLER(YM2608_status_port_0_B_r)154 READ_HANDLER( YM2608_status_port_0_B_r )
155 {
156 /*logerror("PC %04x: 2608 S0B=%02X\n",activecpu_get_pc(),YM2608Read(0,2));*/
157 	return YM2608Read(0,2);
158 }
159 
160 /************************************************/
161 /* Status Read for YM2608 - Chip 1				*/
162 /************************************************/
READ_HANDLER(YM2608_status_port_1_A_r)163 READ_HANDLER( YM2608_status_port_1_A_r ) {
164 	return YM2608Read(1,0);
165 }
166 
READ_HANDLER(YM2608_status_port_1_B_r)167 READ_HANDLER( YM2608_status_port_1_B_r ) {
168 	return YM2608Read(1,2);
169 }
170 
171 /************************************************/
172 /* Port Read for YM2608 - Chip 0				*/
173 /************************************************/
READ_HANDLER(YM2608_read_port_0_r)174 READ_HANDLER( YM2608_read_port_0_r ){
175 	return YM2608Read(0,1);
176 }
177 
178 /************************************************/
179 /* Port Read for YM2608 - Chip 1				*/
180 /************************************************/
READ_HANDLER(YM2608_read_port_1_r)181 READ_HANDLER( YM2608_read_port_1_r ){
182 	return YM2608Read(1,1);
183 }
184 
185 /************************************************/
186 /* Control Write for YM2608 - Chip 0			*/
187 /* Consists of 2 addresses						*/
188 /************************************************/
WRITE_HANDLER(YM2608_control_port_0_A_w)189 WRITE_HANDLER( YM2608_control_port_0_A_w )
190 {
191 	YM2608Write(0,0,data);
192 }
193 
WRITE_HANDLER(YM2608_control_port_0_B_w)194 WRITE_HANDLER( YM2608_control_port_0_B_w )
195 {
196 	YM2608Write(0,2,data);
197 }
198 
199 /************************************************/
200 /* Control Write for YM2608 - Chip 1			*/
201 /* Consists of 2 addresses						*/
202 /************************************************/
WRITE_HANDLER(YM2608_control_port_1_A_w)203 WRITE_HANDLER( YM2608_control_port_1_A_w ){
204 	YM2608Write(1,0,data);
205 }
206 
WRITE_HANDLER(YM2608_control_port_1_B_w)207 WRITE_HANDLER( YM2608_control_port_1_B_w ){
208 	YM2608Write(1,2,data);
209 }
210 
211 /************************************************/
212 /* Data Write for YM2608 - Chip 0				*/
213 /* Consists of 2 addresses						*/
214 /************************************************/
WRITE_HANDLER(YM2608_data_port_0_A_w)215 WRITE_HANDLER( YM2608_data_port_0_A_w )
216 {
217 	YM2608Write(0,1,data);
218 }
219 
WRITE_HANDLER(YM2608_data_port_0_B_w)220 WRITE_HANDLER( YM2608_data_port_0_B_w )
221 {
222 	YM2608Write(0,3,data);
223 }
224 
225 /************************************************/
226 /* Data Write for YM2608 - Chip 1				*/
227 /* Consists of 2 addresses						*/
228 /************************************************/
WRITE_HANDLER(YM2608_data_port_1_A_w)229 WRITE_HANDLER( YM2608_data_port_1_A_w ){
230 	YM2608Write(1,1,data);
231 }
WRITE_HANDLER(YM2608_data_port_1_B_w)232 WRITE_HANDLER( YM2608_data_port_1_B_w ){
233 	YM2608Write(1,3,data);
234 }
235 
236 /**************** end of file ****************/
237 
238 #endif
239