1 #include <stdio.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include <sys/soundcard.h>
6 #include <sys/ioctl.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <string.h>
10 
11 #include "sapLib.h"
12 
13 #define sapcmp(a, b, c) if (strncmp(a, b, strlen(a))==0) {printf("%s: %s", c, b+strlen(a)+1); st=1;}
14 
15 #define sapfind(d, a, c) {unsigned char testBuf[1000]; int st=0; FILE *f=fopen(d, "rb"); do { fgets((char *)testBuf, 1000, f); if(testBuf[0]!=0xff) sapcmp(a, (char *)testBuf, c); } while(testBuf[0]!=0xff); if(st==0) printf("%s: <?>\n", c); fclose(f); }
16 
17 signed short buffer[88200];
18 int fd, format;
19 
main(int argc,char ** argv)20 int main(int argc, char **argv)
21 {
22 	printf("Penguin Sap v0.01 by Jaymz Julian (jaymz@dspaudio.com)\n");
23 	printf("Sap Library v1.52 by Adam Bienias\n");
24 
25 	char *file2play;
26 	int verbose=0;
27 	int bits=16;
28 	int mono=0;
29 	int songNum=0;
30 	// parse the options
31 	if(argc==1)
32 	{
33 		printf("Usage: %s [-v] filename.sap\n", argv[0]);
34 		printf("       -oX : Song number\n");
35 		printf("       -v  : Print verbose info\n");
36 		printf("       -m  : Mono audio output (Default is stereo)\n");
37 		printf("       -8  : 8 bit output (Default is 16 bit)\n");
38 		exit(1);
39 	}
40 
41 	for(int x=1;x<argc;x++)
42 	{
43 		if(argv[x][0]=='-')
44 		{
45 			// it's an option
46 			switch(argv[x][1])
47 			{
48 				case 'v':
49 					verbose=1;
50 					break;
51 				case 'm':
52 					mono=1;
53 					break;
54 				case '8':
55 					bits=8;
56 					break;
57 				case 'o':
58 					songNum=atoi(argv[x]+2);
59 					break;
60 				default:
61 					printf("Invalid paramater - run without any parameters for help!\n");
62 					exit(1);
63 					break;
64 			}
65 		}
66 		else
67 		{
68 			// it's a file
69 			file2play=argv[x];
70 		}
71 	}
72 
73 
74 	printf("Filenames    : %s\n",file2play);
75 	sapMUSICstrc *fish=sapLoadMusicFile(file2play);
76 
77 	if(fish->defSong== -1) fish->defSong=1;
78 	if(fish->numOfSongs== -1) fish->numOfSongs=1;
79 
80 	if(songNum!=0)
81 		sapPlaySong(songNum);
82 	else
83 		songNum=fish->defSong;
84 
85 
86 	// FIXME: detect file type here (binary, chaos music,digi, etc)
87         printf("File format  : Atari XL/XE SAP (Type)\n");
88 
89 	// print sidplay like info
90 	// FIXME: support chaos music/softsynth types
91 	// FIXME: get load address
92 
93 	sapfind(file2play, "NAME"    , "Name         ");
94 	sapfind(file2play, "AUTHOR"  , "Author       ");
95 	sapfind(file2play, "DATE"    , "Copyright    ");
96 	if(verbose==1)
97 	{
98 	        printf("Load Address : <?>\n");
99 		sapfind(file2play, "INIT"    , "Init address ");
100 		sapfind(file2play, "PLAYER"  , "Play address ");
101 	}
102 	sapfind(file2play, "TIME"    , "Play time    ");
103 
104 	printf("Setting Song : %d out of %d (default = %d)\n", songNum, fish->numOfSongs, fish->defSong);
105 
106 	// FIXME: support fastplay
107         printf("Song speed   : 50 Hz VBI (PAL)\n");
108 
109 	printf("Playing, press ^C to stop ...\n");
110 	fflush(stdout);
111 
112 	// loading succesful - init the soundcard
113 	// why does this code work in FLAW, but not in penguin sap?
114 	fd=open("/dev/mixer", O_WRONLY, 0);
115 	fd=open("/dev/dsp", O_WRONLY, 0);
116 	if(bits==16)
117 		format=AFMT_S16_LE;
118 	else
119 		format=AFMT_U8;
120 
121 	ioctl(fd, SNDCTL_DSP_SETFMT, &format);
122 	format=44100;
123 	ioctl(fd, SNDCTL_DSP_SPEED, &format);
124 
125 	if(mono==1)
126 		format=1;
127 	else
128 		format=2;
129 
130 	ioctl(fd, SNDCTL_DSP_CHANNELS, &format);
131 
132 	do
133 	{
134 		int dataSize=22050*4;
135 		sapRenderBuffer(buffer, 22050);
136 		if(mono==1)
137 		{
138 			// transform to mono
139 			for(int c=0;c<22050;c++)
140 				buffer[c]=((buffer[c*2]+buffer[c*2+1])/2);
141 			dataSize/=2;
142 		}
143 
144 		if(bits==8)
145 		{
146 			short ws;
147 			dataSize/=2;
148 			for(int c=0;c<dataSize;c++)
149 			{
150 				ws=(buffer[c]>>8)+128;
151 				((char *)buffer)[c]=(char)ws;
152 			}
153 		}
154 		write(fd, buffer, dataSize);
155 	} while(0==0);
156 }
157