ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/main_sdl.cpp
Revision: 1.11
Committed: 2003-04-11T20:23:02Z (20 years, 11 months ago) by cebix
Branch: MAIN
Changes since 1.10: +80 -2 lines
Log Message:
- added support for Catweasel SID
- replay timing is now based on CIA timer value, removed replayfreq

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * main_sdl.cpp - SIDPlayer SDL main program
3     *
4 cebix 1.11 * SIDPlayer (C) Copyright 1996-2003 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 "sys.h"
22    
23     #include <SDL.h>
24 cebix 1.9 #include <SDL/SDL_endian.h>
25    
26 cebix 1.1 #include <stdio.h>
27     #include <stdlib.h>
28 cebix 1.9 #include <errno.h>
29 cebix 1.1
30 cebix 1.11 #ifdef __unix__
31     #include <unistd.h>
32     #include <sys/time.h>
33     #endif
34    
35 cebix 1.1 #include "main.h"
36 cebix 1.4 #include "prefs.h"
37     #include "sid.h"
38 cebix 1.1
39    
40     /*
41 cebix 1.11 * Get current value of microsecond timer
42     */
43    
44     uint64 GetTicks_usec(void)
45     {
46     #ifdef __unix__
47     struct timeval t;
48     gettimeofday(&t, NULL);
49     return uint64(t.tv_sec) * 1000000 + t.tv_usec;
50     #else
51     return uint64(SDL_GetTicks()) * 1000;
52     #endif
53     }
54    
55    
56     /*
57     * Delay by specified number of microseconds (<1 second)
58     * (adapted from SDL_Delay() source)
59     */
60    
61     void Delay_usec(uint32 usec)
62     {
63     #ifdef __unix__
64     int was_error;
65     #ifndef __linux__ /* Non-Linux implementations need to calculate time left */
66     uint64 then, now, elapsed;
67     #endif
68     struct timeval tv;
69    
70     /* Set the timeout interval - Linux only needs to do this once */
71     #ifdef __linux__
72     tv.tv_sec = 0;
73     tv.tv_usec = usec;
74     #else
75     then = GetTicks_usec();
76     #endif
77     do {
78     errno = 0;
79     #ifndef __linux__
80     /* Calculate the time interval left (in case of interrupt) */
81     now = GetTicks_usec();
82     elapsed = (now-then);
83     then = now;
84     if ( elapsed >= usec ) {
85     break;
86     }
87     usec -= elapsed;
88     tv.tv_sec = 0;
89     tv.tv_usec = usec;
90     #endif
91     was_error = select(0, NULL, NULL, NULL, &tv);
92     } while (was_error && (errno == EINTR));
93     #else
94     SDL_Delay(usec / 1000);
95     #endif
96     }
97    
98    
99     /*
100 cebix 1.1 * Main program
101     */
102    
103     static void usage(const char *prg_name)
104     {
105 cebix 1.7 printf("Usage: %s [OPTION...] FILE [song_number]\n", prg_name);
106 cebix 1.5 PrefsPrintUsage();
107 cebix 1.1 exit(0);
108     }
109    
110     static void quit(void)
111     {
112     ExitAll();
113     SDL_Quit();
114     }
115    
116     int main(int argc, char **argv)
117     {
118     // Print banner
119     printf(
120     PACKAGE " Version " VERSION "\n\n"
121 cebix 1.11 "Copyright (C) 1996-2003 Christian Bauer\n"
122 cebix 1.1 "E-mail: Christian.Bauer@uni-mainz.de\n"
123     "http://www.uni-mainz.de/~bauec002/\n\n"
124     "This is free software with ABSOLUTELY NO WARRANTY.\n"
125     "You are welcome to redistribute it under certain conditions.\n"
126     "For details, see the file COPYING.\n\n"
127     );
128    
129 cebix 1.5 // Initialize everything
130     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
131     fprintf(stderr, "Couldn't initialize SDL (%s)\n", SDL_GetError());
132     exit(1);
133     }
134     atexit(quit);
135     InitAll(argc, argv);
136 cebix 1.10 int32 speed = PrefsFindInt32("speed");
137 cebix 1.5
138     // Parse non-option arguments
139 cebix 1.8 const char *file_name = NULL;
140 cebix 1.1 int song = 0;
141 cebix 1.8 for (int i=1; i<argc; i++) {
142     if (strcmp(argv[i], "--help") == 0)
143     usage(argv[0]);
144     else if (argv[i][0] == '-') {
145     fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
146     usage(argv[0]);
147     } else {
148     if (file_name == NULL)
149     file_name = argv[i]; // First non-option argument is file name
150     else
151     song = atoi(argv[i]); // Second non-option argument is song number
152 cebix 1.3 }
153     }
154 cebix 1.8 if (file_name == NULL)
155     usage(argv[0]);
156 cebix 1.1
157     // Load given PSID file
158 cebix 1.3 if (!LoadPSIDFile(file_name)) {
159     fprintf(stderr, "Couldn't load '%s' (not a PSID file?)\n", file_name);
160 cebix 1.1 exit(1);
161     }
162    
163     // Select song
164     if (song > 0) {
165     if (song > number_of_songs)
166     song = number_of_songs;
167     SelectSong(song - 1);
168     }
169 cebix 1.10
170     SIDAdjustSpeed(speed); // SelectSong and LoadPSIDFile() reset this to 100%
171 cebix 1.1
172     // Print file information
173     printf("Module Name: %s\n", module_name);
174     printf("Author : %s\n", author_name);
175     printf("Copyright : %s\n\n", copyright_info);
176     printf("Playing song %d/%d\n", current_song + 1, number_of_songs);
177    
178 cebix 1.9 // Replay or output to file?
179     const char *outfile = PrefsFindString("outfile");
180     if (outfile) {
181    
182     // Open file
183     SDL_RWops *f = SDL_RWFromFile(outfile, "wb");
184     if (f == NULL) {
185     fprintf(stderr, "Can't open '%s' for writing (%s)\n", outfile, strerror(errno));
186     exit(1);
187     }
188    
189     // Get format information
190     int32 channels = (PrefsFindBool("stereo") ? 2 : 1);
191     int32 bits = (PrefsFindBool("audio16bit") ? 16 : 8);
192     int32 rate = PrefsFindInt32("samplerate");
193     int32 time = PrefsFindInt32("time");
194     int32 bytes_per_frame = channels * (bits / 8);
195     int32 bytes_per_second = rate * bytes_per_frame;
196     int32 data_length = time * bytes_per_second;
197    
198     // Write header
199     SDL_WriteLE32(f, 0x46464952); // "RIFF"
200     SDL_WriteLE32(f, 36 + data_length);
201     SDL_WriteLE32(f, 0x45564157); // "WAVE"
202     SDL_WriteLE32(f, 0x20746D66); // "fmt "
203     SDL_WriteLE32(f, 16);
204     SDL_WriteLE16(f, 1);
205     SDL_WriteLE16(f, channels);
206     SDL_WriteLE32(f, rate);
207     SDL_WriteLE32(f, bytes_per_second);
208     SDL_WriteLE16(f, bytes_per_frame);
209     SDL_WriteLE16(f, bits);
210     SDL_WriteLE32(f, 0x61746164); // "data"
211     SDL_WriteLE32(f, data_length);
212    
213     // Calculate sound and write to file
214     uint8 *buf = new uint8[bytes_per_second];
215     for (int i=0; i<time; i++) {
216     SIDCalcBuffer(buf, bytes_per_second);
217     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
218     if (bits > 8) {
219     // WAV file is little-endian, swap audio data
220     for (int b=0; b<bytes_per_second; b+=2) {
221     uint8 tmp = buf[b];
222     buf[b] = buf[b+1];
223     buf[b+1] = tmp;
224     }
225     }
226     #endif
227     SDL_RWwrite(f, buf, bytes_per_second, 1);
228     }
229     delete[] buf;
230    
231     // Close file
232     SDL_RWclose(f);
233     printf("Output written to '%s'\n", outfile);
234    
235 cebix 1.11 } else if (PrefsFindBool("cwsid")) {
236    
237     // Catweasel output, requires manual timing
238     while (true) {
239     SIDExecute();
240    
241     SDL_Event e;
242     if (SDL_PollEvent(&e)) {
243     if (e.type == SDL_QUIT)
244     break;
245     }
246     }
247    
248 cebix 1.9 } else {
249    
250     // Start replay and enter main loop
251     SDL_PauseAudio(false);
252     while (true) {
253     SDL_Event e;
254     if (SDL_WaitEvent(&e)) {
255     if (e.type == SDL_QUIT)
256     break;
257     }
258 cebix 1.1 }
259     }
260    
261 cebix 1.11 ExitAll();
262 cebix 1.1 return 0;
263     }