Beispiel #1
0
////////////////////////////////////////////////////////////////////////////////
// A helper function for loading an Allegro dat file where cursors are
// supposed to be stored.
MAS::Error MAS::Skin::LoadCursors(ALLEGRO_PATH *dir, ALLEGRO_CONFIG *config) {
   if (!dir || !al_is_path_present(dir)) {
      return Error(Error::NO_FILE);
   }

   MAS::Cursor::ReadSkinData(config);

   al_set_path_filename(dir, al_get_path_component(dir, -1));
   al_set_path_extension(dir, ".ini");
   const char *config_path_t = al_path_cstr(dir, ALLEGRO_NATIVE_PATH_SEP);
   ALLEGRO_CONFIG *mouse_config = al_load_config_file(config_path_t);

   int i;
   char tmp[256];
   char *config_path = strdup(config_path_t);
   int x, y, frames, interval;
   const char *str;

   // Look for each bitmap inside the dat file and load it if it exists
   for (i=0; i<nCursors; i++) {
      al_set_path_filename(dir, cursorName[i]);
      al_set_path_extension(dir, ".png");
      const char *fullPath = al_path_cstr(dir, ALLEGRO_NATIVE_PATH_SEP);
      Bitmap bmp;
      if (bmp.Load(fullPath, Bitmap::MEMORY) == Error::NONE) {
         snprintf(tmp, 256, "%s_FCSX", cursorName[i]);
         x = (str = al_get_config_value(mouse_config, "HOTSPOTS", tmp)) ? strtol(str, NULL, 10) : 0;

         snprintf(tmp, 256, "%s_FCSY", cursorName[i]);
         y = (str = al_get_config_value(mouse_config, "HOTSPOTS", tmp)) ? strtol(str, NULL, 10) : 0;

         snprintf(tmp, 256, "%s_FRMS", cursorName[i]);
         frames = (str = al_get_config_value(mouse_config, "HOTSPOTS", tmp)) ? strtol(str, NULL, 10) : 1;

         snprintf(tmp, 256, "%s_FDUR", cursorName[i]);
         interval = (str = al_get_config_value(mouse_config, "HOTSPOTS", tmp)) ? strtol(str, NULL, 10) : 20;

         curList[i]->Create(bmp, frames);
         curList[i]->SetFocus(x, y);
         curList[i]->SetAnimationInterval(interval);
      }
   }

   al_set_path_filename(dir, "");
   free(config_path);
   al_destroy_config(mouse_config);

   return Error(Error::NONE);
}
Beispiel #2
0
////////////////////////////////////////////////////////////////////////////////
// A helper function for loading an Allegro dat file where samples are
// supposed to be stored.
MAS::Error MAS::Skin::LoadSamples(ALLEGRO_PATH *dir) {
   if (!dir || !al_is_path_present(dir))
      return Error(Error::NO_FILE);

   int i;

   const char *sampleName[] = {
      "SAMPLE_ACTIVATE",
      "SAMPLE_CLOSE",
      "SAMPLE_GOTFOCUS",
      "SAMPLE_KEY",
      "SAMPLE_LOSTFOCUS",
      "SAMPLE_OPEN",
      "SAMPLE_SCROLL"
   };

   // Look for each sample inside the dat file and load it if it exists
   for (i=0; i<nSamples; i++) {
      al_set_path_filename(dir, sampleName[i]);
	  al_set_path_extension(dir, ".wav");
      const char *fullPath = al_path_cstr(dir, ALLEGRO_NATIVE_PATH_SEP);
      Sample spl;
      if (spl.Load(fullPath) == Error::NONE) {
         smpList[i]->Set(spl, true);
      }
   }

   al_set_path_filename(dir, "");

   return Error(Error::NONE);
}
Beispiel #3
0
////////////////////////////////////////////////////////////////////////////////
// A helper function for loading an Allegro dat file where bitmaps are
// supposed to be stored.
MAS::Error MAS::Skin::LoadData(ALLEGRO_PATH *dir, ALLEGRO_CONFIG *config) {
   if (!dir || !al_is_path_present(dir) || !al_get_path_filename(dir)) {
      return Error(Error::SKIN_DAT);
   }

   // load the datafile
   int i;
   char tmp[256];
   const char *str;

   // Look for each bitmap inside and load it if it exists
   for (i=0; i<nBitmaps; i++) {
      al_set_path_filename(dir, bitmapName[i]);
	  al_set_path_extension(dir, ".png");
      const char *fullPath = al_path_cstr(dir, ALLEGRO_NATIVE_PATH_SEP);
      Bitmap bmp;
      if (bmp.Load(fullPath, Bitmap::MEMORY) == Error::NONE) {
         bmpList[i]->Set(bmp, true, MAS::Settings::useVideoMemory ? Bitmap::VIDEO : Bitmap::MEMORY);

         snprintf(tmp, 256, "%s_TCKX", bitmapName[i]);
         bmpList[i]->ThickX((str = al_get_config_value(config, "TILING", tmp)) ? strtol(str, NULL, 10) : -1);
         snprintf(tmp, 256, "%s_TCKY", bitmapName[i]);
         bmpList[i]->ThickY((str = al_get_config_value(config, "TILING", tmp)) ? strtol(str, NULL, 10) : -1);
      }
   }

   al_set_path_filename(dir, "");

   return Error(Error::NONE);
}
Beispiel #4
0
static int allua_Path_set_extension(lua_State * L)
{
   ALLUA_path path = allua_check_path(L, 1);
   const char *s = luaL_checkstring(L, 2);

   lua_pushboolean(L, al_set_path_extension(path, s));

   return 1;
}
Beispiel #5
0
	void Map::SaveMapDialog()
	{
		ALLEGRO_FILECHOOSER *saveDialog;
		saveDialog = al_create_native_file_dialog("..\\Maps\\", "Save Map", "*.*", ALLEGRO_FILECHOOSER_SAVE);
		al_show_native_file_dialog(display_, saveDialog);
		mapPath_ = al_create_path(al_get_native_file_dialog_path(saveDialog,0));
		if(strcmp(al_get_path_extension(mapPath_),"") == 0)
		{
			al_set_path_extension(mapPath_, ".mapa");
		}
		SaveMap();
		al_destroy_native_file_dialog(saveDialog);
	}
Beispiel #6
0
void mapper_tilemap_logic(void)
{
	int i, j;
	T3F_TILEMAP_LAYER * new_layer = NULL;
	ALLEGRO_PATH * temp_path = NULL;
	const char * fn = NULL;
	int mx, my;

	if(t3f_key[ALLEGRO_KEY_F3])
	{
		fn = select_file(mapper_last_level_filename, "Open Tilemap", "*.*;*.t3m", ALLEGRO_FILECHOOSER_FILE_MUST_EXIST);
		if(fn)
		{
			if(mapper_tilemap)
			{
				t3f_destroy_tilemap(mapper_tilemap);
			}
			mapper_tilemap = t3f_load_tilemap(fn);
			strcpy(mapper_last_level_filename, fn);
		}
		t3f_key[ALLEGRO_KEY_F3] = 0;
	}
	if(t3f_key[ALLEGRO_KEY_F4])
	{
		if(mapper_tilemap)
		{
			t3f_destroy_tilemap(mapper_tilemap);
		}
		mapper_tilemap = t3f_create_tilemap(mapper_map_width, mapper_map_height, mapper_map_layers);
		t3f_key[ALLEGRO_KEY_F4] = 0;
	}
	if(mapper_tilemap)
	{
		if(t3f_key[ALLEGRO_KEY_F2])
		{
			fn = select_file(mapper_last_level_filename, "Save Tilemap", "*.*;*.t3m", ALLEGRO_FILECHOOSER_SAVE);
			if(fn)
			{
				temp_path = al_create_path(fn);
				if(temp_path)
				{
					al_set_path_extension(temp_path, ".t3m");
					t3f_save_tilemap(mapper_tilemap, al_path_cstr(temp_path, '/'));
					strcpy(mapper_last_level_filename, al_path_cstr(temp_path, '/'));
					al_destroy_path(temp_path);
				}
			}
			t3f_key[ALLEGRO_KEY_F2] = 0;
		}
		mapper_tilemap_move_logic();
		if(t3f_key[ALLEGRO_KEY_MINUS])
		{
			mapper_current_tile--;
			if(mapper_current_tile < 0)
			{
				mapper_current_tile = mapper_tileset->tiles - 1;
			}
			t3f_key[ALLEGRO_KEY_MINUS] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_EQUALS])
		{
			mapper_current_tile++;
			if(mapper_current_tile >= mapper_tileset->tiles)
			{
				mapper_current_tile = 0;
			}
			t3f_key[ALLEGRO_KEY_EQUALS] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_PGUP])
		{
			if(t3f_key[ALLEGRO_KEY_LCTRL] && mapper_current_layer < mapper_tilemap->layers - 1)
			{
				new_layer = mapper_tilemap->layer[mapper_current_layer + 1];
				mapper_tilemap->layer[mapper_current_layer + 1] = mapper_tilemap->layer[mapper_current_layer];
				mapper_tilemap->layer[mapper_current_layer] = new_layer;
			}
			mapper_current_layer++;
			if(mapper_current_layer >= mapper_tilemap->layers)
			{
				mapper_current_layer = 0;
			}
			t3f_key[ALLEGRO_KEY_PGUP] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_PGDN])
		{
			if(t3f_key[ALLEGRO_KEY_LCTRL] && mapper_current_layer > 0)
			{
				new_layer = mapper_tilemap->layer[mapper_current_layer - 1];
				mapper_tilemap->layer[mapper_current_layer - 1] = mapper_tilemap->layer[mapper_current_layer];
				mapper_tilemap->layer[mapper_current_layer] = new_layer;
			}
			mapper_current_layer--;
			if(mapper_current_layer < 0)
			{
				mapper_current_layer = mapper_tilemap->layers - 1;
			}
			t3f_key[ALLEGRO_KEY_PGDN] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_PAD_MINUS])
		{
			mapper_tilemap->layer[mapper_current_layer]->z -= 1.0;
		}
		if(t3f_key[ALLEGRO_KEY_PAD_PLUS])
		{
			mapper_tilemap->layer[mapper_current_layer]->z += 1.0;
		}
		if(t3f_key[ALLEGRO_KEY_PAD_ASTERISK])
		{

			if(t3f_key[ALLEGRO_KEY_LCTRL])
			{
				/* reset the scale and offset of the current layer */
				if(t3f_key[ALLEGRO_KEY_LSHIFT])
				{
					mapper_tilemap->layer[mapper_current_layer]->scale = 1.0;
					mapper_tilemap->layer[mapper_current_layer]->x = 0.0;
					mapper_tilemap->layer[mapper_current_layer]->y = 0.0;
				}
				/* scale the current layer so that the tiles are their actual size at the layer's current z-coordinate */
				else
				{
					mapper_tilemap->layer[mapper_current_layer]->scale = mapper_get_scale(mapper_tilemap->layer[mapper_current_layer]->z);
					mapper_tilemap->layer[mapper_current_layer]->x = mapper_get_offset_x(mapper_tilemap->layer[mapper_current_layer]->z);
					mapper_tilemap->layer[mapper_current_layer]->y = mapper_get_offset_y(mapper_tilemap->layer[mapper_current_layer]->z);
				}
			}
			else
			{
				mapper_tilemap->layer[mapper_current_layer]->z = 0.0;
			}
			t3f_key[ALLEGRO_KEY_PAD_ASTERISK] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_S])
		{
			if(t3f_key[ALLEGRO_KEY_LCTRL])
			{
				mapper_tilemap->layer[mapper_current_layer]->flags ^= T3F_TILEMAP_LAYER_STATIC;
			}
			else
			{
				mapper_tilemap->layer[mapper_current_layer]->flags ^= T3F_TILEMAP_LAYER_SOLID;
			}
			t3f_key[ALLEGRO_KEY_S] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_INSERT] || t3f_key[ALLEGRO_KEY_I])
		{
			if(mapper_tilemap->layers < 32)
			{
				new_layer = t3f_create_tilemap_layer(mapper_tilemap->layer[mapper_current_layer]->width, mapper_tilemap->layer[mapper_current_layer]->height);
				if(new_layer)
				{
					new_layer->x = mapper_tilemap->layer[mapper_current_layer]->x;
					new_layer->y = mapper_tilemap->layer[mapper_current_layer]->y;
					new_layer->z = mapper_tilemap->layer[mapper_current_layer]->z;
					new_layer->scale = mapper_tilemap->layer[mapper_current_layer]->scale;
					new_layer->speed_x = mapper_tilemap->layer[mapper_current_layer]->speed_x;
					new_layer->speed_y = mapper_tilemap->layer[mapper_current_layer]->speed_y;
					if(t3f_key[ALLEGRO_KEY_LCTRL])
					{
						for(i = 0; i < new_layer->height; i++)
						{
							for(j = 0; j < new_layer->width; j++)
							{
								new_layer->data[i][j] = mapper_tilemap->layer[mapper_current_layer]->data[i][j];
							}
						}
					}
					for(i = mapper_tilemap->layers; i > mapper_current_layer; i--)
					{
						mapper_tilemap->layer[i] = mapper_tilemap->layer[i - 1];
					}
					mapper_tilemap->layer[mapper_current_layer] = new_layer;
					mapper_tilemap->layers++;
				}
			}
			t3f_key[ALLEGRO_KEY_INSERT] = 0;
			t3f_key[ALLEGRO_KEY_I] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_DELETE])
		{
			if(mapper_tilemap->layers > 1)
			{
				t3f_destroy_tilemap_layer(mapper_tilemap->layer[mapper_current_layer]);
				for(i = mapper_current_layer; i < mapper_tilemap->layers - 1; i++)
				{
					mapper_tilemap->layer[i] = mapper_tilemap->layer[i + 1];
				}
				mapper_tilemap->layers--;
				if(mapper_current_layer >= mapper_tilemap->layers)
				{
					mapper_current_layer = mapper_tilemap->layers - 1;
				}
			}
			t3f_key[ALLEGRO_KEY_DELETE] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_1])
		{
			mapper_tilemap->layer[mapper_current_layer]->speed_x = 1.0;
			mapper_tilemap->layer[mapper_current_layer]->speed_y = 1.0;
			t3f_key[ALLEGRO_KEY_1] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_C])
		{
			mapper_bg_color = 1 - mapper_bg_color;
			t3f_key[ALLEGRO_KEY_C] = 0;
		}
		mapper_tilemap_hover_x = (int)(t3f_mouse_x + mapper_camera.x - mapper_tilemap->layer[mapper_current_layer]->x) / (mapper_tileset->width * mapper_tilemap->layer[mapper_current_layer]->scale);
		mapper_tilemap_hover_y = (int)(t3f_mouse_y + mapper_camera.y - mapper_tilemap->layer[mapper_current_layer]->y) / (mapper_tileset->height * mapper_tilemap->layer[mapper_current_layer]->scale);
		if(t3f_key[ALLEGRO_KEY_H])
		{
			if(t3f_key[ALLEGRO_KEY_LSHIFT])
			{
				mapper_tilemap_delete_row(mapper_current_layer, mapper_tilemap_hover_y);
			}
			else
			{
				mapper_tilemap_insert_row(mapper_current_layer, mapper_tilemap_hover_y);
			}
			t3f_key[ALLEGRO_KEY_H] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_V])
		{
			if(t3f_key[ALLEGRO_KEY_LSHIFT])
			{
				mapper_tilemap_delete_column(mapper_current_layer, mapper_tilemap_hover_x);
			}
			else
			{
				mapper_tilemap_insert_column(mapper_current_layer, mapper_tilemap_hover_x);
			}
			t3f_key[ALLEGRO_KEY_V] = 0;
		}
		t3f_get_mouse_mickeys(&mx, &my, NULL);
		if(mapper_tilemap_hover_x < 0 || mapper_tilemap_hover_x >= mapper_tilemap->layer[mapper_current_layer]->width || mapper_tilemap_hover_y < 0 || mapper_tilemap_hover_y >= mapper_tilemap->layer[mapper_current_layer]->height)
		{
			mapper_tilemap_hover_fail = true;
		}
		else
		{
			mapper_tilemap_hover_fail = false;
			if(t3f_mouse_button[0])
			{
				if(t3f_key[ALLEGRO_KEY_LCTRL])
				{
					mapper_tilemap->layer[mapper_current_layer]->x -= mx;
					mapper_tilemap->layer[mapper_current_layer]->y -= my;
				}
				else if(t3f_key[ALLEGRO_KEY_LSHIFT])
				{
					for(i = 0; i < mapper_tilemap->layer[mapper_current_layer]->height; i++)
					{
						for(j = 0; j < mapper_tilemap->layer[mapper_current_layer]->width; j++)
						{
							mapper_tilemap->layer[mapper_current_layer]->data[j][i] = mapper_current_tile;
						}
					}
				}
				else
				{
					mapper_tilemap->layer[mapper_current_layer]->data[mapper_tilemap_hover_y][mapper_tilemap_hover_x] = mapper_current_tile;
				}
			}
		}
		mapper_camera.z = mapper_tilemap->layer[mapper_current_layer]->z;
	}
}
Beispiel #7
0
void mapper_tileset_logic(void)
{
	const char * fn = NULL;
	const char * ext = NULL;
	T3F_ANIMATION * ap = NULL;
	ALLEGRO_BITMAP * bp = NULL;
	ALLEGRO_PATH * temp_path = NULL;
	int i;

	if(t3f_key[ALLEGRO_KEY_F3])
	{
		fn = select_file(mapper_last_level_filename, "Open Tileset", "*.*;*.t3t", ALLEGRO_FILECHOOSER_FILE_MUST_EXIST);
		if(fn)
		{
			if(mapper_tileset)
			{
				t3f_destroy_tileset(mapper_tileset);
			}
			mapper_tileset = t3f_load_tileset(fn);
			strcpy(mapper_last_level_filename, fn);
		}
		t3f_key[ALLEGRO_KEY_F3] = 0;
	}
	if(t3f_key[ALLEGRO_KEY_F4])
	{
		if(mapper_tileset)
		{
			t3f_destroy_tileset(mapper_tileset);
		}
		mapper_tileset = t3f_create_tileset(mapper_tile_width, mapper_tile_height);
		t3f_key[ALLEGRO_KEY_F4] = 0;
	}
	if(mapper_tileset)
	{
		if(t3f_key[ALLEGRO_KEY_F2])
		{
			fn = select_file(mapper_last_level_filename, "Save Tileset", "*.*;*.t3t", ALLEGRO_FILECHOOSER_SAVE);
			if(fn)
			{
				temp_path = al_create_path(fn);
				if(temp_path)
				{
					al_set_path_extension(temp_path, ".t3t");
					t3f_save_tileset(mapper_tileset, al_path_cstr(temp_path, '/'));
					strcpy(mapper_last_level_filename, al_path_cstr(temp_path, '/'));
					al_destroy_path(temp_path);
				}
			}
			t3f_key[ALLEGRO_KEY_F2] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_INSERT] || t3f_key[ALLEGRO_KEY_I])
		{
			fn = select_file(mapper_last_filename, "Open Animation", "*.*;*.ani;*.pcx;*.png;*.tga;*.jpg", ALLEGRO_FILECHOOSER_FILE_MUST_EXIST);
			if(fn)
			{
				ext = mapper_get_extension(fn);
				if(!strcmp(ext, "ani"))
				{
					ap = t3f_load_animation(fn);
					if(ap)
					{
						t3f_add_tile(mapper_tileset, ap);
						mapper_current_tile = mapper_tileset->tiles - 1;
					}
				}
				else
				{
					bp = al_load_bitmap(fn);
					if(bp)
					{
						mapper_import_tiles(bp);
					}
					al_destroy_bitmap(bp);
				}
				strcpy(mapper_last_filename, fn);
			}
			t3f_key[ALLEGRO_KEY_INSERT] = 0;
			t3f_key[ALLEGRO_KEY_I] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_ENTER])
		{
			fn = select_file(mapper_last_filename, "Open Animation", "*.*;*.ani;*.pcx;*.png;*.tga;*.jpg", ALLEGRO_FILECHOOSER_FILE_MUST_EXIST);
			if(fn)
			{
				ext = mapper_get_extension(fn);
				if(!strcmp(ext, "t3a"))
				{
					ap = t3f_load_animation(fn);
					if(ap)
					{
						t3f_destroy_animation(mapper_tileset->tile[mapper_current_tile]->ap);
						mapper_tileset->tile[mapper_current_tile]->ap = ap;
					}
				}
				else
				{
					bp = al_load_bitmap(fn);
					if(bp)
					{
						if(al_get_bitmap_width(bp) < mapper_tile_width)
						{
							al_destroy_bitmap(mapper_tileset->tile[mapper_current_tile]->ap->bitmaps->bitmap[0]);
							mapper_tileset->tile[mapper_current_tile]->ap->bitmaps->bitmap[0] = bp;
						}
						else
						{
							mapper_replace_tiles(bp);
						}
					}
					al_destroy_bitmap(bp);
				}
				strcpy(mapper_last_filename, fn);
			}
			t3f_key[ALLEGRO_KEY_ENTER] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_DELETE])
		{
			if(mapper_current_tile < mapper_tileset->tiles)
			{
				t3f_destroy_tile(mapper_tileset->tile[mapper_current_tile]);
				mapper_tilemap_replace_tile(mapper_current_tile, 0);
				for(i = mapper_current_tile; i < mapper_tileset->tiles - 1; i++)
				{
					mapper_tileset->tile[i] = mapper_tileset->tile[i + 1];
					mapper_tilemap_replace_tile(i + 1, i);
				}
				mapper_tileset->tiles--;
			}
			t3f_key[ALLEGRO_KEY_DELETE] = 0;
		}
		if(t3f_key[ALLEGRO_KEY_A])
		{
			mapper_view = MAPPER_VIEW_TILE_ANI;
			t3f_key[ALLEGRO_KEY_A] = 0;
		}
		mapper_hover_tile = ((int)t3f_mouse_y / mapper_tile_height) * (t3f_virtual_display_width / mapper_tile_width) + ((int)t3f_mouse_x / mapper_tile_width) % (t3f_virtual_display_width / mapper_tile_width);
		if(t3f_mouse_button[0] && mapper_hover_tile < mapper_tileset->tiles)
		{
			mapper_current_tile = mapper_hover_tile;
		}
	}
}
Beispiel #8
0
static void * t3f_play_music_thread(void * arg)
{
    const char * ext = NULL;
    ALLEGRO_PATH * path = NULL;
    int loop_points = 0;
    float loop_start = -1;
    float loop_end = -1;
    bool loop_disabled = false;
    const char * val = NULL;
    ALLEGRO_CONFIG * config = NULL;

    ALLEGRO_DEBUG("music thread start\n");
    t3f_music_gain = 1.0;
    al_lock_mutex(t3f_music_mutex);
    if(t3f_stream)
    {
        t3f_stop_music();
    }
    ALLEGRO_DEBUG("setting file interface\n");
    al_set_new_file_interface(t3f_music_thread_file_interface);
    t3f_stream = al_load_audio_stream(t3f_music_thread_fn, 4, 4096);
    if(!t3f_stream)
    {
        al_unlock_mutex(t3f_music_mutex);
        t3f_set_music_state(T3F_MUSIC_STATE_OFF);
        return NULL;
    }

    ALLEGRO_DEBUG("configuring music\n");
    /* look for loop data */
    path = al_create_path(t3f_music_thread_fn);
    if(path)
    {
        al_set_path_extension(path, ".ini");
        config = al_load_config_file(al_path_cstr(path, '/'));
        if(config)
        {
            val = al_get_config_value(config, "loop", "disabled");
            if(val && !strcasecmp(val, "true"))
            {
                loop_disabled = true;
            }
            if(!loop_disabled)
            {
                val = al_get_config_value(config, "loop", "start");
                if(val)
                {
                    loop_start = atof(val);
                    loop_points++;
                }
                val = al_get_config_value(config, "loop", "end");
                if(val)
                {
                    loop_end = atof(val);
                    loop_points++;
                }
            }
            val = al_get_config_value(config, "settings", "gain");
            if(val)
            {
                t3f_music_gain = atof(val);
                if(t3f_music_gain < 0.0)
                {
                    t3f_music_gain = 0;
                }
                if(t3f_music_gain > 10.0)
                {
                    t3f_music_gain = 10.0;
                }
            }
            al_destroy_config(config);
        }
        al_destroy_path(path);
    }

    if(loop_disabled)
    {
        al_set_audio_stream_playmode(t3f_stream, ALLEGRO_PLAYMODE_ONCE);
    }
    else
    {
        if(loop_points != 2)
        {
            /* loop entire song unless audio is MOD music */
            ext = t3f_get_music_extension(t3f_music_thread_fn);
            if(strcmp(ext, ".xm") && strcmp(ext, ".it") && strcmp(ext, ".mod") && strcmp(ext, ".s3m"))
            {
                al_set_audio_stream_loop_secs(t3f_stream, 0.0, al_get_audio_stream_length_secs(t3f_stream));
                al_set_audio_stream_playmode(t3f_stream, ALLEGRO_PLAYMODE_LOOP);
            }
            else
            {
                al_set_audio_stream_playmode(t3f_stream, ALLEGRO_PLAYMODE_LOOP);
            }
        }
        else
        {
            al_set_audio_stream_loop_secs(t3f_stream, loop_start, loop_end);
            al_set_audio_stream_playmode(t3f_stream, ALLEGRO_PLAYMODE_LOOP);
        }
    }
    ALLEGRO_DEBUG("start the music\n");
    t3f_music_volume = t3f_new_music_volume;
    al_set_audio_stream_gain(t3f_stream, t3f_music_volume * t3f_music_gain);
    al_attach_audio_stream_to_mixer(t3f_stream, al_get_default_mixer());
    al_unlock_mutex(t3f_music_mutex);
    t3f_set_music_state(T3F_MUSIC_STATE_PLAYING);
    return NULL;
}