1 // Cheap Squeak Deluxe audio module
2 // based on MAME sources by Aaron Giles
3 
4 #include "burnint.h"
5 #include "m68000_intf.h"
6 #include "6821pia.h"
7 #include "dac.h"
8 
9 static UINT16 dacvalue;
10 static UINT16 csd_status;
11 static INT32 csd_in_reset;
12 static INT32 csd_is_intialized = 0;
13 static UINT16 *csd_ram = NULL;
14 extern INT32 ssio_spyhunter;
15 
16 // muting & pop-supression logic
17 struct anti_pop {
18     UINT16 lastdacvalue;
19     UINT16 cm30ctr;
20     INT32 ending;
21     INT32 mute;
22     INT32 booting;
23 };
24 
25 static anti_pop ml;
26 
csd_porta_w(UINT16,UINT8 data)27 static void csd_porta_w(UINT16, UINT8 data)
28 {
29     if (!ml.mute) {
30         ml.lastdacvalue = dacvalue;
31         dacvalue = (data << 2) | (dacvalue & 3);
32     }
33 
34     if (ssio_spyhunter) {
35         // csd_ram[0x30/2] continuously counts down as music is playing
36         // if its stopped, or 0 - nothing is playing.  Let's zero-out the dac
37         // so that we don't get loud clicks or pops before or after the music.
38         // 0x4000 + (0x100 << 6) ends up being 0 in the dac.
39         // extra notes:
40         // porta is called every sample, playing or not.
41         // portb is only called when music is playing (if needed)
42         if (ml.cm30ctr == csd_ram[0x30/2] || csd_ram[0x30/2] == 0) {
43             if (ml.mute == 0) {
44                 // counter stopped, begin the ending process.
45                 //bprintf(0, _T("csd ending.\n"));
46                 dacvalue = ml.lastdacvalue;
47                 ml.ending = 1;
48             }
49             // ramp dac from +-dc to 0 (0x100)
50             if (dacvalue > 0x100) dacvalue--;
51             else if (dacvalue < 0x100) dacvalue++;
52             else if (dacvalue == 0x100 && ml.ending) {
53                 // we've gracefully ended a tune, or got stable after boot-up
54                 //bprintf(0, _T("csd %S.\n"), (ml.booting) ? "booted" : "sound ending");
55                 ml.ending = 0;
56                 ml.booting = 0;
57                 ml.lastdacvalue = 0x100;
58             }
59             ml.mute = 1;
60         } else ml.mute = 0;
61 
62         ml.cm30ctr = csd_ram[0x30/2];
63     }
64 
65     if (!ml.booting)
66         DACWrite16Signed(0, 0x4000 + (dacvalue << 6));
67 }
68 
csd_portb_w(UINT16,UINT8 data)69 static void csd_portb_w(UINT16, UINT8 data)
70 {
71     if (!ml.mute) {
72         ml.lastdacvalue = dacvalue;
73         dacvalue = (dacvalue & ~0x3) | (data >> 6);
74     }
75 
76     if (!ml.booting)
77         DACWrite16Signed(0, 0x4000 + (dacvalue << 6));
78 
79     if (~pia_get_ddr_b(0) & 0x30) csd_status = (data >> 4) & 3;
80 }
81 
csd_irq(int state)82 static void csd_irq(int state)
83 {
84 	SekSetIRQLine(4, state ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
85 }
86 
csd_reset_write(int state)87 void csd_reset_write(int state)
88 {
89 	if (csd_is_intialized == 0) return;
90 
91 	csd_in_reset = state;
92 
93 	if (state) {
94 		INT32 cpu_active = SekGetActive();
95 		if (cpu_active == -1) SekOpen(0);
96 		SekReset();
97 		if (cpu_active == -1) SekClose();
98 	}
99 }
100 
csd_write_word(UINT32 address,UINT16 data)101 static void __fastcall csd_write_word(UINT32 address, UINT16 data)
102 {
103 	if ((address & 0x1fff8) == 0x18000) {
104 		pia_write(0, (address / 2) & 3, data & 0xff);
105 		return;
106 	}
107 }
108 
csd_write_byte(UINT32 address,UINT8 data)109 static void __fastcall csd_write_byte(UINT32 address, UINT8 data)
110 {
111 	if ((address & 0x1fff8) == 0x18000) {
112 		pia_write(0, (address / 2) & 3, data);
113 		return;
114 	}
115 }
116 
csd_read_word(UINT32 address)117 static UINT16 __fastcall csd_read_word(UINT32 address)
118 {
119 	if ((address & 0x1fff8) == 0x18000) {
120 		UINT8 ret = pia_read(0, (address / 2) & 3);
121 		return ret | (ret << 8);
122 	}
123 
124 	return 0;
125 }
126 
csd_read_byte(UINT32 address)127 static UINT8 __fastcall csd_read_byte(UINT32 address)
128 {
129 	if ((address & 0x1fff8) == 0x18000) {
130 		return pia_read(0, (address / 2) & 3);
131 	}
132 
133 	return 0;
134 }
135 
csd_data_write(UINT16 data)136 void csd_data_write(UINT16 data)
137 {
138 	if (csd_is_intialized == 0) return;
139 
140     pia_set_input_b(0, data & 0x0f);
141     pia_set_input_ca1(0, ~data & 0x10);
142 }
143 
csd_status_read()144 UINT8 csd_status_read()
145 {
146 	if (csd_is_intialized == 0) return 0;
147 
148 	return csd_status;
149 }
150 
csd_reset_status()151 INT32 csd_reset_status()
152 {
153 	if (csd_is_intialized == 0) return 1;
154 
155 	return csd_in_reset;
156 }
157 
csd_initialized()158 INT32 csd_initialized()
159 {
160 	return csd_is_intialized;
161 }
162 
csd_reset()163 void csd_reset()
164 {
165 	if (csd_is_intialized == 0) return;
166 
167 	SekOpen(0);
168 	SekReset();
169 	DACReset();
170 	SekClose();
171 
172 	pia_reset();
173 
174 	csd_status = 0;
175 	csd_in_reset = 0;
176     dacvalue = 0;
177 
178     // pop-suppression
179     ml.lastdacvalue = 0;
180     ml.ending = 0;
181     ml.mute = 0;
182     ml.booting = (ssio_spyhunter) ? 1 : 0;
183     ml.cm30ctr = 0;
184 }
185 
186 static const pia6821_interface pia_intf = {
187 	0, 0, 0, 0, 0, 0,
188 	csd_porta_w, csd_portb_w, 0, 0,
189 	csd_irq, csd_irq
190 };
191 
csd_init(UINT8 * rom,UINT8 * ram)192 void csd_init(UINT8 *rom, UINT8 *ram)
193 {
194     csd_ram = (UINT16*)ram;
195 	SekInit(0, 0x68000);
196 	SekOpen(0);
197 	SekMapMemory(rom,			0x000000, 0x007fff, MAP_ROM);
198 	SekMapMemory(ram,			0x01c000, 0x01cfff, MAP_RAM);
199 	SekSetWriteWordHandler(0,	csd_write_word);
200 	SekSetWriteByteHandler(0,	csd_write_byte);
201 	SekSetReadWordHandler(0,	csd_read_word);
202 	SekSetReadByteHandler(0,	csd_read_byte);
203 	SekClose();
204 
205 	pia_init();
206 	pia_config(0, PIA_ALTERNATE_ORDERING, &pia_intf);
207 
208 	DACInit(0, 0, 1, SekTotalCycles, 8000000);
209 	DACSetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
210     DACDCBlock(1);
211 
212 	csd_is_intialized = 1;
213 }
214 
csd_exit()215 void csd_exit()
216 {
217 	if (csd_is_intialized == 0) return;
218 
219 	SekExit();
220 	pia_init();
221 	DACExit();
222     csd_is_intialized = 0;
223     csd_ram = NULL;
224 }
225 
csd_scan(INT32 nAction,INT32 * pnMin)226 void csd_scan(INT32 nAction, INT32 *pnMin)
227 {
228 	if (csd_is_intialized == 0) return;
229 
230 	if (nAction & ACB_VOLATILE)
231 	{
232 		SekScan(nAction);
233 		DACScan(nAction, pnMin);
234 		pia_scan(nAction, pnMin);
235 
236 		SCAN_VAR(csd_status);
237 		SCAN_VAR(csd_in_reset);
238         SCAN_VAR(dacvalue);
239         SCAN_VAR(ml);
240 	}
241 }
242