Ejemplo n.º 1
0
/* functions - used to call to this library from other parts of engine */
unsigned int setupSound(void)
{

    /* set up sound library for first use, and init allegro soundsystem */
    music = NULL;
    voice = NULL;
    mixer = NULL;
    if (!al_install_audio()) {

        /* fail if audio does not load for some reason */
        return 0;
    }
    if (!al_init_acodec_addon()) {

        /* fail if audio does not load for some reason */
        return 0;
    }
    if (!al_reserve_samples(8)) {

        /* fail if audio does not load for some reason */
        return 0;

    }
    mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
    voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
    al_attach_mixer_to_voice(mixer, voice);
    return true;

}
Ejemplo n.º 2
0
void Framework::InitialiseAudioSystem()
{
#ifdef WRITE_LOG
  printf( "Framework: Initialise Audio\n" );
#endif
  voice = 0;
  mixer = 0;

	if( audioInitialised || al_install_audio() )
	{
		if( audioInitialised || al_init_acodec_addon() )
		{
			voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
			if( voice != 0 )
			{
				mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
				if( mixer != 0 )
        {
					al_attach_mixer_to_voice(mixer, voice);
        } else {
          al_destroy_voice( voice );
          voice = 0;
        }
			}
		}
	}
}
Ejemplo n.º 3
0
void init_misc_sounds() {
    // Sound effects.
    voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16,   ALLEGRO_CHANNEL_CONF_2);
    mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
    al_attach_mixer_to_voice(mixer, voice);
    sfx_attack = load_sample(              "Attack.ogg",               mixer);
    sfx_pikmin_attack = load_sample(       "Pikmin_attack.ogg",        mixer);
    sfx_pikmin_carrying = load_sample(     "Pikmin_carrying.ogg",      mixer);
    sfx_pikmin_carrying_grab = load_sample("Pikmin_carrying_grab.ogg", mixer);
    sfx_pikmin_caught = load_sample(       "Pikmin_caught.ogg",        mixer);
    sfx_pikmin_dying = load_sample(        "Pikmin_dying.ogg",         mixer);
    sfx_pikmin_held = load_sample(         "Pikmin_held.ogg",          mixer);
    sfx_pikmin_idle = load_sample(         "Pikmin_idle.ogg",          mixer);
    sfx_pikmin_thrown = load_sample(       "Pikmin_thrown.ogg",        mixer);
    sfx_pikmin_pluck = load_sample(        "Pikmin_pluck.ogg",         mixer);
    sfx_pikmin_plucked = load_sample(      "Pikmin_plucked.ogg",       mixer);
    sfx_pikmin_called = load_sample(       "Pikmin_called.ogg",        mixer);
    sfx_dismiss = load_sample(             "Dismiss.ogg",              mixer);
    sfx_olimar_whistle = load_sample(      "Olimar_whistle.ogg",       mixer);
    sfx_louie_whistle = load_sample(       "Louie_whistle.ogg",        mixer);
    sfx_president_whistle = load_sample(   "President_whistle.ogg",    mixer);
    sfx_olimar_name_call = load_sample(    "Olimar_name_call.ogg",     mixer);
    sfx_louie_name_call = load_sample(     "Louie_name_call.ogg",      mixer);
    sfx_president_name_call = load_sample( "President_name_call.ogg",  mixer);
    sfx_throw = load_sample(               "Throw.ogg",                mixer);
    sfx_switch_pikmin = load_sample(       "Switch_Pikmin.ogg",        mixer);
    sfx_camera = load_sample(              "Camera.ogg",               mixer);
}
Ejemplo n.º 4
0
void SoundManager::PlayMusic(int num, bool loop)
{
	DestroyMusic();
	if(num==-1)
		return;
	else if(num==0)
		music = al_load_audio_stream("music/menu.ogg", 4, 2048);
	else if(num==1)
		music = al_load_audio_stream("music/level1.ogg", 4, 2048);

	if(music==NULL)
	{
		al_show_native_message_box(DisplayManager::GetInstance().GetDisplay(),
			"Error!", "SoundManager", "Couldn't load music", "ok sok", ALLEGRO_MESSAGEBOX_ERROR);
		return;
	}

	if(music==NULL)
		return;

	al_set_audio_stream_loop_secs(music, .0f, al_get_audio_stream_length_secs(music));
	if(loop)
		al_set_audio_stream_playmode(music, ALLEGRO_PLAYMODE_LOOP);
	else
		al_set_audio_stream_playmode(music, ALLEGRO_PLAYMODE_ONCE);
	al_attach_audio_stream_to_mixer(music, mixer);
	al_attach_mixer_to_voice(mixer,voice);

}
Ejemplo n.º 5
0
Audio::Audio()
{
#ifdef WRITE_LOG
  fprintf( FRAMEWORK->LogFile, "Framework: Initialise Audio\n" );
#endif

	if( !al_install_audio() )
	{
		fprintf( FRAMEWORK->LogFile, "Audio_Initialise: Failed to install audio\n" );
		return;
	}
	if( !al_init_acodec_addon() )
	{
		fprintf( FRAMEWORK->LogFile, "Audio_Initialise: Failed to install codecs\n" );
		return;
	}

	// Allow playing samples
	al_reserve_samples( 10 );

	audioVoice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
	if( audioVoice == 0 )
	{
		fprintf( FRAMEWORK->LogFile, "Audio_Initialise: Failed to create voice\n" );
		return;
	}
	audioMixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	if( audioMixer == 0 )
	{
		fprintf( FRAMEWORK->LogFile, "Audio_Initialise: Failed to create mixer\n" );
		al_destroy_voice( audioVoice );
		audioVoice = 0;
		return;
	}
	if( !al_attach_mixer_to_voice( audioMixer, audioVoice ) )
	{
		fprintf( FRAMEWORK->LogFile, "Audio_Initialise: Failed to attach mixer to voice\n" );
		al_destroy_voice( audioVoice );
		audioVoice = 0;
		al_destroy_mixer( audioMixer );
		audioMixer = 0;
		return;
	}

	musicStream = nullptr;
}
Ejemplo n.º 6
0
		void AudioWrappers::init_audio(void)
		{
			if (!AudioWrappers::is_enabled()) return;

			voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
			mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
			
			if (voice == NULL)
			{
				PRINT(RAGE_ERROR_CANNOT_CREATE_VOICE);
				return;
			}
			
			if (mixer == NULL)
			{
				PRINT(RAGE_ERROR_CANNOT_CREATE_MIXER);
				return;
			}
			
			al_attach_mixer_to_voice(mixer, voice);
		}
Ejemplo n.º 7
0
bool AllegroSound5::Init()
{
	if ( !al_install_audio() )
	{
		GetLog().Log( CommonLog(), LL_WARNING, "Failed to initialize sound (al_install_audio)" );
		return false;
	}

	if ( !al_init_acodec_addon() )
	{
		GetLog().Log( CommonLog(), LL_WARNING, "Failed to initialize sound (al_init_acodec_addon)" );
		return false;
	}

	m_pVoice = al_create_voice( 44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2 );		

	if ( !m_pVoice )
	{
		GetLog().Log( CommonLog(), LL_WARNING, "Failed to initialize sound (al_create_voice)" );
		return false;
	}

	m_pMusicMixer = al_create_mixer( 44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2 );
	m_pSoundMixer = al_create_mixer( 44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2 );
	m_pMasterMixer = al_create_mixer( 44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2 );

	if ( !m_pMusicMixer || !m_pSoundMixer || !m_pMasterMixer )
	{
		GetLog().Log( CommonLog(), LL_WARNING, "Failed to initialize sound (al_create_mixer)" );
		return false;
	}

	al_attach_mixer_to_mixer( m_pMusicMixer, m_pMasterMixer );
	al_attach_mixer_to_mixer( m_pSoundMixer, m_pMasterMixer );
	al_attach_mixer_to_voice( m_pMasterMixer, m_pVoice );

	return true;
}
Ejemplo n.º 8
0
/* Creates the default voice and mixer if they haven't been created yet. */
static bool create_default_mixer(void)
{
   int voice_frequency = 44100;
   int voice_depth = ALLEGRO_AUDIO_DEPTH_INT16;
   int mixer_frequency = 44100;
   int mixer_depth = ALLEGRO_AUDIO_DEPTH_FLOAT32;

   ALLEGRO_CONFIG *config = al_get_system_config();
   const char *p;
   p = al_get_config_value(config, "audio", "primary_voice_frequency");
   if (p && p[0] != '\0') {
      voice_frequency = atoi(p);
   }
   p = al_get_config_value(config, "audio", "primary_mixer_frequency");
   if (p && p[0] != '\0') {
      mixer_frequency = atoi(p);
   }
   p = al_get_config_value(config, "audio", "primary_voice_depth");
   if (p && p[0] != '\0') {
      voice_depth = string_to_depth(p);
   }
   p = al_get_config_value(config, "audio", "primary_mixer_depth");
   if (p && p[0] != '\0') {
      mixer_depth = string_to_depth(p);
   }

   if (!allegro_voice) {
      allegro_voice = al_create_voice(voice_frequency, voice_depth,
         ALLEGRO_CHANNEL_CONF_2);
      if (!allegro_voice) {
         ALLEGRO_ERROR("al_create_voice failed\n");
         goto Error;
      }
   }

   if (!allegro_mixer) {
      allegro_mixer = al_create_mixer(mixer_frequency, mixer_depth,
         ALLEGRO_CHANNEL_CONF_2);
      if (!allegro_mixer) {
         ALLEGRO_ERROR("al_create_voice failed\n");
         goto Error;
      }
   }

   /* In case this function is called multiple times. */
   al_detach_mixer(allegro_mixer);

   if (!al_attach_mixer_to_voice(allegro_mixer, allegro_voice)) {
      ALLEGRO_ERROR("al_attach_mixer_to_voice failed\n");
      goto Error;
   }

   return true;

Error:

   if (allegro_mixer) {
      al_destroy_mixer(allegro_mixer);
      allegro_mixer = NULL;
   }

   if (allegro_voice) {
      al_destroy_voice(allegro_voice);
      allegro_voice = NULL;
   }

   return false;
}
Ejemplo n.º 9
0
int main(int argc, char **argv)
{
    ALLEGRO_VOICE *voice;
    ALLEGRO_MIXER *mixer;
    ALLEGRO_MIXER *submixer[2];
    ALLEGRO_SAMPLE_INSTANCE *sample[2];
    ALLEGRO_SAMPLE *sample_data[2];
    float sample_time;
    float max_sample_time;
    int i;

    if (!al_init()) {
        abort_example("Could not init Allegro.\n");
    }

    open_log();

    if (argc < 3) {
        log_printf("This example needs to be run from the command line.\nUsage: %s file1 file2\n", argv[0]);
        goto done;
    }

    al_init_acodec_addon();

    if (!al_install_audio()) {
        abort_example("Could not init sound!\n");
    }

    voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16,
                            ALLEGRO_CHANNEL_CONF_2);
    if (!voice) {
        abort_example("Could not create ALLEGRO_VOICE.\n");
    }

    mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,
                            ALLEGRO_CHANNEL_CONF_2);
    submixer[0] = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,
                                  ALLEGRO_CHANNEL_CONF_2);
    submixer[1] = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,
                                  ALLEGRO_CHANNEL_CONF_2);
    if (!mixer || !submixer[0] || !submixer[1]) {
        abort_example("al_create_mixer failed.\n");
    }

    if (!al_attach_mixer_to_voice(mixer, voice)) {
        abort_example("al_attach_mixer_to_voice failed.\n");
    }

    for (i = 0; i < 2; i++) {
        const char *filename = argv[i + 1];
        sample_data[i] = al_load_sample(filename);
        if (!sample_data[i]) {
            abort_example("Could not load sample from '%s'!\n", filename);
        }
        sample[i] = al_create_sample_instance(NULL);
        if (!sample[i]) {
            abort_example("al_create_sample failed.\n");
        }
        if (!al_set_sample(sample[i], sample_data[i])) {
            abort_example("al_set_sample_ptr failed.\n");
        }
        if (!al_attach_sample_instance_to_mixer(sample[i], submixer[i])) {
            abort_example("al_attach_sample_instance_to_mixer failed.\n");
        }
        if (!al_attach_mixer_to_mixer(submixer[i], mixer)) {
            abort_example("al_attach_mixer_to_mixer failed.\n");
        }
    }

    /* Play sample in looping mode. */
    for (i = 0; i < 2; i++) {
        al_set_sample_instance_playmode(sample[i], ALLEGRO_PLAYMODE_LOOP);
        al_play_sample_instance(sample[i]);
    }

    max_sample_time = al_get_sample_instance_time(sample[0]);
    sample_time = al_get_sample_instance_time(sample[1]);
    if (sample_time > max_sample_time)
        max_sample_time = sample_time;

    log_printf("Playing...");

    al_rest(max_sample_time);

    al_set_sample_instance_gain(sample[0], 0.5);
    al_rest(max_sample_time);

    al_set_sample_instance_gain(sample[1], 0.25);
    al_rest(max_sample_time);

    al_stop_sample_instance(sample[0]);
    al_stop_sample_instance(sample[1]);
    log_printf("Done\n");

    /* Free the memory allocated. */
    for (i = 0; i < 2; i++) {
        al_set_sample(sample[i], NULL);
        al_destroy_sample(sample_data[i]);
        al_destroy_sample_instance(sample[i]);
        al_destroy_mixer(submixer[i]);
    }
    al_destroy_mixer(mixer);
    al_destroy_voice(voice);

    al_uninstall_audio();

done:
    close_log(true);

    return 0;
}
Ejemplo n.º 10
0
int main(int argc, char **argv)
{
   ALLEGRO_VOICE *voice;
   ALLEGRO_MIXER *mixer;
   ALLEGRO_SAMPLE_INSTANCE *sample;
   int i;
   char const **filenames;
   int n;

   if (argc < 2) {
      n = 1;
      filenames = malloc(sizeof *filenames);
      filenames[0] = "data/testing.ogg";
   }
   else {
      n = argc - 1;
      filenames = malloc(sizeof *filenames * n);
      for (i = 1; i < argc; ++i) {
         filenames[i - 1] = argv[i];
      }
   }

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }

   open_log();

   al_init_acodec_addon();

   if (!al_install_audio()) {
      abort_example("Could not init sound!\n");
   }

   voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16,
      ALLEGRO_CHANNEL_CONF_2);
   if (!voice) {
      abort_example("Could not create ALLEGRO_VOICE.\n");
   }

   mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,
      ALLEGRO_CHANNEL_CONF_2);
   if (!mixer) {
      abort_example("al_create_mixer failed.\n");
   }

   if (!al_attach_mixer_to_voice(mixer, voice)) {
      abort_example("al_attach_mixer_to_voice failed.\n");
   }

   sample = al_create_sample_instance(NULL);
   if (!sample) {
      abort_example("al_create_sample failed.\n");
   }

   for (i = 0; i < n; ++i) {
      ALLEGRO_SAMPLE *sample_data = NULL;
      const char *filename = filenames[i];
      float sample_time = 0;

      /* Load the entire sound file from disk. */
      sample_data = al_load_sample(filename);
      if (!sample_data) {
         abort_example("Could not load sample from '%s'!\n",
            filename);
         continue;
      }

      if (!al_set_sample(sample, sample_data)) {
         abort_example("al_set_sample_instance_ptr failed.\n");
         continue;
      }

      if (!al_attach_sample_instance_to_mixer(sample, mixer)) {
         abort_example("al_attach_sample_instance_to_mixer failed.\n");
         goto done;
      }

      /* Play sample in looping mode. */
      al_set_sample_instance_playmode(sample, ALLEGRO_PLAYMODE_LOOP);
      al_play_sample_instance(sample);

      sample_time = al_get_sample_instance_time(sample);
      log_printf("Playing '%s' (%.3f seconds) 3 times", filename,
         sample_time);

      al_rest(sample_time);

      if (!al_set_sample_instance_gain(sample, 0.5)) {
         abort_example("Failed to set gain.\n");
      }
      al_rest(sample_time);

      if (!al_set_sample_instance_gain(sample, 0.25)) {
         abort_example("Failed to set gain.\n");
      }
      al_rest(sample_time);

      al_stop_sample_instance(sample);
      log_printf("\nDone playing '%s'\n", filename);

      /* Free the memory allocated. */
      al_set_sample(sample, NULL);
      al_destroy_sample(sample_data);
   }

   al_destroy_sample_instance(sample);
   al_destroy_mixer(mixer);
   al_destroy_voice(voice);

   al_uninstall_audio();

done:
   close_log(true);

   return 0;
}
Ejemplo n.º 11
0
int main( int argc, char* argv[] )
{
	ALLEGRO_EVENT e;
	ALLEGRO_TIMER* t;
	int64_t framesToUpdate = 0;

	if( !al_init() )
	{
		return -1;
	}
	
	al_init_font_addon();
	if( !al_install_keyboard() || !al_install_mouse() || !al_init_primitives_addon() || !al_init_ttf_addon() || !al_init_image_addon() )
	{
		return -1;
	}

#if NETWORK_SUPPORT != 0
	if( !install_network() )
	{
		return -1;
	}
#endif

#if HTTP_SUPPORT
	if( !install_http() )
	{
		return -1;
	}
#ifdef PANDORA
	Downloads = new HttpManager(2);
#else
	Downloads = new HttpManager(6);
#endif
#endif

#if EXIT_IF_NO_AUDIO != 0

	if( !al_install_audio() || !al_init_acodec_addon() )
	{
		return -1;
	}

	voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
	if (!voice)
		return 1;
	mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	if (!mixer)
		return 1;
	if (!al_attach_mixer_to_voice(mixer, voice))
		return 1;

#else

	if( al_install_audio() )
	{
		if( al_init_acodec_addon() )
		{
			voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
			if( voice != 0 )
			{
				mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
				if( mixer != 0 )
					al_attach_mixer_to_voice(mixer, voice);
			}
		}
	}

#endif // EXIT_IF_NO_AUDIO

	// Random number is guarenteed to be random
	srand( 5 );

	GameStack = new StageStack();
	CurrentConfiguration = new Configuration();

	if( CurrentConfiguration->FullScreen )
		al_set_new_display_flags( ALLEGRO_FULLSCREEN_WINDOW );

	al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST);

	bool foundMode = false;
	int fallbackW = 640;
	int fallbackH = 480;

	if( CurrentConfiguration->ForceResolution )
	{
		foundMode = true;
	} else {
		for( int modeIdx = 0; modeIdx < al_get_num_display_modes(); modeIdx++ )
		{
			if( al_get_display_mode( modeIdx, &ScreenMode ) != NULL )
			{
				if( ScreenMode.width == CurrentConfiguration->ScreenWidth && ScreenMode.height == CurrentConfiguration->ScreenHeight )
				{
					foundMode = true;
				} else {
					fallbackW = ScreenMode.width;
					fallbackH = ScreenMode.height;
				}
			}

			if( foundMode )
				break;
		}
	}

	if( foundMode )
	{
		Screen = al_create_display( CurrentConfiguration->ScreenWidth, CurrentConfiguration->ScreenHeight );
	} else {
		Screen = al_create_display( fallbackW, fallbackH );
		CurrentConfiguration->ScreenWidth = fallbackW;
		CurrentConfiguration->ScreenHeight = fallbackH;
	}

	al_hide_mouse_cursor( Screen );

	t = al_create_timer( 1.0 / SCREEN_FPS );
  if( t == NULL )
    Quit = true;
  al_start_timer( t );

	EventQueue = al_create_event_queue();
	al_register_event_source( EventQueue, al_get_display_event_source( Screen ) );
	al_register_event_source( EventQueue, al_get_keyboard_event_source() );
	al_register_event_source( EventQueue, al_get_mouse_event_source() );
	al_register_event_source( EventQueue, al_get_timer_event_source( t ) );
#if NETWORK_SUPPORT != 0
	al_register_event_source( EventQueue, get_network_event_source() );
#endif
#if HTTP_SUPPORT
	Downloads->urlDownloads = CurrentConfiguration->MaxConcurrentDownloads;
	al_register_event_source( EventQueue, get_http_event_source() );
#endif

	Fonts = new FontManager();
	Images = new ImageManager();
	Audio = new SoundManager();

	al_set_blender( ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA );

	GameStack->Push( (Stage*)new BootUp() );

	while( !Quit )
	{
		if( GameStack->IsEmpty() )
		{
			Quit = true;
		} else {
			while( al_get_next_event( EventQueue, &e ) )
			{
#if HTTP_SUPPORT
				Downloads->Event( &e );
#endif
				switch( e.type )
				{
					case ALLEGRO_EVENT_DISPLAY_CLOSE:
						Quit = true;
						break;
					case ALLEGRO_EVENT_JOYSTICK_CONFIGURATION:
						al_reconfigure_joysticks();
						break;
					case ALLEGRO_EVENT_TIMER:
						if( e.timer.source == t )
							framesToUpdate++;
						else if( !GameStack->IsEmpty() )
							GameStack->Current()->Event( &e );
						break;
					default:
						if( !GameStack->IsEmpty() )
							GameStack->Current()->Event( &e );
						switch( e.type )
						{
#if HTTP_SUPPORT
							case ALLEGRO_EVENT_HTTP:
#endif
#if NETWORK_SUPPORT
							case ALLEGRO_EVENT_NETWORK_CONNECTION:
							case ALLEGRO_EVENT_NETWORK_RECEIVEPACKET:
							case ALLEGRO_EVENT_NETWORK_DISCONNECTION:
#endif
							case ALLEGRO_EVENT_BUTTON_CLICK:
							case ALLEGRO_EVENT_MOUSEEX_MOVE:
							case ALLEGRO_EVENT_MOUSEEX_DOWN:
							case ALLEGRO_EVENT_MOUSEEX_UP:
							case ALLEGRO_EVENT_MOUSEEX_CLICK:
							case ALLEGRO_EVENT_MOUSEEX_DOUBLECLICK:
							case ALLEGRO_EVENT_MOUSEEX_BOXED:
							case ALLEGRO_EVENT_MOUSEEX_WHEEL:
								al_unref_user_event( &e.user );
								break;
						}
						break;
				}
			}

			if( framesToUpdate > 0 )
			{
				for( int frmUp = 0; frmUp < framesToUpdate; frmUp++ )
				{
					if( !GameStack->IsEmpty() )
						GameStack->Current()->Update();
				}
				framesToUpdate = 0;
			}

			al_clear_to_color( al_map_rgb( 128, 128, 128 ) );
			if( !GameStack->IsEmpty() )
				GameStack->Current()->Render();
			al_flip_display();

			Images->Tidy();
			Fonts->Tidy();
			Audio->Tidy();
		}
	}

	while( !GameStack->IsEmpty() )
	{
		GameStack->Pop();
	}

	delete Downloads;
	delete Fonts;
	delete Images;
	delete Audio;

	al_destroy_event_queue( EventQueue );
	al_destroy_display( Screen );

#if HTTP_SUPPORT
	uninstall_http();
#endif
#if NETWORK_SUPPORT != 0
	uninstall_network();
#endif
	al_uninstall_keyboard();
	al_uninstall_mouse();
	al_shutdown_primitives_addon();
	al_shutdown_ttf_addon();
	al_shutdown_image_addon();
	al_uninstall_audio();
	al_shutdown_font_addon();

	return 0;
}
Ejemplo n.º 12
0
bool GameLogic::InitializeAllegro() {
	if(!al_init()) {
        fprintf(stderr, "Failed to initialize allegro!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Allegro 5 initialized.\n"); }

	if(!al_install_keyboard()) {
      fprintf(stderr, "Failed to initialize the keyboard!\n");
      return false;
    }
    if(Debug) { fprintf(stderr, "Keyboard initialized.\n"); }

    if(!al_install_mouse()) {
        fprintf(stderr, "Failed to initialize the mouse!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Mouse initialized.\n"); }

    Timer = al_create_timer(TimerStep);
    if(!Timer) {
        fprintf(stderr, "Failed to create Timer!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Timer initialized.\n"); }

    if(!al_init_image_addon()) {
        fprintf(stderr, "Failed to initialize images loading!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Image loading initialized.\n"); }

	if(!al_init_primitives_addon()) {
        fprintf(stderr, "Failed to initialize primitives!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Primitives addon initialized.\n"); }

    al_init_font_addon();
	
    if(!al_init_ttf_addon()) {
        fprintf(stderr, "Failed to initialize TrueType!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "TTF font loading initialized.\n"); }
    
    if(!al_install_audio()) {
        fprintf(stderr, "Failed to initialize audio!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Audio initialized.\n"); }

    if(!al_init_acodec_addon()) {
        fprintf(stderr, "Failed to initialize audio codecs!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Ogg/FLAC initialized.\n"); }

    // create and confirm allegro Display
    Display = al_create_display(DisplayWidth, DisplayHeight);
    if(!Display) {
        fprintf(stderr, "Failed to create Display!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Display initialized.\n"); }

    // Make sure we are on the backbuffer
    al_set_target_bitmap(al_get_backbuffer(Display));
    
    Voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
    if (!Voice) {
        fprintf(stderr, "Could not create ALLEGRO_VOICE.\n");
        return 1;
    }
    if(Debug) { fprintf(stderr, "Voice created.\n"); }

    Mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,ALLEGRO_CHANNEL_CONF_2);
    if (!Mixer) {
        fprintf(stderr, "Could not create ALLEGRO_MIXER.\n");
        return 1;
    }
    if(Debug) { fprintf(stderr, "Mixer created.\n"); }

    if (!al_attach_mixer_to_voice(Mixer, Voice)) {
        fprintf(stderr, "Attaching Mixer to Voice failed.\n");
        return 1;
    }
    if(Debug) { fprintf(stderr, "Mixer attached to Voice.\n"); }
    
    // create and confirm event queue
    EventQueue = al_create_event_queue();
    if(!EventQueue) {
        fprintf(stderr, "Failed to create EventQueue!\n");
        return false;
    }
    if(Debug) { fprintf(stderr, "Event queue created successfully.\n"); }

    al_register_event_source(EventQueue, al_get_display_event_source(Display));
    al_register_event_source(EventQueue, al_get_timer_event_source(Timer));
    al_register_event_source(EventQueue, al_get_mouse_event_source());
    al_register_event_source(EventQueue, al_get_keyboard_event_source());

    // blank the Display
    al_clear_to_color(al_map_rgb(0,0,0));
    al_flip_display();

	// actually start our Timer
    al_start_timer(Timer);

	return true;
}
int main(int argc, char **argv)
{
   const char *filename = "../demos/cosmic_protector/data/sfx/title_music.ogg";
   ALLEGRO_VOICE *voice;
   ALLEGRO_MIXER *mixer;
   ALLEGRO_AUDIO_STREAM *stream;

   if (argc > 1) {
      filename = argv[1];
   }

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
      return 1;
   }

   al_init_primitives_addon();
   al_init_image_addon();
   al_init_acodec_addon();
   
   al_install_keyboard();

   display = al_create_display(640, 480);
   if (!display) {
      abort_example("Could not create display.\n");
      return 1;
   }

   dbuf = al_create_bitmap(640, 480);

   bmp = al_load_bitmap("data/mysha.pcx");
   if (!bmp) {
      abort_example("Could not load data/mysha.pcx\n");
      return 1;
   }

   if (!al_install_audio()) {
      abort_example("Could not init sound.\n");
      return 1;
   }

   voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16,
      ALLEGRO_CHANNEL_CONF_2);
   if (!voice) {
      abort_example("Could not create voice.\n");
      return 1;
   }

   mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32,
      ALLEGRO_CHANNEL_CONF_2);
   if (!mixer) {
      abort_example("Could not create mixer.\n");
      return 1;
   }

   if (!al_attach_mixer_to_voice(mixer, voice)) {
      abort_example("al_attach_mixer_to_voice failed.\n");
      return 1;
   }

   stream = al_load_audio_stream(filename, 4, 2048);
   if (!stream) {
      abort_example("Could not load '%s'\n", filename);
      return 1;
   }

   al_set_audio_stream_playmode(stream, ALLEGRO_PLAYMODE_LOOP);
   al_attach_audio_stream_to_mixer(stream, mixer);

   al_set_mixer_postprocess_callback(mixer, update_meter, NULL);

   main_loop();

   al_destroy_audio_stream(stream);
   al_destroy_mixer(mixer);
   al_destroy_voice(voice);
   al_uninstall_audio();

   al_destroy_bitmap(dbuf);
   al_destroy_bitmap(bmp);

   return 0;
}
Ejemplo n.º 14
0
static inline void HandleEvent(struct Game* game, ALLEGRO_EVENT* ev) {
	switch (ev->type) {
		case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING:
			PauseExecution(game);
			al_acknowledge_drawing_halt(game->display);
			break;

		case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING:
			al_acknowledge_drawing_resume(game->display);
			ReloadGamestates(game);
			ResumeExecution(game);
			break;

		case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:
			if (game->config.autopause) {
				PrintConsole(game, "Focus lost, autopausing...");
				PauseExecution(game);
			}
			break;

		case ALLEGRO_EVENT_DISPLAY_SWITCH_IN:
			if (game->config.autopause) {
				if (game->config.debug.enabled && game->config.debug.livereload) {
					ReloadCode(game);
				}
				ResumeExecution(game);
			}
			break;

		case ALLEGRO_EVENT_DISPLAY_RESIZE:
			PrintConsole(game, "Resize event: %dx%d", ev->display.width, ev->display.height);

#ifdef LIBSUPERDERPY_IMGUI
			ImGui_ImplAllegro5_InvalidateDeviceObjects();
#endif
			al_acknowledge_resize(game->display);
#ifdef LIBSUPERDERPY_IMGUI
			ImGui_ImplAllegro5_CreateDeviceObjects();
#endif

			// SetupViewport can be expensive, so don't do it when the resize event is already outdated or doesn't change anything
			if (((ev->display.width != game->_priv.window_width) || (ev->display.height != game->_priv.window_height)) &&
				(ev->display.width == al_get_display_width(game->display)) && (ev->display.height == al_get_display_height(game->display))) {
				SetupViewport(game);
			}

			break;
		case ALLEGRO_EVENT_KEY_DOWN:
#ifdef ALLEGRO_ANDROID
			if ((ev->keyboard.keycode == ALLEGRO_KEY_MENU) || (ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) {
#else
			if ((ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) {
#endif
				game->_priv.showconsole = !game->_priv.showconsole;
				if ((ev->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL) && (game->config.debug.enabled)) {
					game->_priv.showtimeline = game->_priv.showconsole;
				}
			}

			if (ev->keyboard.keycode == ALLEGRO_KEY_F12) {
				DrawGamestates(game);
				int flags = al_get_new_bitmap_flags();
				al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
				ALLEGRO_BITMAP* bitmap = al_create_bitmap(al_get_display_width(game->display), al_get_display_height(game->display));
				al_set_new_bitmap_flags(flags);
				ALLEGRO_BITMAP* target = al_get_target_bitmap();
				al_set_target_bitmap(bitmap);
				al_draw_bitmap(al_get_backbuffer(game->display), 0, 0, 0);
				al_set_target_bitmap(target);
				PrintConsole(game, "Screenshot made! Storing...");

				struct ScreenshotThreadData* data = malloc(sizeof(struct ScreenshotThreadData));
				data->game = game;
				data->bitmap = bitmap;
#ifndef LIBSUPERDERPY_SINGLE_THREAD
				al_run_detached_thread(ScreenshotThread, data);
#else
				ScreenshotThread(data);
#endif
			}

			break;
		default:
			break;
	}

#ifdef MAEMO5
	// on Maemo we get mouse events instead of touch ones, so we'll rewrite them by ourselves

	if ((ev->type == ALLEGRO_EVENT_MOUSE_AXES) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)) {
		switch (ev->type) {
			case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
				ev->type = ALLEGRO_EVENT_TOUCH_BEGIN;
				break;
			case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
				ev->type = ALLEGRO_EVENT_TOUCH_END;
				break;
			case ALLEGRO_EVENT_MOUSE_AXES:
				ev->type = ALLEGRO_EVENT_TOUCH_MOVE;
				break;
			default:
				break;
		}
		ALLEGRO_DISPLAY* display = ev->mouse.display;
		float dx = ev->mouse.dx;
		float dy = ev->mouse.dy;
		float x = ev->mouse.x;
		float y = ev->mouse.y;
		double timestamp = ev->mouse.timestamp;

		ev->touch.display = display;
		ev->touch.dx = dx;
		ev->touch.dy = dy;
		ev->touch.id = 0;
		ev->touch.primary = true;
		ev->touch.source = (ALLEGRO_TOUCH_INPUT*)al_get_touch_input_event_source();
		ev->touch.timestamp = timestamp;
		ev->touch.x = x;
		ev->touch.y = y;
	}
#endif
}

static inline void HandleDebugEvent(struct Game* game, ALLEGRO_EVENT* ev) {
	switch (ev->type) {
		case ALLEGRO_EVENT_KEY_DOWN:
			switch (ev->keyboard.keycode) {
				case ALLEGRO_KEY_F1:
					if (!game->_priv.paused) {
						PauseExecution(game);
					} else {
						ReloadCode(game);
						ResumeExecution(game);
					}
					break;
				case ALLEGRO_KEY_F9:
					game->_priv.speed = ALLEGRO_BPS_TO_SECS(60.0);
					game->_priv.showconsole = true;
					PrintConsole(game, "DEBUG: Gameplay speed: 1.00x");
					break;
				case ALLEGRO_KEY_F10: {
					double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting
					speed -= 10;
					if (speed < 10) { speed = 10; }
					game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed);
					game->_priv.showconsole = true;
					PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0);
				} break;
				case ALLEGRO_KEY_F11: {
					double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting
					speed += 10;
					if (speed > 600) { speed = 600; }
					game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed);
					game->_priv.showconsole = true;
					PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0);
				} break;
			}

			break;
		default:
			break;
	}
}

static inline bool MainloopEvents(struct Game* game) {
	do {
		ALLEGRO_EVENT ev;

		if (game->_priv.paused && !IS_EMSCRIPTEN) {
			// there's no frame flipping when paused, so avoid pointless busylooping
			al_wait_for_event(game->_priv.event_queue, &ev);
		} else if (!al_get_next_event(game->_priv.event_queue, &ev)) {
			break;
		}

#ifdef LIBSUPERDERPY_IMGUI
		ImGui_ImplAllegro5_ProcessEvent(&ev);
		switch (ev.type) {
			case ALLEGRO_EVENT_KEY_CHAR:
			case ALLEGRO_EVENT_KEY_DOWN:
			case ALLEGRO_EVENT_KEY_UP:
				if (igGetIO()->WantCaptureKeyboard) {
					continue;
				}
				break;
			case ALLEGRO_EVENT_MOUSE_AXES:
			case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
			case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
			case ALLEGRO_EVENT_TOUCH_BEGIN:
			case ALLEGRO_EVENT_TOUCH_CANCEL:
			case ALLEGRO_EVENT_TOUCH_END:
			case ALLEGRO_EVENT_TOUCH_MOVE:
				if (igGetIO()->WantCaptureMouse) {
					continue;
				}
				break;
			default:
				break;
		}
#endif

		if (game->_priv.params.handlers.event) {
			if ((*game->_priv.params.handlers.event)(game, &ev)) {
				continue;
			}
		}

		if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			EventGamestates(game, &ev);
			return false;
		}

		HandleEvent(game, &ev);

		if (game->config.debug.enabled) {
			HandleDebugEvent(game, &ev);
		}

		EventGamestates(game, &ev);

	} while (!al_is_event_queue_empty(game->_priv.event_queue));
	return true;
}

static inline bool MainloopTick(struct Game* game) {
	if (game->_priv.paused) {
		return true;
	}

	struct Gamestate* tmp = game->_priv.gamestates;

#ifdef __EMSCRIPTEN__
	emscripten_pause_main_loop();
#endif

	game->_priv.loading.to_load = 0;
	game->_priv.loading.loaded = 0;
	game->_priv.loading.lock = true;
	game->loading.progress = 0;

	// TODO: support gamestate dependences/ordering
	while (tmp) {
		if (tmp->pending_stop) {
			PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
			game->_priv.current_gamestate = tmp;
			(*tmp->api->stop)(game, tmp->data);
			tmp->started = false;
			tmp->pending_stop = false;
			PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name);
		}

		if (tmp->pending_load) { game->_priv.loading.to_load++; }
		tmp = tmp->next;
	}

	tmp = game->_priv.gamestates;

	while (tmp) {
		if (tmp->pending_unload) {
#ifdef __EMSCRIPTEN__
			al_detach_voice(game->audio.v);
#endif
			PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
			tmp->loaded = false;
			tmp->pending_unload = false;
			game->_priv.current_gamestate = tmp;
			(*tmp->api->unload)(game, tmp->data);
			PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name);
#ifdef __EMSCRIPTEN__
			al_attach_mixer_to_voice(game->audio.mixer, game->audio.v);
#endif
		}
		if (tmp->pending_load) {
#ifdef __EMSCRIPTEN__
			al_detach_voice(game->audio.v);
#endif
			if (tmp->show_loading && game->_priv.loading.gamestate->open) {
				(*game->_priv.loading.gamestate->api->start)(game, game->_priv.loading.gamestate->data);
			}

			if (!tmp->api) {
				if (!OpenGamestate(game, tmp, true) || !LinkGamestate(game, tmp)) {
					tmp->pending_load = false;
					tmp->pending_start = false;
					continue;
				}
			}
			if (tmp->api) {
				PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
				game->_priv.loading.progress = 0;

				game->_priv.loading.current = tmp;
				game->_priv.current_gamestate = tmp;

				struct GamestateLoadingThreadData data = {.game = game, .gamestate = tmp, .bitmap_flags = al_get_new_bitmap_flags()};
				game->_priv.loading.in_progress = true;
				double time = al_get_time();
				game->_priv.loading.time = time;

				CalculateProgress(game);
				if (tmp->show_loading) {
					game->loading.shown = true;
					DrawGamestates(game);
					DrawConsole(game);
					al_flip_display();
#ifdef __EMSCRIPTEN__
					emscripten_sleep(0);
#endif
				}
#ifndef LIBSUPERDERPY_SINGLE_THREAD
				al_run_detached_thread(GamestateLoadingThread, &data);
				while (game->_priv.loading.in_progress) {
					double delta = al_get_time() - game->_priv.loading.time;
					game->time += delta; // TODO: ability to disable passing time during loading
					game->_priv.loading.time += delta;
					if (game->loading.shown && game->_priv.loading.gamestate->open) {
						(*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta);
					}
					DrawGamestates(game);
					if (game->_priv.texture_sync) {
						al_convert_memory_bitmaps();
						game->_priv.texture_sync = false;
						al_signal_cond(game->_priv.texture_sync_cond);
						game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading
					}
					DrawConsole(game);
					al_flip_display();

					if (game->_priv.bsod_sync) {
						al_set_target_bitmap(NULL);
						game->_priv.bsod_sync = false;
						al_signal_cond(game->_priv.bsod_cond);
					}

					al_lock_mutex(game->_priv.bsod_mutex);
					while (game->_priv.in_bsod) {
						al_wait_cond(game->_priv.bsod_cond, game->_priv.bsod_mutex);
					}
					al_unlock_mutex(game->_priv.bsod_mutex);
				}
#else
				GamestateLoadingThread(&data);
				DrawGamestates(game);
				DrawConsole(game);
				al_flip_display();
#ifdef __EMSCRIPTEN__
				emscripten_sleep(0);
#endif
				al_convert_memory_bitmaps();
#endif

				al_set_new_bitmap_flags(data.bitmap_flags);

				ReloadShaders(game, false);

				if (tmp->api->post_load) {
					PrintConsole(game, "[%s] Post-loading...", tmp->name);
					tmp->api->post_load(game, tmp->data);
				}

				game->_priv.loading.progress++;
				CalculateProgress(game);
				PrintConsole(game, "Gamestate \"%s\" loaded successfully in %f seconds.", tmp->name, al_get_time() - time);
				game->_priv.loading.loaded++;

				DrawGamestates(game);
				DrawConsole(game);
				al_flip_display();
#ifdef __EMSCRIPTEN__
				emscripten_sleep(0);
#endif

				tmp->loaded = true;
				tmp->pending_load = false;
			}
			if (tmp->show_loading && game->_priv.loading.gamestate->open) {
				(*game->_priv.loading.gamestate->api->stop)(game, game->_priv.loading.gamestate->data);
			}
			tmp->show_loading = true;
			game->loading.shown = false;
			game->_priv.timestamp = al_get_time();
#ifdef __EMSCRIPTEN__
			al_attach_mixer_to_voice(game->audio.mixer, game->audio.v);
#endif
		}

		tmp = tmp->next;
	}
Ejemplo n.º 15
0
Archivo: main.c Proyecto: dos1/bttbw
int main(int argc, char **argv){
	signal(SIGSEGV, derp);

	srand(time(NULL));

	al_set_org_name("Super Derpy");
    al_set_app_name("Back to the Browser Wars");

       #ifdef ALLEGRO_MACOSX
       char exe_path[MAXPATHLEN];
       char link_path[MAXPATHLEN];

       uint32_t size = sizeof(exe_path);
       _NSGetExecutablePath(exe_path, &size);
       realpath(exe_path, link_path);
       chdir(link_path);
       #endif

	if(!al_init()) {
		fprintf(stderr, "failed to initialize allegro!\n");
		return -1;
	}

	struct Game game;

	InitConfig(&game);

	game._priv.fps_count.frames_done = 0;
	game._priv.fps_count.fps = 0;
	game._priv.fps_count.old_time = 0;

	game._priv.font_bsod = NULL;
	game._priv.console = NULL;

	game.config.fullscreen = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fullscreen", "0"));
	game.config.music = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "music", "10"));
	game.config.voice = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "voice", "10"));
	game.config.fx = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fx", "10"));
	game.config.debug = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "debug", "0"));
	game.config.width = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "width", "1280"));
	if (game.config.width<320) game.config.width=320;
	game.config.height = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "height", "720"));
	if (game.config.height<180) game.config.height=180;

	if(!al_init_image_addon()) {
		fprintf(stderr, "failed to initialize image addon!\n");
		/*al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
															 NULL, ALLEGRO_MESSAGEBOX_ERROR);*/
		return -1;
	}

	if(!al_init_acodec_addon()){
		fprintf(stderr, "failed to initialize audio codecs!\n");
		return -1;
	}

	if(!al_install_audio()){
		fprintf(stderr, "failed to initialize audio!\n");
		return -1;
	}

	if(!al_install_keyboard()){
		fprintf(stderr, "failed to initialize keyboard!\n");
		return -1;
	}

	if(!al_init_primitives_addon()){
		fprintf(stderr, "failed to initialize primitives!\n");
		return -1;
	}

    if(!al_install_mouse()) {
        fprintf(stderr, "failed to initialize the mouse!\n");
        return -1;
    }
	
	al_init_font_addon();

	if(!al_init_ttf_addon()){
		fprintf(stderr, "failed to initialize fonts!\n");
		return -1;
	}

	if (game.config.fullscreen) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
	else al_set_new_display_flags(ALLEGRO_WINDOWED);
	al_set_new_display_option(ALLEGRO_VSYNC, 2-atoi(GetConfigOptionDefault(&game, "SuperDerpy", "vsync", "1")), ALLEGRO_SUGGEST);
	al_set_new_display_option(ALLEGRO_OPENGL, atoi(GetConfigOptionDefault(&game, "SuperDerpy", "opengl", "1")), ALLEGRO_SUGGEST);
#ifdef ALLEGRO_WINDOWS
	al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
#endif

	game.display = al_create_display(game.config.width, game.config.height);
	if(!game.display) {
		fprintf(stderr, "failed to create display!\n");
		return -1;
	}

	SetupViewport(&game);

	PrintConsole(&game, "Viewport %dx%d", game.viewport.width, game.viewport.height);

    ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/bttbw.png"));
	al_set_window_title(game.display, "Back to the Browser Wars");
	al_set_display_icon(game.display, icon);
	al_destroy_bitmap(icon);

    if (game.config.fullscreen) al_hide_mouse_cursor(game.display);
    al_inhibit_screensaver(true);

	al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);

	game._priv.gamestates = NULL;

	game._priv.event_queue = al_create_event_queue();
	if(!game._priv.event_queue) {
		FatalError(&game, true, "Failed to create event queue.");
		al_destroy_display(game.display);
		return -1;
	}

	game.audio.v = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
	game.audio.mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	game.audio.fx = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	game.audio.music = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	game.audio.voice = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
	al_attach_mixer_to_voice(game.audio.mixer, game.audio.v);
	al_attach_mixer_to_mixer(game.audio.fx, game.audio.mixer);
	al_attach_mixer_to_mixer(game.audio.music, game.audio.mixer);
	al_attach_mixer_to_mixer(game.audio.voice, game.audio.mixer);
	al_set_mixer_gain(game.audio.fx, game.config.fx/10.0);
	al_set_mixer_gain(game.audio.music, game.config.music/10.0);
	al_set_mixer_gain(game.audio.voice, game.config.voice/10.0);

	al_register_event_source(game._priv.event_queue, al_get_display_event_source(game.display));
    al_register_event_source(game._priv.event_queue, al_get_mouse_event_source());
    al_register_event_source(game._priv.event_queue, al_get_keyboard_event_source());

	game._priv.showconsole = game.config.debug;

	al_clear_to_color(al_map_rgb(0,0,0));
	game._priv.timer = al_create_timer(ALLEGRO_BPS_TO_SECS(60)); // logic timer
	if(!game._priv.timer) {
		FatalError(&game, true, "Failed to create logic timer.");
		return -1;
	}
	al_register_event_source(game._priv.event_queue, al_get_timer_event_source(game._priv.timer));

	al_flip_display();
	al_start_timer(game._priv.timer);

	setlocale(LC_NUMERIC, "C");

	game.shuttingdown = false;
	game.restart = false;

    game.mediator.lives = 3;
    game.mediator.score = 0;
    game.mediator.modificator = 1;

    game.mediator.heart = CreateCharacter(&game, "heart");
    RegisterSpritesheet(&game, game.mediator.heart, "heart");
    RegisterSpritesheet(&game, game.mediator.heart, "blank");
    LoadSpritesheets(&game, game.mediator.heart);
    SelectSpritesheet(&game, game.mediator.heart, "heart");

	char* gamestate = strdup("dosowisko"); // FIXME: don't hardcore gamestate

	int c;
	while ((c = getopt (argc, argv, "l:s:")) != -1)
		switch (c) {
			case 'l':
				free(gamestate);
				gamestate = strdup("levelX");
				gamestate[5] = optarg[0];
				break;
			case 's':
				free(gamestate);
				gamestate = strdup(optarg);
				break;
		}

	LoadGamestate(&game, gamestate);
    game._priv.gamestates->showLoading = false; // we have only one gamestate right now
    StartGamestate(&game, gamestate);
	free(gamestate);

	char libname[1024] = {};
    snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENTION, "bttbw");
	void *handle = dlopen(libname, RTLD_NOW);
	if (!handle) {
		FatalError(&game, true, "Error while initializing loading screen %s", dlerror());
		exit(1);
	} else {

		#define GS_LOADINGERROR FatalError(&game, true, "Error on resolving loading symbol: %s", dlerror()); exit(1);

		if (!(game._priv.loading.Draw = dlsym(handle, "Draw"))) { GS_LOADINGERROR; }
		if (!(game._priv.loading.Load = dlsym(handle, "Load"))) { GS_LOADINGERROR; }
		if (!(game._priv.loading.Start = dlsym(handle, "Start"))) { GS_LOADINGERROR; }
		if (!(game._priv.loading.Stop = dlsym(handle, "Stop"))) { GS_LOADINGERROR; }
		if (!(game._priv.loading.Unload = dlsym(handle, "Unload"))) { GS_LOADINGERROR; }
	}

	game._priv.loading.data = (*game._priv.loading.Load)(&game);

	bool redraw = false;

	while(1) {
		ALLEGRO_EVENT ev;
		if (redraw && al_is_event_queue_empty(game._priv.event_queue)) {

			struct Gamestate *tmp = game._priv.gamestates;
			int toLoad = 0, loaded = 0;

			// FIXME: move to function
			// TODO: support dependences
			while (tmp) {
				if ((tmp->pending_start) && (tmp->started)) {
					PrintConsole(&game, "Stopping gamestate \"%s\"...", tmp->name);
					(*tmp->api.Gamestate_Stop)(&game, tmp->data);
					tmp->started = false;
					tmp->pending_start = false;
				}

				if ((tmp->pending_load) && (!tmp->loaded)) toLoad++;
				tmp=tmp->next;
			}

			tmp = game._priv.gamestates;
			// FIXME: move to function
			// TODO: support dependences

			double t = -1;

			while (tmp) {
				if ((tmp->pending_load) && (tmp->loaded)) {
					PrintConsole(&game, "Unloading gamestate \"%s\"...", tmp->name);
					al_stop_timer(game._priv.timer);
					tmp->loaded = false;
					tmp->pending_load = false;
					(*tmp->api.Gamestate_Unload)(&game, tmp->data);
					dlclose(tmp->handle);
					tmp->handle = NULL;
					al_start_timer(game._priv.timer);
				} else if ((tmp->pending_load) && (!tmp->loaded)) {
					PrintConsole(&game, "Loading gamestate \"%s\"...", tmp->name);
					al_stop_timer(game._priv.timer);
					// TODO: take proper game name
					char libname[1024];
                    snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENTION, "bttbw", tmp->name);
					tmp->handle = dlopen(libname,RTLD_NOW);
					if (!tmp->handle) {
						//PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
						FatalError(&game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());

						tmp->pending_load = false;
						tmp->pending_start = false;
					} else {

#define GS_ERROR FatalError(&game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue;

						if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; }

						if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; }

						if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; }
						if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; }

						if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; }

						int p = 0;

						void progress(struct Game *game) {
							p++;
							DrawGamestates(game);
							float progress = ((p / (*(tmp->api.Gamestate_ProgressCount) ? (float)*(tmp->api.Gamestate_ProgressCount) : 1))/(float)toLoad)+(loaded/(float)toLoad);
							if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), p, *(tmp->api.Gamestate_ProgressCount));
							if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress);
							DrawConsole(game);
							if (al_get_time() - t >= 1/60.0) {
								al_flip_display();
							}
							t = al_get_time();
						}

						t = al_get_time();

						// initially draw loading screen with empty bar
						DrawGamestates(&game);
						if (tmp->showLoading) {
                            (*game._priv.loading.Draw)(&game, game._priv.loading.data, loaded/(float)toLoad);
						}
						DrawConsole(&game);
						if (al_get_time() - t >= 1/60.0) {
							al_flip_display();
						}
						t = al_get_time();
						tmp->data = (*tmp->api.Gamestate_Load)(&game, &progress); // feel free to replace "progress" with empty function if you want to compile with clang
						loaded++;

						tmp->loaded = true;
						tmp->pending_load = false;
					}
					al_start_timer(game._priv.timer);
				}

				tmp=tmp->next;
			}

			bool gameActive = false;
			tmp=game._priv.gamestates;

			while (tmp) {

				if ((tmp->pending_start) && (!tmp->started) && (tmp->loaded)) {
					PrintConsole(&game, "Starting gamestate \"%s\"...", tmp->name);
					al_stop_timer(game._priv.timer);
					(*tmp->api.Gamestate_Start)(&game, tmp->data);
					al_start_timer(game._priv.timer);
					tmp->started = true;
					tmp->pending_start = false;
				}

				if ((tmp->started) || (tmp->pending_start) || (tmp->pending_load)) gameActive = true;
				tmp=tmp->next;
			}

			if (!gameActive) {
				PrintConsole(&game, "No gamestates left, exiting...");
				break;
			}

			DrawGamestates(&game);
			DrawConsole(&game);
			al_flip_display();
			redraw = false;

		} else {