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, 11 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.4: +56 -62 lines
Log Message:
fixed style

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * SID_linux.h - 6581 emulation, Linux specific stuff
3     *
4 cebix 1.4 * Frodo (C) 1994-1997,2002-2004 Christian Bauer
5 cebix 1.1 *
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 cebix 1.3 // 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 cebix 1.1 #include "VIC.h"
39    
40    
41     /*
42     * Initialization
43     */
44    
45     void DigitalRenderer::init_sound(void)
46     {
47 cebix 1.5 int arg;
48     unsigned long format;
49 cebix 1.1
50 cebix 1.5 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 cebix 1.1 }
83    
84    
85     /*
86     * Destructor
87     */
88    
89     DigitalRenderer::~DigitalRenderer()
90     {
91 cebix 1.5 if (devfd >= 0)
92     close(devfd);
93 cebix 1.1 }
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 cebix 1.5 static int divisor = 0;
121     static int to_output = 0;
122     static int buffer_pos = 0;
123 cebix 1.1
124 cebix 1.5 if (!ready)
125     return;
126 cebix 1.1
127     sample_buf[sample_in_ptr] = volume;
128     sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
129    
130 cebix 1.5 // 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 cebix 1.3 }
145    
146    
147     /*
148     * Renderer for Catweasel card
149     */
150    
151 cebix 1.5 // Renderer class
152 cebix 1.3 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 cebix 1.1 }