ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID_linux.h
Revision: 1.5
Committed: 2004-12-04T13:24:35Z (19 years, 3 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.4: +56 -62 lines
Log Message:
fixed style

File Contents

# Content
1 /*
2 * SID_linux.h - 6581 emulation, Linux specific stuff
3 *
4 * Frodo (C) 1994-1997,2002-2004 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <linux/soundcard.h>
25
26 // Catweasel ioctls (included here for convenience)
27 #include <linux/ioctl.h>
28 #define CWSID_IOCTL_TYPE ('S')
29 #define CWSID_IOCTL_RESET _IO(CWSID_IOCTL_TYPE, 0)
30 #define CWSID_IOCTL_CARDTYPE _IOR(CWSID_IOCTL_TYPE, 4, int)
31 #define CWSID_IOCTL_PAL _IO(CWSID_IOCTL_TYPE, 0x11)
32 #define CWSID_IOCTL_NTSC _IO(CWSID_IOCTL_TYPE, 0x12)
33 #define CWSID_IOCTL_DOUBLEBUFFER _IOW(CWSID_IOCTL_TYPE, 0x21, int)
34 #define CWSID_IOCTL_DELAY _IOW(CWSID_IOCTL_TYPE, 0x22, int)
35 #define CWSID_MAGIC 0x100
36 #define HAVE_CWSID 1
37
38 #include "VIC.h"
39
40
41 /*
42 * Initialization
43 */
44
45 void DigitalRenderer::init_sound(void)
46 {
47 int arg;
48 unsigned long format;
49
50 ready = false;
51 devfd = open("/dev/dsp", O_WRONLY);
52 if (devfd < 0)
53 return;
54
55 ioctl(devfd, SNDCTL_DSP_GETFMTS, &format);
56 if (!(format & AFMT_S16_LE))
57 return;
58 format = AFMT_S16_LE;
59 ioctl(devfd, SNDCTL_DSP_SETFMT, &format);
60
61 // Buffer size: 2^9 == 512 bytes. Note that too large buffers will not work
62 // very well: The speed of the C64 is slowed down to an average speed of
63 // 100% by the blocking write() call in EmulateLine(). If you use a buffer
64 // of, say 4096 bytes, that will happen only about every 4 frames, which
65 // means that the emulation runs much faster in some frames, and much
66 // slower in others.
67 // On really fast machines, it might make sense to use an even smaller
68 // buffer size.
69 arg = 0x00100009;
70 ioctl(devfd, SNDCTL_DSP_SETFRAGMENT, &arg);
71 arg = 0;
72 ioctl(devfd, SNDCTL_DSP_STEREO, &arg);
73 arg = 44100;
74 ioctl(devfd, SNDCTL_DSP_SPEED, &arg);
75 ioctl(devfd, SOUND_PCM_READ_RATE, &arg);
76 if (arg < 43000 || arg > 45000)
77 return;
78
79 ioctl(devfd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
80 sound_buffer = new int16[sndbufsize];
81 ready = true;
82 }
83
84
85 /*
86 * Destructor
87 */
88
89 DigitalRenderer::~DigitalRenderer()
90 {
91 if (devfd >= 0)
92 close(devfd);
93 }
94
95
96 /*
97 * Pause sound output
98 */
99
100 void DigitalRenderer::Pause(void)
101 {
102 }
103
104
105 /*
106 * Resume sound output
107 */
108
109 void DigitalRenderer::Resume(void)
110 {
111 }
112
113
114 /*
115 * Fill buffer, sample volume (for sampled voice)
116 */
117
118 void DigitalRenderer::EmulateLine(void)
119 {
120 static int divisor = 0;
121 static int to_output = 0;
122 static int buffer_pos = 0;
123
124 if (!ready)
125 return;
126
127 sample_buf[sample_in_ptr] = volume;
128 sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
129
130 // Now see how many samples have to be added for this line
131 divisor += SAMPLE_FREQ;
132 while (divisor >= 0)
133 divisor -= TOTAL_RASTERS*SCREEN_FREQ, to_output++;
134
135 // Calculate the sound data only when we have enough to fill
136 // the buffer entirely
137 if ((buffer_pos + to_output) >= sndbufsize) {
138 int datalen = sndbufsize - buffer_pos;
139 to_output -= datalen;
140 calc_buffer(sound_buffer + buffer_pos, datalen*2);
141 write(devfd, sound_buffer, sndbufsize*2);
142 buffer_pos = 0;
143 }
144 }
145
146
147 /*
148 * Renderer for Catweasel card
149 */
150
151 // Renderer class
152 class CatweaselRenderer : public SIDRenderer {
153 public:
154 CatweaselRenderer();
155 virtual ~CatweaselRenderer();
156
157 virtual void Reset(void);
158 virtual void EmulateLine(void) {}
159 virtual void WriteRegister(uint16 adr, uint8 byte);
160 virtual void NewPrefs(Prefs *prefs) {}
161 virtual void Pause(void) {}
162 virtual void Resume(void) {}
163
164 private:
165 int cwsid_fh; // Catweasel device file handle
166 };
167
168 // Constructor: Open Catweasel device and reset SID
169 CatweaselRenderer::CatweaselRenderer()
170 {
171 cwsid_fh = open("/dev/sid", O_WRONLY);
172 if (cwsid_fh >= 0) {
173 int i;
174 if (ioctl(cwsid_fh, CWSID_IOCTL_CARDTYPE, &i) < 0 || i != CWSID_MAGIC) {
175 close(cwsid_fh);
176 cwsid_fh = -1;
177 } else {
178 ioctl(cwsid_fh, CWSID_IOCTL_RESET);
179 ioctl(cwsid_fh, CWSID_IOCTL_DOUBLEBUFFER, 0);
180 }
181 }
182
183 Reset();
184 }
185
186 // Destructor: Reset SID and close Catweasel device
187 CatweaselRenderer::~CatweaselRenderer()
188 {
189 Reset();
190
191 if (cwsid_fh >= 0) {
192 close(cwsid_fh);
193 cwsid_fh = -1;
194 }
195 }
196
197 // Reset SID
198 void CatweaselRenderer::Reset(void)
199 {
200 if (cwsid_fh >= 0) {
201 uint8 zero = 0;
202 ioctl(cwsid_fh, CWSID_IOCTL_RESET);
203 lseek(cwsid_fh, 24, SEEK_SET);
204 write(cwsid_fh, &zero, 1);
205 }
206 }
207
208 // Write to register
209 void CatweaselRenderer::WriteRegister(uint16 adr, uint8 byte)
210 {
211 if (cwsid_fh >= 0 && adr < 0x1a) {
212 lseek(cwsid_fh, adr, SEEK_SET);
213 write(cwsid_fh, &byte, 1);
214 lseek(cwsid_fh, adr, SEEK_SET);
215 write(cwsid_fh, &byte, 1);
216 }
217 }