1 /*
2 tempest for eliza code
3 Copyright (C) 2001 Erik Thiele
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <math.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <SDL.h>
26 #include <string.h>
27
28 double carrier;
29 int resx;
30 int resy;
31 int horizontalspan;
32 double pixelclock;
33
34 SDL_Surface *screen;
35 Uint32 white, black;
36
37 class zeit : public timeval {
38 public:
zeit()39 zeit() { setzero(); };
getcurrenttime()40 void getcurrenttime() { gettimeofday (this,0); };
subtract(const zeit & subme)41 void subtract (const zeit &subme)
42 {
43 tv_sec-=subme.tv_sec;
44 tv_usec-=subme.tv_usec;
45 normalize();
46 };
add(const zeit & addme)47 void add (const zeit &addme)
48 {
49 tv_sec+=addme.tv_sec;
50 tv_usec+=addme.tv_usec;
51 normalize();
52 };
normalize()53 void normalize()
54 {
55 while (tv_usec<0) {
56 tv_usec+=1000000;
57 tv_sec--;
58 };
59 while (tv_usec>=1000000) {
60 tv_usec-=1000000;
61 tv_sec++;
62 };
63 };
zero()64 bool zero()
65 {
66 return (tv_sec==0)&&(tv_usec==0);
67 };
setzero()68 void setzero()
69 {
70 tv_sec=tv_usec=0;
71 };
print()72 void print()
73 {
74 printf("%8d:%8d\n",int(tv_sec),int(tv_usec));
75 };
setdouble(const double val)76 void setdouble(const double val)
77 {
78 long long i=(long long)(val*1000000);
79 tv_usec=i%1000000;
80 tv_sec=i/1000000;
81 normalize();
82 };
83 };
84
pixelchen(const int x,const int y,const Uint32 pixel)85 inline void pixelchen (const int x, const int y, const Uint32 pixel)
86 {
87 Uint8 *bits=((Uint8*)screen->pixels)+y*screen->pitch+x*screen->format->BytesPerPixel;
88 switch(screen->format->BytesPerPixel) {
89 case 1:
90 *((Uint8 *)(bits)) = (Uint8)pixel;
91 break;
92 case 2:
93 *((Uint16 *)(bits)) = (Uint16)pixel;
94 break;
95 case 3:
96 { /* Format/endian independent */
97 Uint8 r, g, b;
98
99 r = (pixel>>screen->format->Rshift)&0xFF;
100 g = (pixel>>screen->format->Gshift)&0xFF;
101 b = (pixel>>screen->format->Bshift)&0xFF;
102 *((bits)+screen->format->Rshift/8) = r;
103 *((bits)+screen->format->Gshift/8) = g;
104 *((bits)+screen->format->Bshift/8) = b;
105 }
106 break;
107 case 4:
108 *((Uint32 *)(bits)) = (Uint32)pixel;
109 break;
110 };
111 };
112
waituntil(const zeit & desttime)113 void waituntil (const zeit &desttime)
114 {
115 zeit tm(desttime);
116 zeit cur;
117 cur.getcurrenttime();
118 tm.subtract(cur);
119
120 select(1,0,0,0,&tm);
121 };
122
mkrealsound(double freq)123 void mkrealsound(double freq)
124 {
125 SDL_Rect myrect;
126 myrect.x=myrect.y=0;
127 myrect.w=resx;
128 myrect.h=resy;
129 SDL_FillRect(screen,&myrect,black);
130
131 int x, y;
132 double t;
133
134 double ftfp2 = freq / pixelclock * 2.0;
135 double fcfp2 = carrier / pixelclock * 2.0;
136
137 t = 0;
138 for (y = 0; y < resy; y++) {
139 if (int(t*ftfp2)%2) {
140 // 1
141 t+=resx;
142 }else{
143 // 0
144 for (x = 0; x < resx; x++) {
145 if (int(t*fcfp2)%2)
146 pixelchen(x,y,white);
147 t++;
148 };
149 };
150
151 t += horizontalspan - resx;
152 }
153 }
154
note(int nr)155 double note (int nr)
156 {
157 return pow(2.0,nr/12.0)*440.0*2;
158 };
159
160
161 int curoct, curnot;
162 double curlen;
163 bool loaded;
164 zeit timefornextsound;
165
resetplay()166 void resetplay()
167 {
168 curoct=0;
169 curnot=0;
170 curlen=128;
171 loaded=false;
172 timefornextsound.setzero();
173 };
174
finishplay()175 void finishplay ()
176 {
177 SDL_Rect myrect;
178 myrect.x=myrect.y=0;
179 myrect.w=resx;
180 myrect.h=resy;
181 SDL_FillRect(screen,&myrect,black);
182
183 waituntil(timefornextsound);
184 SDL_UpdateRect(screen,0,0,resx,resy);
185 };
186
flushplay()187 void flushplay ()
188 {
189 if (loaded) {
190 if (curnot==-1000) {
191 SDL_Rect myrect;
192 myrect.x=myrect.y=0;
193 myrect.w=resx;
194 myrect.h=resy;
195 SDL_FillRect(screen,&myrect,black);
196
197 waituntil(timefornextsound);
198 }else{
199 mkrealsound(note(curnot+12*curoct));
200 };
201 if (timefornextsound.zero()) {
202 timefornextsound.getcurrenttime();
203 }else{
204 waituntil(timefornextsound);
205 };
206 SDL_UpdateRect(screen,0,0,resx,resy);
207
208 zeit length;
209 length.setdouble(curlen/40.0);
210 timefornextsound.add(length);
211 loaded=false;
212 };
213 };
214
play(const char * const song)215 void play (const char *const song)
216 {
217 int pos=0;
218 while (pos<int(strlen(song))) {
219 SDL_Event event;
220 while(SDL_PollEvent(&event)) if (event.type == SDL_MOUSEBUTTONDOWN) exit(0);
221 switch(song[pos]) {
222 case 'c': flushplay(); curnot=0; loaded=true; break;
223 case 'd': flushplay(); curnot=2; loaded=true; break;
224 case 'e': flushplay(); curnot=4; loaded=true; break;
225 case 'f': flushplay(); curnot=5; loaded=true; break;
226 case 'g': flushplay(); curnot=7; loaded=true; break;
227 case 'a': flushplay(); curnot=9; loaded=true; break;
228 case 'b': flushplay(); curnot=11; loaded=true; break;
229 case 'p': flushplay(); curnot=-1000; loaded=true; break;
230 case '#': curnot++; break;
231 case '1': flushplay(); curlen=128; break;
232 case '2': flushplay(); curlen=64; break;
233 case '4': flushplay(); curlen=32; break;
234 case '5': flushplay(); curlen=48; break;
235 case '8': flushplay(); curlen=16; break;
236 case '6': flushplay(); curlen=8; break;
237 case 'u': flushplay(); curoct=-2; break;
238 case 'l': flushplay(); curoct=-1; break;
239 case 'h': flushplay(); curoct=0; break;
240 case 'x': flushplay(); curoct=1; break;
241 default:break;
242 };
243 pos++;
244 };
245 flushplay();
246 };
247
usage()248 void usage()
249 {
250 printf("\nwrong parameters ! read readme file!\n\n");
251 exit(1);
252 };
253
main(int argc,char * argv[])254 int main(int argc, char *argv[])
255 {
256 carrier=10000000.0;
257 resx=1024;
258 resy=768;
259 horizontalspan=1400;
260 pixelclock=105.0 * 1e6;
261 char *filename;
262
263 atexit(SDL_Quit);
264
265 printf(
266 "\n"
267 "Tempest for Eliza - by erikyyy !\n"
268 "--------------------------------\n"
269 "\n"
270 "Read the README file to understand what's happening\n"
271 "if you do not read it, you will NOT know what to do\n"
272 );
273
274 if (argc!=7) usage();
275 pixelclock=atof(argv[1]);
276 resx=atol(argv[2]);
277 resy=atol(argv[3]);
278 horizontalspan=atol(argv[4]);
279 carrier=atof(argv[5]);
280 filename=argv[6];
281
282 printf("\n"
283 "Pixel Clock %.0f Hz\n"
284 "X Resolution %d Pixels\n"
285 "Y Resolution %d Pixels\n"
286 "Horizontal Total %d Pixels\n"
287 "AM Carrier Frequency %.0f Hz\n"
288 "\n\n",
289 pixelclock,resx,resy,horizontalspan,carrier);
290
291 if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
292 fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
293 exit(1);
294 };
295
296 /* Have a preference for 8-bit, but accept any depth */
297 screen = SDL_SetVideoMode(resx, resy, 8, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_FULLSCREEN);
298 if ( screen == NULL ) {
299 fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
300 exit(1);
301 }
302 printf("Have Set %d bits-per-pixel mode\n",
303 screen->format->BitsPerPixel);
304
305 SDL_Color col[2];
306 col[0].r=col[0].g=col[0].b=0xff; // white
307 col[1].r=col[1].g=col[1].b=0x00; // black
308
309 SDL_SetColors(screen,col,0,2);
310 white = SDL_MapRGB(screen->format,0xff,0xff,0xff);
311 black = SDL_MapRGB(screen->format,0x00,0x00,0x00);
312
313 char song[100000];
314 FILE *input=fopen(filename,"r");
315 if (!input) { printf("cannot open file\n"); return 1; };
316 resetplay();
317 char *ret;
318 do {
319 ret=fgets(song,100000,input);
320 if (ret) {
321 for (unsigned i=0;i<strlen(song);i++)
322 if (song[i]=='*') song[i]=0;
323 play (song);
324 }
325 } while(ret);
326 finishplay();
327 fclose(input);
328
329 return 0;
330 };
331