From: Grazvydas Ignotas Date: Sat, 8 Nov 2014 20:25:02 +0000 (+0200) Subject: fusilli-client: add recipe X-Git-Tag: sz_172rc~34 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=openpandora.oe.git;a=commitdiff_plain;h=a9e404ff17660f02a18d1a256f8527421896b968;ds=sidebyside fusilli-client: add recipe --- diff --git a/recipes/fusilli-client/files/sparrowDefines.h b/recipes/fusilli-client/files/sparrowDefines.h new file mode 100644 index 0000000..06ad68e --- /dev/null +++ b/recipes/fusilli-client/files/sparrowDefines.h @@ -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 + * + * 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 + #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_FACTOR - 2 ^ . 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 , but with guaranteed high precision + * spMulLow(a,b) - Does the same as , 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 , but with guaranteed high precision + * spDivLow(a,b) - Does the same as , but maybe with lower precision + * spSquare(a) - Squares the fixed point number a with the help of . */ +#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)<=0 && b<(1<(-1< 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 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 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 +#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 index 0000000..7feab5c --- /dev/null +++ b/recipes/fusilli-client/files/sparrowNet.c @@ -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 + * + * For feedback and questions about my Files and Projects please mail me, + * Alexander Matthes (Ziz) , zizsdl_at_googlemail.com */ + +#include "sparrowNet.h" +#include +#include + +//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 + #include +#else + #include + #include + #include + #include +#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 index 0000000..9f48471 --- /dev/null +++ b/recipes/fusilli-client/files/sparrowNet.h @@ -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 + * + * 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 +#include +#include + +/* 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 + * 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 . 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 */ +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 */ +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 struct*/ +PREFIX spNetC4AProfilePointer spNetC4AGetProfile(); + +/* Function: spNetC4AFreeProfile + * + * Frees the profile you got from . + * + * 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 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 + * . The available games are saved here. + * timeOut - after this time in ms the thread is killed. Get it with + * + * + * 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 + * to get the status of the task. Don't + * forget to delete the returned task struct with + * at the end. + * + * Parameters: + * gameList - a pointer to spNetC4AGamePointer, which is in fact a pointer to + * . The available games are saved here. + * timeOut - after this time in ms the thread is killed. Get it with + * + * + * Returns: + * spNetC4ATaskPointer - Pointer to at success and NULL if an + * error occured.*/ +PREFIX spNetC4ATaskPointer spNetC4AGetGameParallel(spNetC4AGamePointer* gameList,int timeOut); + +/* Function: spNetC4ADeleteGames + * + * Frees the linked list returned by . + * + * Parameters: + * firstGame - pointer to 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 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 + * . 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 + * + * + * Returns: + * int - 1 if the function failed for some reason, 0 at success starting + * the task. + * + * See also: */ +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 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 + * . 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 + * + * + * Returns: + * int - 1 if the function failed for some reason, 0 at success starting + * the task. + * + * See also: */ +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 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 + * . 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 + * + * + * Returns: + * spNetC4ATaskPointer - Pointer to at success and NULL if an + * error occured. + * + * See also: */ +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 + * . 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 + * to get the status of the task. Don't + * forget to delete the returned task struct with + * at the end. + * + * Parameters: + * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to + * . 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 + * + * + * Returns: + * spNetC4ATaskPointer - Pointer to at success and NULL if an + * error occured. + * + * See also: */ +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 afterwards. Don't forget to + * free every copy with afterwards! + * + * Parameters: + * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to + * , which shall be copied + * newList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to + * , 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 + * before (instead of getting the scores twice). + * + * Parameters: + * scoreList - a pointer to spNetC4AProfilePointer, which is in fact a pointer to + * */ +PREFIX void spNetC4AMakeScoresUnique(spNetC4AScorePointer* scoreList); + +/* Function: spNetC4ADeleteScores + * + * Frees the linked list returned by . + * + * Parameters: + * firstScore - pointer to 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 to get the status of the task. + * Don't forget to delete the returned task struct with + * 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 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 + * . 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 to get the status of the task. + * Don't forget to delete the returned task struct with + * 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 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 + * If timeOut is 0, no thread is started, but the + * score is written to the cache if enabled! + * + * Returns: + * spNetC4ATaskPointer - Pointer to 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 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 , 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 + * + * + * Returns: + * int - 1 if the function failed for some reason, 0 at success starting + * the task. + * + * See Also: + * */ +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 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 + * + * + * 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 + * is, that the prid is read from the profile struct + * instead of being new created. The task runs + * in background! Use 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 + * + * + * Returns: + * int - 1 if the function failed for some reason, 0 at success starting + * the task. + * + * See Also: + * */ +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 + * ! + * + * Parameters: + * task - pointer to returned from the parallel functions.*/ +PREFIX void spNetC4ACancelTaskParallel(spNetC4ATaskPointer task); + +/* Function: spNetC4AGetTaskResult + * + * Gets the result of the task when finished (check with + * ). + * + * 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 + * ). + * + * Parameters: + * task - pointer to 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 returned from the parallel functions. + * + * Returns: + * int - the timeOut in ms.*/ +PREFIX int spNetC4AGetTimeOutParallel(spNetC4ATaskPointer task); + +/* Function: spNetC4AGetStatus + * + * Gets the status of , , + * , & . + * + * Returns: + * int - */ +PREFIX int spNetC4AGetStatus(); + +/* Function: spNetC4AGetStatusParallel + * + * Gets the status of & . + * + * Parameters: + * task - pointer to returned from the parallel functions + * + * Returns: + * int - */ +PREFIX int spNetC4AGetStatusParallel(spNetC4ATaskPointer task); + + +/* Function: spNetC4ADeleteProfileFile + * + * Deletes the profile file on your system, NOT the online account at skeezix + * server. See also .*/ +PREFIX void spNetC4ADeleteProfileFile(); + +/* Function: spNetC4ADeleteTask + * + * Deletes the task struct returned by the parallel working task functions. + * + * Parameters: + * task - Pointer to , 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 index 0000000..1ff70cb --- /dev/null +++ b/recipes/fusilli-client/fusilli-client_git.bb @@ -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}/ +}