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