From 1192c4575ea7afdf38e3fa0df4587a08620af11e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 21 Jul 2020 10:00:46 +0200 Subject: SZS v2.18a --- project/src/lib-numeric.c | 2050 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2050 insertions(+) create mode 100644 project/src/lib-numeric.c (limited to 'project/src/lib-numeric.c') diff --git a/project/src/lib-numeric.c b/project/src/lib-numeric.c new file mode 100644 index 0000000..bfe5ecb --- /dev/null +++ b/project/src/lib-numeric.c @@ -0,0 +1,2050 @@ + +/*************************************************************************** + * _______ _______ _______ * + * | ___ |____ | ___ | * + * | | |_| / /| | |_| * + * | |_____ / / | |_____ * + * |_____ | / / |_____ | * + * _ | | / / _ | | * + * | |___| |/ /____| |___| | * + * |_______|_______|_______| * + * * + * Wiimms SZS Tools * + * https://szs.wiimm.de/ * + * * + *************************************************************************** + * * + * This file is part of the SZS project. * + * Visit https://szs.wiimm.de/ for project details and sources. * + * * + * Copyright (c) 2011-2020 by Dirk Clemens * + * * + *************************************************************************** + * * + * This program 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. * + * * + * This program 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. * + * * + * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt * + * * + ***************************************************************************/ + +#include "lib-std.h" +#include "lib-szs.h" +#include "lib-brres.h" +#include "lib-breff.h" +#include "lib-xbmg.h" +#include "lib-image.h" +#include "dclib-utf8.h" +#include "ui.h" +#include "db-mkw.h" + +#include +#include +#include + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// scan size options /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int ScanOptAlignU8 ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_align_u8, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align-u8", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptAlignPACK ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_align_pack, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align-pack", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptAlignBRRES ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_align_brres, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align-brres", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptAlignBREFF ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_align_breff, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align-breff", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptAlignBREFT ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_align_breft, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align-breft", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptAlign ( ccp arg ) +{ + const int stat = ScanSizeOptU32( + &opt_align, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "align", // ccp opt_name + 0x00001, // u64 min + 0x10000, // u64 max + 0, // u32 multiple + 1, // u32 pow2 + true // bool print_err + ) != ERR_OK; + + if (!stat) + opt_align_u8 = opt_align_pack = + opt_align_brres = opt_align_breff = opt_align_breft = opt_align; + return stat; +} + +//----------------------------------------------------------------------------- + +int ScanOptMaxFileSize ( ccp arg ) +{ + return ScanSizeOptU32( + &opt_max_file_size, // u32 * num + arg, // ccp source + MiB, // default_factor1 + 0, // int force_base + "max-file-size", // ccp opt_name + MiB, // u64 min + GiB, // u64 max + 0, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ) != ERR_OK; +} + +//----------------------------------------------------------------------------- + +int ScanOptEpsilon ( ccp arg ) +{ + // [[2do]] ??? + + if ( !arg || !*arg ) + { + epsilon_pos = DEF_EPSILON_POS; + epsilon_rot = DEF_EPSILON_ROT; + epsilon_scale = DEF_EPSILON_SCALE; + epsilon_time = DEF_EPSILON_TIME; + } + else + { + double epsilon = strtod(arg,0); + if ( epsilon < 0.0 ) + epsilon = 0.0; + + epsilon_pos = + epsilon_rot = + epsilon_scale = + epsilon_time = epsilon; + } + + return 0; +} + +//----------------------------------------------------------------------------- + +int ScanOptNMipmaps ( ccp arg ) +{ + static const KeywordTab_t tab[] = + { + { 0, "OFF", "AUTO", 0 }, + { 0,0,0,0 } + }; + + const KeywordTab_t * cmd = ScanKeyword(0,arg,tab); + if (cmd) + { + opt_n_images = cmd->id; + return 0; + } + + uint num = 0; + const int stat = ScanSizeOptU32( + &num, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "n-mipmaps", // ccp opt_name + 0, // u64 min + MAX_MIPMAPS, // u64 max + 0, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ) != ERR_OK; + + if (!stat) + opt_n_images = num + 1; + return stat; +} + +//----------------------------------------------------------------------------- + +int ScanOptMaxMipmaps ( ccp arg ) +{ + uint num = 0; + const int stat = ScanSizeOptU32( + &num, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "max-mipmaps", // ccp opt_name + 0, // u64 min + MAX_MIPMAPS, // u64 max + 0, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ) != ERR_OK; + + if (!stat) + opt_max_images = num + 1; + return stat; +} + +//----------------------------------------------------------------------------- + +int ScanOptMipmapSize ( ccp arg ) +{ + uint num = 0; + const int stat = ScanSizeOptU32( + &num, // u32 * num + arg, // ccp source + 1, // default_factor1 + 0, // int force_base + "mipmap-size", // ccp opt_name + 1, // u64 min + 1024, // u64 max + 0, // u32 multiple + 0, // u32 pow2 + true // bool print_err + ) != ERR_OK; + + if (!stat) + opt_min_mipmap_size = num > 1 ? num : 1; + return stat; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// scan num/range /////////////// +/////////////////////////////////////////////////////////////////////////////// + +double strtod_comma ( const char *nptr, char **endptr ) +{ + DASSERT(nptr); + + char *end; + double d = strtod(nptr,&end); + if ( end && *end == ',' ) + { + *(char*)end = '.'; + char *end2; + d = strtod(nptr,&end2); + *(char*)end = ','; + end = end2; + } + if (endptr) + *endptr = end; + return d; +} + +/////////////////////////////////////////////////////////////////////////////// + +char * ScanNumU32 +( + ccp arg, // text to scan (valid pointer) + u32 * p_stat, // NULL or return status: + // number of scanned numbers (0..1) + u32 * p_num, // return value (valid pointer) + u32 min, // min allowed value (fix num) + u32 max // max allowed value (fix num) +) +{ + ASSERT(arg); + ASSERT(p_num); + TRACE("ScanNumU32(%s)\n",arg); + + while ( *arg > 0 && *arg <= ' ' ) + arg++; + + char * end; + u32 num = strtoul(arg,&end, arg[1] >= '0' && arg[1] <= '9' ? 10 : 0 ); + u32 stat = end > arg; + if (stat) + { + if ( num < min ) + num = min; + else if ( num > max ) + num = max; + + while ( *end > 0 && *end <= ' ' ) + end++; + } + else + num = 0; + + if (p_stat) + *p_stat = stat; + *p_num = num; + + TRACE("END ScanNumU32() stat=%u, n=%u ->%s\n",stat,num,arg); + return end; +} + +/////////////////////////////////////////////////////////////////////////////// + +char * ScanRangeU32 +( + ccp arg, // text to scan (valid pointer) + u32 * p_stat, // NULL or return status: + // number of scanned numbers (0..2) + u32 * p_n1, // first return value (valid pointer) + u32 * p_n2, // second return value (valid pointer) + u32 min, // min allowed value (fix num) + u32 max // max allowed value (fix num) +) +{ + ASSERT(arg); + ASSERT(p_n1); + ASSERT(p_n2); + TRACE("ScanRangeU32(%s)\n",arg); + + int stat = 0; + u32 n1 = ~(u32)0, n2 = 0; + + while ( *arg > 0 && *arg <= ' ' ) + arg++; + + if ( *arg == '-' ) + n1 = min; + else + { + char * end; + u32 num = strtoul(arg,&end,0); + if ( arg == end ) + goto abort; + + stat = 1; + arg = end; + n1 = num; + + while ( *arg > 0 && *arg <= ' ' ) + arg++; + } + + if ( *arg != '-' && *arg != ':' ) + { + stat = 1; + n2 = n1; + goto abort; + } + arg++; + + while ( *arg > 0 && *arg <= ' ' ) + arg++; + + char * end; + n2 = strtoul(arg,&end,0); + if ( end == arg ) + n2 = max; + stat = 2; + arg = end; + + abort: + + if ( stat > 0 ) + { + if ( n1 < min ) + n1 = min; + if ( n2 > max ) + n2 = max; + } + + if ( !stat || n1 > n2 ) + { + stat = 0; + n1 = ~(u32)0; + n2 = 0; + } + + if (p_stat) + *p_stat = stat; + *p_n1 = n1; + *p_n2 = n2; + + while ( *arg > 0 && *arg <= ' ' ) + arg++; + + TRACE("END ScanRangeU32() stat=%u, n=%u..%u ->%s\n",stat,n1,n2,arg); + return (char*)arg; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +unsigned long int strtoul16 +( + const u16 * ptr16, + u16 ** end16, + int base +) +{ + DASSERT(ptr16); + + char buf[100]; + char * dest = buf; + const u16 * p16 = ptr16; + while ( dest < buf + sizeof(buf)-1 ) + { + int ch = be16(p16++); + if ( ch >= '0' && ch <= '9' + || ch >= 'a' && ch <= 'f' + || ch >= 'A' && ch <= 'F' + || ch == 'x' + || ch == 'X' + || isspace(ch) + ) + { + *dest++ = ch; + } + else + break; + } + DASSERT( dest < buf + sizeof(buf) ); + *dest = 0; + + char *end; + unsigned long num = strtoul(buf,&end,base); + if (end16) + *end16 = (u16*)ptr16 + (end-buf); + return num; +} + +/////////////////////////////////////////////////////////////////////////////// + +u16 * skip_ctrl16 ( const u16 * ptr ) +{ + DASSERT(ptr); + for(;;) + { + const u16 ch = be16(ptr); + if ( !ch || ch > ' ' ) + return (u16*)ptr; + ptr++; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +u16 * ScanNum16U32 +( + const u16 * arg, // text to scan (valid pointer) + u32 * p_stat, // NULL or return status: + // number of scanned numbers (0..1) + u32 * p_num, // return value (valid pointer) + u32 min, // min allowed value (fix num) + u32 max // max allowed value (fix num) +) +{ + ASSERT(arg); + ASSERT(p_num); + TRACE("ScanNum16U32()\n"); + + arg = skip_ctrl16(arg); + + u16 * end; + u32 num = strtoul16(arg,&end, arg[1] >= '0' && arg[1] <= '9' ? 10 : 0 ); + u32 stat = end > arg; + if (stat) + { + if ( num < min ) + num = min; + else if ( num > max ) + num = max; + + end = skip_ctrl16(end); + } + else + num = 0; + + if (p_stat) + *p_stat = stat; + *p_num = num; + + TRACE("END ScanNum16U32() stat=%u, n=%u\n",stat,num); + return end; +} + +/////////////////////////////////////////////////////////////////////////////// + +u16 * ScanRange16U32 +( + const u16 * arg, // text to scan (valid pointer) + u32 * p_stat, // NULL or return status: + // number of scanned numbers (0..2) + u32 * p_n1, // first return value (valid pointer) + u32 * p_n2, // second return value (valid pointer) + u32 min, // min allowed value (fix num) + u32 max // max allowed value (fix num) +) +{ + ASSERT(arg); + ASSERT(p_n1); + ASSERT(p_n2); + TRACE("ScanRangeU32()\n"); + + int stat = 0; + + u32 n1 = ~(u32)0, n2 = 0; + arg = skip_ctrl16(arg); + + if ( be16(arg) == '-' ) + n1 = min; + else + { + u16 * end; + u32 num = strtoul16(arg,&end,0); + if ( arg == end ) + goto abort; + + stat = 1; + arg = skip_ctrl16(end); + n1 = num; + } + + if ( be16(arg) != '-' ) + { + stat = 1; + n2 = n1; + goto abort; + } + + arg = skip_ctrl16(arg+1); + u16 * end; + n2 = strtoul16(arg,&end,0); + if ( end == arg ) + n2 = max; + stat = 2; + arg = end; + + abort: + + if ( stat > 0 ) + { + if ( n1 < min ) + n1 = min; + if ( n2 > max ) + n2 = max; + } + + if ( !stat || n1 > n2 ) + { + stat = 0; + n1 = ~(u32)0; + n2 = 0; + } + + if (p_stat) + *p_stat = stat; + *p_n1 = n1; + *p_n2 = n2; + + arg = skip_ctrl16(arg); + + TRACE("END ScanRange16U32() stat=%u, n=%u..%u\n",stat,n1,n2); + return (u16*)arg; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// vector calculations /////////////// +/////////////////////////////////////////////////////////////////////////////// + +double LengthF +( + const float *a, // A vector (x,y,z) + const float *b // B vector (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double d0 = a[0] - b[0]; + const double d1 = a[1] - b[1]; + const double d2 = a[2] - b[2]; + + return sqrt ( d0*d0 + d1*d1 + d2*d2 ); +} + +/////////////////////////////////////////////////////////////////////////////// + +double Length2F +( + const float * a, // A vector (x,y,z) + const float * b // B vector (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double d0 = a[0] - b[0]; + const double d1 = a[1] - b[1]; + const double d2 = a[2] - b[2]; + + return d0*d0 + d1*d1 + d2*d2; +} + +/////////////////////////////////////////////////////////////////////////////// + +double LengthD +( + const double * a, // A vector (x,y,z) + const double * b // B vector (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double d0 = a[0] - b[0]; + const double d1 = a[1] - b[1]; + const double d2 = a[2] - b[2]; + + return sqrt ( d0*d0 + d1*d1 + d2*d2 ); +} + +/////////////////////////////////////////////////////////////////////////////// + +double Length2D +( + const double * a, // A vector (x,y,z) + const double * b // B vector (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double d0 = a[0] - b[0]; + const double d1 = a[1] - b[1]; + const double d2 = a[2] - b[2]; + + return d0*d0 + d1*d1 + d2*d2; +} + +/////////////////////////////////////////////////////////////////////////////// + +double AngleVector +( + const float * prev, // vector (x,y,z) of previous point + const float * point, // vector (x,y,z) of current point + const float * next, // vector (x,y,z) of next point + bool return_degree // true: return in normed degree; false: radiants +) +{ + DASSERT(prev); + DASSERT(point); + DASSERT(next); + + noTRACE("ANGLE: %11.3f %11.3f | %11.3f %11.3f | %11.3f %11.3f\n", + prev[0], prev[2], point[0], point[2], next[0], next[2] ); + + const double ax = point[0] - prev[0]; + const double az = point[2] - prev[2]; + if ( abs(ax) + abs(az) < 1e-6 ) + return 0.0; + + const double bx = next[0] - point[0]; + const double bz = next[2] - point[2]; + if ( abs(bx) + abs(bz) < 1e-6 ) + return 0.0; + + if (!return_degree) + return atan2(bx,bz) - atan2(ax,az); + + const double deg = ( atan2(bx,bz) - atan2(ax,az) ) * ( 180 / M_PI ); + return deg > 180.0 ? deg - 360.0 : deg <= -180.0 ? deg + 360.0 : deg; +} + +/////////////////////////////////////////////////////////////////////////////// + +void WidthAndDirection +( + double * r_width, // if not NULL: return width here + double * r_direction, // if not NULL: return direction here + bool return_degree, // true: return in normed degree; false: radiants + const float * a, // A point (x,y) + const float * b // B point (x,y) +) +{ + const double dx = b[0] - a[0]; + const double dy = b[1] - a[1]; + const double width = sqrt ( dx*dx + dy*dy ); + if (r_width) + *r_width = width; + + if (r_direction) + { + if ( width < 1e-6 ) + *r_direction = 0.0; + else if (return_degree) + { + double deg = atan2(dx,dy) * ( 180 / M_PI ) + 90; + *r_direction = deg > 180.0 ? deg - 360.0 : deg; + } + else + *r_direction = atan2(dx,dy); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +double CalcDirection2F +( + const float * a, // A point (x,y) + const float * b // B point (x,y) +) +{ + const double dx = b[0] - a[0]; + const double dy = b[1] - a[1]; + return fabs(dx) + fabs(dy) < 1e-6 + ? 0.0 + : atan2(dx,dy); +} + +/////////////////////////////////////////////////////////////////////////////// + +float3 CalcDirection3F +( + const float * a, // A point (x,y,z) + const float * b // B point (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double dx = b[0] - a[0]; + const double dy = b[1] - a[1]; + const double dz = b[2] - a[2]; + const double hl = sqrt ( dx*dx + dz*dz ); + + float3 res; + res.x = fabs(dy) + fabs(hl) < 1e-6 ? 0.0 : atan2(dy,hl) * ( -180.0 / M_PI ); + res.y = fabs(dx) + fabs(dz) < 1e-6 ? 0.0 : atan2(dx,dz) * ( 180.0 / M_PI ); + res.z = 0.0; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +double3 CalcDirection3D +( + const double3 * a, // A point (x,y,z) + const double3 * b // B point (x,y,z) +) +{ + DASSERT(a); + DASSERT(b); + + const double dx = b->x - a->x; + const double dy = b->y - a->y; + const double dz = b->z - a->z; + const double hl = sqrt ( dx*dx + dz*dz ); + + double3 res; + res.x = fabs(dy) + fabs(hl) < 1e-6 ? 0.0 : atan2(dy,hl) * ( -180.0 / M_PI ); + res.y = fabs(dx) + fabs(dz) < 1e-6 ? 0.0 : atan2(dx,dz) * ( 180.0 / M_PI ); + res.z = 0.0; + return res; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void Scale +( + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *scale, // NULL or scaling vector + double3 *pt, // pointer to first point to rotate + uint pt_delta, // delta in bytes to next point + uint n_pt // number of points to rotate +) +{ + DASSERT( pt || !n_pt ); + + if (scale) + { + if (origin) + { + for ( ; n_pt-- > 0; pt = (double3*)((u8*)pt + pt_delta) ) + { + pt->x = ( pt->x - origin->x ) * scale->x + origin->x; + pt->y = ( pt->y - origin->y ) * scale->y + origin->y; + pt->z = ( pt->z - origin->z ) * scale->z + origin->z; + } + } + else + { + for ( ; n_pt-- > 0; pt = (double3*)((u8*)pt + pt_delta) ) + { + pt->x *= scale->x; + pt->y *= scale->y; + pt->z *= scale->z; + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void Rotate +( + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *rot, // rotation vector + double3 *pt1, // pointer to first point to rotate + uint pt_delta, // delta in bytes to next point + uint n_pt // number of points to rotate +) +{ + DASSERT(pt1); + + if (!rot) + return; + + bool have_rot[3]; + have_rot[0] = fabs(rot->x) > 1e-6; + have_rot[1] = fabs(rot->y) > 1e-6; + have_rot[2] = fabs(rot->z) > 1e-6; + if ( !have_rot[0] && !have_rot[1] && !have_rot[2] ) + return; + + uint p; + for ( p = 0; p < 3; p++ ) + { + if (!have_rot[p]) + continue; + + const double rad_rot = rot->v[p] * (M_PI/180.0); + const uint a = (p+2) % 3; + const uint b = (p+1) % 3; + + if (origin) + { + uint i; + double3 *pt = pt1; + for ( i = n_pt; i-- > 0; pt = (double3*)((u8*)pt+pt_delta) ) + { + const double da = pt->v[a] - origin->v[a]; + const double db = pt->v[b] - origin->v[b]; + const double rad = atan2(da,db) + rad_rot; + const double len = sqrt(da*da+db*db); + + pt->v[a] = sin(rad) * len + origin->v[a]; + pt->v[b] = cos(rad) * len + origin->v[b]; + } + } + else + { + uint i; + double3 *pt = pt1; + for ( i = n_pt; i-- > 0; pt = (double3*)((u8*)pt+pt_delta) ) + { + const double da = pt->v[a]; + const double db = pt->v[b]; + const double rad = atan2(da,db) + rad_rot; + const double len = sqrt(da*da+db*db); + + pt->v[a] = sin(rad) * len; + pt->v[b] = cos(rad) * len; + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void Translate +( + const double3 *trans, // NULL or translation vector + double3 *pt, // pointer to first point to rotate + uint pt_delta, // delta in bytes to next point + uint n_pt // number of points to rotate +) +{ + DASSERT( pt || !n_pt ); + + if (trans) + for ( ; n_pt-- > 0; pt = (double3*)((u8*)pt + pt_delta) ) + { + pt->x += trans->x; + pt->y += trans->y; + pt->z += trans->z; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void AxisRotate +( + const double3 *a1, // first axis point + const double3 *a2, // second axis point + double degree, // degree of rotation + double3 *pt1, // pointer to first point to rotate + uint pt_delta, // delta in bytes to next point + uint n_pt // number of points to rotate +) +{ + DASSERT(a1); + DASSERT(a2); + DASSERT( pt1 || !n_pt ); + + + //--- some precalculations + + double3 n12; + Sub3(n12,*a2,*a1); + Unit3(n12); + + const double rad = degree * (M_PI/180.0); + const double fsin = sin(rad); + const double fcos = cos(rad); + + uint i; + double3 *pt = pt1; + for ( i = n_pt; i-- > 0; pt = (double3*)((u8*)pt+pt_delta) ) + { + double3 d13, n13, nx, base; + Sub3(d13,*pt,*a1); + CrossProd3(nx,n12,d13); + CrossProd3(n13,nx,n12); + Sub3(base,*pt,n13); + + pt->x = fcos * n13.x + fsin * nx.x + base.x; + pt->y = fcos * n13.y + fsin * nx.y + base.y; + pt->z = fcos * n13.z + fsin * nx.z + base.z; + } +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +double Degree // output: -180.00 .. +180.00 +( + double rad // radians +) +{ + double deg = fmod( rad * (180.0/M_PI) + 180.0, 360.0 ); + return deg < 0.0 ? deg + 180.0 : deg - 180.0; +} + +/////////////////////////////////////////////////////////////////////////////// + +float NormDegreeF // output: -180.00 .. +180.00 +( + float deg +) +{ + deg = fmod( deg + 180.0, 360.0 ); + return deg < 0.0 ? deg + 180.0 : deg - 180.0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void MinMax3 +( + double3 *min, // valid pointer to initialized min value + double3 *max, // valid pointer to initialized max value + const double3 *val, // valid pointer to source list + int n_val // if >0: number of elements in 'val' +) +{ + DASSERT(min); + DASSERT(max); + DASSERT(val); + + while ( n_val-- > 0 ) + { + if ( min->x > val->x ) min->x = val->x; + if ( min->y > val->y ) min->y = val->y; + if ( min->z > val->z ) min->z = val->z; + + if ( max->x < val->x ) max->x = val->x; + if ( max->y < val->y ) max->y = val->y; + if ( max->z < val->z ) max->z = val->z; + + val++; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void UnitZero3 ( double3 *dest, const double3 *src ) +{ + DASSERT(dest); + DASSERT(src); + + double len = Length3(*src); + double min = len * 1e-5; + int dirty = 0; + + if ( fabs(src->x) < min ) + { + dest->x = 0.0; + dirty = true; + } + else + dest->x = src->x; + + if ( fabs(src->y) < min ) + { + dest->y = 0.0; + dirty = true; + } + else + dest->y = src->y; + + if ( fabs(src->z) < min ) + { + dest->z = 0.0; + dirty = true; + } + else + dest->z = src->z; + + if (dirty) + len = Length3(*dest); + + if (len) + { + dest->x /= len; + dest->y /= len; + dest->z /= len; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +double CalcNormals +( + // return length of p1..p2 + + double3 *res_norm, // return 3 normals here + const double3 *p1, // first point + const double3 *p2, // second point + const double3 *dir, // NULL or helper point for normal[1] + double r // radius == length of norm[0]..norm[2] +) +{ + DASSERT(res_norm); + DASSERT(p1); + DASSERT(p2); + + bool vertical = false; + + Sub3(res_norm[0],*p2,*p1); + double len0 = Length3(res_norm[0]); + if ( len0 < 1e-9 ) + { + len0 = 0.0; + res_norm[0].x = 0.0; + res_norm[0].y = 0.0; + res_norm[0].z = 1.0; + } + else + { + res_norm[0].x /= len0; + res_norm[0].y /= len0; + res_norm[0].z /= len0; + vertical = fabs(res_norm[0].y) > 0.9; + } + + double3 temp; + if (!dir) + { + dir = &temp; + memcpy(&temp,p1,sizeof(temp)); + if (vertical) + temp.z += 1000; + else + temp.y += 1000; + } + + double3 dist; + Sub3(dist,*dir,*p1); + CrossProd3(res_norm[2],res_norm[0],dist); + double len1 = Length3(res_norm[2]); + if ( len1 < 1e-9 ) + { + if (vertical) + { + temp.x = temp.y = 0.0; + temp.z = 1000.0; + } + else + { + temp.x = temp.z = 0.0; + temp.y = 1000.0; + } + CrossProd3(res_norm[2],res_norm[0],temp); + len1 = Length3(res_norm[2]); + } + len1 = r / len1; + res_norm[2].x *= len1; + res_norm[2].y *= len1; + res_norm[2].z *= len1; + + CrossProd3(res_norm[1],res_norm[2],res_norm[0]); + res_norm[0].x *= r; + res_norm[0].y *= r; + res_norm[0].z *= r; + + return len0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// OverlapCubeTri() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +bool OverlapCubeTri +( + double3 *cube_mid, // middle of the cube + double cube_width, // width of the cube + double3 *pt1, // first point of triangle + double3 *pt2, // second point of triangle + double3 *pt3 // third point of triangle +) +{ + ERROR0(ERR_NOT_IMPLEMENTED,0); + return false; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// triangles /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void CalcTriMetricsByPoints +( + tri_metrics_t *met, // result + const double3 *p1, // NULL or first point + const double3 *p2, // NULL or second point + const double3 *p3 // NULL or third point +) +{ + DASSERT(met); + memset(met,0,sizeof(*met)); + if (p1) Assign3(met->p1,*p1); + if (p2) Assign3(met->p2,*p2); + if (p3) Assign3(met->p3,*p3); + CalcTriMetrics(met); +} + +/////////////////////////////////////////////////////////////////////////////// + +void CalcTriMetrics ( tri_metrics_t *met ) +{ + DASSERT(met); + + double3 x, y, z; + Sub3(x,met->p2,met->p1); + Sub3(y,met->p3,met->p2); + Sub3(z,met->p1,met->p3); + + // calc side lengths + const double a2 = LengthSqare3(x); met->l1 = sqrt(a2); + const double b2 = LengthSqare3(y); met->l2 = sqrt(b2); + const double c2 = LengthSqare3(z); met->l3 = sqrt(c2); + + // calc area ( 0.0625 = 1/16 ) + met->area = sqrt(( 2*(a2*b2+a2*c2+b2*c2) - a2*a2 - b2*b2 - c2*c2 ) * 0.0625 ); + + // calc heights + const double area2 = 2*met->area; + met->h1 = area2/met->l1; + met->h2 = area2/met->l2; + met->h3 = area2/met->l3; + MinMax3p(met->min_ht,met->max_ht,met->h1,met->h2,met->h3); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// octahedron_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void CreateRegularOctahedron +( + octahedron_t *oct, // valid pointer, initialize + double radius, // radius of octahedron + const double3 *rot, // not NULL: rotate octahedron + const double3 *shift // not NULL: shift octahedron +) +{ + DASSERT(oct); + + double3 radius3; + radius3.x = radius3.y = radius3.z = radius; + CreateOctahedron(oct,&radius3,rot,shift); +} + +//----------------------------------------------------------------------------- + +void CreateRegularOctahedronF +( + octahedron_t *oct, // valid pointer, initialize + double radius, // radius of octahedron + const float *rot, // not NULL: 3D vector, rotate octahedron + const float *shift // not NULL: 3D vector, shift octahedron +) +{ + DASSERT(oct); + + double3 radius3; + radius3.x = radius3.y = radius3.z = radius; + + double3 *rot3 = 0, rot3_data; + if (rot) + { + rot3_data.x = *rot++; + rot3_data.y = *rot++; + rot3_data.z = *rot; + rot3 = &rot3_data; + } + + double3 *shift3 = 0, shift3_data; + if (shift) + { + shift3_data.x = *shift++; + shift3_data.y = *shift++; + shift3_data.z = *shift; + shift3 = &shift3_data; + } + + CreateOctahedron(oct,&radius3,rot3,shift3); +} + +//----------------------------------------------------------------------------- + +void CreateOctahedron +( + octahedron_t *oct, // valid pointer, initialize + const double3 *radius, // radius of octahedron + const double3 *rot, // not NULL: rotate octahedron + const double3 *shift // not NULL: shift octahedron +) +{ + DASSERT(oct); + DASSERT(radius); + + oct->x1.x = -radius->x; + oct->x1.y = 0.0; + oct->x1.z = 0.0; + + oct->x2.x = +radius->x; + oct->x2.y = 0.0; + oct->x2.z = 0.0; + + oct->y1.x = 0.0; + oct->y1.y = -radius->y; + oct->y1.z = 0.0; + + oct->y2.x = 0.0; + oct->y2.y = +radius->y; + oct->y2.z = 0.0; + + oct->z1.x = 0.0; + oct->z1.y = 0.0; + oct->z1.z = -radius->z; + + oct->z2.x = 0.0; + oct->z2.y = 0.0; + oct->z2.z = +radius->z; + + if (rot) + RotateOctahedron(oct,0,rot); + if (shift) + ShiftOctahedron(oct,shift); +} + +//----------------------------------------------------------------------------- + +void ScaleOctahedron +( + octahedron_t *oct, // valid octahedron data + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *scale // not NULL: scale octahedron +) +{ + DASSERT(oct); + if (scale) + { + if (origin) + { + uint p; + for ( p = 0; p < 6; p++ ) + { + oct->p[p].x = ( oct->p[p].x - origin->x ) * scale->x + origin->x; + oct->p[p].y = ( oct->p[p].y - origin->y ) * scale->y + origin->y; + oct->p[p].z = ( oct->p[p].z - origin->z ) * scale->z + origin->z; + } + } + else + { + uint p; + for ( p = 0; p < 6; p++ ) + { + oct->p[p].x *= scale->x; + oct->p[p].y *= scale->y; + oct->p[p].z *= scale->z; + } + } + } +} + +//----------------------------------------------------------------------------- + +void RotateOctahedron +( + octahedron_t *oct, // valid octahedron data + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *rot // not NULL: rotate octahedron +) +{ + if (rot) + Rotate(origin,rot,oct->p,sizeof(*oct->p),6); +} + +//----------------------------------------------------------------------------- + +void ShiftOctahedron +( + octahedron_t *oct, // valid octahedron data + const double3 *shift // not NULL: shift octahedron +) +{ + DASSERT(oct); + if (shift) + { + uint p; + for ( p = 0; p < 6; p++ ) + { + oct->p[p].x += shift->x; + oct->p[p].y += shift->y; + oct->p[p].z += shift->z; + } + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// cuboid_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void CreateCube +( + cuboid_t *cub, // valid pointer, initialize + double width, // width of cube + const double3 *rot, // not NULL: rotate cube + const double3 *shift // not NULL: shift cube +) +{ + DASSERT(cub); + + double3 size; + size.x = size.y = size.z = width; + CreateCuboid(cub,&size,rot,shift); +} + +//----------------------------------------------------------------------------- + +void CreateCubeF +( + cuboid_t *cub, // valid pointer, initialize + double width, // width of cube + const float *rot, // not NULL: 3D vector, rotate cube + const float *shift // not NULL: 3D vector, shift cube +) +{ + DASSERT(cub); + + double3 size; + size.x = size.y = size.z = width; + + double3 *rot3 = 0, rot3_data; + if (rot) + { + rot3_data.x = *rot++; + rot3_data.y = *rot++; + rot3_data.z = *rot; + rot3 = &rot3_data; + } + + double3 *shift3 = 0, shift3_data; + if (shift) + { + shift3_data.x = *shift++; + shift3_data.y = *shift++; + shift3_data.z = *shift; + shift3 = &shift3_data; + } + + CreateCuboid(cub,&size,rot3,shift3); +} + +//----------------------------------------------------------------------------- + +void CreateCuboid +( + cuboid_t *cub, // valid pointer, initialize + const double3 *size, // base size of cuboid + const double3 *rot, // not NULL: rotate cuboid + const double3 *shift // not NULL: shift cuboid +) +{ + DASSERT(cub); + DASSERT(size); + + double3 s; + s.x = size->x / 2; + s.y = size->y / 2; + s.z = size->z / 2; + + uint p; + for ( p = 0; p < 8; p++ ) + { + cub->p[p].x = p & 1 ? +s.x : -s.x; + cub->p[p].y = p & 2 ? +s.y : -s.y; + cub->p[p].z = p & 4 ? +s.z : -s.z; + } + + if (rot) + RotateCuboid(cub,0,rot); + if (shift) + ShiftCuboid(cub,shift); +} + +//----------------------------------------------------------------------------- + +void CreateCuboidF +( + cuboid_t *cub, // valid pointer, initialize + const float *size, // base size of cuboid + const float *rot, // not NULL: rotate cuboid + const float *shift // not NULL: shift cuboid +) +{ + DASSERT(cub); + DASSERT(size); + + double3 size3; + size3.x = *size++; + size3.y = *size++; + size3.z = *size; + + double3 *rot3 = 0, rot3_data; + if (rot) + { + rot3_data.x = *rot++; + rot3_data.y = *rot++; + rot3_data.z = *rot; + rot3 = &rot3_data; + } + + double3 *shift3 = 0, shift3_data; + if (shift) + { + shift3_data.x = *shift++; + shift3_data.y = *shift++; + shift3_data.z = *shift; + shift3 = &shift3_data; + } + + CreateCuboid(cub,&size3,rot3,shift3); +} + +//----------------------------------------------------------------------------- + +void ScaleCuboid +( + cuboid_t *cub, // valid cuboid data + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *scale // not NULL: scale cuboid +) +{ + DASSERT(cub); + if (scale) + { + if (origin) + { + uint p; + for ( p = 0; p < 8; p++ ) + { + cub->p[p].x = ( cub->p[p].x - origin->x ) * scale->x + origin->x; + cub->p[p].y = ( cub->p[p].y - origin->y ) * scale->y + origin->y; + cub->p[p].z = ( cub->p[p].z - origin->z ) * scale->z + origin->z; + } + } + else + { + uint p; + for ( p = 0; p < 8; p++ ) + { + cub->p[p].x *= scale->x; + cub->p[p].y *= scale->y; + cub->p[p].z *= scale->z; + } + } + } +} + +//----------------------------------------------------------------------------- + +void RotateCuboid +( + cuboid_t *cub, // valid cuboid data + const double3 *origin, // origin of rotation, NULL = v(0,0,0) + const double3 *rot // not NULL: rotate cuboid +) +{ + if (rot) + Rotate(origin,rot,cub->p,sizeof(*cub->p),8); +} + +//----------------------------------------------------------------------------- + +void ShiftCuboid +( + cuboid_t *cub, // valid cuboid data + const double3 *shift // not NULL: shift cuboid +) +{ + DASSERT(cub); + if (shift) + { + uint p; + for ( p = 0; p < 8; p++ ) + { + cub->p[p].x += shift->x; + cub->p[p].y += shift->y; + cub->p[p].z += shift->z; + } + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// index lists /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void InitializeIL ( IndexList_t * il, ccp prefix ) +{ + DASSERT(il); + + memset(il,0,sizeof(*il)); + il->prefix = prefix; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ResetIL ( IndexList_t * il ) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + + uint i; + for ( i = 0; i < il->used; i++ ) + FreeString(il->list[i]); + FREE(il->list); + + InitializeIL(il,il->prefix); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FillIL +( + IndexList_t * il, // valid index list + uint min_fill // fill minimum # elements +) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + + if (il->prefix) + { + if ( min_fill > il->used ) + DefineIL(il,min_fill-1,0,0); + + uint i; + for ( i = 0; i < il->used; i++ ) + if (!il->list[i]) + { + if ( il->next_index < i ) + il->next_index = i; + char buf[VARNAME_SIZE+1]; + snprintf(buf,sizeof(buf),"%s%u",il->prefix,il->next_index++); + il->list[i] = STRDUP(buf); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void DefineIL +( + IndexList_t * il, // valid index list + uint index, // index of object + ccp name, // name of object + bool move_name // true: 'name' is alloced -> move it +) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + + if ( index >= il->size ) + { + il->size = 3*il->size/2 + 10; + if ( il->size < index + 10 ) + il->size = index + 10; + il->list = REALLOC(il->list,il->size*sizeof(*il->list)); + } + DASSERT( il->list ); + DASSERT( index < il->size ); + + uint used = il->used; + while ( used <= index ) + il->list[used++] = 0; + il->used = used; + DASSERT( index < il->used ); + + FreeString(il->list[index]); + il->list[index] = move_name || !name ? name : STRDUP(name); + noPRINT("DEFINE-IL() %s = %u\n", name, index ); + + if ( name && il->prefix ) + { + ccp prefix = il->prefix; + while ( *prefix && toupper((int)*prefix) == toupper((int)*name) ) + prefix++, name++; + + if ( !*prefix && *name ) + { + char *end; + uint next = strtoul(name,&end,10) + 1; + if ( !*end && il->next_index < next ) + il->next_index = next; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool RemoveIL +( + IndexList_t * il, // valid index list + uint index // index of object +) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + if ( index >= il->used ) + return false; + + ccp *ptr = il->list + index; + FreeString(*ptr); + il->used--; + if ( index < il->used ) + memmove(ptr,ptr+1,sizeof(*ptr)*(il->used-index)); + il->list[il->used] = 0; + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp GetNameIL +( + IndexList_t * il, // valid index list + uint index // index of object +) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + + if ( index >= il->used ) + return "-1"; + DASSERT( index < il->used ); + + ccp name = il->list[index]; + if (!name) + { + FillIL(il,0); + name = il->list[index]; + } + DASSERT(name); + return name; +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintNameIL +( + FILE * f, // output files + IndexList_t * il, // valid index list + uint index, // index of object + uint align, // align end of name to character pos + uint fw, // field width of name + uint indent // indention of continuation line +) +{ + DASSERT(il); + DASSERT( il->used <= il->size ); + DASSERT( !il->list == !il->size ); + + ccp name = GetNameIL(il,index); + DASSERT(name); + const uint nlen = strlen(name); + + if ( nlen > fw ) + { + // print with continuation line + if ( align < fw ) + fprintf(f,"%s\r\n%*s%*s%*s", name, indent,"", align,">", fw-align,">" ); + else + fprintf(f,"%s\r\n%*s%*s", name, indent,"", fw,">" ); + } + else if ( nlen > align ) + { + // use extra space of fw + fprintf(f,"%-*s", fw, name ); + } + else if ( align < fw ) + { + // aligned output + fprintf(f,"%*s%*s", align, name, fw-align, "" ); + } + else + { + // aligned output + fprintf(f,"%*s", fw, name ); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// color conversions /////////////// +/////////////////////////////////////////////////////////////////////////////// + + +int ScanOptCmprDefault ( ccp arg ) +{ + DASSERT( opt_cmpr_def[4] == 0xff ); + DASSERT( opt_cmpr_def[5] == 0xff ); + DASSERT( opt_cmpr_def[6] == 0xff ); + DASSERT( opt_cmpr_def[7] == 0xff ); + + static u8 reset[8] = { 0x00,0x00, 0x00,0x20, 0xff,0xff,0xff,0xff }; + memcpy(opt_cmpr_def,reset,sizeof(opt_cmpr_def)); + opt_cmpr_valid = false; + + if ( !arg || !strcmp(arg,"-") ) + return 0; + + char *end; + u32 col1 = str2ul(arg,&end,16); + if ( end == arg ) + return 0; + + u32 col2 = col1; + arg = end; + while (isspace((int)*arg)) + arg++; + if ( *arg == ',' ) + { + arg++; + col2 = str2ul(arg,&end,16); + if ( end == arg ) + col2 = col1; + } + + u16 c1 = RGB_to_RGB565(col1); + u16 c2 = RGB_to_RGB565(col2); + if ( c1 > c2 ) + { + const u16 temp = c1; + c1 = c2; + c2 = temp; + } + else if ( c1 == c2 ) + { + c1 &= ~0x0020; // modify least significant bit of green + c2 |= 0x0020; + } + + write_be16(opt_cmpr_def,c1); + write_be16(opt_cmpr_def+2,c2); + opt_cmpr_valid = true; + + #if 0 + PRINT("%08x,%08x -> %04x,%04x\n",col1,col2,c1,c2); + HEXDUMP16(0,0,opt_cmpr_def,8); + #endif + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// color conversion tables /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const u8 cc38[8] = // convert 3-bit color to 8-bit color +{ + 0x00,0x24,0x49,0x6d, 0x92,0xb6,0xdb,0xff +}; + +//----------------------------------------------------------------------------- + +const u8 cc48[16] = // convert 4-bit color to 8-bit color +{ + 0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77, 0x88,0x99,0xaa,0xbb, 0xcc,0xdd,0xee,0xff +}; + +//----------------------------------------------------------------------------- + +const u8 cc58[32] = // convert 5-bit color to 8-bit color +{ + 0x00,0x08,0x10,0x19, 0x21,0x29,0x31,0x3a, 0x42,0x4a,0x52,0x5a, 0x63,0x6b,0x73,0x7b, + 0x84,0x8c,0x94,0x9c, 0xa5,0xad,0xb5,0xbd, 0xc5,0xce,0xd6,0xde, 0xe6,0xef,0xf7,0xff +}; + +//----------------------------------------------------------------------------- + +const u8 cc68[64] = // convert 6-bit color to 8-bit color +{ + 0x00,0x04,0x08,0x0c, 0x10,0x14,0x18,0x1c, 0x20,0x24,0x28,0x2d, 0x31,0x35,0x39,0x3d, + 0x41,0x45,0x49,0x4d, 0x51,0x55,0x59,0x5d, 0x61,0x65,0x69,0x6d, 0x71,0x75,0x79,0x7d, + 0x82,0x86,0x8a,0x8e, 0x92,0x96,0x9a,0x9e, 0xa2,0xa6,0xaa,0xae, 0xb2,0xb6,0xba,0xbe, + 0xc2,0xc6,0xca,0xce, 0xd2,0xd7,0xdb,0xdf, 0xe3,0xe7,0xeb,0xef, 0xf3,0xf7,0xfb,0xff +}; + +/////////////////////////////////////////////////////////////////////////////// + +const u8 cc83[256] = // convert 8-bit color to 3-bit color +{ + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01, 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x02, 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, + 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, + 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, + 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, + 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, + 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x07,0x07,0x07, + 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07 +}; + +//----------------------------------------------------------------------------- + +const u8 cc84[256] = // convert 8-bit color to 4-bit color +{ + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, 0x01,0x01,0x02,0x02, 0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x02,0x02,0x02,0x03, 0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04, 0x04,0x05,0x05,0x05, + 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x06,0x06, + 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x07, + 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07, + 0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08, + 0x08,0x09,0x09,0x09, 0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09, + 0x09,0x09,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a, + 0x0a,0x0a,0x0a,0x0b, 0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b, 0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c, + 0x0c,0x0c,0x0c,0x0c, 0x0c,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x0d, + 0x0d,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e, + 0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0f, 0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f +}; + +//----------------------------------------------------------------------------- + +const u8 cc85[256] = // convert 8-bit color to 5-bit color +{ + 0x00,0x00,0x00,0x00, 0x00,0x01,0x01,0x01, 0x01,0x01,0x01,0x01, 0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02, 0x02,0x03,0x03,0x03, 0x03,0x03,0x03,0x03, 0x03,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, 0x04,0x04,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x06,0x06, + 0x06,0x06,0x06,0x06, 0x06,0x06,0x07,0x07, 0x07,0x07,0x07,0x07, 0x07,0x07,0x08,0x08, + 0x08,0x08,0x08,0x08, 0x08,0x08,0x09,0x09, 0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x0a, + 0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0b, 0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0c, + 0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0d, 0x0d,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x0d, + 0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e, 0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f, + 0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10, 0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11, + 0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12, 0x12,0x13,0x13,0x13, 0x13,0x13,0x13,0x13, + 0x13,0x14,0x14,0x14, 0x14,0x14,0x14,0x14, 0x14,0x15,0x15,0x15, 0x15,0x15,0x15,0x15, + 0x15,0x16,0x16,0x16, 0x16,0x16,0x16,0x16, 0x16,0x16,0x17,0x17, 0x17,0x17,0x17,0x17, + 0x17,0x17,0x18,0x18, 0x18,0x18,0x18,0x18, 0x18,0x18,0x19,0x19, 0x19,0x19,0x19,0x19, + 0x19,0x19,0x1a,0x1a, 0x1a,0x1a,0x1a,0x1a, 0x1a,0x1a,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1c, 0x1c,0x1c,0x1c,0x1c, 0x1c,0x1c,0x1c,0x1d, 0x1d,0x1d,0x1d,0x1d, + 0x1d,0x1d,0x1d,0x1e, 0x1e,0x1e,0x1e,0x1e, 0x1e,0x1e,0x1e,0x1f, 0x1f,0x1f,0x1f,0x1f +}; + +//----------------------------------------------------------------------------- + +const u8 cc85s1[256] = // convert 8-bit color to 5-bit color, shifted by 1 bit +{ + 0x00,0x00,0x00,0x00, 0x00,0x02,0x02,0x02, 0x02,0x02,0x02,0x02, 0x02,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04, 0x04,0x06,0x06,0x06, 0x06,0x06,0x06,0x06, 0x06,0x08,0x08,0x08, + 0x08,0x08,0x08,0x08, 0x08,0x08,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0c,0x0c, + 0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x10,0x10, + 0x10,0x10,0x10,0x10, 0x10,0x10,0x12,0x12, 0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x14, + 0x14,0x14,0x14,0x14, 0x14,0x14,0x14,0x16, 0x16,0x16,0x16,0x16, 0x16,0x16,0x16,0x18, + 0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x1a, 0x1a,0x1a,0x1a,0x1a, 0x1a,0x1a,0x1a,0x1a, + 0x1c,0x1c,0x1c,0x1c, 0x1c,0x1c,0x1c,0x1c, 0x1e,0x1e,0x1e,0x1e, 0x1e,0x1e,0x1e,0x1e, + 0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20, 0x22,0x22,0x22,0x22, 0x22,0x22,0x22,0x22, + 0x24,0x24,0x24,0x24, 0x24,0x24,0x24,0x24, 0x24,0x26,0x26,0x26, 0x26,0x26,0x26,0x26, + 0x26,0x28,0x28,0x28, 0x28,0x28,0x28,0x28, 0x28,0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2c,0x2c,0x2c, 0x2c,0x2c,0x2c,0x2c, 0x2c,0x2c,0x2e,0x2e, 0x2e,0x2e,0x2e,0x2e, + 0x2e,0x2e,0x30,0x30, 0x30,0x30,0x30,0x30, 0x30,0x30,0x32,0x32, 0x32,0x32,0x32,0x32, + 0x32,0x32,0x34,0x34, 0x34,0x34,0x34,0x34, 0x34,0x34,0x36,0x36, 0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x38, 0x38,0x38,0x38,0x38, 0x38,0x38,0x38,0x3a, 0x3a,0x3a,0x3a,0x3a, + 0x3a,0x3a,0x3a,0x3c, 0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3e, 0x3e,0x3e,0x3e,0x3e +}; + +//----------------------------------------------------------------------------- + +const u8 cc86[256] = // convert 8-bit color to 6-bit color +{ + 0x00,0x00,0x00,0x01, 0x01,0x01,0x01,0x02, 0x02,0x02,0x02,0x03, 0x03,0x03,0x03,0x04, + 0x04,0x04,0x04,0x05, 0x05,0x05,0x05,0x06, 0x06,0x06,0x06,0x07, 0x07,0x07,0x07,0x08, + 0x08,0x08,0x08,0x09, 0x09,0x09,0x09,0x0a, 0x0a,0x0a,0x0a,0x0b, 0x0b,0x0b,0x0b,0x0c, + 0x0c,0x0c,0x0c,0x0d, 0x0d,0x0d,0x0d,0x0e, 0x0e,0x0e,0x0e,0x0f, 0x0f,0x0f,0x0f,0x10, + 0x10,0x10,0x10,0x11, 0x11,0x11,0x11,0x12, 0x12,0x12,0x12,0x13, 0x13,0x13,0x13,0x14, + 0x14,0x14,0x14,0x15, 0x15,0x15,0x15,0x15, 0x16,0x16,0x16,0x16, 0x17,0x17,0x17,0x17, + 0x18,0x18,0x18,0x18, 0x19,0x19,0x19,0x19, 0x1a,0x1a,0x1a,0x1a, 0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1c,0x1c, 0x1d,0x1d,0x1d,0x1d, 0x1e,0x1e,0x1e,0x1e, 0x1f,0x1f,0x1f,0x1f, + 0x20,0x20,0x20,0x20, 0x21,0x21,0x21,0x21, 0x22,0x22,0x22,0x22, 0x23,0x23,0x23,0x23, + 0x24,0x24,0x24,0x24, 0x25,0x25,0x25,0x25, 0x26,0x26,0x26,0x26, 0x27,0x27,0x27,0x27, + 0x28,0x28,0x28,0x28, 0x29,0x29,0x29,0x29, 0x2a,0x2a,0x2a,0x2a, 0x2a,0x2b,0x2b,0x2b, + 0x2b,0x2c,0x2c,0x2c, 0x2c,0x2d,0x2d,0x2d, 0x2d,0x2e,0x2e,0x2e, 0x2e,0x2f,0x2f,0x2f, + 0x2f,0x30,0x30,0x30, 0x30,0x31,0x31,0x31, 0x31,0x32,0x32,0x32, 0x32,0x33,0x33,0x33, + 0x33,0x34,0x34,0x34, 0x34,0x35,0x35,0x35, 0x35,0x36,0x36,0x36, 0x36,0x37,0x37,0x37, + 0x37,0x38,0x38,0x38, 0x38,0x39,0x39,0x39, 0x39,0x3a,0x3a,0x3a, 0x3a,0x3b,0x3b,0x3b, + 0x3b,0x3c,0x3c,0x3c, 0x3c,0x3d,0x3d,0x3d, 0x3d,0x3e,0x3e,0x3e, 0x3e,0x3f,0x3f,0x3f +}; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// misc /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetIntModeName ( IntMode_t mode ) +{ + switch(mode) + { + case IMD_UNSET: return "-"; + + case IMD_BE0: return "BE"; + case IMD_BE1: return "BE1"; + case IMD_BE2: return "BE2"; + case IMD_BE3: return "BE3"; + case IMD_BE4: return "BE4"; + case IMD_BE5: return "BE5"; + case IMD_BE6: return "BE6"; + case IMD_BE7: return "BE7"; + case IMD_BE8: return "BE8"; + + case IMD_LE0: return "LE"; + case IMD_LE1: return "LE1"; + case IMD_LE2: return "LE2"; + case IMD_LE3: return "LE3"; + case IMD_LE4: return "LE4"; + case IMD_LE5: return "LE5"; + case IMD_LE6: return "LE6"; + case IMD_LE7: return "LE7"; + case IMD_LE8: return "LE8"; + + default: return "?"; + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + -- cgit v1.3.1