CnC_Remastered_Collection/REDALERT/INTERPAL.CPP
PG-SteveT 03416d24e1 Initial Source Code commit
Initial commit of original Tiberian Dawn and Red Alert source code converted to build as DLLs, and compatible with the release version of Command & Conquer Remastered.
2020-05-27 12:16:20 -07:00

466 lines
17 KiB
C++

//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
/* $Header: /CounterStrike/INTERPAL.CPP 1 3/03/97 10:24a Joe_bostic $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : INTERPAL.CPP *
* *
* Programmer : Steve Tall *
* *
* Start Date : December 7th 1995 *
* *
*---------------------------------------------------------------------------------------------*
* Overview: *
* This module contains functions to allow use of old 320x200 animations on a 640x400 screen *
* *
* Functions: *
* Read_Interpolation_Palette -- reads an interpolation palette table from disk *
* Write_Interpolation_Palette -- writes an interpolation palette to disk *
* Create_Palette_Interpolation_Table -- build the palette interpolation table *
* Increase_Palette_Luminance -- increase the contrast of a palette *
* Interpolate_2X_Scale -- Stretch a 320x200 graphic buffer into 640x400 *
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
BOOL InterpolationPaletteChanged = FALSE;
extern "C" {
extern void __cdecl Asm_Interpolate (unsigned char* src_ptr ,
unsigned char* dest_ptr ,
int lines ,
int src_width ,
int dest_width);
extern void __cdecl Asm_Interpolate_Line_Double (unsigned char* src_ptr ,
unsigned char* dest_ptr ,
int lines ,
int src_width ,
int dest_width);
extern void __cdecl Asm_Interpolate_Line_Interpolate (unsigned char* src_ptr ,
unsigned char* dest_ptr ,
int lines ,
int src_width ,
int dest_width);
}
#define SIZE_OF_PALETTE 256
extern "C"{
unsigned char PaletteInterpolationTable[SIZE_OF_PALETTE][SIZE_OF_PALETTE];
unsigned char * InterpolationPalette;
}
/***********************************************************************************************
* Read_Interpolation_Palette -- reads an interpolation palette table from disk *
* *
* *
* *
* INPUT: name of palette file *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 12/12/95 12:15PM ST : Created *
*=============================================================================================*/
void Read_Interpolation_Palette (char const * palette_file_name)
{
CCFileClass palette_file(palette_file_name);
if (palette_file.Is_Available()) {
palette_file.Open(READ);
palette_file.Read(&PaletteInterpolationTable[0][0], 256*256);
palette_file.Close();
InterpolationPaletteChanged = FALSE;
}
}
/***********************************************************************************************
* Write_Interpolation_Palette -- writes an interpolation palette table to disk *
* *
* *
* *
* INPUT: name of palette file *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 12/12/95 12:15PM ST : Created *
*=============================================================================================*/
void Write_Interpolation_Palette (char const * palette_file_name)
{
CCFileClass palette_file(palette_file_name);
if (!palette_file.Is_Available()) {
palette_file.Open(WRITE);
palette_file.Write(&PaletteInterpolationTable[0][0], 256*256);
palette_file.Close();
}
}
/***************************************************************************
* CREATE_PALETTE_INTERPOLATION_TABLE *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 12/06/1995 MG : Created. *
*=========================================================================*/
void Create_Palette_Interpolation_Table( void )
{
// Asm_Create_Palette_Interpolation_Table();
#if (1)
int i;
int j;
int p;
unsigned char * first_palette_ptr;
unsigned char * second_palette_ptr;
unsigned char * match_pal_ptr;
int first_r;
int first_g;
int first_b;
int second_r;
int second_g;
int second_b;
int diff_r;
int diff_g;
int diff_b;
int dest_r;
int dest_g;
int dest_b;
int distance;
int closest_distance;
int index_of_closest_color;
//
// Create an interpolation table for the current palette.
//
first_palette_ptr = (unsigned char *) InterpolationPalette;
for ( i = 0; i < SIZE_OF_PALETTE; i ++ ) {
//
// Get the first palette entry's RGB.
//
first_r = *first_palette_ptr;
first_palette_ptr ++;
first_g = *first_palette_ptr;
first_palette_ptr ++;
first_b = *first_palette_ptr;
first_palette_ptr ++;
second_palette_ptr = (unsigned char *) InterpolationPalette;
for ( j = 0; j < SIZE_OF_PALETTE; j ++ ) {
//
// Get the second palette entry's RGB.
//
second_r = *second_palette_ptr;
second_palette_ptr ++;
second_g = *second_palette_ptr;
second_palette_ptr ++;
second_b = *second_palette_ptr;
second_palette_ptr ++;
//
// Now calculate the RGB halfway between the first and second colors.
//
dest_r = ( first_r + second_r ) >> 1;
dest_g = ( first_g + second_g ) >> 1;
dest_b = ( first_b + second_b ) >> 1;
//
// Now find the color in the palette that most closely matches the interpolated color.
//
index_of_closest_color = 0;
// closest_distance = (256 * 256) * 3;
closest_distance = 500000;
match_pal_ptr = (unsigned char *) InterpolationPalette;
for ( p = 0; p < SIZE_OF_PALETTE; p ++ ) {
diff_r = ( ((int) (*match_pal_ptr)) - dest_r );
match_pal_ptr ++;
diff_g = ( ((int) (*match_pal_ptr)) - dest_g );
match_pal_ptr ++;
diff_b = ( ((int) (*match_pal_ptr)) - dest_b );
match_pal_ptr ++;
distance = ( diff_r * diff_r ) + ( diff_g * diff_g ) + ( diff_b * diff_b );
if ( distance < closest_distance ) {
closest_distance = distance;
index_of_closest_color = p;
}
}
PaletteInterpolationTable[ i ][ j ] = (unsigned char) index_of_closest_color;
}
}
#endif
InterpolationPaletteChanged = FALSE;
return;
}
/***********************************************************************************************
* Increase_Palette_Luminance -- increase contrast of colours in a palette *
* *
* *
* *
* INPUT: ptr to palette *
* percentage increase of red *
* percentage increase of green *
* percentage increase of blue *
* cap value for colours *
* *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 12/12/95 12:16PM ST : Created *
*=============================================================================================*/
void Increase_Palette_Luminance (unsigned char * palette , int red_percentage , int green_percentage , int blue_percentage , int cap)
{
unsigned int red;
unsigned int green;
unsigned int blue;
for (int i=0 ; i<SIZE_OF_PALETTE*3 ; i+=3) {
red = (unsigned)*(palette+i);
green = (unsigned)*(palette+i+1);
blue = (unsigned)*(palette+i+2);
red += red*red_percentage/100;
green += green*green_percentage/100;
blue += blue*blue_percentage/100;
red = MIN (cap, (int)red);
green = MIN (cap, (int)green);
blue = MIN (cap, (int)blue);
*(palette+i) =(unsigned char)red;
*(palette+i+1) =(unsigned char)green;
*(palette+i+2) =(unsigned char)blue;
}
}
int CopyType =0;
#ifdef WIN32
/***************************************************************************
* INTERPOLATE_2X_SCALE *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 12/06/1995 MG : Created. *
*=========================================================================*/
void Interpolate_2X_Scale( GraphicBufferClass * source, GraphicViewPortClass * dest , char const * palette_file_name)
{
// Not needed. ST - 5/13/2019
source; dest; palette_file_name;
#if (0)
unsigned char * src_ptr;
unsigned char * dest_ptr;
unsigned char * last_dest_ptr;
unsigned char * end_of_source;
int src_width;
int dest_width;
// int width_counter;
BOOL source_locked = FALSE;
BOOL dest_locked = FALSE;
/*
**If a palette table exists on disk then read it in otherwise create it
*/
if (InterpolationPaletteChanged) {
if (palette_file_name) {
Read_Interpolation_Palette(palette_file_name);
}
if (InterpolationPaletteChanged) {
Create_Palette_Interpolation_Table();
}
}
/*
** Write the palette table to disk so we don't have to create it again next time
*/
if (palette_file_name) {
Write_Interpolation_Palette(palette_file_name);
}
if ( dest == &SeenBuff ) Hide_Mouse();
Wait_Blit();
/*
** Lock video surfaces if required
*/
if (source->Get_IsDirectDraw()) {
if (!source->Lock()) {
if (dest == &SeenBuff) Show_Mouse();
return;
}
source_locked = TRUE;
}
if (dest->Get_IsDirectDraw()) {
if (!dest->Lock()) {
if (source_locked) {
source->Unlock();
}
if (dest == &SeenBuff) Show_Mouse();
return;
}
dest_locked = TRUE;
}
//
// Get pointers to the source and destination buffers.
//
src_ptr = (unsigned char *) source->Get_Offset();
dest_ptr = (unsigned char *) dest->Get_Offset();
end_of_source = src_ptr + ( source->Get_Width() * source->Get_Height() );
//
// Get width of source and dest buffers.
//
src_width = source->Get_Width();
dest_width = 2*(dest->Get_Width() + dest->Get_XAdd() + dest->Get_Pitch());
last_dest_ptr = dest_ptr;
/*
** Call the appropriate assembly language copy routine
*/
#if (1)
switch (CopyType) {
case 0:
Asm_Interpolate ( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);
break;
case 1:
Asm_Interpolate_Line_Double( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);
break;
case 2:
Asm_Interpolate_Line_Interpolate( src_ptr , dest_ptr , source->Get_Height() , src_width , dest_width);
break;
}
#endif
#if (0)
//
// Copy over the first pixel (upper left).
//
*dest_ptr = *src_ptr;
src_ptr ++;
dest_ptr ++;
//
// Scale copy.
//
width_counter = 0;
while ( src_ptr < end_of_source ) {
//
// Blend this pixel with the one to the left and place this new color in the dest buffer.
//
*dest_ptr = PaletteInterpolationTable[ (*src_ptr) ][ (*( src_ptr - 1 )) ];
dest_ptr ++;
//
// Now place the source pixel into the dest buffer.
//
*dest_ptr = *src_ptr;
src_ptr ++;
dest_ptr ++;
width_counter ++;
if ( width_counter == src_width ) {
width_counter = 0;
last_dest_ptr += dest_width;
dest_ptr = last_dest_ptr;
}
}
#endif
if (source_locked) source->Unlock();
if (dest_locked) dest->Unlock();
if (dest == &SeenBuff) Show_Mouse();
//BG long *longptr = (long *)&PaletteInterpolationTable[0][0];
//BG Mono_Printf("Clock cycles: %08x\n",*longptr);
#endif
}
#endif