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 (21 years, 6 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

# Content
1 /*
2 * main_sdl.cpp - SIDPlayer SDL main program
3 *
4 * SIDPlayer (C) Copyright 1996-2003 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 "sys.h"
22
23 #include <SDL.h>
24 #include <SDL/SDL_endian.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29
30 #ifdef __unix__
31 #include <unistd.h>
32 #include <sys/time.h>
33 #endif
34
35 #include "main.h"
36 #include "prefs.h"
37 #include "sid.h"
38
39
40 /*
41 * 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 * Main program
101 */
102
103 static void usage(const char *prg_name)
104 {
105 printf("Usage: %s [OPTION...] FILE [song_number]\n", prg_name);
106 PrefsPrintUsage();
107 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 "Copyright (C) 1996-2003 Christian Bauer\n"
122 "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 // 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 int32 speed = PrefsFindInt32("speed");
137
138 // Parse non-option arguments
139 const char *file_name = NULL;
140 int song = 0;
141 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 }
153 }
154 if (file_name == NULL)
155 usage(argv[0]);
156
157 // Load given PSID file
158 if (!LoadPSIDFile(file_name)) {
159 fprintf(stderr, "Couldn't load '%s' (not a PSID file?)\n", file_name);
160 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
170 SIDAdjustSpeed(speed); // SelectSong and LoadPSIDFile() reset this to 100%
171
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 // 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 } 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 } 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 }
259 }
260
261 ExitAll();
262 return 0;
263 }