Added font file loading.
[cantaveria.git] / backend.c
blobb2cf763366777271c05c85171b24d9d92453b3b6
1 /*
2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
23 #include <SDL/SDL.h>
24 #include <SDL/SDL_opengl.h>
26 #include "backend.h"
27 #include "game.h"
28 #include "loader.h"
29 #include "sound.h"
31 SDL_Surface* video;
32 int gl_flag = 0;
33 int W, H;
35 int since(){
36 static int last = 0;
37 int now = SDL_GetTicks();
38 int diff = now - last;
39 last = now;
40 return diff;
43 void delay(int ms){
44 SDL_Delay(ms);
48 int keymap[32];
49 int butmap[MAX_PLAYERS][8];
50 int joymap[MAX_PLAYERS];
52 int keynum(int name){
53 return keymap[name];
56 int butnum(int joy, int name){
57 return butmap[joy][name];
61 void backend_quit(){
62 printf("sdl: quit\n");
63 SDL_LockAudio();
64 SDL_CloseAudio();
65 SDL_Quit();
74 void input(){
76 SDL_Event e;
78 while(SDL_PollEvent(&e) != 0){
79 switch(e.type){
80 case SDL_KEYDOWN:
81 game.handler.keydown(e.key.keysym.sym);
82 break;
83 case SDL_KEYUP:
84 game.handler.keyup(e.key.keysym.sym);
85 break;
86 case SDL_JOYBUTTONDOWN:
87 game.handler.joypress(e.jbutton.which, e.jbutton.button);
88 break;
89 case SDL_JOYBUTTONUP:
90 game.handler.joyrelease(e.jbutton.which, e.jbutton.button);
91 break;
92 case SDL_JOYAXISMOTION:
93 if(e.jaxis.axis == 0){
94 game.handler.joymovex(e.jaxis.which, e.jaxis.value);
96 else if(e.jaxis.axis == 1){
97 game.handler.joymovey(e.jaxis.which, e.jaxis.value);
99 break;
100 case SDL_QUIT:
101 game.end = 1;
102 break;
107 void control(int type, int par1, int par2){
109 switch(type){
110 case KEYDOWN:
111 game.handler.keydown(par1);
112 break;
113 case KEYUP:
114 game.handler.keyup(par1);
115 break;
116 case JOYMOVEX:
117 game.handler.joymovex(par1, par2);
118 break;
119 case JOYMOVEY:
120 game.handler.joymovey(par1, par2);
121 break;
122 case JOYPRESS:
123 game.handler.joypress(par1, par2);
124 break;
125 case JOYRELEASE:
126 game.handler.joyrelease(par1, par2);
127 break;
144 drawing model
146 the backend will draw the current state of the game
147 in the following way.
149 it will render a stage at a given position. a stage is
150 N backgrounds
151 1 background tiles
152 1 wall tiles and
153 1 foreground tiles
155 then it will render the sprites
158 the stage is measured in terms of screens
159 each screen is 20x15 tiles, each tile is 16 pixels square
160 each screen can have one tile set of 256 tiles
163 /***************/
164 /*graphics data*/
165 /***************/
167 struct {
168 char* filename;
169 SDL_Surface* surf;
170 GLuint texture;
171 int w;
172 int h;
173 } gfx[MAX_GFX];
174 int gfx_count = 0;
176 sprite* sprites[MAX_SPRITES];
177 int sprite_count = 0;
179 animation* animations[MAX_ANIMATIONS];
180 int anim_count = 0;
182 int stage_enabled = 0;
184 int screen_offset = 0;
186 struct {
187 int x, y;
188 } camera;
192 /********************/
193 /* drawing routines */
194 /********************/
196 void draw_sprite_sdl(sprite* spr){
197 int x = spr->x - 0 + screen_offset;
198 int y = spr->y - 0;
199 int w = spr->w;
200 int h = spr->h;
202 int X = spr->frame.x;
203 int Y = spr->frame.y;
205 SDL_Surface* surf = gfx[spr->gfxid].surf;
206 SDL_Rect r1 = {X,Y,w,h};
207 SDL_Rect r2 = {x,y,w,h};
208 SDL_BlitSurface(surf,&r1,video,&r2);
211 void draw_sprite_gl(sprite* spr){
212 int x = spr->x - camera.x + screen_offset;
213 int y = spr->y - camera.y;
214 int w = spr->w;
215 int h = spr->h;
217 glBindTexture( GL_TEXTURE_2D, gfx[spr->gfxid].texture );
219 double X0 = spr->frame.x0;
220 double Y0 = spr->frame.y0;
221 double X1 = spr->frame.x1;
222 double Y1 = spr->frame.y1;
224 glBegin( GL_QUADS );
225 glTexCoord2d(X0,Y0);
226 glVertex3f(x,y,0);
228 glTexCoord2d(X1,Y0);
229 glVertex3f(x+w,y,0);
231 glTexCoord2d(X1,Y1);
232 glVertex3f(x+w,y+h,0);
234 glTexCoord2d(X0,Y1);
235 glVertex3f(x,y+h,0);
236 glEnd();
239 void draw_screen_sdl(zone* z, int si, int sj){
240 struct screen* scr = z->screens+si+z->w*sj;
241 SDL_Surface* surf = gfx[z->tileset].surf;
242 int x = si*20*16 - camera.x;
243 int y = sj*15*16 - camera.y;
245 for(int j=0; j < 15; j++){
246 for(int i=0; i < 20; i++){
247 if(x > 320 || y > 240 || x < -16 || y < -16) continue;
248 int gfx = scr->tiles[i][j].gfx;
249 if(gfx != 0){
250 SDL_Rect r1 = {gfx&7,gfx>>3,16,16};
251 SDL_Rect r2 = { x, y,16,16};
252 SDL_BlitSurface(surf,&r1,video,&r2);
254 else{
255 //draw background
257 x += 16;
259 x -= 320;
260 y += 16;
264 void draw_screen_gl(zone* z, int si, int sj){
271 void draw(){
273 if(!gl_flag){
275 SDL_FillRect(video, 0, 0xffffffff);
277 //draw walls and background
278 if(stage_enabled){
279 draw_screen_sdl(zones[0],0,0);
282 //draw sprites
283 for(int i=0; i < sprite_count; i++){
284 draw_sprite_sdl(sprites[i]);
287 //draw foreground tile/sprites
289 SDL_UpdateRect(video,0,0,0,0);
291 else{
293 glClearColor(1.0,1.0,1.0,0.0);
294 glClear( GL_COLOR_BUFFER_BIT );
296 if(stage_enabled){
297 draw_screen_gl(zones[0],0,0);
300 for(int i=0; i < sprite_count; i++){
301 draw_sprite_gl(sprites[i]);
304 SDL_GL_SwapBuffers();
310 /*******************/
311 /* message control */
312 /*******************/
314 typedef struct {
315 utf32 u;
316 int gfx;
317 int x, y, w, h;
318 int k1, k2;
319 } vwchar;
321 struct treenode* chartree = NULL;
325 int ptrcomp(void* k1, void* k2){
326 return (k2 - k1);
329 void set_message(char* str){
330 utf32 u;
331 int N = 0;
332 do {
333 N += unicode_getc(str+N, &u);
334 vwchar* C = tree_search(chartree, ptrcomp, (void*)u);
335 printf("%04lx[%p] ",u, C);
336 } while(u);
337 printf("\n");
340 void advance_message(){
344 void clear_message(){
348 void complete_message(){
353 void init_text(){
354 vwchar* C = xmalloc(sizeof(vwchar));
355 C->gfx = 0;
356 C->u = ' ';
357 C->x = 0;
358 C->y = 0;
359 C->w = 7;
360 C->k1 = 0;
361 C->k2 = 0;
362 chartree = xmalloc(sizeof(treenode));
363 chartree->l = NULL;
364 chartree->r = NULL;
365 chartree->value = C;
366 chartree->key = (void*)' ';
368 //set font height
370 //setup mini font
374 vwchar* load_vwchar(reader* rd, int gfx){
375 utf32 u;
376 int x, y, w, k1, k2;
377 char str[256];
378 int ret = loader_scanline(rd, "%256s %d %d %d %d %d\n",str,&x,&y,&w,&k1,&k2);
379 if(ret == EOF){
380 return NULL;
382 unicode_getc(str,&u);
383 vwchar* C = xmalloc(sizeof(vwchar));
384 C->gfx = gfx;
385 C->u = u;
386 C->x = x;
387 C->y = y;
388 C->w = w;
389 C->k1 = k1;
390 C->k2 = k2;
391 return C;
394 void print_tree(treenode* node){
395 printf("(%lx,",(utf32)node->key);
396 if(node->l){
397 print_tree(node->l);
399 else{
400 printf("()");
402 printf(",");
403 if(node->r){
404 print_tree(node->r);
406 else{
407 printf("()");
409 printf(")");
413 void randomly_insert(vwchar* C[], int count){
414 for(int i=0; i<count-1; i++){
415 int j = randint(0,count-i-1);
416 tree_insert(chartree, ptrcomp, (void*)C[j]->u, C[j]);
417 C[j] = C[count-i-1];
418 C[count-i-1] = NULL;
423 int load_font(char* filename){
424 printf("load_font: loading %s\n",filename);
425 char buf[256] = "fonts/";
426 strmcat(buf, filename, 256);
427 reader* rd = loader_open(buf);
428 if(!rd){
429 fatal_error("load_font: cannot open %s\n",filename);
432 char str[256];
433 loader_scanline(rd, "%256s", str);
434 int gfx = load_gfx(str);
436 /* we read 64 characters at a time and insert them
437 randomly into the binary search tree. this is supposed
438 to help produce a more balanced tree. */
439 vwchar* C[64];
440 int ptr = 0;
442 C[ptr] = load_vwchar(rd, gfx);
443 while(C[ptr]){
444 if(ptr==64){
445 randomly_insert(C, 64);
446 ptr = 0;
448 else{
449 C[++ptr] = load_vwchar(rd, gfx);
453 randomly_insert(C, ptr);
455 printf("load_font: character tree is the following\n");
456 print_tree(chartree);
457 printf("\n");
459 return 0;
464 /***********/
465 /* utility */
466 /***********/
468 void point_camera(int x, int y){
469 camera.x = x;
470 camera.y = y;
473 void animate_sprites(){
474 for(int i=0; i<sprite_count; i++){
475 sprite* spr = sprites[i];
477 spr->frame_counter += dt;
478 animation* ani = animations[spr->anim];
481 while(spr->frame_counter > ani->frame_lens[spr->current_frame]){
482 spr->frame_counter -= ani->frame_lens[spr->current_frame];
483 spr->current_frame++;
484 if(spr->current_frame == ani->frame_count){
485 spr->current_frame = 0;
487 spr->frame = ani->frames[spr->current_frame];
490 if(spr->update) spr->update(spr, spr->userdata);
497 /********************/
498 /* graphics loading */
499 /********************/
501 SDL_Surface* SDL_NewSurface(int w, int h){
502 char prefix[32] = "SDL_NewSurface";
503 SDL_Surface* tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,w,h,32,0,0,0,0);
504 if(!tmp){
505 out_of_memory(prefix);
508 SDL_Surface* surf = SDL_DisplayFormat(tmp);
509 if(!surf){
510 out_of_memory(prefix);
513 SDL_FreeSurface(tmp);
515 SDL_FillRect(surf,0,0x00ffffff);
517 return surf;
521 load_pixmap filename
522 loads a pixmap file stored in the gfx/ subdir
523 returns an SDL surface in the 24bit format RGBRGBRGB...
525 load_gfx filename
526 returns the gfx id of the graphics with filename
527 may or may not load a new gfx object with load_pixmap
528 in sdl mode this sets up the gfx surface for color key transparency
529 in opengl mode this converts the 24bit to 32bit texture with alpha channel
531 load_sprite filename
532 reads a sprite definition from from the sprites/ subdir
533 loads a new animation structure as defined the file
534 uses load_gfx to get gfx id for animation graphics
535 therefore, may or may not load new graphics
536 returns an sprite id number used to instantiate new sprites
541 SDL_Surface* load_pixmap(char* filename){
542 char path[256] = "gfx/";
543 strmcat(path, filename, 256);
545 reader* rd = loader_open(path);
546 if(!rd){
547 return NULL;
550 unsigned char header[18];
551 loader_read(rd, header, 18);
553 int w = header[12] + (header[13]<<8);
554 int h = header[14] + (header[15]<<8);
555 int bpp = header[16];
557 SDL_Surface* surf = SDL_CreateRGBSurface(0,w,h,bpp,
558 0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
559 if(!surf){
560 out_of_memory("load_pixmap");
562 loader_read(rd, surf->pixels, w*(bpp/8)*h);
563 loader_close(rd);
565 return surf;
568 int load_gfx(char* filename){
569 if(gfx_count == MAX_GFX){
570 fatal_error("load_gfx: cannot load any more than %d graphics\n",MAX_GFX);
573 printf("loading %s\n",filename);
576 for(int i=0; i<gfx_count; i++){/*check for already loaded gfx*/
577 if(strcmp(gfx[i].filename, filename)==0){
578 return i;
582 SDL_Surface* src = load_pixmap(filename);
583 if(!src){
584 fatal_error("load_gfx: failed to load %s\n",filename);
587 if(!gl_flag){
588 SDL_Surface* surf = SDL_DisplayFormatAlpha(src);
589 SDL_SetAlpha(surf, 0, 0);
591 Uint32 key = SDL_MapRGB(surf->format, (COLOR_KEY&0xff0000)>>16,
592 (COLOR_KEY&0x00ff00)>>8,
593 (COLOR_KEY&0x0000ff)>>0);
594 SDL_SetColorKey(surf, SDL_SRCCOLORKEY, key);
596 SDL_FreeSurface(src);
599 gfx[gfx_count].filename = strxcpy(filename);
600 gfx[gfx_count].surf = surf;
601 gfx[gfx_count].w = surf->w;
602 gfx[gfx_count].h = surf->h;
604 else {
605 GLuint texture;
607 SDL_Surface* conv = SDL_CreateRGBSurface(0, src->w, src->h, 32,
608 0xff<<16,0xff<<8,0xff<<0,0);
610 SDL_BlitSurface(src, NULL, conv, NULL);
612 int N = 0;
613 int M = 3;
614 Uint8* conv_bytes = conv->pixels;
615 Uint32 key = SDL_MapRGB(src->format,(COLOR_KEY&0xff0000)>>16,
616 (COLOR_KEY&0x00ff00)>>8,
617 (COLOR_KEY&0x0000ff)>>0);
618 for(int i=0; i<src->w; i++){
619 for(int j=0; j<src->h; j++){
620 Uint32 pixel = *((Uint32*)(src->pixels+N));
621 conv_bytes[M] = pixel==key ? SDL_ALPHA_TRANSPARENT : SDL_ALPHA_OPAQUE;
622 N += src->format->BytesPerPixel;
623 M += 4;
627 glGenTextures( 1, &texture );
628 glBindTexture( GL_TEXTURE_2D, texture );
630 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
631 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
632 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
633 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
635 glTexImage2D( GL_TEXTURE_2D, 0, 4, conv->w, conv->h, 0,
636 GL_BGRA, GL_UNSIGNED_BYTE, conv->pixels );
638 gfx[gfx_count].filename = strxcpy(filename);
639 gfx[gfx_count].texture = texture;
640 gfx[gfx_count].w = src->w;
641 gfx[gfx_count].h = src->h;
643 SDL_FreeSurface(conv);
644 SDL_FreeSurface(src);
648 return gfx_count++;
651 int load_sprite(char* filename, int id){
652 printf("loading %s\n",filename);
654 char path[1024] = "sprites/";
655 strncat(path, filename, 1023 - strlen(filename));
657 reader* rd = loader_open(path);
658 if(!rd){
659 return -1;
662 animation* ani = xmalloc(sizeof(animation));
664 char str[256];
665 int w, h;
666 int frame_count;
667 int loop_mode;
669 loader_scanline(rd,"%256s",str);
670 loader_scanline(rd,"%d %d %d %d",&w,&h,&loop_mode,&frame_count);
672 ani->frame_lens = xmalloc(frame_count*sizeof(short));
673 ani->frames = xmalloc(frame_count*sizeof(struct frame));
674 ani->frame_count = frame_count;
676 int g = load_gfx(str);
677 if(g < 0)
678 return -1;
680 ani->gfxid = g;
682 int W = gfx[g].w;
683 int H = gfx[g].h;
684 ani->w = w;
685 ani->h = h;
687 for(int i=0; i < frame_count; i++){
688 int l, x, y;
689 loader_scanline(rd, "%d %d %d", &l, &x, &y);
690 ani->frame_lens[i] = l;
691 if(!gl_flag){
692 ani->frames[i].x = x;
693 ani->frames[i].y = y;
695 else{
696 ani->frames[i].x0 = ((double)x)/W;
697 ani->frames[i].y0 = ((double)y)/H;
698 ani->frames[i].x1 = ((double)(x+w))/W;
699 ani->frames[i].y1 = ((double)(y+h))/W;
703 loader_close(rd);
704 animations[id] = ani;
705 return 0;
711 /********************/
712 /* graphics control */
713 /********************/
715 sprite* enable_sprite(int sprnum){
716 if(!animations[sprnum]){
717 fatal_error("enable_sprite: you just tried to enable sprite with type %d, which does not exist\n",sprnum);
719 if(sprite_count == MAX_SPRITES){
720 /* need a priority based way to create important sprites if full */
721 return NULL;
723 sprite* spr = xmalloc(sizeof(sprite));
724 animation* ani = animations[sprnum];
726 spr->number = sprite_count;
727 spr->frame_counter = 0;
728 spr->current_frame = 0;
729 spr->frame = ani->frames[0];
730 spr->gfxid = ani->gfxid;
731 spr->anim = sprnum;
732 spr->x = 0;
733 spr->y = 0;
734 spr->w = ani->w;
735 spr->h = ani->h;
736 spr->vx = 0;
737 spr->vy = 0;
738 spr->update = NULL;
739 spr->userdata = NULL;
741 sprites[sprite_count++] = spr;
742 return spr;
745 void disable_sprite(sprite* spr){
746 sprite* tmp = sprites[spr->number];
747 sprites[spr->number] = sprites[sprite_count--];
748 free(tmp);
751 sprite* copy_sprite(sprite* spr){
752 if(sprite_count == MAX_SPRITES){
753 /* need way to make important sprites when full */
754 return NULL;
756 sprite* copy = xmalloc(sizeof(sprite));
757 *copy = *spr;
758 sprites[sprite_count++] = copy;
759 return copy;
764 Sint16* lout;
765 Sint16* rout;
766 int buffer_size;
768 extern void process_audio(short lout[], short rout[], int len);
770 void audio_callback(void *userdata, Uint8 *stream, int len){
771 Sint16* out = (Sint16*)stream;
773 process_audio(lout, rout, buffer_size);
775 for(int i=0; i<buffer_size; i++){
776 out[i*2 ] = lout[i];
777 out[i*2 + 1] = rout[i];
784 /******************/
785 /* initialization */
786 /******************/
788 void backend_init(int argc, char* argv[]){
790 srand(RANDOM_SEED);
792 init_text();
794 for(int i=0; i<MAX_ANIMATIONS; i++){
795 animations[i] = NULL;
798 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)==-1){
799 report_error("sdl: %s\n",SDL_GetError());
800 exit(-1);
804 /* options */
805 int fullscreen = 0;
806 for(int i=0; i<argc; i++){
807 if(!strcmp(argv[i], "-gl")){
808 gl_flag = 1;
809 continue;
811 if(!strcmp(argv[i], "-f")){
812 fullscreen = 1;
814 if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")){
815 printf("options:\n");
816 printf(" -gl use opengl video mode\n");
817 printf(" -f use fullscreen video mode\n");
818 printf(" -h print this help\n");
819 printf(" -v print version info\n");
820 exit(0);
822 if(!strcmp(argv[i], "-v")){
823 printf("cantaveria (v%d.%d)\n",VERSION_MAJOR,VERSION_MINOR);
824 printf("Copyright 2009 Evan Rinehart\n\n");
826 printf("This program is distributed under the terms of the GNU General\n"
827 "Public License (v2) and comes with ABSOLUTELY NO WARRANTY.\n\n");
829 printf("Send questions, comments, and bugs to evanrinehart@gmail.com\n\n");
831 printf("Send money to:\n");
832 printf("1850 Claiborne St\n");
833 printf("Mandeville, LA 70448\n");
834 printf("United States of America\n\n");
836 printf("Thanks! :)\n");
837 exit(0);
842 /* keymap */
843 keymap[ESCAPE_KEY] = SDLK_ESCAPE;
844 keymap[PAUSE_KEY] = SDLK_PAUSE;
846 keymap[LEFT_KEY] = SDLK_LEFT;
847 keymap[RIGHT_KEY] = SDLK_RIGHT;
848 keymap[UP_KEY] = SDLK_UP;
849 keymap[DOWN_KEY] = SDLK_DOWN;
851 keymap[FIRE_KEY] = SDLK_z;
852 keymap[JUMP_KEY] = SDLK_x;
853 keymap[INVENTORY_KEY] = SDLK_a;
854 keymap[SPECIAL_KEY] = SDLK_s;
856 keymap[L_KEY] = SDLK_q;
857 keymap[R_KEY] = SDLK_w;
858 keymap[START_KEY] = SDLK_RETURN;
859 keymap[SELECT_KEY] = SDLK_TAB;
861 /* joysticks */
862 int N = SDL_NumJoysticks();
863 printf("sdl: detected %d joysticks\n",N);
864 for(int i=0; i<N; i++){
865 if(SDL_JoystickOpen(i)){
866 printf(" joy%d: %s\n",i,SDL_JoystickName(i));
868 else{
869 printf(" joy%d: %s (failed to open)\n",i,SDL_JoystickName(i));
874 /* video */
875 int flags = 0;
877 SDL_WM_SetCaption("cantaveria","cantaveria");
878 SDL_ShowCursor(SDL_DISABLE);
879 const SDL_VideoInfo* vinfo = SDL_GetVideoInfo();
882 if(fullscreen && gl_flag){
883 W = vinfo->current_w;
884 H = vinfo->current_h;
886 else if(gl_flag){
887 //W = 320;
888 //H = 240;
889 W = 640;
890 H = 480;
891 //W = 960;
892 //H = 720;
894 else if(fullscreen){
895 W = 320;
896 H = 240;
898 else{
899 W = 320;
900 H = 240;
903 //double aspect = vinfo->current_w*1.0 / vinfo->current_h;
904 double aspect = ((double)W) / H;
907 if(gl_flag){
908 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
909 //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
910 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
911 flags |= SDL_OPENGL;
914 if(fullscreen){
915 flags |= SDL_FULLSCREEN;
916 screen_offset = (aspect*SCREEN_H - SCREEN_W)/2;
919 printf("video:\n");
920 printf(" resolution: %d x %d %s\n",W,H,fullscreen?"fullscreen":"windowed");
921 printf(" aspect ratio: %g\n",((double)W)/H);
922 printf(" opengl: %s\n",gl_flag?"yes":"no");
923 printf(" x-offset: %d\n",screen_offset);
925 video = SDL_SetVideoMode(W,H,32,flags);
926 if(video == NULL){
927 report_error("sdl: %s\n",SDL_GetError());
928 exit(-1);
931 printf(" video on\n");
933 if(gl_flag){
934 glEnable(GL_BLEND);
935 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
937 glEnable( GL_TEXTURE_2D );
938 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
940 glViewport( 0, 0, W, H );
942 glClear( GL_COLOR_BUFFER_BIT );
944 glMatrixMode( GL_PROJECTION );
945 glLoadIdentity();
946 if(fullscreen){
947 glOrtho(0.0f, 240*aspect, 240, 0.0f, -1.0f, 1.0f);
949 else{
950 glOrtho(0.0f, 320, 240, 0.0f, -1.0f, 1.0f);
953 glMatrixMode( GL_MODELVIEW );
954 glLoadIdentity();
958 /* setup audio */
959 SDL_AudioSpec audio;
960 audio.freq = SAMPLE_RATE;
961 audio.format = AUDIO_S16;
962 audio.channels = 2;
963 audio.samples = BUFFER_SIZE;
964 audio.callback = audio_callback;
966 SDL_AudioSpec gotten;
968 if(SDL_OpenAudio(&audio, &gotten)<0){
969 report_error("sdl: cannot open audio (%s)\n", SDL_GetError());
970 exit(-1);
973 printf("audio:\n");
974 printf(" sample rate = %d\n",gotten.freq);
975 printf(" channels = %d\n",gotten.channels);
976 printf(" samples = %d\n",gotten.samples);
977 printf(" format = %d\n",gotten.format);
979 if(gotten.format != AUDIO_S16){
980 printf(" WARNING: audio format not AUDIO_S16 :(\n");
983 lout = xmalloc(gotten.samples*2);
984 rout = xmalloc(gotten.samples*2);
985 buffer_size = gotten.samples;
987 printf(" sound on\n");
988 SDL_PauseAudio(0);
991 /* were done here */
993 SDL_Rect** modes;
994 int i;
996 modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
998 if (modes == (SDL_Rect**)0) {
999 printf("No modes available!\n");
1000 exit(-1);
1003 if (modes == (SDL_Rect**)-1) {
1004 printf("All resolutions available.\n");
1006 else{
1007 printf("Available Modes\n");
1008 for (i=0; modes[i]; ++i)
1009 printf(" %d x %d\n", modes[i]->w, modes[i]->h);