CnC_Red_Alert/WIN32LIB/SRCDEBUG/LIB.CPP

218 lines
9.3 KiB
C++

/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 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.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: g:/library/source/rcs/./lib.c 1.16 1994/05/20 15:34:33 joe_bostic Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Library Routines *
* *
* File Name : LIB.C *
* *
* Programmer : Scott Bowen *
* *
* Start Date : January 14, 1993 *
* *
* Last Update : May 20, 1993 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Add_Long_To_Pointer -- Pointer arithmatic when pointer could be XMS. *
* Find_Argv -- Checks to see if string is in arguement *
* Mono_Mem_Dump -- Dumps memory to mono monitor with hex and char. *
* Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values *
* Convert_RGB_To_HSV -- Converts RGB to RSV coordinates. *
* Set_Search_Drives -- Sets up the CDRom and HardDrive paths. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include "misc.h"
//PRIVATE unsigned Divide_With_Round(unsigned num, unsigned den);
/***************************************************************************
* Divide_With_Round -- Divides integers and round to nearest integer. *
* *
* INPUT: int numberator. *
* int denominator. *
* *
* OUTPUT: Returns value rounded. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/13/1992 SB : Created. *
*=========================================================================*/
static unsigned Divide_With_Round(unsigned num, unsigned den)
{
// return num/den + (0 ro 1). 1 if the remainder is more than half the denominator.
return( (num / den) + (unsigned)((num % den) >= ((den + 1) >> 1)) );
}
#define HSV_BASE 255 // This is used to get a little better persion on HSV conversion.
#define RGB_BASE 63 // Not 64, this is really the max value.
/***************************************************************************
* Convert_RGB_To_HSV -- Converts RGB to RSV coordinates. *
* *
* INPUT: int r,g, and b values. *
* int *h, *s, and *v pointers. *
* *
* OUTPUT: Assigns values to *h, *s, and *v. *
* *
* WARNINGS: The reason we use a different base for HSV then RGB is *
* because we loose alot of persision by not using floating *
* point. Using the same base value (63) made it so that *
* about 50% of the time one RGB value would be one different *
* then the original if you went from RGB to HSV to RGB. *
* Using 255 drop it down to about 9% of the time we get an *
* off value. To get it perfect, we would have to make the *
* HSV base larger - but then you need to do all calculations *
* in long instead of unsigned int. *
* HISTORY: *
* 02/11/1992 SB : Created. *
*=========================================================================*/
void Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v)
{
unsigned int m, r1, g1, b1, tmp;
// Convert RGB base to HSV base.
r = Divide_With_Round((r * HSV_BASE), RGB_BASE);
g = Divide_With_Round((g * HSV_BASE), RGB_BASE);
b = Divide_With_Round((b * HSV_BASE), RGB_BASE);
// Set hue to default.
*h = 0;
// Set v = Max(r,g,b) to find dominant primary color.
*v = (r > g) ? r : g;
if (b > *v) *v = b;
// Set m = min(r,g,b) to find amount of white.
m = (r < g) ? r : g;
if (b < m) m = b;
// Determine the normalized saturation.
if (*v != 0) {
*s = Divide_With_Round( (*v - m) * HSV_BASE ,*v);
} else {
*s = 0;
}
if (*s != 0) {
tmp = *v - m;
r1 = Divide_With_Round( (*v - r) * HSV_BASE, tmp);
g1 = Divide_With_Round( (*v - g) * HSV_BASE, tmp);
b1 = Divide_With_Round( (*v - b) * HSV_BASE, tmp);
// Find effect of second most predominant color.
// In which section of the hexagon of colors does the color lie?
if ((*v) == r) {
if (m == g) {
*h = 5 * HSV_BASE + b1;
} else {
*h = 1 * HSV_BASE - g1;
}
} else {
if ((*v) == g) {
if (m == b) {
*h = 1 * HSV_BASE + r1;
} else {
*h = 3 * HSV_BASE - b1;
}
} else {
// *v == b
if (m == r) {
*h = 3 * HSV_BASE + g1;
} else {
*h = 5 * HSV_BASE - r1;
}
}
}
// Divide by six and round.
*h = Divide_With_Round(*h, 6);
}
}
/***************************************************************************
* Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values *
* *
* INPUT: int h,s, and v coordinates *
* int *r, *g, and *b pointers. *
* *
* OUTPUT: Assigns values to *r, *g, and *b. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/11/1992 SB : Created. *
*=========================================================================*/
void Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b)
{
unsigned int i; // Integer part.
unsigned int f; // Fractional or remainder part. f/HSV_BASE gives fraction.
unsigned int tmp; // Tempary variable to help with calculations.
unsigned int values[7]; // Possible rgb values. Don't use zero.
h *= 6;
f = h % HSV_BASE;
// Set up possible red, green and blue values.
values[1] =
values[2] = v;
//
// The following lines of code change
// values[3] = (v * (HSV_BASE - ( (s * f) / HSV_BASE) )) / HSV_BASE;
// values[4] = values[5] = (v * (HSV_BASE - s)) / HSV_BASE;
// values[6] = (v * (HSV_BASE - (s * (HSV_BASE - f)) / HSV_BASE)) / HSV_BASE;
// so that the are rounded divides.
//
tmp = Divide_With_Round(s * f, HSV_BASE);
values[3] = Divide_With_Round(v * (HSV_BASE - tmp), HSV_BASE);
values[4] =
values[5] = Divide_With_Round(v * (HSV_BASE - s), HSV_BASE);
tmp = HSV_BASE - Divide_With_Round(s * (HSV_BASE - f), HSV_BASE);
values[6] = Divide_With_Round(v * tmp, HSV_BASE);
// This should not be rounded.
i = h / HSV_BASE;
i += (i > 4) ? -4 : 2;
*r = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
i += (i > 4) ? -4 : 2;
*b = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
i += (i > 4) ? -4 : 2;
*g = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
}