fusilli-client: add recipe
authorGrazvydas Ignotas <notasas@gmail.com>
Sat, 8 Nov 2014 20:25:02 +0000 (22:25 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sat, 8 Nov 2014 20:25:02 +0000 (22:25 +0200)
recipes/fusilli-client/files/sparrowDefines.h [new file with mode: 0644]
recipes/fusilli-client/files/sparrowNet.c [new file with mode: 0644]
recipes/fusilli-client/files/sparrowNet.h [new file with mode: 0644]
recipes/fusilli-client/fusilli-client_git.bb [new file with mode: 0644]

diff --git a/recipes/fusilli-client/files/sparrowDefines.h b/recipes/fusilli-client/files/sparrowDefines.h
new file mode 100644 (file)
index 0000000..06ad68e
--- /dev/null
@@ -0,0 +1,630 @@
+ /* This file is part of sparrow3d.
+  * Sparrow3d is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation, either version 2 of the License, or
+  * (at your option) any later version.
+  * 
+  * Sparrow3d is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  * 
+  * You should have received a copy of the GNU General Public License
+  * along with Foobar.  If not, see <http://www.gnu.org/licenses/>
+  * 
+  * For feedback and questions about my Files and Projects please mail me,
+  * Alexander Matthes (Ziz) , zizsdl_at_googlemail.com */
+
+/* Title: sparrowDefines
+ * 
+ * SparrowDefines contains many #defines used by the library or which
+ * may be usefull for your application */
+#ifndef _SPARROW_DEFINES_H
+#define _SPARROW_DEFINES_H
+
+/* These are defines for creating or using the library in C or C++ */
+#ifdef WIN32
+       #include <windows.h>
+       #if BUILDING_DLL
+               # define DLLIMPORT __declspec (dllexport)
+       #else /* Not BUILDING_DLL */
+               # define DLLIMPORT __declspec (dllimport)
+       #endif /* Not BUILDING_DLL */
+       #ifdef __cplusplus
+               #define PREFIX extern "C" DLLIMPORT
+       #else
+               #define PREFIX DLLIMPORT
+       #endif
+#else
+       #ifdef __cplusplus
+               #define PREFIX extern "C"
+       #else
+               #define PREFIX
+       #endif
+#endif
+
+/* Defines: Fixed Point Arithmetic Constants
+ * 
+ * The following #defines are for the fixed point arithmetic in
+ * sparrow3d. Change the values only, if you know, what you are doing.
+ * There should be optimal already.
+ * 
+ * SP_ACCURACY - Defines how many bits are used for the decimal place
+ * SP_HALF_ACCURACY - The half of <SP_ACCURACY>
+ * SP_ACCURACY_FACTOR - 2 ^ <SP_ACCURACY>. Needed for float conversation
+ * SP_SQRT_ACCURACY - Accurary of the internal sqrt lookuptable
+ * SP_PI - Fixed point Pi
+ * SP_MATH_ACCURACY - (In)accuracy of the cos and sin lookup table
+ * SP_ONE - 1.0f in fixed point*/
+
+#define SP_ACCURACY 16
+#define SP_HALF_ACCURACY 8
+#define SP_ACCURACY_FACTOR 65536.0f
+#define SP_SQRT_ACCURACY 16
+#define SP_PI 205888
+/* This is not really accuracy... More inaccuracy ^^ */
+#define SP_MATH_ACCURACY 4
+/* a fast define for the fixed point value 1.0 */
+#define SP_ONE 65536
+
+/* Defines: Fixed Point Arithmetics
+ * 
+ * These are some #defines for fast multiplication and division of
+ * fixed point numbers. Use them like normal functions, e.g.
+ * Sint32 a = spMul(b,c); instead of a = b * c (which will not work).
+ * However multiplying a fixed point number with a "normal" integer just works
+ * with the normal multiplication. For addition you have to convert!
+ * 
+ * spMul(a,b) - Multiplies fixed point number a with the fixed point number b
+ * spMulHigh(a,b) - Does the same as <spMul(a,b)>, but with guaranteed high precision
+ * spMulLow(a,b) - Does the same as <spMul(a,b)>, but maybe with lower precision
+ * spDiv(a,b) - Divides fixed point number a with the fixed point number b
+ * spDivHigh(a,b) - Does the same as <spDiv(a,b)>, but with guaranteed high precision
+ * spDivLow(a,b) - Does the same as <spDiv(a,b)>, but maybe with lower precision
+ * spSquare(a) - Squares the fixed point number a with the help of <spMul(a,b)>. */
+#define spMulHigh(a,b) ((Sint64)(a)*(Sint64)(b)>>SP_ACCURACY)
+#define spMulLow(a,b) (((a)>>SP_HALF_ACCURACY)*((b)>>SP_HALF_ACCURACY))
+
+#ifdef FAST_MULTIPLICATION
+       #define spMul(a,b) spMulLow(a,b)
+#else
+       #define spMul(a,b) spMulHigh(a,b)
+#endif
+
+#define spSquare(a) spMul(a,a)
+
+#define spDivHigh(a,b) (((Sint64)(a)<<SP_ACCURACY)/(Sint64)(b))
+/*#define spDivLow(a,b) ((b>=0 && b<(1<<SP_ACCURACY))? \
+                                                                                (a*spGetOne_over_x_pointer()[b]): \
+                                                                                ( \
+                                                                                        (b <0 && b>(-1<<SP_ACCURACY))? \
+                                                                                        (-a*spGetOne_over_x_pointer()[-b]): \
+                                                                                        (((a<<SP_HALF_ACCURACY)/b)<<SP_HALF_ACCURACY) \
+                                                                                ))*/
+#define spDivLow(a,b) (((a<<SP_HALF_ACCURACY)/b)<<SP_HALF_ACCURACY)
+#ifdef FAST_DIVISION
+       #define spDiv(a,b) spDivLow(a,b)
+#else
+       #define spDiv(a,b) spDivHigh(a,b)
+#endif
+
+/* Defines: Fixed Point Conversion
+ * 
+ * These conversions are no function calls, but defines. That means *before* the
+ * compiler compiles the code, it is replaced by the defined rule. E.g., you
+ * want to convert the float a to a fixed point number using spFloatToFixed. You
+ * call
+ * > Sint32 foo = spFloatToFixed(bar);
+ * Internal the compiler will make this:
+ * > Sint32 foo = ((Sint32)((float)(bar)*SP_ACCURACY_FACTOR));
+ * This saves you a function call. But it gets MUCH cheaper, if you don't have
+ * a float variable as parameter, but a number like 1.5f. Example:
+ * > Sint32 foo = spFloatToFixed(1.5);
+ * will become to:
+ * > Sint32 foo = ((Sint32)((float)(1.5f)*SP_ACCURACY_FACTOR));
+ * As no unknown parameter is in this equation the compiler will calculate it
+ * at *compile time*, which means: In you final binary, the (binary) code will
+ * just be:
+ * > Sint32 foo = 98304;
+ * which is obviouly *incredible* fast.
+ * 
+ * spFixedToFloat(x) - converts the fixed point number a to a float
+ * spFloatToFixed(x) - converts the float a to a fixed point number
+ * spIntToFixed(x) - converts the int x to a fixed point number
+ * spFixedToInt(x) - converts the fixed point number x to an int with cutting of
+ * the decimal place.
+ * spFixedRoundInt(x) - converts the fixed point number x with round to an int */
+
+#define spFixedToFloat(x) ((float)(x)/SP_ACCURACY_FACTOR)
+#define spFloatToFixed(x) ((Sint32)((float)(x)*SP_ACCURACY_FACTOR))
+#define spIntToFixed(x) ((Sint32)(((int)(x))<<SP_ACCURACY))
+#define spFixedToInt(x) ((int)(((Sint32)(x))>>SP_ACCURACY))
+
+#define spFixedRoundInt(x) ((int)(((Sint32)(x)+(1 << SP_ACCURACY-1))>>SP_ACCURACY))
+
+/* Defines: Generic Buttons
+ * 
+ * The following (long) list of #defines gives you the numbers and names
+ * of the generic device buttons or of the buttons on the explicit
+ * device. The Dingoo e.g. has the A button on the right, but GP2X and
+ * others on the left. That means: If you want the button with the
+ * CAPTION "A" use SP_BUTTON_A, but if you want the LEFT Button on every
+ * device use SP_BUTTON_LEFT, which will be SP_BUTTON_A on the gp2x or
+ * SP_BUTTON_Y on the Dingoo. The same for the names. Buttons like
+ * SP_BUTTON_L or similar are defined just one time - because they are
+ * the same on every device.
+ * 
+ * SP_BUTTON_START - number of the "Start" or "Menu" button
+ * SP_BUTTON_SELECT - number of the "Select", "||" or similar button
+ * SP_BUTTON_L - number of the left shoulder button
+ * SP_BUTTON_R - number of the right shoulder button
+ * SP_BUTTON_A - number of the A button. On every device at another position!
+ * SP_BUTTON_B - number of the B button. On every device at another position!
+ * SP_BUTTON_X - number of the X button. On every device at another position!
+ * SP_BUTTON_Y - number of the Y button. On every device at another position!
+ * SP_BUTTON_LEFT - number of the left button. On every device at the same position!
+ * SP_BUTTON_RIGHT - number of the right button. On every device at the same position!
+ * SP_BUTTON_UP - number of the up button. On every device at the same position!
+ * SP_BUTTON_DOWN - number of the down button. On every device at the same position!
+ * SP_PRACTICE_OK - number of the button, which is on the specific device the
+ * standard button for "ok".
+ * SP_PRACTICE_CANCEL - number of the button, which is on the specific device
+ * SP_PRACTICE_3 - number of the button, which is on the specific device the
+ * neither ok nor cancel.
+ * SP_PRACTICE_4 - number of the other button, which is on the specific device
+ * neither ok nor cancel. */
+/* Defines: Generic Buttons Names
+ * 
+ * SP_BUTTON_START_NAME - name of the "Start" or "Menu" button
+ * SP_BUTTON_SELECT_NAME - name of the "Select", "||" or similar button
+ * SP_BUTTON_L_NAME - name of the left shoulder button
+ * SP_BUTTON_R_NAME - name of the right shoulder button
+ * SP_BUTTON_A_NAME - name of the A button.
+ * SP_BUTTON_B_NAME - name of the B button.
+ * SP_BUTTON_X_NAME - name of the X button.
+ * SP_BUTTON_Y_NAME - name of the Y button.
+ * SP_BUTTON_LEFT_NAME - name of the left button.
+ * SP_BUTTON_RIGHT_NAME - name of the right button.
+ * SP_BUTTON_UP_NAME - name of the up button.
+ * SP_BUTTON_DOWN_NAME - name of the down button.
+ * SP_PAD_NAME - name of the pad (e.g. "Arrows keys" on the PC)
+ * SP_PRACTICE_OK_NAME - name of the button, which is on the specific device the
+ * standard button for "ok".
+ * SP_PRACTICE_CANCEL_NAME - name of the button, which is on the specific device
+ * the standard button for canceling an action.
+ * SP_PRACTICE_3_NAME - name of the button, which is on the specific device the
+ * neither ok nor cancel.
+ * SP_PRACTICE_4_NAME - name of the other button, which is on the specific device
+ * neither ok nor cancel*/
+#ifdef GP2X
+       #define SP_AXIS_UP 0
+       #define SP_AXIS_LEFTUP 1
+       #define SP_AXIS_LEFT 2
+       #define SP_AXIS_LEFTDOWN 3
+       #define SP_AXIS_DOWN 4
+       #define SP_AXIS_RIGHTDOWN 5
+       #define SP_AXIS_RIGHT 6
+       #define SP_AXIS_RIGHTUP 7
+       #define SP_BUTTON_START 8
+       #define SP_BUTTON_SELECT 9
+       #define SP_BUTTON_L 10
+       #define SP_BUTTON_R 11
+       #define SP_BUTTON_A 12
+       #define SP_BUTTON_B 13
+       #define SP_BUTTON_X 14
+       #define SP_BUTTON_Y 15
+       #define SP_BUTTON_LEFT SP_BUTTON_A
+       #define SP_BUTTON_UP SP_BUTTON_Y
+       #define SP_BUTTON_RIGHT SP_BUTTON_B
+       #define SP_BUTTON_DOWN SP_BUTTON_X
+       #define SP_BUTTON_GP2X_ONLY_VOLPLUS 16
+       #define SP_BUTTON_GP2X_ONLY_VOLMINUS 17
+       #define SP_BUTTON_GP2X_ONLY_TIP 18
+       //just for different practices
+       #define SP_PRACTICE_OK SP_BUTTON_B
+       #define SP_PRACTICE_CANCEL SP_BUTTON_X
+       #define SP_PRACTICE_3 SP_BUTTON_A
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+#elif defined CAANOO
+       #define SP_BUTTON_A 0
+       #define SP_BUTTON_X 1
+       #define SP_BUTTON_B 2
+       #define SP_BUTTON_Y 3
+       #define SP_BUTTON_LEFT SP_BUTTON_A
+       #define SP_BUTTON_UP SP_BUTTON_Y
+       #define SP_BUTTON_RIGHT SP_BUTTON_B
+       #define SP_BUTTON_DOWN SP_BUTTON_X
+       #define SP_BUTTON_L 4
+       #define SP_BUTTON_R 5
+       #define SP_BUTTON_START 6
+       //SELECT == HELP I
+       #define SP_BUTTON_SELECT 8
+       //the Caanoo has a hardware volume control...
+       #define SP_PRACTICE_OK SP_BUTTON_B
+       #define SP_PRACTICE_CANCEL SP_BUTTON_X
+       #define SP_PRACTICE_3 SP_BUTTON_A
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+#elif defined DINGUX
+       #define SP_BUTTON_START 8
+       #define SP_BUTTON_SELECT 9
+       #define SP_BUTTON_L 10
+       #define SP_BUTTON_R 11
+       #define SP_BUTTON_A 12
+       #define SP_BUTTON_B 13
+       #define SP_BUTTON_X 14
+       #define SP_BUTTON_Y 15
+       #define SP_BUTTON_LEFT SP_BUTTON_Y
+       #define SP_BUTTON_UP SP_BUTTON_X
+       #define SP_BUTTON_RIGHT SP_BUTTON_A
+       #define SP_BUTTON_DOWN SP_BUTTON_B
+       #define SP_PRACTICE_OK SP_BUTTON_A
+       #define SP_PRACTICE_CANCEL SP_BUTTON_X
+       #define SP_PRACTICE_3 SP_BUTTON_B
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+#elif defined GCW
+       #define SP_BUTTON_START 8
+       #define SP_BUTTON_SELECT 9
+       #define SP_BUTTON_L 10
+       #define SP_BUTTON_R 11
+       #define SP_BUTTON_A 12
+       #define SP_BUTTON_B 13
+       #define SP_BUTTON_X 14
+       #define SP_BUTTON_Y 15
+       #define SP_BUTTON_LEFT SP_BUTTON_X
+       #define SP_BUTTON_UP SP_BUTTON_Y
+       #define SP_BUTTON_RIGHT SP_BUTTON_A
+       #define SP_BUTTON_DOWN SP_BUTTON_B
+       #define SP_PRACTICE_OK SP_BUTTON_A
+       #define SP_PRACTICE_CANCEL SP_BUTTON_B
+       #define SP_PRACTICE_3 SP_BUTTON_X
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+#elif defined PANDORA
+       #define SP_AXIS_LEFTRIGHT 0
+       #define SP_AXIS_UPDOWN 1
+       #define SP_BUTTON_START 8
+       #define SP_BUTTON_SELECT 9
+       #define SP_BUTTON_L 10
+       #define SP_BUTTON_R 11
+       #define SP_BUTTON_A 12
+       #define SP_BUTTON_B 13
+       #define SP_BUTTON_X 14
+       #define SP_BUTTON_Y 15
+       #define SP_BUTTON_LEFT SP_BUTTON_A
+       #define SP_BUTTON_UP SP_BUTTON_Y
+       #define SP_BUTTON_RIGHT SP_BUTTON_B
+       #define SP_BUTTON_DOWN SP_BUTTON_X
+       #define SP_PRACTICE_OK SP_BUTTON_A
+       #define SP_PRACTICE_CANCEL SP_BUTTON_X
+       #define SP_PRACTICE_3 SP_BUTTON_B
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+#else //PC
+       #define SP_AXIS_LEFTRIGHT 0
+       #define SP_AXIS_UPDOWN 1
+       #define SP_BUTTON_SELECT_NOWASD 1
+       #define SP_BUTTON_L_NOWASD 2
+       #define SP_BUTTON_R_NOWASD 3
+       #define SP_BUTTON_A_NOWASD 4
+       #define SP_BUTTON_B_NOWASD 5
+       #define SP_BUTTON_X_NOWASD 6
+       #define SP_BUTTON_Y_NOWASD 7
+       #define SP_BUTTON_START 8
+       #define SP_BUTTON_SELECT 9
+       #define SP_BUTTON_L 10
+       #define SP_BUTTON_R 11
+       #define SP_BUTTON_A 12
+       #define SP_BUTTON_B 13
+       #define SP_BUTTON_X 14
+       #define SP_BUTTON_Y 15
+       #define SP_BUTTON_LEFT SP_BUTTON_A
+       #define SP_BUTTON_UP SP_BUTTON_Y
+       #define SP_BUTTON_RIGHT SP_BUTTON_B
+       #define SP_BUTTON_DOWN SP_BUTTON_X
+       #define SP_BUTTON_LEFT_NOWASD SP_BUTTON_A_NOWASD
+       #define SP_BUTTON_UP_NOWASD SP_BUTTON_Y_NOWASD
+       #define SP_BUTTON_RIGHT_NOWASD SP_BUTTON_B_NOWASD
+       #define SP_BUTTON_DOWN_NOWASD SP_BUTTON_X_NOWASD
+       #define SP_PRACTICE_OK SP_BUTTON_A
+       #define SP_PRACTICE_CANCEL SP_BUTTON_B
+       #define SP_PRACTICE_3 SP_BUTTON_X
+       #define SP_PRACTICE_4 SP_BUTTON_Y
+       #define SP_PRACTICE_OK_NOWASD SP_BUTTON_A_NOWASD
+       #define SP_PRACTICE_CANCEL_NOWASD SP_BUTTON_B_NOWASD
+       #define SP_PRACTICE_3_NOWASD SP_BUTTON_X_NOWASD
+       #define SP_PRACTICE_4_NOWASD SP_BUTTON_Y_NOWASD
+#endif
+
+#define SP_BUTTON_START_NOWASD SP_BUTTON_START
+#ifndef X86CPU
+       #define SP_BUTTON_SELECT_NOWASD SP_BUTTON_SELECT
+       #define SP_BUTTON_L_NOWASD SP_BUTTON_L
+       #define SP_BUTTON_R_NOWASD SP_BUTTON_R
+       #define SP_BUTTON_A_NOWASD SP_BUTTON_A
+       #define SP_BUTTON_B_NOWASD SP_BUTTON_B
+       #define SP_BUTTON_X_NOWASD SP_BUTTON_X
+       #define SP_BUTTON_Y_NOWASD SP_BUTTON_Y
+       #define SP_PRACTICE_OK_NOWASD SP_PRACTICE_OK
+       #define SP_PRACTICE_CANCEL_NOWASD SP_PRACTICE_CANCEL
+       #define SP_PRACTICE_3_NOWASD SP_PRACTICE_3
+       #define SP_PRACTICE_4_NOWASD SP_PRACTICE_4
+       #define SP_BUTTON_LEFT_NOWASD SP_BUTTON_LEFT
+       #define SP_BUTTON_UP_NOWASD SP_BUTTON_UP
+       #define SP_BUTTON_RIGHT_NOWASD SP_BUTTON_RIGHT
+       #define SP_BUTTON_DOWN_NOWASD SP_BUTTON_DOWN
+#endif
+
+#ifdef F100
+       #define SP_BUTTON_START_NAME "Start"
+       #define SP_BUTTON_SELECT_NAME "Select"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_B_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_X_NAME
+       #define SP_PAD_NAME "D-Pad"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#elif defined WIZ
+       #define SP_BUTTON_START_NAME "Menu"
+       #define SP_BUTTON_SELECT_NAME "Select"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_B_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_X_NAME
+       #define SP_PAD_NAME "D-Pad"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#elif defined CAANOO
+       #define SP_BUTTON_START_NAME "Home"
+       #define SP_BUTTON_SELECT_NAME "Help I"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_B_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_X_NAME
+       #define SP_PAD_NAME "Stick"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#elif defined DINGUX
+       #define SP_BUTTON_START_NAME "Start"
+       #define SP_BUTTON_SELECT_NAME "Select"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_X_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_B_NAME
+       #define SP_PAD_NAME "D-Pad"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#elif defined GCW
+       #define SP_BUTTON_START_NAME "Start"
+       #define SP_BUTTON_SELECT_NAME "Select"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_X_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_B_NAME
+       #define SP_PAD_NAME "D-Pad"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#elif defined PANDORA
+       #define SP_BUTTON_START_NAME "Start"
+       #define SP_BUTTON_SELECT_NAME "Select"
+       #define SP_BUTTON_L_NAME "L"
+       #define SP_BUTTON_R_NAME "R"
+       #define SP_BUTTON_A_NAME "A"
+       #define SP_BUTTON_B_NAME "B"
+       #define SP_BUTTON_X_NAME "X"
+       #define SP_BUTTON_Y_NAME "Y"
+       #define SP_BUTTON_LEFT_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_UP_NAME SP_BUTTON_Y_NAME
+       #define SP_BUTTON_RIGHT_NAME SP_BUTTON_B_NAME
+       #define SP_BUTTON_DOWN_NAME SP_BUTTON_X_NAME
+       #define SP_PAD_NAME "D-Pad"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+#else
+       #define SP_BUTTON_START_NAME "Return"
+       #define SP_BUTTON_START_NOWASD_NAME "Return"
+       #define SP_BUTTON_SELECT_NAME "Backspace"
+       #define SP_BUTTON_SELECT_NOWASD_NAME "Esc"
+       #define SP_BUTTON_L_NAME "q"
+       #define SP_BUTTON_L_NOWASD_NAME "PgUp"
+       #define SP_BUTTON_R_NAME "e"
+       #define SP_BUTTON_R_NOWASD_NAME "PgDn"
+       #define SP_BUTTON_A_NAME "a"
+       #define SP_BUTTON_A_NOWASD_NAME "Ctrl"
+       #define SP_BUTTON_B_NAME "d"
+       #define SP_BUTTON_B_NOWASD_NAME "Alt"
+       #define SP_BUTTON_X_NAME "s"
+       #define SP_BUTTON_X_NOWASD_NAME "AltGr"
+       #define SP_BUTTON_Y_NAME "w"    
+       #define SP_BUTTON_Y_NOWASD_NAME "Shift"
+       #define SP_BUTTON_LEFT_NAME         SP_BUTTON_A_NAME
+       #define SP_BUTTON_LEFT_NOWASD_NAME  SP_BUTTON_A_NOWASD_NAME
+       #define SP_BUTTON_UP_NAME           SP_BUTTON_Y_NAME
+       #define SP_BUTTON_UP_NOWASD_NAME    SP_BUTTON_Y_NOWASD_NAME
+       #define SP_BUTTON_RIGHT_NAME        SP_BUTTON_B_NAME
+       #define SP_BUTTON_RIGHT_NOWASD_NAME SP_BUTTON_B_NOWASD_NAME
+       #define SP_BUTTON_DOWN_NAME         SP_BUTTON_X_NAME
+       #define SP_BUTTON_DOWN_NOWASD_NAME  SP_BUTTON_X_NOWASD_NAME
+       #define SP_PAD_NAME "Arrow Keys"
+       #define SP_PRACTICE_OK_NAME SP_BUTTON_A_NAME
+       #define SP_PRACTICE_CANCEL_NAME SP_BUTTON_B_NAME
+       #define SP_PRACTICE_3_NAME SP_BUTTON_X_NAME
+       #define SP_PRACTICE_4_NAME SP_BUTTON_Y_NAME
+       #define SP_PRACTICE_OK_NOWASD_NAME SP_BUTTON_A_NOWASD_NAME
+       #define SP_PRACTICE_CANCEL_NOWASD_NAME SP_BUTTON_B_NOWASD_NAME
+       #define SP_PRACTICE_3_NOWASD_NAME SP_BUTTON_X_NOWASD_NAME
+       #define SP_PRACTICE_4_NOWASD_NAME SP_BUTTON_Y_NOWASD_NAME
+#endif
+
+#ifndef X86CPU
+       #define SP_BUTTON_START_NOWASD_NAME SP_BUTTON_START_NAME
+       #define SP_BUTTON_SELECT_NOWASD_NAME SP_BUTTON_SELECT_NAME
+       #define SP_BUTTON_L_NOWASD_NAME SP_BUTTON_L_NAME
+       #define SP_BUTTON_R_NOWASD_NAME SP_BUTTON_R_NAME
+       #define SP_BUTTON_A_NOWASD_NAME SP_BUTTON_A_NAME
+       #define SP_BUTTON_B_NOWASD_NAME SP_BUTTON_B_NAME
+       #define SP_BUTTON_X_NOWASD_NAME SP_BUTTON_X_NAME
+       #define SP_BUTTON_Y_NOWASD_NAME SP_BUTTON_Y_NAME
+       #define SP_PRACTICE_OK_NOWASD_NAME     SP_PRACTICE_OK_NAME
+       #define SP_PRACTICE_CANCEL_NOWASD_NAME SP_PRACTICE_CANCEL_NAME
+       #define SP_PRACTICE_3_NOWASD_NAME      SP_PRACTICE_3_NAME
+       #define SP_PRACTICE_4_NOWASD_NAME            SP_PRACTICE_4_NAME
+       #define SP_BUTTON_LEFT_NOWASD_NAME     SP_BUTTON_LEFT_NAME
+       #define SP_BUTTON_UP_NOWASD_NAME       SP_BUTTON_UP_NAME
+       #define SP_BUTTON_RIGHT_NOWASD_NAME    SP_BUTTON_RIGHT_NAME
+       #define SP_BUTTON_DOWN_NOWASD_NAME     SP_BUTTON_DOWN_NAME
+#endif
+
+/* Defines: Generic Buttons Masks
+ * 
+ * Mask of the buttons, Useful for <spPollKeyboardInput>s last parameter.
+ * 
+ * SP_BUTTON_START_MASK - mask of the "Start" or "Menu" button
+ * SP_BUTTON_SELECT_MASK - mask of the "Select", "||" or similar button
+ * SP_BUTTON_L_MASK - mask of the left shoulder button
+ * SP_BUTTON_R_MASK - mask of the right shoulder button
+ * SP_BUTTON_A_MASK - mask of the A button.
+ * SP_BUTTON_B_MASK - mask of the B button.
+ * SP_BUTTON_X_MASK - mask of the X button.
+ * SP_BUTTON_Y_MASK - mask of the Y button.
+ * SP_BUTTON_LEFT_MASK - mask of the left button.
+ * SP_BUTTON_RIGHT_MASK - mask of the right button.
+ * SP_BUTTON_UP_MASK - mask of the up button.
+ * SP_BUTTON_DOWN_MASK - mask of the down button.
+ * SP_PRACTICE_OK_MASK - mask of the button, which is on the specific device the
+ * standard button for "ok".
+ * SP_PRACTICE_CANCEL_MASK - mask of the button, which is on the specific device
+ * the standard button for canceling an action.
+ * SP_PRACTICE_3_MASK - mask of the button, which is on the specific device the
+ * neither ok nor cancel.
+ * SP_PRACTICE_4_MASK - mask of the other button, which is on the specific device
+ * neither ok nor cancel. */
+
+//Bit masks for every button
+#define SP_BUTTON_START_MASK (1 << SP_BUTTON_START)
+#define SP_BUTTON_SELECT_MASK (1 << SP_BUTTON_SELECT)
+#define SP_BUTTON_L_MASK (1 << SP_BUTTON_L)
+#define SP_BUTTON_R_MASK (1 << SP_BUTTON_R)
+#define SP_BUTTON_A_MASK (1 << SP_BUTTON_A)
+#define SP_BUTTON_B_MASK (1 << SP_BUTTON_B)
+#define SP_BUTTON_X_MASK (1 << SP_BUTTON_X)
+#define SP_BUTTON_Y_MASK (1 << SP_BUTTON_Y)
+#define SP_BUTTON_LEFT_MASK (1 << SP_BUTTON_LEFT)
+#define SP_BUTTON_UP_MASK (1 << SP_BUTTON_UP)
+#define SP_BUTTON_RIGHT_MASK (1 << SP_BUTTON_RIGHT)
+#define SP_BUTTON_DOWN_MASK (1 << SP_BUTTON_DOWN)
+#define SP_PRACTICE_OK_MASK (1 << SP_PRACTICE_OK)
+#define SP_PRACTICE_CANCEL_MASK (1 << SP_PRACTICE_CANCEL)
+#define SP_PRACTICE_3_MASK (1 << SP_PRACTICE_3)
+#define SP_PRACTICE_4_MASK (1 << SP_PRACTICE_4)
+#define SP_BUTTON_START_NOWASD_MASK (1 << SP_BUTTON_START_NOWASD)
+#define SP_BUTTON_SELECT_NOWASD_MASK (1 << SP_BUTTON_SELECT_NOWASD)
+#define SP_BUTTON_L_NOWASD_MASK (1 << SP_BUTTON_L_NOWASD)
+#define SP_BUTTON_R_NOWASD_MASK (1 << SP_BUTTON_R_NOWASD)
+#define SP_BUTTON_A_NOWASD_MASK (1 << SP_BUTTON_A_NOWASD)
+#define SP_BUTTON_B_NOWASD_MASK (1 << SP_BUTTON_B_NOWASD)
+#define SP_BUTTON_X_NOWASD_MASK (1 << SP_BUTTON_X_NOWASD)
+#define SP_BUTTON_Y_NOWASD_MASK (1 << SP_BUTTON_Y_NOWASD)
+#define SP_BUTTON_LEFT_NOWASD_MASK (1 << SP_BUTTON_LEFT_NOWASD)
+#define SP_BUTTON_UP_NOWASD_MASK (1 << SP_BUTTON_UP_NOWASD)
+#define SP_BUTTON_RIGHT_NOWASD_MASK (1 << SP_BUTTON_RIGHT_NOWASD)
+#define SP_BUTTON_DOWN_NOWASD_MASK (1 << SP_BUTTON_DOWN_NOWASD)
+#define SP_PRACTICE_OK_NOWASD_MASK (1 << SP_PRACTICE_OK_NOWASD)
+#define SP_PRACTICE_CANCEL_NOWASD_MASK (1 << SP_PRACTICE_CANCEL_NOWASD)
+#define SP_PRACTICE_3_NOWASD_MASK (1 << SP_PRACTICE_3_NOWASD)
+#define SP_PRACTICE_4_NOWASD_MASK (1 << SP_PRACTICE_4_NOWASD)
+#ifdef GP2X
+       #define SP_BUTTON_GP2X_ONLY_VOLPLUS_MASK (1 << SP_BUTTON_GP2X_ONLY_VOLPLUS)
+       #define SP_BUTTON_GP2X_ONLY_VOLMINUS_MASK (1 << SP_BUTTON_GP2X_ONLY_VOLMINUS)
+       #define SP_BUTTON_GP2X_ONLY_TIP_MASK (1 << SP_BUTTON_GP2X_ONLY_TIP)
+#endif
+
+/* Defines: Directions
+ * 
+ * These are some #defines e.g. for sparrowPrimitives to determine,
+ * where the base of the drawn primitive is.
+ * 
+ * SP_CENTER - center
+ * SP_LEFT - left
+ * SP_TOP - top
+ * SP_RIGHT - right
+ * SP_BOTTOM - bottom
+ * SP_FIXED - sets the base to a fixed position*/
+#define SP_CENTER 0
+#define SP_LEFT 1
+#define SP_TOP 2
+#define SP_RIGHT 3
+#define SP_BOTTOM 4
+#define SP_FIXED 5
+
+// Define: SP_NO_TOUCHSCREEN_EMULATION
+// Used by <spSetTouchscreenEmulationButtons>
+#define SP_NO_TOUCHSCREEN_EMULATION -1
+
+// Define: SP_ALPHA_COLOR
+// If alphatest is enabled, this (pink) color will not be drawn, it is "transparent".
+#define SP_ALPHA_COLOR 63519
+
+// Define: SP_DEVICE_STRING
+// Gives you the name of the device, e.g. "GP2X F100" or "Personal Computer"
+#ifdef F100
+       #define SP_DEVICE_STRING "GP2X F100"
+#elif defined WIZ
+       #define SP_DEVICE_STRING "GP2X Wiz"
+#elif defined CAANOO
+       #define SP_DEVICE_STRING "GP2X Caanoo"
+#elif defined DINGUX
+       #define SP_DEVICE_STRING "Dingoo"
+#elif defined GCW
+       #define SP_DEVICE_STRING "GCW Zero"
+#elif defined PANDORA
+       #define SP_DEVICE_STRING "Open Pandora"
+#elif defined WIN32
+       #define SP_DEVICE_STRING "Windows PC"
+#else
+       #define SP_DEVICE_STRING "Linux PC"
+#endif
+
+#endif
diff --git a/recipes/fusilli-client/files/sparrowNet.c b/recipes/fusilli-client/files/sparrowNet.c
new file mode 100644 (file)
index 0000000..7feab5c
--- /dev/null
@@ -0,0 +1,1896 @@
+ /* This file is part of sparrow3d.
+  * Sparrow3d is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation, either version 2 of the License, or
+  * (at your option) any later version.
+  * 
+  * Sparrow3d is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  * 
+  * You should have received a copy of the GNU General Public License
+  * along with Foobar.  If not, see <http://www.gnu.org/licenses/>
+  * 
+  * For feedback and questions about my Files and Projects please mail me,
+  * Alexander Matthes (Ziz) , zizsdl_at_googlemail.com */
+
+#include "sparrowNet.h"
+#include <stdio.h>
+#include <errno.h>
+
+//This is a copy of spReadOneLine sparrowFile. However, I don't want the
+//extra dependency of libSparrow3d or linking sparrowFile twice.
+int internal_spNet_spReadOneLine( SDL_RWops* file , char* buffer, int buffer_len)
+{
+       int pos = 0;
+       buffer[pos] = 0;
+       while (pos < buffer_len)
+       {
+               if (SDL_RWread( file, &(buffer[pos]), 1, 1 ) <= 0)
+                       return 1; //EOF
+               if ( buffer[pos] == '\n' )
+                       break;
+               if (buffer[pos] != '\r') //fucking windows line break
+                       pos++;
+       }
+       buffer[pos] = 0;
+       return 0; //not EOF
+}
+
+spNetC4ATaskPointer spGlobalC4ATask = NULL;
+SDL_mutex* spCacheMutex = NULL;
+
+spNetC4ATaskPointer createNewC4ATask()
+{
+       spNetC4ATaskPointer task = (spNetC4ATaskPointer)malloc(sizeof(spNetC4ATask));
+       task->statusMutex = SDL_CreateMutex();
+       task->status = 0;
+       task->dataPointer = NULL;
+       task->timeOut = 0;
+       task->thread = NULL;
+       task->result = 0;
+       task->threadStatus = 0;
+       task->message = 0;
+       return task;
+}
+
+void spNetC4ADeleteTask(spNetC4ATaskPointer task)
+{
+       SDL_DestroyMutex(task->statusMutex);
+       free(task);
+}
+
+PREFIX void spInitNet()
+{
+       if(SDLNet_Init()==-1)
+               printf("SDLNet_Init: %s\n", SDLNet_GetError());
+       spGlobalC4ATask = createNewC4ATask();
+       spCacheMutex = SDL_CreateMutex();
+}
+
+void fill_ip_struct(spNetIPPointer ip)
+{
+       ip->type = IPV4;
+       ip->address.ipv4 = ip->sdl_address.host; //bytes are set automaticly, yeah!
+       ip->port = ip->sdl_address.port;        
+}
+
+PREFIX spNetIP spNetResolve(char* host,Uint16 port)
+{
+       spNetIP result;
+       SDLNet_ResolveHost(&(result.sdl_address), host, port);
+       fill_ip_struct(&result);
+       return result;
+}
+
+PREFIX char* spNetResolveHost(spNetIP ip,char* host,int host_len)
+{
+       const char* sdlHost = SDLNet_ResolveIP(&(ip.sdl_address));
+       if (strlen(sdlHost) >= host_len)
+       {
+               host = NULL;
+               return NULL;
+       }
+       sprintf(host,"%s",sdlHost);
+       return host;
+}
+
+PREFIX spNetTCPConnection spNetOpenClientTCP(spNetIP ip)
+{
+       spNetTCPConnection result;
+
+       result=SDLNet_TCP_Open(&(ip.sdl_address));
+       if(!result) {
+               printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+               return NULL;
+       }
+       return result;
+}
+
+PREFIX spNetTCPServer spNetOpenServerTCP(Uint16 port)
+{
+       IPaddress ip;
+       spNetTCPServer result;
+
+       if(SDLNet_ResolveHost(&ip,NULL,port)==-1) {
+               printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+               return NULL;
+       }
+       result=SDLNet_TCP_Open(&ip);
+       if(!result) {
+               printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+               return NULL;
+       }
+       return result;
+}
+
+PREFIX spNetTCPConnection spNetAcceptTCP(spNetTCPServer server)
+{
+       return SDLNet_TCP_Accept(server);
+}
+
+PREFIX spNetIP spNetGetConnectionIP(spNetTCPConnection connection)
+{
+       IPaddress *temp_ip;
+       temp_ip=SDLNet_TCP_GetPeerAddress(connection);
+       spNetIP result;
+       if(!temp_ip) {
+               printf("SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
+               printf("This may be a server socket.\n");
+               printf("However, the ip may not be valid!\n");
+       }
+       result.sdl_address = *temp_ip;
+       fill_ip_struct(&result);
+       return result;
+}
+
+PREFIX int spNetSendTCP(spNetTCPConnection connection,void* data,int length)
+{
+       return SDLNet_TCP_Send(connection,data,length);
+}
+
+PREFIX int spNetSendHTTP(spNetTCPConnection connection,char* data)
+{
+       return spNetSendTCP(connection,data,strlen(data)+1);
+}
+
+typedef struct receivingStruct *receivingPointer;
+typedef struct receivingStruct {
+       spNetTCPConnection connection;
+       void* data;
+       int length;
+       SDL_mutex* mutex;
+       int done;
+       SDL_Thread* thread;
+       int result;
+       receivingPointer next;
+} receivingType;
+
+int tcpReceiveThread(void* data)
+{
+       receivingPointer tcpData = (receivingPointer)data;
+       int res=spNetReceiveTCP(tcpData->connection,tcpData->data,tcpData->length);
+       SDL_mutexP(tcpData->mutex);
+       tcpData->done = 1;
+       tcpData->result = res;
+       SDL_mutexV(tcpData->mutex);
+       return res;
+}
+
+int tcpReceiveThread_http(void* data)
+{
+       receivingPointer tcpData = (receivingPointer)data;
+       int res=spNetReceiveHTTP(tcpData->connection,(char*)tcpData->data,tcpData->length);
+       SDL_mutexP(tcpData->mutex);
+       tcpData->done = 1;
+       tcpData->result = res;
+       SDL_mutexV(tcpData->mutex);
+       return res;
+}
+
+receivingPointer firstReceiving = NULL;
+
+SDL_Thread* allreadyReceiving(spNetTCPConnection connection)
+{
+       receivingPointer before = NULL;
+       receivingPointer mom = firstReceiving;
+       while (mom)
+       {
+               if (mom->connection == connection)
+               {
+                       SDL_mutexP(mom->mutex);
+                       if (mom->done)
+                       {
+                               SDL_mutexV(mom->mutex); //The Thread lost the interest on this struct
+                               //Removing mom
+                               if (before)
+                               {
+                                       SDL_mutexP(before->mutex);
+                                       before->next = mom->next;
+                                       SDL_mutexV(before->mutex);
+                               }
+                               else
+                                       firstReceiving = mom->next;
+                               SDL_DestroyMutex(mom->mutex);
+                               if (mom->result<=0) //connection destroyed!
+                               {
+                                       free(mom);
+                                       return (SDL_Thread*)(-1);
+                               }
+                               free(mom);
+                               return NULL;
+                       }
+                       SDL_mutexV(mom->mutex);
+                       return mom->thread;
+               }
+               before = mom;
+               mom = mom->next;
+       }       
+       return NULL;
+}
+
+PREFIX int spNetReceiveTCP(spNetTCPConnection connection,void* data,int length)
+{
+       char* data_pointer = (char*)data;
+       return SDLNet_TCP_Recv(connection,&(data_pointer[0]),length);
+}
+
+PREFIX SDL_Thread* spNetReceiveTCPUnblocked(spNetTCPConnection connection,void* data,int length)
+{
+       SDL_Thread* thread;
+       if (thread = allreadyReceiving(connection))
+               return thread;
+       receivingPointer tcpData = (receivingPointer)malloc(sizeof(receivingType));
+       tcpData->connection = connection;
+       tcpData->data = data;
+       tcpData->length = length;
+       tcpData->connection = connection;
+       tcpData->done = 0;
+       tcpData->mutex = SDL_CreateMutex();
+       tcpData->next = firstReceiving;
+       firstReceiving = tcpData;
+       tcpData->thread = SDL_CreateThread(tcpReceiveThread,tcpData);
+       return tcpData->thread;
+}
+
+PREFIX int spNetReceiveHTTP(spNetTCPConnection connection,char* data,int length)
+{
+       int received = 0;
+       while (length > 0)
+       {
+               int new_received = spNetReceiveTCP(connection,&(data[received]),length);
+               received+=new_received;
+               length-=new_received;
+               if (new_received == 0)
+                       return received;
+       }
+       return received;
+}
+
+PREFIX SDL_Thread* spNetReceiveHTTPUnblocked(spNetTCPConnection connection,char* data,int length)
+{
+       SDL_Thread* thread;
+       if (thread = allreadyReceiving(connection))
+               return thread;
+       receivingPointer tcpData = (receivingPointer)malloc(sizeof(receivingType));
+       tcpData->connection = connection;
+       tcpData->data = data;
+       tcpData->length = length;
+       tcpData->connection = connection;
+       tcpData->done = 0;
+       tcpData->mutex = SDL_CreateMutex();
+       tcpData->next = firstReceiving;
+       firstReceiving = tcpData;
+       tcpData->thread = SDL_CreateThread(tcpReceiveThread_http,tcpData);
+       return tcpData->thread;
+}
+
+PREFIX int spNetReceiveStillWaiting(SDL_Thread* thread)
+{
+       receivingPointer before = NULL;
+       receivingPointer mom = firstReceiving;
+       while (mom)
+       {
+               if (mom->thread == thread)
+               {
+                       SDL_mutexP(mom->mutex);
+                       if (mom->done)
+                       {
+                               SDL_mutexV(mom->mutex); //The Thread lost the interest on this struct
+                               //Removing mom
+                               if (before)
+                               {
+                                       SDL_mutexP(before->mutex);
+                                       before->next = mom->next;
+                                       SDL_mutexV(before->mutex);
+                               }
+                               else
+                                       firstReceiving = mom->next;
+                               SDL_DestroyMutex(mom->mutex);
+                               free(mom);
+                               return 0;
+                       }
+                       SDL_mutexV(mom->mutex);
+                       return 1;
+               }
+               before = mom;
+               mom = mom->next;
+       }       
+       return 0;
+}
+
+PREFIX void spNetCloseTCP(spNetTCPConnection connection)
+{
+       SDLNet_TCP_Close(connection);
+}
+
+PREFIX void spQuitNet()
+{
+       spNetC4ADeleteTask(spGlobalC4ATask);
+       spGlobalC4ATask = NULL;
+       SDL_mutexP(spCacheMutex);
+       SDL_DestroyMutex(spCacheMutex);
+       SDLNet_Quit();
+}
+
+#ifdef PANDORA
+       #include "pnd_locate.h"
+#endif
+
+typedef struct getgenericStruct *getgenericPointer;
+typedef struct getgenericStruct {
+       spNetC4ATaskPointer task;
+       int ( *function )( void* data );
+} getgenericType;
+
+typedef struct getgameStruct *getgamePointer;
+typedef struct getgameStruct {
+       spNetC4ATaskPointer task;
+       int ( *function )( void* data );
+       spNetC4AGamePointer* game;
+} getgameType;
+
+typedef struct getscoreStruct *getscorePointer;
+typedef struct getscoreStruct {
+       spNetC4ATaskPointer task;
+       int ( *function )( void* data );
+       spNetC4AScorePointer* score;
+       spNetC4AProfilePointer profile;
+       int year;
+       int month;
+       char game[256];
+} getscoreType;
+
+typedef struct commitStruct *commitPointer;
+typedef struct commitStruct {
+       spNetC4ATaskPointer task;
+       int ( *function )( void* data );
+       spNetC4AProfilePointer profile;
+       char game[256];
+       int score;
+       char system[256];
+       spNetC4AScorePointer* scoreList;
+} commitType;
+
+typedef struct createStruct *createPointer;
+typedef struct createStruct {
+       spNetC4ATaskPointer task;
+       int ( *function )( void* data );
+       spNetC4AProfilePointer* profile;
+       char longname[256];
+       char shortname[256];
+       char password[256];
+       char email[256];
+       int deleteFile;
+} createType;
+
+int spNetC4ACaching = 0;
+char spCacheFilename[256] = "";
+
+//This is usefull for debugging without threading influences:
+/*#define SDL_CreateThread SDL_CreateThreadWithoutThreading
+SDL_Thread* SDL_CreateThreadWithoutThreading(int (*fn)(void *),void* data)
+{
+       fn(data);
+       return NULL;
+}*/
+
+
+typedef struct cacheStruct *cachePointer;
+typedef struct cacheStruct {
+       char game[256];
+       char system[256];
+       char prid[256];
+       int score;
+       cachePointer next;
+} cacheType;
+
+cachePointer read_cache()
+{
+       SDL_RWops *file = SDL_RWFromFile(spCacheFilename, "rb");
+       if (file)
+       {
+               char game[256];
+               char system[256];
+               char prid[256];
+               int score;
+               cachePointer cache = NULL;
+               cachePointer last = NULL;
+               while (1)
+               {
+                       if (SDL_RWread(file,game,256,1) <= 0)
+                               break;
+                       if (SDL_RWread(file,system,256,1) <= 0)
+                               break;
+                       if (SDL_RWread(file,prid,256,1) <= 0)
+                               break;
+                       if (SDL_RWread(file,&score,sizeof(int),1) <= 0)
+                               break;
+                       cachePointer new_cache = (cachePointer)malloc(sizeof(cacheType));
+                       memcpy(new_cache->game,game,256);
+                       memcpy(new_cache->system,system,256);
+                       memcpy(new_cache->prid,prid,256);
+                       new_cache->score = score;
+                       new_cache->next = NULL;
+                       if (last)
+                               last->next = new_cache;
+                       else
+                               cache = new_cache;
+                       last = new_cache;
+               }
+               SDL_RWclose(file);
+               return cache;
+       }
+       return NULL;
+}
+
+void write_to_cache(char* game,char* system,char* prid,int score,int lock)
+{
+       if (lock)
+               SDL_mutexP(spCacheMutex);
+       cachePointer cache = NULL;
+       if (spNetC4ACaching != 1)
+               cache = read_cache();
+       //Searching one of game
+       cachePointer mom = cache;
+       int nr = 0;
+       while (mom)
+       {
+               if (strcmp(mom->game,game) == 0)
+                       break;
+               nr++;
+               mom = mom->next;
+       }
+       if (mom)
+       {
+               if  ((spNetC4ACaching == 2 && mom->score < score) ||
+                       (spNetC4ACaching == 3 && mom->score > score))
+               {
+                       //Seek and rewrite
+                       SDL_RWops *file = SDL_RWFromFile(spCacheFilename, "r+b");
+                       SDL_RWseek(file,nr*(256*3+sizeof(int))+256*3,SEEK_SET);
+                       SDL_RWwrite(file,&score,sizeof(int),1);
+                       SDL_RWclose(file);
+               }
+       }
+       else
+       {
+               SDL_RWops *file = SDL_RWFromFile(spCacheFilename, "ab");
+               SDL_RWwrite(file,game,256,1);
+               SDL_RWwrite(file,system,256,1);
+               SDL_RWwrite(file,prid,256,1);
+               SDL_RWwrite(file,&score,sizeof(int),1);
+               SDL_RWclose(file);
+       }               
+       while (cache)
+       {
+               mom = cache->next;
+               free(cache);
+               cache = mom;
+       }
+       if (lock)
+               SDL_mutexV(spCacheMutex);
+}
+
+int spNetC4AUberThread(getgenericPointer data)
+{
+       int startTime = SDL_GetTicks();
+       SDL_Thread* thread = SDL_CreateThread(data->function,data);
+       while (1)
+       {
+       #ifdef REALGP2X
+               //TODO: Implement!
+               SDL_Delay(100);
+       #elif defined WIN32
+               SDL_Delay(100); 
+       #else
+               usleep(100000);
+       #endif
+               int newTime = SDL_GetTicks();
+               int diff = newTime - startTime;
+               startTime = newTime;
+               data->task->timeOut -= diff;
+               SDL_mutexP(data->task->statusMutex);
+               int status = data->task->status;
+               SDL_mutexV(data->task->statusMutex);
+               //only 1 second left, lets send a message
+               if (data->task->message == 0 && (status == SP_C4A_CANCELED || data->task->timeOut <= 1000))
+                       data->task->message = 1;
+               //time is over. If the message is reset we assume the thread will finish, otherwise...
+               if (data->task->message == 1 && (status == SP_C4A_CANCELED || data->task->timeOut <= 0))
+               {
+                       //Waiting for the write cache mutex ANYWAY.
+                       SDL_mutexP(spCacheMutex);
+                       SDL_KillThread(thread);
+                       SDL_mutexV(spCacheMutex);
+                       data->task->result = 1;
+                       SDL_mutexP(data->task->statusMutex);
+                       if (data->task->timeOut <= 0)
+                               data->task->status = SP_C4A_TIMEOUT;
+                       data->task->threadStatus = 0;
+                       SDL_mutexV(data->task->statusMutex);
+                       int result = data->task->result;
+                       data->task->dataPointer = NULL;
+                       free(data);
+                       return result;
+               }
+               if (status <= 0) //finished somehow
+               {                       
+                       SDL_WaitThread(thread,&(data->task->result));
+                       SDL_mutexP(data->task->statusMutex);
+                       data->task->threadStatus = 0;
+                       SDL_mutexV(data->task->statusMutex);
+                       int result = data->task->result;
+                       data->task->dataPointer = NULL;
+                       free(data);
+                       return result;
+               }
+       }
+}
+
+char* my_strchr(char* buffer, char c, char ignore)
+{
+       int i;
+       int in_ignore = 0;
+       for (i = 0; buffer[i]!=0; i++)
+       {
+               if (buffer[i] == ignore)
+                       in_ignore = 1-in_ignore;
+               if (!in_ignore && buffer[i] == c)
+                       return &(buffer[i]);
+       }
+       return NULL;
+}
+
+void fill_between_paraphrases(char* buffer, char* dest, int max_size)
+{
+       int i,j = 0;
+       int in_paraphrases = 0;
+       for (i = 0; buffer[i]!=0; i++)
+       {
+               if (buffer[i] == '\"')
+               {
+                       switch (in_paraphrases)
+                       {
+                               case 0: in_paraphrases = 1; break;
+                               case 1: dest[j]=0;return;
+                       }
+                       continue;
+               }
+               if (in_paraphrases)
+               {
+                       dest[j] = buffer[i];
+                       j++;
+                       if (j == max_size)
+                       {
+                               dest[j-1] = 0;
+                               return;
+                       }
+               }
+       }
+}
+
+void internal_CreateDirectoryChain( const char* directories)
+{
+       //Creating copy:
+       int len = strlen(directories)+1;
+       #ifdef __GNUC__
+               char directoriesCopy[len];
+       #else
+               char* directoriesCopy = (char*)malloc( len * sizeof(char) );
+       #endif
+       memcpy(directoriesCopy,directories,len);
+       //Splitting in subdirectories
+       char* subString = directoriesCopy;
+       char* endOfString = strchr(subString,'/');
+       if (endOfString == NULL)
+               endOfString = strchr(subString,0);
+       while (endOfString)
+       {
+               char oldChar = endOfString[0];
+               endOfString[0] = 0;
+               #ifdef WIN32
+
+                       if (CreateDirectory(directoriesCopy,NULL))
+                       {}
+                       else
+                       if (GetLastError() != ERROR_ALREADY_EXISTS)
+                               break;
+               #else
+                       int error = mkdir(directoriesCopy,0777);
+                       if (errno == 0 || errno == EEXIST || errno == ENOENT) //thats okay :)
+                       {}
+                       else //not okay
+                               break;
+               #endif
+               endOfString[0] = oldChar;
+               if (oldChar == 0)
+                       break;
+               subString = &(endOfString[1]);
+               endOfString = strchr(subString,'/');
+               if (endOfString == NULL)
+                       endOfString = strchr(subString,0);
+       }
+       #ifndef __GNUC__
+               free(directoriesCopy);
+       #endif
+}
+
+#ifdef PANDORA
+       #define PROFILE_FILENAME_MAKRO char *locate_filename = pnd_locate_filename ( "/media/*/pandora/appdata/c4a-mame/:.", "c4a-prof" ); \
+               char filename[256] = "./c4a-prof"; \
+               if (locate_filename) \
+                       sprintf(filename,"%s",locate_filename); \
+               else \
+               { \
+                       locate_filename = pnd_locate_filename ( "/media/*/pandora/:.", "appdata" ); \
+                       if (locate_filename) \
+                       { \
+                               sprintf(filename,"%s/c4a-mame",locate_filename); \
+                               internal_CreateDirectoryChain(filename); \
+                               sprintf(filename,"%s/c4a-mame/c4a-prof",locate_filename); \
+                       } \
+               }
+#elif defined GCW || (defined X86CPU && !defined WIN32)
+       #define PROFILE_FILENAME_MAKRO char filename[256]; \
+               sprintf(filename,"%s/.config/compo4all",getenv("HOME"));\
+               internal_CreateDirectoryChain(filename);\
+               sprintf(filename,"%s/.config/compo4all/c4a-prof",getenv("HOME"));
+#else
+       #define PROFILE_FILENAME_MAKRO char filename[256] = "./c4a-prof";
+#endif
+
+PREFIX void spNetC4ASetCaching(int value)
+{
+       spNetC4ACaching = value;
+}
+
+void set_cache_filename()
+{
+       PROFILE_FILENAME_MAKRO
+       sprintf(spCacheFilename,"%s",filename);
+       sprintf(&spCacheFilename[strlen(spCacheFilename)-4],"cache");
+}
+
+PREFIX spNetC4AProfilePointer spNetC4AGetProfile()
+{
+       set_cache_filename();
+       spNetC4AProfilePointer profile = NULL;
+       PROFILE_FILENAME_MAKRO
+       //Parsing the file
+       SDL_RWops *file=SDL_RWFromFile(filename,"rb");
+       if (file == NULL)
+               return NULL;
+       profile = (spNetC4AProfilePointer)malloc(sizeof(spNetC4AProfile));
+       char buffer[2048];
+       internal_spNet_spReadOneLine(file,buffer,2048);
+       internal_spNet_spReadOneLine(file,buffer,2048);
+       char* pos = strstr( buffer, "\"longname\":");
+       pos+=11;
+       fill_between_paraphrases( pos, profile->longname, 256);
+       
+       pos = strstr( buffer, "\"shortname\":");
+       pos+=12;
+       fill_between_paraphrases( pos, profile->shortname, 256);
+       
+       pos = strstr( buffer, "\"prid\":");
+       pos+=7;
+       fill_between_paraphrases( pos, profile->prid, 256);
+
+       pos = strstr( buffer, "\"email\":");
+       pos+=8;
+       fill_between_paraphrases( pos, profile->email, 256);
+
+       pos = strstr( buffer, "\"password\":");
+       pos+=11;
+       fill_between_paraphrases( pos, profile->password, 256);
+       SDL_RWclose(file);
+       return profile;
+}
+
+PREFIX void spNetC4AFreeProfile(spNetC4AProfilePointer profile)
+{
+       if (profile)
+               free(profile);
+}
+
+int c4a_getgame_thread(void* data)
+{
+       getgamePointer gameData = ((getgamePointer)data);
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               SDL_mutexP(gameData->task->statusMutex);
+               gameData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(gameData->task->statusMutex);
+               return 1;
+       }       
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+       {
+               SDL_mutexP(gameData->task->statusMutex);
+               gameData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(gameData->task->statusMutex);
+               return 1;
+       }
+       char get_string[512] = "GET /curgamelist_1\n\n";
+       if (spNetSendHTTP(connection,get_string) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(gameData->task->statusMutex);
+               gameData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(gameData->task->statusMutex);
+               return 1;
+       }
+       //skeezix saves the top500. So 100 byte should be enough...
+       //Haha. NOT! minislug had 50950 with a top 500...
+       char buffer[100001]; 
+       int length;
+       if ((length = spNetReceiveHTTP(connection,buffer,100000)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(gameData->task->statusMutex);
+               gameData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(gameData->task->statusMutex);
+               return 1;
+       }
+       buffer[length] = 0;
+       spNetCloseTCP(connection);
+       //Searching the first [
+       char* found = strchr( buffer, '[' );
+       if (found == NULL)
+       {
+               SDL_mutexP(gameData->task->statusMutex);
+               gameData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(gameData->task->statusMutex);
+               return 1;
+       }
+       //Reading game by game
+       //Searching the starting {
+       while (found)
+       {
+               char* start = strchr( found, '{' );
+               if (start == NULL)
+               {
+                       SDL_mutexP(gameData->task->statusMutex);
+                       gameData->task->status = SP_C4A_ERROR;
+                       SDL_mutexV(gameData->task->statusMutex);
+                       return 1;
+               }
+               char* end = my_strchr( start, '}', '\"'); //ignore "text}"-parts
+               if (start == NULL)
+               {
+                       SDL_mutexP(gameData->task->statusMutex);
+                       gameData->task->status = SP_C4A_ERROR;
+                       SDL_mutexV(gameData->task->statusMutex);
+                       return 1;
+               }
+               //Creating substring:
+               end[0] = 0;
+               //Now we search in the substring
+               //Search for the long name:
+               char* pos = strstr( start, "\"longname\":");
+               pos+=11;
+               char longname[256];
+               fill_between_paraphrases( pos, longname, 128);
+               
+               pos = strstr( start, "\"gamename\":");
+               pos+=11;
+               char shortname[256];
+               fill_between_paraphrases( pos, shortname, 128);
+               
+               pos = strstr( start, "\"genre\":");
+               pos+=8;
+               char genre[256];
+               fill_between_paraphrases( pos, genre, 128);
+               
+               pos = strstr( start, "\"field\":");
+               pos+=8;
+               char field[256];
+               fill_between_paraphrases( pos, field, 128);
+               
+               pos = strstr( start, "\"status\":");
+               pos+=9;
+               char status[256];
+               fill_between_paraphrases( pos, status, 128);
+               
+               //Re"inserting" substring:
+               end[0] = '}';
+               found = strchr( end, '{' );
+               
+               //Adding the found stuff to the array:
+               spNetC4AGamePointer new_game = (spNetC4AGamePointer)malloc(sizeof(spNetC4AGame));
+               sprintf(new_game->longname,"%s",longname);
+               sprintf(new_game->shortname,"%s",shortname);
+               sprintf(new_game->genre,"%s",genre);
+               if (strcmp(status,"available") == 0)
+                       new_game->status = 1;
+               else
+               if (strcmp(status,"active") == 0)
+                       new_game->status = 2;
+               else
+                       new_game->status = 0;
+               if (strcmp(field,"arcade") == 0)
+                       new_game->field = 1;
+               else
+               if (strcmp(field,"indie") == 0)
+                       new_game->field = 0;
+               else
+                       new_game->field = -1;
+               
+               //sorted insert
+               //Searching the next and before element:
+               spNetC4AGamePointer before = NULL;
+               spNetC4AGamePointer next = *(gameData->game);
+               while (next)
+               {
+                       if (strcmp(new_game->longname,next->longname) < 0)
+                               break;
+                       before = next;
+                       next = next->next;
+               }
+               if (before == NULL) //new first element!
+               {
+                       new_game->next = next;
+                       (*(gameData->game)) = new_game;
+               }
+               else
+               {
+                       before->next = new_game;
+                       new_game->next = next;
+               }
+       }       
+       SDL_mutexP(gameData->task->statusMutex);
+       gameData->task->status = SP_C4A_OK;
+       SDL_mutexV(gameData->task->statusMutex);
+       return 0;
+}
+
+PREFIX int spNetC4AGetGame(spNetC4AGamePointer* gameList,int timeOut)
+{
+       (*gameList) = NULL;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               getgamePointer data = (getgamePointer)malloc(sizeof(getgameType));
+               data->function = c4a_getgame_thread;
+               data->task = spGlobalC4ATask;
+               data->game = gameList;
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;       
+}
+
+PREFIX spNetC4ATaskPointer spNetC4AGetGameParallel(spNetC4AGamePointer* gameList,int timeOut)
+{
+       (*gameList) = NULL;
+       spNetC4ATaskPointer task = createNewC4ATask();
+       task->status = SP_C4A_PROGRESS;
+       //Starting a background thread, which does the fancy stuff
+       getgamePointer data = (getgamePointer)malloc(sizeof(getgameType));
+       data->function = c4a_getgame_thread;
+       data->task = task;
+       data->game = gameList;
+       task->dataPointer = data;
+       task->timeOut = timeOut;
+       task->threadStatus = 1;
+       #ifdef _MSC_VER
+               task->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+       #else
+               task->thread = SDL_CreateThread(spNetC4AUberThread,data);
+       #endif
+       return task;
+}
+
+int c4a_getscore_thread(void* data)
+{
+       getscorePointer scoreData = (getscorePointer)data;
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               SDL_mutexP(scoreData->task->statusMutex);
+               scoreData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(scoreData->task->statusMutex);
+               return 1;
+       }       
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+       {
+               SDL_mutexP(scoreData->task->statusMutex);
+               scoreData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(scoreData->task->statusMutex);
+               return 1;
+       }
+       char get_string[512];
+       if (scoreData->year && scoreData->month)
+               sprintf(get_string,"GET /json_1/%s/%i%02i/\n\n",scoreData->game,scoreData->year,scoreData->month);
+       else
+               sprintf(get_string,"GET /json_1/%s/all\n\n",scoreData->game);
+       if (spNetSendHTTP(connection,get_string) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(scoreData->task->statusMutex);
+               scoreData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(scoreData->task->statusMutex);
+               return 1;
+       }
+       //skeezix saves the top500. So 100 byte should be enough...
+       //Haha. NOT! minislug had 50950 with a top 500...
+       char buffer[100001]; 
+       int length;
+       if ((length = spNetReceiveHTTP(connection,buffer,100000)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(scoreData->task->statusMutex);
+               scoreData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(scoreData->task->statusMutex);
+               return 1;
+       }
+       buffer[length] = 0;
+       spNetCloseTCP(connection);
+       //Searching the first [
+       char* found = strchr( buffer, '[' );
+       if (found == NULL)
+       {
+               SDL_mutexP(scoreData->task->statusMutex);
+               scoreData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(scoreData->task->statusMutex);
+               return 1;
+       }
+       //Reading score by score
+       //Searching the starting {
+       int rank = 1;
+       spNetC4AScorePointer lastScore = NULL;
+       while (found)
+       {
+               char* start = strchr( found, '{' );
+               if (start == NULL)
+               {
+                       SDL_mutexP(scoreData->task->statusMutex);
+                       scoreData->task->status = SP_C4A_ERROR;
+                       SDL_mutexV(scoreData->task->statusMutex);
+                       return 1;
+               }
+               char* end = my_strchr( start, '}', '\"'); //ignore "text}"-parts
+               if (start == NULL)
+               {
+                       SDL_mutexP(scoreData->task->statusMutex);
+                       scoreData->task->status = SP_C4A_ERROR;
+                       SDL_mutexV(scoreData->task->statusMutex);
+                       return 1;
+               }
+               //Creating substring:
+               end[0] = 0;
+               //Now we search in the substring
+               //Search for the long name:
+               char* pos = strstr( start, "\"longname\":");
+               pos+=11;
+               char longname[128];
+               fill_between_paraphrases( pos, longname, 128);
+               
+               pos = strstr( start, "\"shortname\":");
+               pos+=12;
+               char shortname[128];
+               fill_between_paraphrases( pos, shortname, 128);
+               
+               pos = strstr( start, "\"score\":");
+               pos+=8;
+               int score = atoi(pos);
+               
+               pos = strstr( start, "\"time\":");
+               pos+=7;
+               Uint64 commitTime = (Uint64)(atof(pos)); //float becase of bigger numbers
+               
+               //Re"inserting" substring:
+               end[0] = '}';
+               found = strchr( end, '{' );
+               
+               //Adding the found stuff to the array:
+               if (longname[0] == 0 || shortname[0] == 0)
+                       continue;
+               if (scoreData->profile && (strcmp(scoreData->profile->longname,longname) != 0 || strcmp(scoreData->profile->shortname,shortname) != 0))
+                       continue;
+               spNetC4AScorePointer new_score = (spNetC4AScorePointer)malloc(sizeof(spNetC4AScore));
+               sprintf(new_score->longname,"%s",longname);
+               sprintf(new_score->shortname,"%s",shortname);
+               new_score->score = score;
+               new_score->commitTime = commitTime;
+               new_score->next = NULL;
+               new_score->rank = rank;
+               if (lastScore == NULL)
+                       (*(scoreData->score)) = new_score;
+               else
+                       lastScore->next = new_score;
+               lastScore = new_score;
+               rank++;
+       }       
+       
+       SDL_mutexP(scoreData->task->statusMutex);
+       scoreData->task->status = SP_C4A_OK;
+       SDL_mutexV(scoreData->task->statusMutex);
+       return 0;
+}
+
+PREFIX void spNetC4ADeleteGames(spNetC4AGamePointer* gameList)
+{
+       if (gameList == NULL)
+               return;
+       while (*gameList)
+       {
+               spNetC4AGamePointer next = (*gameList)->next;
+               free(*gameList);
+               (*gameList) = next;
+       }
+}
+
+PREFIX int spNetC4AGetScore(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int timeOut)
+{
+       (*scoreList) = NULL;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               getscorePointer data = (getscorePointer)malloc(sizeof(getscoreType));
+               data->function = c4a_getscore_thread;
+               data->task = spGlobalC4ATask;
+               data->score = scoreList;
+               data->profile = profile;
+               data->year = 0;
+               data->month = 0;
+               sprintf(data->game,"%s",game);
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+PREFIX int spNetC4AGetScoreOfMonth(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int year,int month,int timeOut)
+{
+       (*scoreList) = NULL;
+       if (month < 1 || month > 12)
+               return 1;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               getscorePointer data = (getscorePointer)malloc(sizeof(getscoreType));
+               data->function = c4a_getscore_thread;
+               data->task = spGlobalC4ATask;
+               data->score = scoreList;
+               data->profile = profile;
+               data->year = year;
+               data->month = month;
+               sprintf(data->game,"%s",game);
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+PREFIX spNetC4ATaskPointer spNetC4AGetScoreParallel(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int timeOut)
+{
+       (*scoreList) = NULL;
+       spNetC4ATaskPointer task = createNewC4ATask();
+       task->status = SP_C4A_PROGRESS;
+       //Starting a background thread, which does the fancy stuff
+       getscorePointer data = (getscorePointer)malloc(sizeof(getscoreType));
+       data->function = c4a_getscore_thread;
+       data->task = task;
+       data->score = scoreList;
+       data->profile = profile;
+       data->year = 0;
+       data->month = 0;
+       sprintf(data->game,"%s",game);
+       task->dataPointer = data;
+       task->timeOut = timeOut;
+       task->threadStatus = 1;
+       #ifdef _MSC_VER
+               task->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+       #else
+               task->thread = SDL_CreateThread(spNetC4AUberThread,data);
+       #endif
+       return task;
+}
+
+PREFIX spNetC4ATaskPointer spNetC4AGetScoreOfMonthParallel(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int year,int month,int timeOut)
+{
+       (*scoreList) = NULL;
+       if (month < 1 || month > 12)
+               return NULL;
+       spNetC4ATaskPointer task = createNewC4ATask();
+       task->status = SP_C4A_PROGRESS;
+       SDL_mutexV(task->statusMutex);
+       //Starting a background thread, which does the fancy stuff
+       getscorePointer data = (getscorePointer)malloc(sizeof(getscoreType));
+       data->function = c4a_getscore_thread;
+       data->task = task;
+       data->score = scoreList;
+       data->profile = profile;
+       data->year = year;
+       data->month = month;
+       sprintf(data->game,"%s",game);
+       task->dataPointer = data;
+       task->timeOut = timeOut;
+       task->threadStatus = 1;
+       #ifdef _MSC_VER
+               task->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+       #else
+               task->thread = SDL_CreateThread(spNetC4AUberThread,data);
+       #endif
+       return task;
+}
+
+PREFIX void spNetC4AFilterScore(spNetC4AScorePointer* scoreList)
+{
+       spNetC4AScorePointer mom = *scoreList;
+       spNetC4AScorePointer before = NULL;
+       while (mom)
+       {
+               //Search for mom:
+               spNetC4AScorePointer inner = *scoreList;
+               while (inner != NULL && inner != mom)
+               {
+                       if (strcmp(mom->longname,inner->longname) == 0 &&
+                               strcmp(mom->shortname,inner->shortname) == 0)
+                               break;
+                       inner = inner->next;
+               }
+               spNetC4AScorePointer next = mom->next;
+               //already there!
+               if (inner != mom)
+               {
+                       if (before)
+                               before->next = next;
+                       free(mom);
+               }
+               else
+                       before = mom;
+               mom = next;
+       }
+}
+
+static int do_the_real_c4a_commit(spNetIP ip,commitPointer commitData,char* game,char* system,char* prid,int score)
+{
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+               return 1;
+       char commit_string[2048];
+       sprintf(commit_string,"PUT /plugtally_1/scoreonly/%s/%s/%s?score=%i HTTP/1.1\r\nHost: skeezix.wallednetworks.com:13001\r\nAccept: */*\r\nContent-Length: 0\r\nExpect: 100-continue\r\n",game,system,prid,score);
+       if (spNetSendHTTP(connection,commit_string) == 0)
+       {
+               spNetCloseTCP(connection);
+               return 1;
+       }
+       spNetCloseTCP(connection);
+       //Adding to scoreList ;)
+       if (commitData->scoreList)
+       {
+               spNetC4AScorePointer new_score = (spNetC4AScorePointer)malloc(sizeof(spNetC4AScore));
+               sprintf(new_score->longname,"%s",commitData->profile->longname);
+               sprintf(new_score->shortname,"%s",commitData->profile->shortname);
+               new_score->score = score;
+               new_score->commitTime = time(NULL);
+               new_score->next = (*(commitData->scoreList));
+               (*(commitData->scoreList)) = new_score;
+       }
+       return 0;
+}
+
+
+#ifndef __GNUC__
+       #include <windows.h>
+       #include <tchar.h>
+#else
+       #include <dirent.h>
+       #include <sys/types.h>
+       #include <sys/stat.h>
+       #include <unistd.h>
+#endif
+
+int c4a_commit_thread(void* data)
+{
+       commitPointer commitData = (commitPointer)data;
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               if (spNetC4ACaching && commitData->game[0] != 0)
+                       write_to_cache(commitData->game,commitData->system,commitData->profile->prid,commitData->score,1);
+               SDL_mutexP(commitData->task->statusMutex);
+               commitData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(commitData->task->statusMutex);
+               return 1;
+       }
+       if (commitData->game[0] != 0)
+       {
+               if (do_the_real_c4a_commit(ip,commitData,commitData->game,commitData->system,commitData->profile->prid,commitData->score))
+               {
+                       if (spNetC4ACaching)
+                               write_to_cache(commitData->game,commitData->system,commitData->profile->prid,commitData->score,1);
+                       SDL_mutexP(commitData->task->statusMutex);
+                       commitData->task->status = SP_C4A_ERROR;
+                       SDL_mutexV(commitData->task->statusMutex);
+                       return 1;
+               }
+       }
+       //Checking for stuff in the cache
+       SDL_mutexP(spCacheMutex);
+       cachePointer cache = read_cache();
+       if (cache)
+       {
+               while (cache)
+               {
+                       cachePointer next = cache->next;
+                       if (do_the_real_c4a_commit(ip,commitData,cache->game,cache->system,cache->prid,cache->score))
+                               break;
+                       free(cache);
+                       cache = next;
+                       if (commitData->task->message == 1)
+                       {
+                               commitData->task->message = 2;
+                               break;
+                       }
+               }
+               #ifdef WIN32
+                       DeleteFile(spCacheFilename);
+               #else
+                       remove(spCacheFilename);
+               #endif
+               //if cache is still existing, we need to write back the rest of the cache
+               while (cache)
+               {
+                       cachePointer next = cache->next;
+                       write_to_cache(cache->game,cache->system,cache->prid,cache->score,0);
+                       free(cache);
+                       cache = next;
+               }
+                       
+       }
+       SDL_mutexV(spCacheMutex);
+       
+       SDL_mutexP(commitData->task->statusMutex);
+       commitData->task->status = SP_C4A_OK;
+       SDL_mutexV(commitData->task->statusMutex);
+       return 0;
+}
+
+PREFIX int spNetC4AHowManyCached()
+{
+       int result = 0;
+       SDL_mutexP(spCacheMutex);
+       SDL_RWops *file = SDL_RWFromFile(spCacheFilename, "rb");
+       if (file)
+       {
+               char buffer[256*3+sizeof(int)];
+               while (1)
+               {
+                       if (SDL_RWread(file,buffer,256*3+sizeof(int),1) <= 0)
+                               break;
+                       result++;
+               }
+               SDL_RWclose(file);
+       }
+       SDL_mutexV(spCacheMutex);
+       return result;
+}
+
+int already_in_highscore(spNetC4AScorePointer scoreList,spNetC4AProfilePointer profile,int score)
+{
+       if (scoreList == NULL)
+               return 0;
+       while (scoreList)
+       {
+               if (strcmp(scoreList->longname,profile->longname) == 0 &&
+                   strcmp(scoreList->shortname,profile->shortname) == 0 &&
+                   scoreList->score == score)
+                       return 1;
+               scoreList = scoreList->next;
+       }
+       return 0;
+}
+
+#ifdef GP2X
+       #define SET_SYSTEM(system) sprintf(system,"gp2x");
+#elif defined(CAANOO)
+       #define SET_SYSTEM(system) sprintf(system,"caanoo");
+#elif defined(WIZ)
+       #define SET_SYSTEM(system) sprintf(system,"wiz");
+#elif defined(DINGUX)
+       #define SET_SYSTEM(system) sprintf(system,"dingux");
+#elif defined(GCW)     
+       #define SET_SYSTEM(system) sprintf(system,"gcw");
+#elif defined(PANDORA) 
+       #define SET_SYSTEM(system) sprintf(system,"pandora");
+#elif defined(WIN32)
+       #define SET_SYSTEM(system) sprintf(system,"win32");
+#else
+       #define SET_SYSTEM(system) sprintf(system,"linux");
+#endif
+
+
+PREFIX int spNetC4ACommitScore(spNetC4AProfilePointer profile,char* game,int score,spNetC4AScorePointer* scoreList,int timeOut)
+{
+       if (profile == NULL && game[0]!=0)
+               return 1;
+       int already = 0;
+       if (scoreList && already_in_highscore(*scoreList,profile,score))
+               already = 1;
+       if (timeOut == 0)
+       {
+               if (already == 0 && spNetC4ACaching)
+               {
+                       char system[256];
+                       SET_SYSTEM(system);
+                       write_to_cache(game,system,profile->prid,score,1);                      
+               }
+               return 1;
+       }
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               commitPointer data = (commitPointer)malloc(sizeof(commitType));
+               data->task = spGlobalC4ATask;
+               data->function = c4a_commit_thread;
+               data->score = score;
+               data->profile = profile;
+               data->scoreList = scoreList;
+               if (already)
+                       data->game[0] = 0;
+               else
+                       sprintf(data->game,"%s",game);
+               SET_SYSTEM(data->system);
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return already;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+PREFIX spNetC4ATaskPointer spNetC4ACommitScoreParallel(spNetC4AProfilePointer profile,char* game,int score,spNetC4AScorePointer* scoreList,int timeOut)
+{
+       if (profile == NULL)
+               return NULL;
+       int already = 0;
+       if (scoreList && already_in_highscore(*scoreList,profile,score))
+               already = 1;
+       if (timeOut == 0)
+       {
+               if (already == 0 && spNetC4ACaching)
+               {
+                       char system[256];
+                       SET_SYSTEM(system);
+                       write_to_cache(game,system,profile->prid,score,1);                      
+               }
+               return NULL;
+       }
+       spNetC4ATaskPointer task = createNewC4ATask();
+       task->status = SP_C4A_PROGRESS;
+       //Starting a background thread, which does the fancy stuff
+       commitPointer data = (commitPointer)malloc(sizeof(commitType));
+       data->task = task;
+       data->function = c4a_commit_thread;
+       data->score = score;
+       data->profile = profile;
+       data->scoreList = scoreList;
+       if (already)
+               data->game[0] = 0;
+       else
+               sprintf(data->game,"%s",game);
+       SET_SYSTEM(data->system);
+       task->dataPointer = data;
+       task->timeOut = timeOut;
+       task->threadStatus = 1;
+       #ifdef _MSC_VER
+               task->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+       #else
+               task->thread = SDL_CreateThread(spNetC4AUberThread,data);
+       #endif
+       return task;
+}
+
+PREFIX void spNetC4ACopyScoreList(spNetC4AScorePointer* scoreList,spNetC4AScorePointer* newList)
+{
+       if (scoreList == NULL)
+               return;
+       if (newList == NULL)
+               return;
+       spNetC4AScorePointer mom = *scoreList;
+       spNetC4AScorePointer last = NULL;
+       while (mom)
+       {
+               spNetC4AScorePointer copy_score = (spNetC4AScorePointer)malloc(sizeof(spNetC4AScore));
+               sprintf(copy_score->longname,"%s",mom->longname);
+               sprintf(copy_score->shortname,"%s",mom->shortname);
+               copy_score->score = mom->score;
+               copy_score->commitTime = mom->commitTime;
+               copy_score->rank = mom->rank;
+               if (last)
+                       last->next = copy_score;
+               else
+                       *newList = copy_score;
+               last = copy_score;
+               mom = mom->next;
+       }
+       if (last)
+               last->next = NULL;
+       else
+               *newList = NULL;
+}
+
+typedef struct __ScoreNameStruct *__ScoreNamePointer;
+typedef struct __ScoreNameStruct {
+       char longname[256];
+       char shortname[256];
+       __ScoreNamePointer next;
+} __ScoreName;
+
+PREFIX void spNetC4AMakeScoresUnique(spNetC4AScorePointer* scoreList)
+{
+       if (scoreList == NULL)
+               return;
+       spNetC4AScorePointer mom = *scoreList;
+       spNetC4AScorePointer before = NULL;
+       __ScoreNamePointer name = NULL;
+       __ScoreNamePointer searchStart = NULL;
+       while (mom)
+       {
+               //search mom in name:
+               __ScoreNamePointer search = searchStart;
+               while (search)
+               {
+                       if (strcmp(mom->shortname,search->shortname) == 0 &&
+                               strcmp(mom->longname,search->longname) == 0 )
+                               break; //found
+                       search = search->next;
+               }
+               if (search) //found -> remove
+               {
+                       spNetC4AScorePointer next = mom->next;
+                       before->next = next;
+                       free(mom);
+                       mom = next;
+               }
+               else //add
+               {
+                       __ScoreNamePointer add = (__ScoreNamePointer)malloc(sizeof(__ScoreName));
+                       sprintf(add->longname,"%s",mom->longname);
+                       sprintf(add->shortname,"%s",mom->shortname);
+                       add->next = searchStart;
+                       searchStart = add;
+                       before = mom;
+                       mom = mom->next;
+               }
+       }
+       while (searchStart)
+       {
+               __ScoreNamePointer next = searchStart->next;
+               free(searchStart);
+               searchStart = next;
+       }
+}
+
+PREFIX void spNetC4ADeleteScores(spNetC4AScorePointer* scoreList)
+{
+       if (scoreList == NULL)
+               return;
+       while (*scoreList)
+       {
+               spNetC4AScorePointer next = (*scoreList)->next;
+               free(*scoreList);
+               (*scoreList) = next;
+       }
+}
+
+void fill_with_random_hex(char* buffer,int count)
+{
+       int i;
+       for (i = 0; i < count; i++)
+       {
+               int c = rand()%16;
+               char cha;
+               if (c < 10)
+                       cha = c+'0';
+               else
+                       cha = c-10+'a';
+               buffer[i] = cha;
+       }
+}
+
+int c4a_create_thread(void* data)
+{
+       createPointer createData = (createPointer)data;
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }       
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       char create_string[2048];
+       char buffer[2048];
+       char prid[37] = "";
+       //generating a new, random prid:
+       fill_with_random_hex(prid,8);
+       prid[ 8]='-';
+       fill_with_random_hex(&(prid[ 9]),4);
+       prid[13]='-';
+       fill_with_random_hex(&(prid[14]),4);
+       prid[18]='-';
+       fill_with_random_hex(&(prid[19]),4);
+       prid[23]='-';
+       fill_with_random_hex(&(prid[24]),12);
+       prid[36]=0;
+       sprintf(create_string,"{\"email\": \"%s\", \"shortname\": \"%s\", \"password\": \"%s\", \"prid\": \"%s\", \"longname\": \"%s\"}",createData->email,createData->shortname,createData->password,prid,createData->longname);
+       sprintf(buffer,"PUT /setprofile_1 HTTP/1.1\r\nUser-Agent: sparrowNet/1.0\r\nHost: %i.%i.%i.%i:13001\r\nAccept: */*\r\nContent-Length: %i\r\nExpect: 100-continue\r\n\r\n",ip.address.ipv4_bytes[0],ip.address.ipv4_bytes[1],ip.address.ipv4_bytes[2],ip.address.ipv4_bytes[3],strlen(create_string));
+       if (spNetSendTCP(connection,buffer,strlen(buffer)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       if (spNetSendTCP(connection,create_string,strlen(create_string)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       spNetCloseTCP(connection);
+       PROFILE_FILENAME_MAKRO
+       SDL_RWops *file=SDL_RWFromFile(filename,"wb");
+       SDL_RWwrite(file,prid,36,1);
+       char c = '\n';
+       SDL_RWwrite(file,&c,1,1);
+       SDL_RWwrite(file,create_string,strlen(create_string),1);
+       SDL_RWclose(file);
+       (*(createData->profile)) = (spNetC4AProfilePointer)malloc(sizeof(spNetC4AProfile));
+       sprintf((*(createData->profile))->longname,"%s",createData->longname);
+       sprintf((*(createData->profile))->shortname,"%s",createData->shortname);
+       sprintf((*(createData->profile))->password,"%s",createData->password);
+       sprintf((*(createData->profile))->email,"%s",createData->email);
+       sprintf((*(createData->profile))->prid,"%s",prid);
+       SDL_mutexP(createData->task->statusMutex);
+       createData->task->status = SP_C4A_OK;
+       SDL_mutexV(createData->task->statusMutex);
+       return 0;       
+}
+
+PREFIX int spNetC4ACreateProfile(spNetC4AProfilePointer* profile, char* longname,char* shortname,char* password,char* email,int timeOut)
+{
+       if (profile == NULL)
+               return 1;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               createPointer data = (createPointer)malloc(sizeof(createType));
+               data->task = spGlobalC4ATask;
+               data->function = c4a_create_thread;
+               data->profile = profile;
+               sprintf(data->longname,"%s",longname);
+               sprintf(data->shortname,"%s",shortname);
+               sprintf(data->password,"%s",password);
+               sprintf(data->email,"%s",email);
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+int c4a_delete_thread(void* data)
+{
+       createPointer createData = (createPointer)data;
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }       
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       char create_string[2048];
+       char buffer[2048];
+       sprintf(create_string,"{\"email\": \"%s\", \"shortname\": \"%s\", \"password\": \"%s\", \"prid\": \"%s\", \"longname\": \"%s\"}",(*(createData->profile))->email,(*(createData->profile))->shortname,(*(createData->profile))->password,(*(createData->profile))->prid,(*(createData->profile))->longname);
+       sprintf(buffer,"PUT /delprofile_1 HTTP/1.1\r\nUser-Agent: sparrowNet/1.0\r\nHost: %i.%i.%i.%i:13001\r\nAccept: */*\r\nContent-Length: %i\r\nExpect: 100-continue\r\n\r\n",ip.address.ipv4_bytes[0],ip.address.ipv4_bytes[1],ip.address.ipv4_bytes[2],ip.address.ipv4_bytes[3],strlen(create_string));
+       if (spNetSendTCP(connection,buffer,strlen(buffer)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       if (spNetSendTCP(connection,create_string,strlen(create_string)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       spNetCloseTCP(connection);
+       (*(createData->profile)) = NULL;        
+       if (createData->deleteFile)
+               spNetC4ADeleteProfileFile();
+       SDL_mutexP(createData->task->statusMutex);
+       createData->task->status = SP_C4A_OK;
+       SDL_mutexV(createData->task->statusMutex);
+       return 0;
+}
+
+PREFIX int spNetC4ADeleteAccount(spNetC4AProfilePointer* profile,int deleteFile,int timeOut)
+{
+       if (profile == NULL)
+               return 1;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               createPointer data = (createPointer)malloc(sizeof(createType));
+               data->task = spGlobalC4ATask;
+               data->function = c4a_delete_thread;
+               data->profile = profile;
+               data->deleteFile = deleteFile;
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,c4a_delete_thread);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,c4a_delete_thread);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+PREFIX void spNetC4ADeleteProfileFile()
+{
+       PROFILE_FILENAME_MAKRO
+//Copied from spRemoveFile to avoid dependencies
+#ifdef WIN32
+       DeleteFile(filename);
+#else
+       remove(filename);
+#endif 
+}
+
+int c4a_edit_thread(void* data)
+{
+       createPointer createData = (createPointer)data;
+       spNetIP ip = spNetResolve("skeezix.wallednetworks.com",13001);
+       if (ip.address.ipv4 == SP_INVALID_IP)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }       
+       spNetTCPConnection connection = spNetOpenClientTCP(ip);
+       if (connection == NULL)
+       {
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       char create_string[2048];
+       char buffer[2048];
+       sprintf(create_string,"{\"email\": \"%s\", \"shortname\": \"%s\", \"password\": \"%s\", \"prid\": \"%s\", \"longname\": \"%s\"}",createData->email,createData->shortname,createData->password,(*(createData->profile))->prid,createData->longname);
+       sprintf(buffer,"PUT /setprofile_1 HTTP/1.1\r\nUser-Agent: sparrowNet/1.0\r\nHost: %i.%i.%i.%i:13001\r\nAccept: */*\r\nContent-Length: %i\r\nExpect: 100-continue\r\n\r\n",ip.address.ipv4_bytes[0],ip.address.ipv4_bytes[1],ip.address.ipv4_bytes[2],ip.address.ipv4_bytes[3],strlen(create_string));
+       if (spNetSendTCP(connection,buffer,strlen(buffer)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       if (spNetSendTCP(connection,create_string,strlen(create_string)) == 0)
+       {
+               spNetCloseTCP(connection);
+               SDL_mutexP(createData->task->statusMutex);
+               createData->task->status = SP_C4A_ERROR;
+               SDL_mutexV(createData->task->statusMutex);
+               return 1;
+       }
+       spNetCloseTCP(connection);
+       PROFILE_FILENAME_MAKRO
+       SDL_RWops *file=SDL_RWFromFile(filename,"wb");
+       SDL_RWwrite(file,(*(createData->profile))->prid,strlen((*(createData->profile))->prid),1);
+       char c = '\n';
+       SDL_RWwrite(file,&c,1,1);
+       SDL_RWwrite(file,create_string,strlen(create_string),1);
+       SDL_RWclose(file);
+       sprintf((*(createData->profile))->longname,"%s",createData->longname);
+       sprintf((*(createData->profile))->shortname,"%s",createData->shortname);
+       sprintf((*(createData->profile))->password,"%s",createData->password);
+       sprintf((*(createData->profile))->email,"%s",createData->email);
+       SDL_mutexP(createData->task->statusMutex);
+       createData->task->status = SP_C4A_OK;
+       SDL_mutexV(createData->task->statusMutex);
+       return 0;       
+}
+
+PREFIX int spNetC4AEditProfile(spNetC4AProfilePointer* profile,char* longname,char* shortname,char* password,char* email,int timeOut)
+{
+       if (profile == NULL)
+               return 1;
+       SDL_mutexP(spGlobalC4ATask->statusMutex);
+       if (spGlobalC4ATask->status != SP_C4A_PROGRESS)
+       {
+               spGlobalC4ATask->status = SP_C4A_PROGRESS;
+               SDL_mutexV(spGlobalC4ATask->statusMutex);
+               //Starting a background thread, which does the fancy stuff
+               createPointer data = (createPointer)malloc(sizeof(createType));
+               data->task = spGlobalC4ATask;
+               data->function = c4a_edit_thread;
+               data->profile = profile;
+               sprintf(data->longname,"%s",longname);
+               sprintf(data->shortname,"%s",shortname);
+               sprintf(data->password,"%s",password);
+               sprintf(data->email,"%s",email);
+               spGlobalC4ATask->dataPointer = data;
+               spGlobalC4ATask->timeOut = timeOut;
+               spGlobalC4ATask->threadStatus = 1;
+               #ifdef _MSC_VER
+                       spGlobalC4ATask->thread = SDL_CreateThread((int (__cdecl *)(void *))spNetC4AUberThread,data);
+               #else
+                       spGlobalC4ATask->thread = SDL_CreateThread(spNetC4AUberThread,data);
+               #endif
+               return 0;
+       }
+       SDL_mutexV(spGlobalC4ATask->statusMutex);
+       return 1;
+}
+
+PREFIX int spNetC4AGetStatusParallel(spNetC4ATaskPointer task)
+{
+       SDL_mutexP(task->statusMutex);
+       if (task->threadStatus)
+       {
+               SDL_mutexV(task->statusMutex);
+               return SP_C4A_PROGRESS;
+       }
+       int status = task->status;
+       SDL_mutexV(task->statusMutex);
+       return status;
+}
+
+PREFIX int spNetC4AGetStatus()
+{
+       return spNetC4AGetStatusParallel(spGlobalC4ATask);
+}
+
+PREFIX void spNetC4ACancelTaskParallel(spNetC4ATaskPointer task)
+{
+       SDL_mutexP(task->statusMutex);
+       if (task->status > 0)
+       {
+               task->status = SP_C4A_CANCELED;
+               SDL_mutexV(task->statusMutex);
+               SDL_WaitThread(task->thread,NULL);
+       }
+       else
+               SDL_mutexV(task->statusMutex);
+}
+
+PREFIX void spNetC4ACancelTask()
+{
+       spNetC4ACancelTaskParallel(spGlobalC4ATask);
+}
+
+PREFIX int spNetC4AGetTaskResult()
+{
+       return spGlobalC4ATask->result;
+}
+
+PREFIX int spNetC4AGetTaskResultParallel(spNetC4ATaskPointer task)
+{
+       return task->result;
+}
+
+PREFIX int spNetC4AGetTimeOut()
+{
+       return spGlobalC4ATask->timeOut;
+}
+
+PREFIX int spNetC4AGetTimeOutParallel(spNetC4ATaskPointer task)
+{
+       return task->timeOut;
+}
diff --git a/recipes/fusilli-client/files/sparrowNet.h b/recipes/fusilli-client/files/sparrowNet.h
new file mode 100644 (file)
index 0000000..9f48471
--- /dev/null
@@ -0,0 +1,813 @@
+ /* This file is part of sparrow3d.
+  * Sparrow3d is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation, either version 2 of the License, or
+  * (at your option) any later version.
+  * 
+  * Sparrow3d is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  * 
+  * You should have received a copy of the GNU General Public License
+  * along with Foobar.  If not, see <http://www.gnu.org/licenses/>
+  * 
+  * For feedback and questions about my Files and Projects please mail me,
+  * Alexander Matthes (Ziz) , zizsdl_at_googlemail.com */
+
+#ifndef _SPARROW_NET_H
+#define _SPARROW_NET_H
+
+#include "sparrowDefines.h"
+#include <SDL_net.h>
+#include <SDL_thread.h>
+#include <time.h>
+
+/* File: sparrowNet
+ * 
+ * SparrowNet is a basic network API based on SDL_net. Until now UDP is not
+ * implemented! However, you can use the ip structs from here for the UDP
+ * part of SDL_net on your own. ;)
+ * 
+ * Furthermore sparrowNet has some fancy functions for getting and submitting
+ * scores for the compo4all online highscore system.*/
+
+enum spAddress {IPV4, IPV6};
+
+/* Section: General & TCP Stuff
+ * 
+ * Types and Functions for initializing sparrowNet and sending data over tcp.*/
+
+/* Type: spNetIP
+ * 
+ * An IP address resolved by sparrowNet.
+ * 
+ * Variables:
+ * address.ipv4 (Uint32) - 32 bit ipv4 address
+ * address.ipv4_bytes (Uint8[4]) - 4 x 8bit ipv4 address
+ * address.ipv6 (Uint32[4]) - 128 bit ipv6 address
+ * address.ipv6_bytes (Uint8[16]) - 16 x 8bit ipv6 address
+ * port (Uint16) - port of the address
+ * sdl_address (IPaddress) - ip address struct of SDL*/
+typedef struct spNetIPStruct *spNetIPPointer;
+typedef struct spNetIPStruct {
+       enum spAddress type;
+       union {
+               Uint32 ipv4;
+               Uint8 ipv4_bytes[4];
+               Uint32 ipv6[4];
+               Uint8 ipv6_bytes[16];
+       } address;
+       Uint16 port;
+       IPaddress sdl_address;
+} spNetIP;
+
+typedef struct spNetC4ATaskStruct *spNetC4ATaskPointer;
+typedef struct spNetC4ATaskStruct {
+       SDL_mutex* statusMutex;
+       int status;
+       void *dataPointer;
+       int timeOut;
+       SDL_Thread* thread;
+       int result;
+       int threadStatus;
+       int message;
+} spNetC4ATask;
+
+/* Define: SP_INVALID_IP
+ * 
+ * Same as INADDR_NONE of SDL_Net. Means, that the ip returned by <spNetResolve>
+ * was not found and is invalid. */
+#define SP_INVALID_IP INADDR_NONE
+
+/* Type: spNetTCPConnection 
+ * 
+ * a type for open tcp connections. In fact just SDL_net's TCPsocket.*/
+typedef TCPsocket spNetTCPConnection;
+/* Type: spNetTCPServer
+ * 
+ * a type for server sessions. In fact just SDL_net's TCPsocket.*/
+typedef TCPsocket spNetTCPServer;
+
+/* Function: spInitNet
+ * 
+ * Initializes sparrowNet. Call always before using this library!*/
+PREFIX void spInitNet();
+
+/* Function: spQuitNet
+ * 
+ * Quits sparrowNet.*/
+PREFIX void spQuitNet();
+
+/* Function: spNetResolve
+ * 
+ * Resolves a hostname to an ip. Only ipv4 is supported at the moment!
+ * 
+ * Parameters:
+ * host - the host name
+ * port - the port you want to access (later)
+ * 
+ * Returns:
+ * spNetIP - the ip in the type <spNetIP>. If address.ipv4 is SP_INVALID_IP, the
+ * function calls failed!*/
+PREFIX spNetIP spNetResolve(char* host,Uint16 port);
+
+/* Function: spNetResolveHost
+ * 
+ * Gives you the hostname to an ip.
+ * 
+ * Parameters:
+ * ip - ip the the host you want to know
+ * host - a pointer, where to put the string
+ * host_len - the maximal length of the host string. Keep the ending 0 in mind!
+ * 
+ * Returns:
+ * char* - the pointer "host" from above*/
+PREFIX char* spNetResolveHost(spNetIP ip,char* host,int host_len);
+
+/* Function: spNetOpenClientTCP
+ * 
+ * Opens a connection to an ip
+ * 
+ * Parameters:
+ * ip - the ip
+ * 
+ * Returns:
+ * spNetTCPConnection - handle for the connection */
+PREFIX spNetTCPConnection spNetOpenClientTCP(spNetIP ip); 
+
+/* Function: spNetOpenServerTCP
+ * 
+ * Creates a server, which listens at a port
+ * 
+ * Parameters:
+ * port - the port
+ * 
+ * Returns:
+ * spNetTCPServer - handle for the server*/
+PREFIX spNetTCPServer spNetOpenServerTCP(Uint16 port);
+
+/* Function: spNetAcceptTCP
+ * 
+ * If a client tries to connect to your server, this function returns an
+ * established tcp connection from your server to the client.
+ * 
+ * Parameters:
+ * server - the server returned by <spNetOpenServerTCP>*/
+PREFIX spNetTCPConnection spNetAcceptTCP(spNetTCPServer server);
+
+/* Function: spNetGetConnectionIP
+ * 
+ * Gives you the ip of your connected client.
+ * 
+ * Parameters:
+ * connection - a connection, where you want to know other side
+ * 
+ * Returns
+ * spNetIP - the ip as <spNetIP>*/
+PREFIX spNetIP spNetGetConnectionIP(spNetTCPConnection connection);
+
+/* Function: spNetSendTCP
+ * 
+ * Sends a tcp package to the ether.
+ * 
+ * Parameters:
+ * connection - the connection to send a tcp package with
+ * data - data to send. Can be a pointer to literally anything.
+ * length - length of the data to be sent (in bytes)
+ * 
+ * Returns:
+ * int - the number of sent bytes. If unequal length the connection seem to be
+ * closed */
+PREFIX int spNetSendTCP(spNetTCPConnection connection,void* data,int length);
+
+/* Function: spNetSendHTTP
+ * 
+ * Sends text over TCP with spNetSendTCP.
+ * 
+ * Parameters:
+ * connection - the connection to send a tcp package with
+ * data - the string to send
+ * 
+ * Returns:
+ * int - the number of sent bytes. If unequal length the connection seem to be
+ * closed */
+PREFIX int spNetSendHTTP(spNetTCPConnection connection,char* data);
+
+/* Function: spNetReceiveTCP
+ * 
+ * Receives data from the other side. This function blocks your application
+ * until the client actually sends something!
+ * 
+ * Parameters:
+ * connection - the connection you want to receive tcp packages from
+ * data - data to receive. Can be a pointer to literally anything.
+ * length - maximal data to receive
+ * 
+ * Returns:
+ * int - the number of received bytes. If 0 something strange happend. E.g. your
+ * counterside explodes or just closed the connection. However your connection
+ * is invalid now! Better close, too. */
+PREFIX int spNetReceiveTCP(spNetTCPConnection connection,void* data,int length);
+
+/* Function: spNetReceiveHTTP
+ * 
+ * Receives data from the other side until the other side disconnects. This
+ * function blocks your application until the client actually sends something!
+ * You can of course use other protocols than http. ;)
+ * 
+ * Parameters:
+ * connection - the connection you want to receive tcp packages from
+ * data - pointer to the text to receive
+ * length - maximal length of the text
+ * 
+ * Returns:
+ * int - the number of received characters. If 0 something strange happend. E.g.
+ * your counterside explodes or just closed the connection. However your
+ * connection is invalid now! Better close, too. */
+PREFIX int spNetReceiveHTTP(spNetTCPConnection connection,char* data,int length);
+
+/* Function: spNetReceiveTCPUnblocked
+ * 
+ * Receives data from the other side. This function does not block your
+ * application! However, it may need a while until your counterpart sends
+ * something and your data string stays invalid.
+ * 
+ * Parameters:
+ * connection - the connection you want to receive tcp packages from
+ * data - data to receive. Can be a pointer to literally anything.
+ * length - maximal data to receive
+ * 
+ * Returns:
+ * SDL_Thread* - a handle to the created background thread. E.g. you can kill
+ * it with SDL_KillThread if you don't want to wait anymore. If (void*)(-1) is
+ * returned the connection is closed (or your counterside exploded).*/
+PREFIX SDL_Thread* spNetReceiveTCPUnblocked(spNetTCPConnection connection,void* data,int length);
+
+/* Function: spNetReceiveHTTPUnblocked
+ * 
+ * Receives data from the other side until the other side disconnects. This
+ * function does not block your application! However, it may need a while until
+ * your counterpart sends something and your data string stays invalid. You
+ * can of course use other protocols than http. ;)
+ * 
+ * Parameters:
+ * 
+ * connection - the connection you want to receive tcp packages from
+ * data - pointer to the text to receive
+ * length - maximal length of the text
+ * 
+ * Returns:
+ * SDL_Thread* - a handle to the created background thread. E.g. you can kill
+ * it with SDL_KillThread if you don't want to wait anymore. If (void*)(-1) is
+ * returned the connection is closed (or your counterside exploded).*/
+PREFIX SDL_Thread* spNetReceiveHTTPUnblocked(spNetTCPConnection connection,char* data,int length);
+
+/* Function: spNetReceiveStillWaiting
+ * 
+ * Says, whether a receive call (identified by the thread handle) still waits
+ * for an incoming signal. Usefull for timeouts.
+ * 
+ * Parameters:
+ * thread - thread of the receiving call, which is maybe still running
+ * 
+ * Returns:
+ * int - 1 if the thread still waits or 0 if not.*/
+PREFIX int spNetReceiveStillWaiting(SDL_Thread* thread);
+
+/* Function: spNetCloseTCP
+ * 
+ * Closes a tcp connection or a server session.
+ * 
+ * Parameter:
+ * connection - connection to close*/
+PREFIX void spNetCloseTCP(spNetTCPConnection connection);
+
+/* Section: Compo4all stuff
+ * 
+ * Types and Functions for sending and receiving data to and from the compo4all
+ * server.*/
+
+/* Defines: Compo4all statuses
+ * 
+ * Statuses for the committing and score-loading functions.
+ * 
+ * SP_C4A_PROGRESS - transfer of data is in progress
+ * SP_C4A_OK - process is done and everything was fine
+ * SP_C4A_ERROR - process is done, but something went wrong */
+#define SP_C4A_PROGRESS 1
+#define SP_C4A_OK 0
+#define SP_C4A_ERROR -1
+#define SP_C4A_TIMEOUT -2
+#define SP_C4A_CANCELED -3
+
+/* Type: spNetC4AGame
+ * 
+ * Type for a linked list of games from the compo4all highscore servers
+ * 
+ * Variables:
+ * longname - full name of the game
+ * shortname - short name of the game
+ * status - the status of the highscore: 1 means available, 2 even more
+ * available (called "active" by skeezix, don't really know, what this means),
+ * 0 inactive, which means, you shouldn't show that game except for testing
+ * purpose.
+ * genre - the genre of the game.
+ * field - which kind of game is it? 0 means just an indie game, 1 is a mame
+ * game, -1 means "don't know" or "to be decided".
+ * next - pointer to the next element in the list*/
+typedef struct spNetC4AGameStruct *spNetC4AGamePointer;
+typedef struct spNetC4AGameStruct {
+       char longname[256];
+       char shortname[256];
+       int status;
+       char genre[256];
+       int field;
+       spNetC4AGamePointer next;
+} spNetC4AGame;
+
+/* Type: spNetC4AScore
+ * 
+ * Type for a linked list of scores gotten from the compo4all highscore servers
+ * 
+ * Variables:
+ * longname - full name of the player
+ * shortname - three digit short name of the player
+ * score - the reached points
+ * commitTime - time of type time_t (seconds since 1.1.1970 00:00:00),
+ * when the score was committed. Use localtime of time.h to "decrypt"
+ * this type. ;)
+ * next - pointer to the next element in the list
+ * rank - rank in the score */
+typedef struct spNetC4AScoreStruct *spNetC4AScorePointer;
+typedef struct spNetC4AScoreStruct {
+       char longname[256];
+       char shortname[256];
+       int score;
+       time_t commitTime;
+       spNetC4AScorePointer next;
+       int rank;
+} spNetC4AScore;
+
+/* Type: spNetC4AProfile
+ * 
+ * A struct for your *unique* C4A Profile.
+ * 
+ * Variables:
+ * prid - unique id of your account. Keep it for you. ;)
+ * longname - your full name
+ * shortname - your 3 digit short name */
+typedef struct spNetC4AProfileStruct *spNetC4AProfilePointer;
+typedef struct spNetC4AProfileStruct {
+       char prid[256];
+       char longname[256];
+       char shortname[256];
+       char password[256];
+       char email[256];
+} spNetC4AProfile;
+
+
+/* Function: spNetC4AGetProfile
+ * 
+ * Reads your profile out of your c4a-prof file. On the pandora the file is
+ * created by compo4all and stored on a pandora specific place. On other systems
+ * for now your c4a-prof should be in the folder of your application.
+ * 
+ * Returns:
+ * spNetC4AProfilePointer - a pointer to an <spNetC4AProfile> struct*/
+PREFIX spNetC4AProfilePointer spNetC4AGetProfile();
+
+/* Function: spNetC4AFreeProfile
+ * 
+ * Frees the profile you got from <spNetC4AGetProfile>.
+ * 
+ * Parameters:
+ * profile - profile to free. However of course your profile is not deleted. ;)*/
+PREFIX void spNetC4AFreeProfile(spNetC4AProfilePointer profile);
+
+/* Function: spNetC4AGetGame
+ * 
+ * Loads all games listed on the C4A server. Use <spNetC4AGetStatus> to get the
+ * status of the task. Only one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * gameList - a pointer to spNetC4AGamePointer, which is in fact a pointer to
+ * <spNetC4AGame>. The available games are saved here.
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.*/
+PREFIX int spNetC4AGetGame(spNetC4AGamePointer* gameList,int timeOut);
+
+/* Function: spNetC4AGetGameParallel
+ * 
+ * Loads all games listed on the C4A server. Use
+ * <spNetC4AGetStatusParallel> to get the status of the task. Don't
+ * forget to delete the returned task struct with <spNetC4ADeleteTask>
+ * at the end.
+ * 
+ * Parameters:
+ * gameList - a pointer to spNetC4AGamePointer, which is in fact a pointer to
+ * <spNetC4AGame>. The available games are saved here.
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * spNetC4ATaskPointer - Pointer to <spNetC4ATask> at success and NULL if an
+ * error occured.*/
+PREFIX spNetC4ATaskPointer spNetC4AGetGameParallel(spNetC4AGamePointer* gameList,int timeOut);
+
+/* Function: spNetC4ADeleteGames
+ * 
+ * Frees the linked list returned by <spNetC4AGetGame>.
+ * 
+ * Parameters:
+ * firstGame - pointer to <spNetC4AGame> to free*/
+PREFIX void spNetC4ADeleteGames(spNetC4AGamePointer* gameList);
+
+/* Function: spNetC4AGetScore
+ * 
+ * Loads a top 500 for a given game from the compo4all server. The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AScorePointer, which is in fact a pointer to
+ * <spNetC4AScore>. The scores are saved here.
+ * profile - an optional pointer to your profile. If given only your scores are
+ * added to the scores-list above
+ * game - name of the game on the server
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.
+ * 
+ * See also: <spNetC4AGetScoreOfMonth>*/
+PREFIX int spNetC4AGetScore(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int timeOut);
+
+/* Function: spNetC4AGetScoreOfMonth
+ * 
+ * Loads a top 500 of a month for a given game from the compo4all
+ * server. The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to
+ * <spNetC4AScore>. The scores are saved here.
+ * profile - an optional pointer to your profile. If given only your scores are
+ * added to the scores-list above
+ * game - name of the game on the server
+ * year - year to load (e.g. 2013)
+ * month - month to load (e.g. 3 for march)
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.
+ * 
+ * See also: <spNetC4AGetScore>*/
+PREFIX int spNetC4AGetScoreOfMonth(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int year,int month,int timeOut);
+
+/* Function: spNetC4AGetScore
+ * 
+ * Loads a top 500 for a given game from the compo4all server. The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AScorePointer, which is in fact a pointer to
+ * <spNetC4AScore>. The scores are saved here.
+ * profile - an optional pointer to your profile. If given only your scores are
+ * added to the scores-list above
+ * game - name of the game on the server
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * spNetC4ATaskPointer - Pointer to <spNetC4ATask> at success and NULL if an
+ * error occured.
+ * 
+ * See also: <spNetC4AGetScoreOfMonthParallel>*/
+PREFIX spNetC4ATaskPointer spNetC4AGetScoreParallel(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int timeOut);
+
+/* Function: spNetC4AFilterScore
+ * 
+ * Makes, that every name appears only once in the scoreList
+ * 
+ * Parameter:
+ * scoreList - a pointer to spNetC4AScorePointer, which is in fact a pointer to
+ * <spNetC4AScore>. These scores are changed.*/
+PREFIX void spNetC4AFilterScore(spNetC4AScorePointer* scoreList);
+
+/* Function: spNetC4AGetScoreOfMonth
+ * 
+ * Loads a top 500 of a month for a given game from the compo4all
+ * server. The task runs in background! Use
+ * <spNetC4AGetStatusParallel> to get the status of the task. Don't
+ * forget to delete the returned task struct with <spNetC4ADeleteTask>
+ * at the end.
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to
+ * <spNetC4AScore>. The scores are saved here.
+ * profile - an optional pointer to your profile. If given only your scores are
+ * added to the scores-list above
+ * game - name of the game on the server
+ * year - year to load (e.g. 2013)
+ * month - month to load (e.g. 3 for march)
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * spNetC4ATaskPointer - Pointer to <spNetC4ATask> at success and NULL if an
+ * error occured.
+ * 
+ * See also: <spNetC4AGetScoreParallel>*/
+PREFIX spNetC4ATaskPointer spNetC4AGetScoreOfMonthParallel(spNetC4AScorePointer* scoreList,spNetC4AProfilePointer profile,char* game,int year,int month,int timeOut);
+
+/* Function: spNetC4CopyScoreList
+ * 
+ * Makes an unique copy of the passed scorelist, e.g. if you want to remove
+ * double names with <spNetC4AMakeScoresUnique> afterwards. Don't forget to
+ * free every copy with <spNetC4ADeleteScores> afterwards!
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to
+ * <spNetC4AScore>, which shall be copied
+ * newList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to
+ * <spNetC4AScore>, to which the copy shall be written*/
+PREFIX void spNetC4ACopyScoreList(spNetC4AScorePointer* scoreList,spNetC4AScorePointer* newList);
+
+/* Function: spNetC4AMakeScoresUnique
+ * 
+ * Removes any double occurence of names in the score. Afterwars every
+ * name only occurs ones with the best score of this player. Be careful:
+ * Afterwards you can't use this list for uploading scores if they don't
+ * exist anymore. If you want both make a copy of the list with
+ * <spNetC4ACopyScoreList> before (instead of getting the scores twice).
+ * 
+ * Parameters:
+ * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to
+ * <spNetC4AScore> */
+PREFIX void spNetC4AMakeScoresUnique(spNetC4AScorePointer* scoreList);
+
+/* Function: spNetC4ADeleteScores
+ * 
+ * Frees the linked list returned by <spNetC4AGetScore>.
+ * 
+ * Parameters:
+ * firstScore - pointer to <spNetC4AScore> to free*/
+PREFIX void spNetC4ADeleteScores(spNetC4AScorePointer* scoreList);
+
+/* Function: spNetC4ACommitScore
+ * 
+ * Commits a score to a specific game to compo4all server. The task runs
+ * in background! Use <spNetC4AGetStatusParallel> to get the status of the task.
+ * Don't forget to delete the returned task struct with <spNetC4ADeleteTask>
+ * at the end.
+ * 
+ * Parameters:
+ * profile - the profile you want to commit tthe score with
+ * game - name of the game on the server. If this is empty (""), at least the
+ * c4a cache will be tried to commit.
+ * score - reached score
+ * scoreList - pass the struct returned by <spNetC4AGetScore> to compare
+ * your score to that list and avoid committing the same score twice. If
+ * it is not in the list, it will added afterwards for later
+ * comparements.
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>. If timeOut is 0, no thread is started, but the
+ * score is written to the cache if enabled!
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason (e.g. the score is
+ * already in the scoreList), 0 at success starting the task.*/
+PREFIX int spNetC4ACommitScore(spNetC4AProfilePointer profile,char* game,int score,spNetC4AScorePointer* scoreList,int timeOut);
+
+/* Function: spNetC4ACommitScoreParallel
+ * 
+ * Commits a score to a specific game to compo4all server. The task runs
+ * in background! Use <spNetC4AGetStatusParallel> to get the status of the task.
+ * Don't forget to delete the returned task struct with <spNetC4ADeleteTask>
+ * at the end.
+ * 
+ * Parameters:
+ * profile - the profile you want to commit tthe score with
+ * game - name of the game on the server
+ * score - reached score
+ * scoreList - pass the struct returned by <spNetC4AGetScore> to compare
+ * your score to that list and avoid committing the same score twice. If
+ * it is not in the list, it will added afterwards for later
+ * comparements.
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut> If timeOut is 0, no thread is started, but the
+ * score is written to the cache if enabled!
+ * 
+ * Returns:
+ * spNetC4ATaskPointer - Pointer to <spNetC4ATask> at success and NULL if an
+ * error occured.*/
+PREFIX spNetC4ATaskPointer spNetC4ACommitScoreParallel(spNetC4AProfilePointer profile,char* game,int score,spNetC4AScorePointer* scoreList,int timeOut);
+
+/* Function: spNetC4ACreateProfile
+ * 
+ * Creates a new profile on skeezix' server. Blocks your application! However,
+ * if network is avaible, should be quite fast. Furthermore it creates the
+ * c4a-prof file needed by all supported applications. The path of the file is
+ * platform depended. Overwrites an already existing file! The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * Only for Pandora: If no c4a-prof is created until now and no c4a-mame appdata
+ * folder is available it will be created in the first folder in /media with
+ * pandora/appdata in it. It MAY be, that skeezix's C4A Manager will not find
+ * this c4a-prof if it will be installed later on another SD card! However the
+ * spaghetti client, the fusilli client and the Sparrow C4A Manager will find
+ * this profile file in any case (if you don't create a second c4a-prof with
+ * skeezix c4a manager. It that case it is random which c4a-prof is used in the
+ * end...)
+ * 
+ * Parameters:
+ * 
+ * profile - a pointer to a pointer to <spNetC4AProfile>, where the profile
+ * shall be saved to.
+ * longname - the long name of the player. Should only be alphanumeric.
+ * shortname - the short name of the player. Should exactly 3 alphanumeric,
+ * capital letters.
+ * password - alphanumeric password
+ * email - the mail address of the new account. Can be "".
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.
+ * 
+ * See Also:
+ * <spNetC4AEditProfile>*/
+PREFIX int spNetC4ACreateProfile(spNetC4AProfilePointer* profile, char* longname,char* shortname,char* password,char* email,int timeOut);
+
+/* Function: spNetC4ADeleteAccount
+ * 
+ * Deletes the given profile on skeezix server and maybe the file on your
+ * system. The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * profile - profile to delete from the server.
+ * deleteFile - 1 if you want to delete the c4a-prof file at the end
+ * (at success), too. 0 leaves to file.
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.*/
+PREFIX int spNetC4ADeleteAccount(spNetC4AProfilePointer* profile,int deleteFile,int timeOut);
+
+/* Function: spNetC4AEditProfile
+ * 
+ * Edits an already existing profile on skeezix' server. Blocks your
+ * application! However, if network is avaible, should be quite fast.
+ * Furthermore it rewrites the c4a-prof file needed by all supported
+ * applications. The path of the file is platform depended. If the account
+ * doesn't exist now, it will created. The big difference to
+ * <spNetC4ACreateProfile> is, that the prid is read from the profile struct
+ * instead of being new created. The task runs
+ * in background! Use <spNetC4AGetStatus> to get the status of the task. Only
+ * one compo4all background task can run at one time!
+ * 
+ * Parameters:
+ * 
+ * profile - the profile to change.
+ * longname - the long name of the player. Should only be alphanumeric.
+ * shortname - the short name of the player. Should exactly 3 alphanumeric,
+ * capital letters.
+ * password - alphanumeric password
+ * email - the mail address of the new account. Can be "".
+ * timeOut - after this time in ms the thread is killed. Get it with
+ * <spNetC4AGetTimeOut>
+ * 
+ * Returns:
+ * int - 1 if the function failed for some reason, 0 at success starting
+ * the task.
+ * 
+ * See Also:
+ * <spNetC4ACreateProfile>*/
+PREFIX int spNetC4AEditProfile(spNetC4AProfilePointer* profile,char* longname,char* shortname,char* password,char* email,int timeOut);
+
+/* Function: spNetC4ACancelTask
+ * 
+ * Cancels the C4A task running right now (if one is started).*/
+PREFIX void spNetC4ACancelTask();
+
+/* Function: spNetC4ACancelTaskParallel
+ * 
+ * Cancels the given C4A task. Don't forget to delete it afterwards with
+ * <spNetC4ADeleteTask>!
+ * 
+ * Parameters:
+ * task - pointer to <spNetC4ATask> returned from the parallel functions.*/
+PREFIX void spNetC4ACancelTaskParallel(spNetC4ATaskPointer task);
+
+/* Function: spNetC4AGetTaskResult
+ * 
+ * Gets the result of the task when finished (check with
+ * <spNetC4AGetStatus>).
+ * 
+ * Returns:
+ * int - 0 if everything went fine, 1 at error*/
+PREFIX int spNetC4AGetTaskResult();
+
+/* Function: spNetC4AGetTaskResultParallel
+ * 
+ * Gets the result of the given task when finished (check with
+ * <spNetC4AGetStatusParallel>).
+ * 
+ * Parameters:
+ * task - pointer to <spNetC4ATask> returned from the parallel functions.
+ * 
+ * Returns:
+ * int - 0 if everything went fine, 1 at error*/
+PREFIX int spNetC4AGetTaskResultParallel(spNetC4ATaskPointer task);
+
+/* Function: spNetC4AGetTimeOut
+ * 
+ * Gives you the time out of the C4A tasks.
+ * 
+ * Returns:
+ * int - the timeOut in ms.*/
+PREFIX int spNetC4AGetTimeOut();
+
+/* Function: spNetC4AGetTimeOutParallel
+ * 
+ * Gives you the time out of the given C4A task.
+ * 
+ * Parameters:
+ * task - pointer to <spNetC4ATask> returned from the parallel functions.
+ * 
+ * Returns:
+ * int - the timeOut in ms.*/
+PREFIX int spNetC4AGetTimeOutParallel(spNetC4ATaskPointer task);
+
+/* Function: spNetC4AGetStatus
+ * 
+ * Gets the status of <spNetC4AGetScore>, <spNetC4ACommitScore>,
+ * <spNetC4ACreateProfile>, <spNetC4AEditProfile> & <spNetC4ADeleteAccount>.
+ * 
+ * Returns:
+ * int - <Compo4all statuses>*/
+PREFIX int spNetC4AGetStatus();
+
+/* Function: spNetC4AGetStatusParallel
+ * 
+ * Gets the status of <spNetC4AGetScoreParallel> & <spNetC4ACommitScoreParallel>.
+ * 
+ * Parameters:
+ * task - pointer to <spNetC4ATask> returned from the parallel functions
+ * 
+ * Returns:
+ * int - <Compo4all statuses>*/
+PREFIX int spNetC4AGetStatusParallel(spNetC4ATaskPointer task);
+
+
+/* Function: spNetC4ADeleteProfileFile
+ * 
+ * Deletes the profile file on your system, NOT the online account at skeezix
+ * server. See also <spNetC4ADeleteAccount>.*/
+PREFIX void spNetC4ADeleteProfileFile();
+
+/* Function: spNetC4ADeleteTask
+ * 
+ * Deletes the task struct returned by the parallel working task functions.
+ * 
+ * Parameters:
+ * task - Pointer to <spNetC4ATask>, which is returned by the parallel functions.*/
+PREFIX void spNetC4ADeleteTask(spNetC4ATaskPointer task);
+
+/* Function: spNetC4ASetCaching
+ * 
+ * (De)Activates caching for C4A scores. If caching is enabled every time
+ * spNetC4ACommitScore* fails, it is written to a cache file and the next time
+ * spNetC4ACommitScore* is called it will be tried to be committed again
+ * 
+ * Parameters:
+ * value - 0: No caching
+ * 1: Everything is cached
+ * 2: Only the best score of a game is cached
+ * 3: Same like 2, but lower score is better*/
+PREFIX void spNetC4ASetCaching(int value);
+
+/* Function: spNetC4AHowManyCached
+ * 
+ * Returns how many scores are cached
+ * 
+ * Returns:
+ * int - the number of cached scores*/
+PREFIX int spNetC4AHowManyCached();
+#endif
diff --git a/recipes/fusilli-client/fusilli-client_git.bb b/recipes/fusilli-client/fusilli-client_git.bb
new file mode 100644 (file)
index 0000000..1ff70cb
--- /dev/null
@@ -0,0 +1,37 @@
+DESCRIPTION = "An alternative client for skeezix c4a network"
+LICENSE = "GPLv3"
+
+DEPENDS = "virtual/libsdl libsdl-net pandora-libpnd"
+RDEPENDS = "libsdl-net pandora-libpnd"
+
+PR = "r0"
+
+SRC_URI = " \
+  git://github.com/theZiz/fusilli-client.git;protocol=git;branch=master \
+  file://sparrowNet.c \
+  file://sparrowNet.h \
+  file://sparrowDefines.h \
+"
+
+SRCREV = "60bb6d2d121eb23a59e6502d33ca1246be033710"
+
+S = "${WORKDIR}/git"
+
+CFLAGS += "-g -DPANDORA"
+# crazy
+CFLAGS += "-DX86CPU"
+
+do_compile() {
+       cp ${WORKDIR}/sparrowNet.c ${S}/
+       cp ${WORKDIR}/sparrowNet.h ${S}/
+       cp ${WORKDIR}/sparrowDefines.h ${S}/
+
+       # not everyone knows how to write makefiles..
+       oe_runmake CPP='${CC}' SPARROW_FOLDER=. LIB= STATIC=sparrowNet.c \
+               DYNAMIC='${LDFLAGS} -lSDL_net -lSDL -lpnd'
+}
+
+do_install() {
+       install -d ${D}${bindir}/
+       install -m 0755 fusilli ${D}${bindir}/
+}