1 /***************************************************************************
2 
3 								-= Seta Games =-
4 
5 					driver by	Luca Elia (eliavit@unina.it)
6 
7 
8 Sound Chip:
9 
10 	X1-010 					[Seta Custom]
11 	Unsigned 16 Bit PCM 	[Fixed Per Game Pitch?]
12 	16 Voices				[There's More Data Written!]
13 
14 Format:
15 
16 	8 registers per channel (mapped to the lower bytes of 16 words on the 68K)
17 
18 	Reg:	Bits:		Meaning:
19 
20 	0		7654 321-
21 			---- ---0	Key On / Off
22 
23 	1		7654 ----	Volume 1(L?)
24 			---- 3210	Volume 2(R?)
25 
26 	2					? (high byte?)
27 	3					? (low  byte?)
28 
29 	4					Sample Start / 0x1000 			[Start/End in bytes]
30 	5					0x100 - (Sample End / 0x1000)	[PCM ROM is Max 1MB?]
31 
32 	6					?
33 	7					?
34 
35 
36 Hardcoded Values (for now):
37 
38 	PCM ROM region:		REGION_SOUND1
39 	Sample Frequency:	4, 6, 8 KHz
40 
41 ***************************************************************************/
42 #include "driver.h"
43 
44 /* Variables and functions that driver has access to */
45 unsigned char *seta_sound_ram;
46 
47 #define SETA_NUM_CHANNELS 16
48 
49 /* Variables only used here */
50 static int firstchannel, frequency;
51 static int seta_reg[SETA_NUM_CHANNELS][8];
52 
53 
54 
55 
seta_sh_start(const struct MachineSound * msound)56 int seta_sh_start(const struct MachineSound *msound)
57 {
58 	int i;
59 	int vol[MIXER_MAX_CHANNELS];
60 
61 	for (i = 0;i < MIXER_MAX_CHANNELS;i++)	vol[i] = 100;
62 	firstchannel = mixer_allocate_channels(SETA_NUM_CHANNELS,vol);
63 
64 	for (i = 0; i < SETA_NUM_CHANNELS; i++)
65 	{
66 		char buf[40];
67 		sprintf(buf,"X1-010 Channel #%d",i);
68 		mixer_set_name(firstchannel + i,buf);
69 	}
70 	return 0;
71 }
72 
seta_sh_start_4KHz(const struct MachineSound * msound)73 int seta_sh_start_4KHz(const struct MachineSound *msound)
74 {
75 	frequency = 4000;
76 	return seta_sh_start(msound);
77 }
78 
seta_sh_start_6KHz(const struct MachineSound * msound)79 int seta_sh_start_6KHz(const struct MachineSound *msound)
80 {
81 	frequency = 6000;
82 	return seta_sh_start(msound);
83 }
84 
seta_sh_start_8KHz(const struct MachineSound * msound)85 int seta_sh_start_8KHz(const struct MachineSound *msound)
86 {
87 	frequency = 8000;
88 	return seta_sh_start(msound);
89 }
90 
91 
92 
93 /* Use these for 8 bit CPUs */
94 
95 
READ_HANDLER(seta_sound_r)96 READ_HANDLER( seta_sound_r )
97 {
98 	int channel	=	offset / 8;
99 	int reg		=	offset % 8;
100 
101 	if (channel < SETA_NUM_CHANNELS)
102 	{
103 		switch (reg)
104 		{
105 			case 0:
106 				return ( mixer_is_sample_playing(firstchannel + channel) ? 1 : 0 );
107 			default:
108 				//logerror("PC: %06X - X1-010 channel %X, register %X read!\n",cpu_get_pc(),channel,reg);
109 				return seta_reg[channel][reg];
110 		}
111 	}
112 
113 	return seta_sound_ram[offset];
114 }
115 
116 
117 
118 
119 #define DUMP_REGS \
120 	logerror("X1-010 REGS: ch %X] %02X %02X %02X %02X - %02X %02X %02X %02X\n", \
121 							channel, \
122 							seta_reg[channel][0],seta_reg[channel][1], \
123 							seta_reg[channel][2],seta_reg[channel][3], \
124 							seta_reg[channel][4],seta_reg[channel][5], \
125 							seta_reg[channel][6],seta_reg[channel][7] );
126 
127 
WRITE_HANDLER(seta_sound_w)128 WRITE_HANDLER( seta_sound_w )
129 {
130 	int channel, reg;
131 
132 	seta_sound_ram[offset] = data;
133 
134 	if (Machine->sample_rate == 0)		return;
135 
136 	channel	=	offset / 8;
137 	reg		=	offset % 8;
138 
139 	if (channel >= SETA_NUM_CHANNELS)	return;
140 
141 	seta_reg[channel][reg] = data & 0xff;
142 
143 	switch (reg)
144 	{
145 
146 		case 0:
147 
148 			//DUMP_REGS
149 
150 			if (data & 1)	// key on
151 			{
152 				int volume	=	seta_reg[channel][1];
153 
154 				int start	=	seta_reg[channel][4]           * 0x1000;
155 				int end		=	(0x100 - seta_reg[channel][5]) * 0x1000; // from the end of the rom
156 
157 				int len		=	end - start;
158 				int maxlen	=	memory_region_length(REGION_SOUND1);
159 
160 				if (!( (start < end) && (end <= maxlen) ))
161 				{
162 					//logerror("PC: %06X - X1-010 OUT OF RANGE SAMPLE: %06X - %06X, channel %X\n",cpu_get_pc(),start,end,channel);
163 					//DUMP_REGS
164 					return;
165 				}
166 
167 #if 1
168 /* Print some more debug info */
169 //logerror("PC: %06X - Play 16 bit sample %06X - %06X, channel %X\n",cpu_get_pc(),start, end, channel);
170 //DUMP_REGS
171 #endif
172 
173 				/*
174 				   Twineagl continuosly writes 1 to reg 0 of the channel, so
175 				   the sample is restarted every time and never plays to the
176 				   end. It looks like the previous sample must be explicitly
177 				   stopped before a new one can be played
178 				*/
179 				if ( seta_sound_r(offset) & 1 )	return;	// play to the end
180 
181 				/* These samples are probaly looped and use the 3rd & 4th register's value */
182 				if (data & 2)	return;
183 
184 				/* left and right speaker's volume can be set indipendently.
185 				   We use a mean volume for now */
186 				mixer_set_volume(firstchannel + channel, ((volume & 0xf)+(volume >> 4))*100/(2*0xf)  );
187 
188 				/* I assume the pitch is fixed for a given board. It ranges
189 				   from 4 to 8 KHz for the games I've seen */
190 
191 				mixer_play_sample_16(
192 					firstchannel + channel,
193 					(short *) (memory_region(REGION_SOUND1) + start),	// start
194 					len,												// len
195 					frequency,											// frequency
196 					0);													// loop
197 			}
198 			else
199 				mixer_stop_sample(channel + firstchannel);
200 
201 			break;
202 
203 	}
204 }
205 
206 
207 
208 
209 
210 /* Use these for 16 bit CPUs */
211 
READ_HANDLER(seta_sound_word_r)212 READ_HANDLER( seta_sound_word_r )
213 {
214 	return seta_sound_r(offset/2) & 0xff;
215 }
216 
WRITE_HANDLER(seta_sound_word_w)217 WRITE_HANDLER( seta_sound_word_w )
218 {
219 	if ( (data & 0x00ff0000) == 0 )
220 		seta_sound_w(offset/2, data & 0xff);
221 }
222