/*****************************************************************************

        GRAOUMF TRACKER 2
        Author: Laurent de Soras, 1996-2016

--- Legal stuff ---

This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.

*****************************************************************************/



#if defined (BASE_CURRENT_HEADER)
	#error Inclusion recursive du header BASE.
#endif
#define	BASE_CURRENT_HEADER

#if ! defined (BASE_HEADER_INCLUDED)
#define	BASE_HEADER_INCLUDED



/*\\\ INCLUDES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

#include "archi.h"

#include <string>



/*\\\ CONSTANTES ET MACROS PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

#define	MIN(x,y)					(((x)<=(y)) ? (x) : (y))
#define	MAX(x,y)					(((x)>=(y)) ? (x) : (y))
#define	ABS(x)					(((x)>=0) ? (x) : -(x))
#define	SGN(x)					(((x)>0) ? 1 : (((x)<0) ? -1 : 0 ))
#define	STRUCT_OFFSET(x,y)	((BYTE *)(&(((x *)0)->y)) - (BYTE *)0)

#define	BASE_peek(x)			(* ((BYTE *)(x)))
#define	BASE_poke(x,y)			(* ((BYTE *)(x)) = (y))
#define	BASE_dpeek(x)			(* ((WORD *)(x)))
#define	BASE_dpoke(x,y)		(* ((WORD *)(x)) = (y))
#define	BASE_lpeek(x)			(* ((LWORD *)(x)))
#define	BASE_lpoke(x,y)		(* ((LWORD *)(x)) = (y))

/* Type non signe, x_int, x_frac, y_int, y_frac */
#define	BASE_ADDX(t,x1,x0,y1,y0)	((x1) + (y1) + ((t)(x0) + (t)(y0) < (t)(x0)))
#define	BASE_SUBX(t,x1,x0,y1,y0)	((x1) - (y1) - ((t)(x0) - (t)(y0) > (t)(x0)))

/* Multiplication SLWORD * ULWORD -> SLWORD de poids fort */
#define	BASE_MUL_32S_32U_U32S(a,b)	((SLWORD) (((SQWORD)(a) * (b)) >> 32))
/*
Traduc en asm:
- eax = a (32 bits signe)
- edx = b (32 bits non signe)
			shr		edx, 1
			imul		edx
			sal		edx, 1
- edx = resultat
On perd 1 bit de precision sur le multiplicateur et 1 bit sur le resultat mais
le resultat est beaucoup plus rapide a calculer. Pour ne pas perdre le dernier
bit du resultat, on peut remplacer la derniere instruction par:
			shdl		edx, eax, 1
*/

/* Multiplication SLWORD * SLWORD -> SLWORD de poids moyen (bits 16 a 47) */
#define	BASE_MUL_32S_32S_M32S(a,b)	((SLWORD) (((SQWORD)(a) * (b)) >> 16))

template <class T> void	BASE_swap (T &x, T &y)
{
	T	temp;

	temp = x;
	x = y;
	y = temp;
}



/*\\\ TYPES & STRUCTURES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

typedef	char	ASCIIDBL [24];	/* Contient un double ecrit sur 24 caracteres ("%+#.16E" dans printf) */



/*\\\ PROTOTYPES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

/*--------------------------------------------------------------------------*/
/*      Routines de conversions diverses                                    */
/*--------------------------------------------------------------------------*/

WORD	BASE_intel_word (WORD a);
LWORD	BASE_intel_lword (LWORD a);
WORD	BASE_moto_word (WORD a);
LWORD	BASE_moto_lword (LWORD a);
WORD	BASE_intel_word_to_moto (WORD a);
LWORD	BASE_intel_lword_to_moto (LWORD a);

WORD	BASE_dpeek_moto (const void *adresse);
WORD	BASE_dpeek_intel (const void *adresse);
void	BASE_dpoke_moto (void *adresse, WORD mot);
void	BASE_dpoke_intel (void *adresse, WORD mot);

LWORD	BASE_lpeek_moto (const void *adresse);
LWORD	BASE_lpeek_intel (const void *adresse);
void	BASE_lpoke_moto (void *adresse, LWORD mot_long);
void	BASE_lpoke_intel (void *adresse, LWORD mot_long);

void	BASE_invert_word (WORD *adresse);
void	BASE_invert_lword (LWORD *adresse);

double	BASE_asciidbl_to_double (const ASCIIDBL ascii);
void		BASE_double_to_asciidbl (double nbr, ASCIIDBL ascii);

signed int	BASE_quartet_to_int (signed int quartet);
int	BASE_get_quartet (long number, int pos);
char	BASE_digit_to_char (int d);
void BASE_slword_to_base (SLWORD n, char *text0, int base, int maxlen);
void BASE_ulword_to_base (ULWORD n, char *text0, int base, int maxlen);
void	BASE_pourcent (ULWORD n1, ULWORD n2, char *text0);
void	BASE_truefalse (bool flag, char *chaine_0);
void	BASE_onoff (bool flag, char *chaine_0);
void	BASE_yesno (bool flag, char *chaine_0);

bool	BASE_compare_id4 (const void *id1_ptr, const void *id2_ptr);

signed long	BASE_power (signed long nbr, int pwr);
inline bool	BASE_is_null (double val);
inline bool	BASE_is_infinite (double val);
inline double	BASE_safe_double_inversion (double val);
inline double	BASE_lin_to_db (double val);
inline double	BASE_db_to_lin (double val);

bool	BASE_double_to_unsigned_q (double nbr, int &num, int &denom, int max_num, int max_denom);

long	BASE_get_distance_in_circular_buffer (long length, signed long reference_cursor, signed long test_cursor);

void	BASE_date_to_absolute_day (long &abs_day, int day, int month, int year);
void  BASE_absolute_day_to_date (long abs_day, int &day, int &month, int &year);

int	BASE_get_fader_pos (double val, double inf_val, double sup_val, int length, bool log_flag = false);
double	BASE_get_fader_val (signed int pos, double inf_val, double sup_val, int length, bool log_flag = false);



/*--------------------------------------------------------------------------*/
/*      Manipulations de chaines                                            */
/*--------------------------------------------------------------------------*/

void	BASE_double_to_fix (char *string_0, double nbr, int pre, int post);
void	BASE_double_to_float (char *string_0, double nbr, int len);
void	BASE_double_to_simple (char *string_0, double nbr);

void	BASE_fill_string (char *s, char c, size_t n, size_t sizemax);
void	BASE_copy_string (const char *ss, char *sd, size_t n, size_t destlen);
void	BASE_invert_string (char *text0);
void	BASE_trim_string (char *text0);
void	BASE_complete_string (char *string_0, size_t new_len);
signed int	BASE_compare_string (const char *s1_0, const char *s2_0);
signed long	BASE_search_in_string_nocase (const char *s1_0, const char *s2_0);
signed int	BASE_parse_command_line (char *text_0, char *argv [], int max_argc, const char *delimiter_0);
bool	BASE_is_delimiter (char	c, const char *delimiter_0);

template <class T>
void    BASE_push_back_utf8_to_utf16 (T &utf16, const char *utf8_0, bool trailing_zero_flag);
std::wstring BASE_conv_utf8_to_utf16 (const char *utf8_0);
std::string	BASE_conv_utf16_to_utf8 (const wchar_t *utf16_0);
bool	BASE_is_utf8_lead_byte (char c);




/*\\\ VARIABLES EXTERNES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ FIN DU FICHIER \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

#endif

#undef BASE_CURRENT_HEADER
