Index: mania_drive.c
===================================================================
--- mania_drive.c	(revision 415)
+++ mania_drive.c	(revision 416)
@@ -89,7 +89,9 @@
 void build_gui_NeedRestart(void);
 void build_gui_Story(void);
 void showMessage(char *file, int id);
+void build_gui_Solo(void);
 
+
 #define NET_SCORE_TRACK	(RAYDIUM_NETWORK_PACKET_BASE+1)
 #define NET_RESTART	(RAYDIUM_NETWORK_PACKET_BASE+2)
 #define NET_CHANGE_MAP	(RAYDIUM_NETWORK_PACKET_BASE+3)
@@ -464,6 +466,18 @@
 }
 
 
+void btnOtherTracksSolo(raydium_gui_Object *w)
+{
+char track[RAYDIUM_MAX_NAME_LEN];
+
+raydium_gui_read_name("menu","cboTrack",track);
+raydium_parser_db_set("ManiaDrive-LastSoloTrack",track);
+
+drive(track);
+mode=MODE_SOLO;
+}
+
+
 void btnBackToMainMenu(raydium_gui_Object *w)
 {
 change_music_volume(music_volume);
@@ -724,6 +738,12 @@
 credits_start();
 }
 
+void btnSoloTracks(raydium_gui_Object *w)
+{
+raydium_gui_window_delete_name("menu");
+build_gui_Solo();
+}
+
 void gui_menu_BestTime(raydium_gui_Object *w)
 {
 char track[RAYDIUM_MAX_NAME_LEN];
@@ -849,7 +869,46 @@
 gui_start();
 }
 
+void build_gui_Solo(void)
+{
+int handle;
+char l[RAYDIUM_GUI_DATASIZE];
+char lasttrack[RAYDIUM_MAX_NAME_LEN];
+int ilt;
 
+handle=raydium_gui_window_create("menu",48,10,50,40);
+
+raydium_parser_db_get("ManiaDrive-LastSoloTrack",lasttrack,"");
+
+raydium_register_variable(l,RAYDIUM_REGISTER_STR,"list");
+raydium_php_exec("mania_localtracks.php");
+raydium_register_variable_unregister_last();
+
+ilt=raydium_gui_list_id(lasttrack,l);
+if(ilt<0) ilt=0;
+
+raydium_gui_widget_sizes(0,0,18);
+raydium_gui_label_create("lblMode",handle,50,90,"- Other Tracks -",0,0,0);
+
+raydium_gui_widget_sizes(0,0,16);
+raydium_gui_label_create("lbl1",handle,50,75,"Here, you can play offline with:",0.7,0,0);
+raydium_gui_label_create("lbl2",handle,50,65,"- User tracks",0.7,0,0);
+raydium_gui_label_create("lbl3",handle,50,55,"- Downloaded internet tracks",0.7,0,0);
+
+raydium_gui_widget_sizes(0,0,18);
+raydium_gui_label_create("lblTrack",handle,24,35,"Track :",0,0,0);
+raydium_gui_widget_sizes(25,4,18);
+raydium_gui_combo_create("cboTrack",handle,37,30,l,ilt);
+
+raydium_gui_widget_sizes(15,5,18);
+raydium_gui_button_create("btnDrive",handle,35,5,"Drive !",btnOtherTracksSolo);
+
+raydium_gui_widget_sizes(6,3,14);
+raydium_gui_button_create("btnBackToMain",handle,5,5,"<",btnBackToMainMenu);
+
+gui_start();
+}
+
 // Return 1 if "filename" story is completed
 signed char build_gui_Story_sub(int handle, char *filename, float x1, float x2, int id)
 {
@@ -947,6 +1006,9 @@
 
 raydium_gui_widget_sizes(6,3,14);
 raydium_gui_button_create("btnBackToMain",handle,5,3,"<",btnBackToMainMenu);
+raydium_gui_widget_sizes(20,4,18);
+raydium_gui_button_create("btnSolo",handle,40,3,"Other tracks",btnSoloTracks);
+
 gui_start();
 
 if(completed && !congrats)
Index: raydium/headers/sound.h
===================================================================
--- raydium/headers/sound.h	(revision 0)
+++ raydium/headers/sound.h	(revision 1)
@@ -0,0 +1,249 @@
+#ifndef _SOUND_H
+#define _SOUND_H
+/*=
+Sound and music
+2600
+**/
+
+// Introduction
+/**
+The Raydium sound API is pretty easy to use and there's only need to use a 
+few functions to make your program ouput sounds or music.
+
+On top of this, there are a bunch of functions to modify the sound behavior.
+
+Raydium uses OpenAL and OggVorbis? for its sounds and musics, for a basic 
+use of our sound API you only need to know one thing: OpenAL uses buffers 
+for its sounds and you need to be able to address the sounds separately.
+For this we use ALuint in our code. Each buffer is associated to a source,
+we have an array of all available sources and then, you only need to have 
+a simple int that acts as an index in this array. See below for more
+informations.
+
+Music is readed thru libogg, streamed from disk. If you want to play an
+OGG audio track, the only thing you've to do is to call the suitable function.
+You can use ##raydium_sound_music_eof_callback## if needed. This event is
+fired when sound track ends, allowing you to switch to another file.
+Prototype for this callback is ##int callback(char *new_track)##, allowing
+you to do something like ##strcpy(new_track,"foobar.ogg"); return 1;##.
+Return 0 if you do not want to switch to another audio file (this will stops
+music playback).
+
+This document is not an alternative to OpenAL papers, and only provides
+informations about Raydium's interface to OpenAL.
+See specifications here: http://www.openal.org/documentation.html
+**/
+
+extern void raydium_sound_verify (char *caller);
+/**
+This functions checks if any error occured during last OpenAL operation.
+You don't have to call this function by yourself, since every function of
+this API will do it.
+**/
+
+extern int raydium_sound_Array3IsValid(ALfloat *a);
+/**
+Since OpenAL is very sensitive to malformed values, this function is used
+internally to check consistency of provided ALfloat arrays.
+**/
+
+extern void raydium_sound_InitSource (int src);
+/**
+Internal use.
+**/
+
+extern int raydium_sound_LoadWav (const char *fname);
+/**
+This function tries to load the ##fname## wav file into a buffer, if 
+successful, it returns the source id, else 0.
+**/
+
+extern int raydium_sound_SourceVerify (int src);
+/**
+Internal id checks.
+**/
+
+extern int raydium_sound_SetSourceLoop (int src, char loop);
+/**
+Modifies the ##loop## property of the ##src## source (loops if loop is non-zero, 
+default value for a source is "true").
+Returns 0 if ok, -1 if error.
+**/
+
+extern int raydium_sound_GetSourcePitch (int src, ALfloat * p);
+/**
+Returns current pitch for ##src## source.
+**/
+
+extern int raydium_sound_SetSourcePitch (int src, ALfloat p);
+/**
+Sets pitch for ##src## source.
+Current OpenAL spec is not clear about pitch's limits. Raydium will 
+clamp values to to ]0,2] interval.
+**/
+
+extern int raydium_sound_GetSourceGain (int src, ALfloat * g);
+/**
+Returns current gain ("volume") for ##src## source.
+**/
+
+extern int raydium_sound_SetSourceGain (int src, ALfloat g);
+/**
+Sets gain ("volume") for ##src## source.
+Current OpenAL spec is not clear about pitch's limits. Raydium do not allows
+negative values, but no upper limit is set.
+Warning: some OpenAL implementations will provide strange gain curves. More
+work is needed on this issue.
+**/
+
+extern int raydium_sound_SetSourcePos (int src, ALfloat Pos[]);
+/**
+Sets 3D position of ##src## source.
+##Pos## is a 3 * ALfloat array.
+**/
+
+extern int raydium_sound_SetSourcePosCamera(int src);
+/**
+Sets 3D position of ##src## source on the current camera position.
+**/
+
+extern int raydium_sound_GetSourcePos (int src, ALfloat * Pos[]);
+/**
+Returns current 3D position of ##src## source.
+##Pos## is a 3 * ALfloat array.
+**/
+
+extern int raydium_sound_SetSourceDir (int src, ALfloat Dir[]);
+/**
+Sets 3D direction of ##src## source.
+##Dir## is a 3 * ALfloat array.
+**/
+
+extern int raydium_sound_GetSourceDir (int src, ALfloat * Dir[]);
+/**
+Returns current 3D direction of ##src## source.
+##Dir## is a 3 * ALfloat array.
+**/
+
+extern int raydium_sound_SetSourceVel (int src, ALfloat Vel[]);
+/**
+Sets 3D velocity of ##src## source.
+##Vel## is a 3 * ALfloat array.
+**/
+
+extern int raydium_sound_GetSourceVel (int src, ALfloat * Vel[]);
+/**
+Returns current 3D velocity of ##src## source.
+##Vel## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_SetListenerPos (ALfloat Pos[]);
+/**
+Sets 3D position of listener.
+This is done automatically by Raydium, each frame, using camera informations
+##Pos## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_GetListenerPos (ALfloat * Pos[]);
+/**
+Returns current 3D position of listener.
+##Pos## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_SetListenerOr (ALfloat Or[]);
+/**
+Sets 3D orientation of listener.
+This is done automatically by Raydium, each frame, using camera informations
+##Or## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_GetListenerOr (ALfloat * Or[]);
+/**
+Returns current 3D orientation of listener.
+##Or## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_SetListenerVel (ALfloat Vel[]);
+/**
+Sets 3D velocity of Listener.
+##Vel## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_GetListenerVel (ALfloat * Vel[]);
+/**
+Returns current 3D velocity of Listener.
+##Vel## is a 3 * ALfloat array.
+**/
+
+extern void raydium_sound_init (void);
+/**
+Internal use.
+**/
+
+extern int raydium_sound_SourcePlay (int src);
+/**
+Plays the ##src## source.
+If ##src## was already in "play" state, the buffer is rewinded.
+Returns 0 if ok, -1 if error.
+**/
+
+extern int raydium_sound_SourceStop (int src);
+/**
+Stops the ##src## source.
+Returns 0 if ok, -1 if error.
+**/
+
+extern int raydium_sound_SourcePause (int src);
+/**
+Will pause the ##src## source.
+Returns 0 if ok, -1 if error.
+**/
+
+extern int raydium_sound_SourceUnpause (int src);
+/**
+##src## will restart playback after being paused.
+Returns 0 if ok, -1 if error.
+**/
+
+extern void raydium_sound_close (void);
+/**
+Internal use.
+**/
+
+extern int BufferData (ALuint buffer, OggVorbis_File * file, vorbis_info * ogginfo);
+extern void raydium_sound_internal_cleanstreambuffs (void);
+extern int StartMusic (ALuint musicsource, ALuint * buffers, OggVorbis_File * file, vorbis_info * ogginfo);
+extern int raydium_sound_load_music (char *fname);
+/**
+Opens fname **OGG** music file and prepairs Raydium for playing it.
+The music will be automatically played after a call to this function.
+This function will use R3S (data repositories) if needed.
+To switch to another audio track, simply call again this function.
+Send ##NULL## or an empty string to cancel music playback.
+Returns 0 if ok, -1 if error
+
+See also ##raydium_sound_music_eof_callback## at the top of this chapter.
+**/
+
+extern void raydium_sound_music_callback (void);
+/**
+Internal use.
+**/
+
+extern void raydium_sound_callback (void);
+/**
+Internal use.
+**/
+
+// Example
+/**
+%%(c)
+int sound;
+sound=raydium_sound_LoadWav("explo.wav");
+raydium_sound_SetSourceLoop(sound,0);
+[...]
+if(explosion) raydium_sound_SourcePlay(sound);
+%%
+**/
+
+#endif
Index: raydium/headers/normal.h
===================================================================
--- raydium/headers/normal.h	(revision 0)
+++ raydium/headers/normal.h	(revision 1)
@@ -0,0 +1,40 @@
+#ifndef _NORMAL_H
+#define _NORMAL_H
+
+/*=
+Normals
+1600
+**/
+
+// Introduction
+/**
+This file provides some usefull functions for normal generation and smoothing.
+You can find some more informations about normals at the top of this guide. 
+**/
+
+
+extern void raydium_normal_generate_lastest_triangle (int default_visu);
+/**
+Generate normal for the last created triangle (see ##raydium_vertex_index##)
+if ##default_visu## is true ( != 0 ), this function will restore "visu" 
+normals too.
+**/
+
+extern void raydium_normal_restore_all (void);
+/**
+This function restore visu normals with standard ones (##raydium_vertex_normal_*##)
+**/
+
+extern void raydium_normal_regenerate_all (void);
+/**
+This function will regenerate standard and visu normals for the whole 
+scene (ground, objects, ...).
+**/
+
+extern void raydium_normal_smooth_all (void);
+/**
+This function will smooth the whole scene, using adjacent vertices.
+Note this function can take a lot of time.
+**/
+
+#endif
Index: raydium/headers/camera.h
===================================================================
--- raydium/headers/camera.h	(revision 0)
+++ raydium/headers/camera.h	(revision 1)
@@ -0,0 +1,173 @@
+#ifndef _CAMERA_H
+#define _CAMERA_H
+
+/*=
+Camera
+2200
+**/
+
+// Introduction
+/**
+Raydium provides camera management functions, allowing the coder to
+move camera with very simple functions, even for complex moves.
+You have to place your camera once per frame (not more, not less).
+
+"look_at" style functions can be affected by ##raydium_camera_look_at_roll##
+global variable, if needed.
+
+A few words about camera path: Take a look to a .cam file if you want to
+understand this simple file format, but you probably only need the ##cam.c##
+application, dedicated to camera path creation.
+
+Some camera functions are provided by physics module, see suitable chapter.
+**/
+
+
+extern void raydium_camera_vectors (GLfloat * res3);
+/**
+This function will return two vectors (2 * 3 * GLfloat), giving the camera 
+orientation (front vector and up vector). At this day, the up vector is 
+always the same as the world up vector, even if the camera is rotated 
+or upside down (and yes, this MUST be corrected :).
+
+Designed for internal uses, before all.
+**/
+
+extern void raydium_camera_internal_prepare(void);
+/**
+Internal use. (pre)
+**/
+
+extern void raydium_camera_internal (GLfloat x, GLfloat y, GLfloat z);
+/**
+Internal use. (post)
+**/
+
+extern void raydium_camera_place (GLfloat x, GLfloat y, GLfloat z, GLfloat lacet, GLfloat tangage, GLfloat roulis);
+/**
+Sets the camera at (x,y,z) position, and using (lacet,tangage,roulis) 
+as rotation angles.
+**/
+
+extern void raydium_camera_look_at (GLfloat x, GLfloat y, GLfloat z, GLfloat x_to, GLfloat y_to, GLfloat z_to);
+/**
+Sets the camera at (x,y,z) position, and looks at (x_to,y_to,z_to).
+**/
+
+extern void raydium_camera_replace (void);
+/**
+You'll need to reset camera position and orientation after each object drawing.
+If this is unclear to you, read the "example" section, below.
+
+You will need to make your own 3D transformations (GLRotate, GLTranslate, 
+...) to draw your objects, or you can use the following function.
+**/
+
+extern void raydium_camera_replace_go (GLfloat * pos, GLfloat * R);
+/**
+This function will replace the camera, as ##raydium_camera_replace()##,
+but will place "3D drawing cursor" at position ##pos## (3 GLfloat) with 
+rotation ##R## (4 GLfloat quaternion).
+
+No eulers (rotx, roty, rotz) version of this function is provided for now.. 
+Do you really need it ?
+**/
+
+// Example of camera use
+/**
+1. place camera
+2. move "drawing cursor" to object's place
+3. draw object
+4. reset camera to initial place (the one given at step 1)
+5. move "drawing cursor" to another object's place
+6. draw another object
+7. [...]
+
+Steps 4 and 5 can be done with raydium_camera_replace_go().
+**/
+
+void raydium_camera_rumble(GLfloat amplitude, GLfloat ampl_evo, GLfloat secs);
+/**
+Camera (any type) will rumble for ##secs## seconds, with ##amplitude## (radians).
+This ##amplitude## will be incremented of ##ampl_evo## every second (negative
+values are allowed).
+An ##amplitude## is always positive.
+**/
+
+extern void raydium_camera_smooth (GLfloat px, GLfloat py, GLfloat pz, GLfloat lx, GLfloat ly, GLfloat lz, GLfloat zoom, GLfloat roll, GLfloat step);
+/**
+Smooth style clone of ##raydium_camera_look_at##.
+Roll is given by ##roll## and not global variable ##raydium_camera_look_at_roll##
+as for regular look_at function.
+##zoom## is the requested FOV.
+Play with step to modify smoothing level of the movement. A good way to use
+this function is the following usage :
+%%(c) raydium_camera_smooth(cam[0],cam[1],cam[2],pos[1],-pos[2],pos[0],70,0,raydium_frame_time*3); %%
+**/
+
+extern void raydium_camera_path_init (int p);
+/**
+Internal use.
+**/
+
+extern void raydium_camera_path_init_all (void);
+/**
+Internal use.
+**/
+
+extern int raydium_camera_path_find (char *name);
+/**
+Lookups path's id using filename ##name##.
+This function will not try to load a camera path if it's not found, and
+will return -1.
+**/
+
+extern int raydium_camera_path_load (char *filename);
+/**
+Obvious : use this function to load a camera path.
+**/
+
+extern void raydium_camera_path_draw (int p);
+/**
+Draws ##p## camera path, as red lines. This must be done at each frame. 
+**/
+
+extern void raydium_camera_path_draw_name (char *path);
+/**
+Same as above, but using camera path's name.
+**/
+
+extern char raydium_camera_smooth_path (char *path, GLfloat step, GLfloat * x, GLfloat * y, GLfloat * z, GLfloat * zoom, GLfloat * roll);
+/**
+Returns the (##x,y,z##) point of the camera path for step ##step##, using
+provided ##zoom## (FOV) and ##roll## angle.
+It's important to note that ##step## is a float.
+Mostly for internal use.
+**/
+
+extern void raydium_camera_path_reset(void);
+/**
+Next smooth call will be instantaneous.
+**/
+
+extern void raydium_camera_smooth_path_to_pos (char *path, GLfloat lx, GLfloat ly, GLfloat lz, GLfloat path_step, GLfloat smooth_step);
+/**
+"Camera on path looking to a point"
+simple ##raydium_camera_smooth## version:
+Give a path name, a "look_at" point (##lx,ly,lz##), a current ##step##, and
+a ##smooth_step## time factor (see ##raydium_camera_smooth## example above).
+**/
+
+extern void raydium_camera_smooth_pos_to_path (GLfloat lx, GLfloat ly, GLfloat lz, char *path, GLfloat path_step, GLfloat smooth_step);
+/**
+"Camera on point looking at a path"
+Same style as previous function.
+**/
+
+extern void raydium_camera_smooth_path_to_path (char *path_from, GLfloat path_step_from, char *path_to, GLfloat path_step_to, GLfloat smooth_step);
+/**
+"Camera on a path looking at another path"
+Same style as previous functions.
+**/
+
+#endif