Files
TeslaRel410/CODE/RP/MUNGA_L4/L4VB16.CPP
T
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:21:58 -05:00

5501 lines
126 KiB
C++

//===========================================================================//
// File: L4vb16.cpp //
// Project: MUNGA Brick: Applications-specific controls module //
// Contents: Interface specification for buffered 16-bit display //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 02/08/95 CPB Initial coding. //
// 11/01/95 CPB Removed 128 color limitation on auxiliary displays //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <mungal4.hpp>
#pragma hdrstop
#if !defined(L4VB16_HPP)
# include <l4vb16.hpp>
#endif
#if defined(TRACE_SCREEN_COPY)
static BitTrace Screen_Copy("Screen Copy");
#define SET_SCREEN_COPY() Screen_Copy.Set()
#define CLEAR_SCREEN_COPY() Screen_Copy.Clear()
#else
#define SET_SCREEN_COPY()
#define CLEAR_SCREEN_COPY()
#endif
#define BLIT_STATISTICS
#if defined(BLIT_STATISTICS)
static int
dirtyPixelCount,
transferPixelCount,
overflowPixelCount;
#endif
//#define DEBUG
#if defined(DEBUG)
static Logical
printFlag=True;
# define Diag_on printFlag=True
# define Diag_off printFlag=False
# define Diag_Tell(stuff) if(printFlag){cout << stuff;}
#else
# define Diag_on
# define Diag_off
# define Diag_Tell(n)
#endif
extern "C" void
SVGASetMode(
int mode,
LWord pageFlipFcnpointer
);
extern "C" void
SVGASetPage(
int page
);
extern "C" int
SVGATransfer32(
int dest_offset,
Word *source_pointer,
LWord changed_bits
);
extern "C" int
SVGATransfer32x(
int dest_offset,
Word *source_pointer,
LWord changed_bits
);
extern "C" void
SVGASetSplitterClock(
Logical state
);
extern "C" void
SVGAZeroPalette(
Word DAC_port
);
extern "C" void
SVGAWriteFullPalette(
Byte *firstColorByte,
Word DAC_port
);
extern "C" void
SVGAReadFullPalette(
Byte *firstColorByte,
Word DAC_port
);
extern "C" void
SVGAWritePaletteMask(
Word DAC_port,
Byte new_mask
);
extern "C" void
SVGAFunkyVideo(
Logical on_off
);
//########################################################################
//############################# BitWrangler ##############################
//########################################################################
//
// A "bitwrangler" manages a group of bits by segregating them into two groups:
// "active", and "inactive". Active bits are those specified within a given
// bit mask as "ones", and inactive bits are those specified as "zeros".
//
// Once initialized, the bitwrangler may be requested to increment either
// the active bit field or the inactive bit field: the "carry" is propagated
// from the least significant bit through the most significant bit, and if
// an overflow is generated it is returned as "False".
//
// Why in the world would anyone want such a bizarre object?
// It's used here to generate palettes and translation tables according
// to bit allocations for a GraphicsPort. "Unused" colors are easily
// found and set to proper values.
//
class BitWrangler
{
public:
BitWrangler(int bit_mask, int total_length);
~BitWrangler()
{}
void ResetActive();
void ResetInactive();
Logical IncrementActive();
Logical IncrementInactive();
int NumberOfActiveBits();
int NumberOfInactiveBits();
int Value;
protected:
int length;
int bitMask;
};
//
// Bitwrangler initialization
//
BitWrangler::BitWrangler(int bit_mask, int total_length)
{
Verify(bit_mask != 0);
bitMask = bit_mask;
length = total_length;
Value = 0;
Check_Fpu();
}
//
// Reset all "active" bits to zero
//
void
BitWrangler::ResetActive()
{
Value &= ~ bitMask;
Check_Fpu();
}
//
// Reset all "inactive" bits to zero
//
void
BitWrangler::ResetInactive()
{
Value &= bitMask;
Check_Fpu();
}
//
// Increment the "active" bit field, and return "false" if overflow
//
Logical
BitWrangler::IncrementActive()
{
int single_bit;
int count(length);
for(single_bit=1; count>0; --count, single_bit <<= 1)
{
//
// If it's an active bit, process it
//
if (bitMask & single_bit)
{
//
// Invert the bit
//
Value ^= single_bit;
//
// If the bit is now set, it was zero, so exit
//
if (Value & single_bit)
{
Check_Fpu();
return True;
}
}
}
//
// All the active bits are set, so return false
//
Check_Fpu();
return False;
}
//
// Increment the "inactive" bit field, and return "false" if overflow
//
Logical
BitWrangler::IncrementInactive()
{
int single_bit;
int count(length);
int inverse_mask(~bitMask);
for(single_bit=1; count>0; --count, single_bit <<= 1)
{
//
// If it's an inactive bit, process it
//
if (inverse_mask & single_bit)
{
//
// Invert the bit
//
Value ^= single_bit;
//
// If the bit is now set, it was zero, so exit
//
if (Value & single_bit)
{
Check_Fpu();
return True;
}
}
}
//
// All the inactive bits are set, so return false
//
Check_Fpu();
return False;
}
//
// Return the number of "active" bits
//
int
BitWrangler::NumberOfActiveBits()
{
int count(0), temp(bitMask);
while(temp != 0)
{
++count;
temp = temp & (temp-1);
}
Check_Fpu();
return count;
}
//
// Return the number of "inactive" bits
//
int
BitWrangler::NumberOfInactiveBits()
{
Check_Fpu();
return length-NumberOfActiveBits();
}
//########################################################################
//######################### Video16BitBuffered ###########################
//########################################################################
//
//NOTE: the application assumes that the origin is in the lower left
// corner of the display, and all parameters passed to these routines
// use the application's coordinate system.
//
// All of the methods here convert these values to the SCREEN
// coordinate system, with the origin in the UPPER LEFT corner of
// the display.
//
//===================================================================
// Creator
//===================================================================
Video16BitBuffered::Video16BitBuffered(int x, int y):
GraphicsDisplay(x, y),
pixelBuffer(x, y)
{
# if defined(DEBUG)
Tell(
"Video16BitBuffered::Video16BitBuffered()\n"
);
# endif
int
i,
changed_size;
Verify(pixelBuffer.Data.MapPointer != NULL);
height = y;
width = x;
changedBitWidth = (width >> 5);
changed_size = height * changedBitWidth;
maximumY = height-1;
maximumX = width-1;
//---------------------------------------------------------
// Create 'changedLine' and 'changedBit' arrays
//---------------------------------------------------------
changedLine = new Byte[height];
changedBit = new LWord[changed_size];
if (changedLine == NULL || changedBit == NULL)
{
# if defined(DEBUG)
Tell("INVALID!\n");
# endif
valid = False;
return;
}
else
{
Register_Pointer(changedLine);
Register_Pointer(changedBit);
valid = True;
}
# if defined(DEBUG)
Tell("changedLine=" << changedLine << "\n");
Tell("changedBit=" << changedBit << "\n");
# endif
//---------------------------------------------------------
// Clear the 'changedBit' array
//---------------------------------------------------------
memset(changedLine, 0, height);
//---------------------------------------------------------
// Clear the 'changedBit' array
//---------------------------------------------------------
LWord
*bit_dest;
for (i=changed_size,bit_dest=changedBit; i>0; --i,++bit_dest)
{
*bit_dest = (LWord) 0;
}
Check_Fpu();
}
//===================================================================
// Destructor
//===================================================================
Video16BitBuffered::~Video16BitBuffered()
{
Check(this);
if (changedLine != NULL)
{
Unregister_Pointer(changedLine);
delete changedLine;
changedLine = NULL;
}
if (changedBit != NULL)
{
Unregister_Pointer(changedBit);
delete changedBit;
changedBit = NULL;
}
Check_Fpu();
}
//===================================================================
// TestInstance
//===================================================================
Logical
Video16BitBuffered::TestInstance() const
{
return True;
}
//===================================================================
// ShowInstance
//===================================================================
void
Video16BitBuffered::ShowInstance(
char *indent
)
{
cout << indent << "Video16BitBuffered:\n";
Check(this);
char
temp[80];
Str_Copy(temp,indent, 80);
Str_Cat(temp,"...", 80);
cout << temp << "width =" << width << "\n";
cout << temp << "height =" << height << "\n";
cout << temp << "maximumX =" << maximumX << "\n";
cout << temp << "maximumY =" << maximumY << "\n";
cout << temp << "changedLine=" << changedLine << "\n";
cout << temp << "changedBit =" << changedBit << "\n";
pixelBuffer.ShowInstance(temp);
GraphicsDisplay::ShowInstance(temp);
Check_Fpu();
}
//===================================================================
// buildDestPointer
//===================================================================
void
Video16BitBuffered::buildDestPointer(
int screenX,
int screenY,
Word **pixel_pointer,
LWord **changed_bit_pointer,
LWord *changed_bit
)
{
Verify(valid);
Verify(pixel_pointer != NULL);
Verify(changed_bit_pointer != NULL);
Verify(changed_bit != NULL);
Verify(screenX >= 0);
Verify(screenX < width);
Verify(screenY >= 0);
Verify(screenY < height);
*pixel_pointer = pixelBuffer.Data.MapPointer +
screenX +
(screenY * width);
Verify(*pixel_pointer >= pixelBuffer.Data.MapPointer);
Verify(*pixel_pointer < &pixelBuffer.Data.MapPointer[height*width]);
*changed_bit_pointer = changedBit +
(screenX >> 5) +
(screenY * changedBitWidth);
Verify(*changed_bit_pointer >= changedBit);
Verify(*changed_bit_pointer < &changedBit[height*changedBitWidth]);
*changed_bit = 1L << (0x1F - (screenX & 0x1F));
Verify(*changed_bit != 0L);
Diag_Tell(
"Video16BitBuffered::buildDestPointer(" << screenX <<
", " << screenY << hex <<
") = pix " << *pixel_pointer <<
", cbp " << *changed_bit_pointer <<
", cb " << *changed_bit << dec <<
"\n"
);
Diag_Tell("changedBitWidth=" << changedBitWidth << "\n");
Check_Fpu();
}
//===================================================================
// MarkChangedLines
//===================================================================
#if defined(BLIT_STATISTICS)
# define SET_CHANGED(pointer, bits) *pointer |= bits; ++dirtyPixelCount
#else
# define SET_CHANGED(pointer, bits) *pointer |= bits
#endif
#define LEFT_CHANGED(pointer, bits) \
bits <<= 1; \
if (bits == 0) { --pointer; bits=0x00000001L; }
#define RIGHT_CHANGED(pointer, bits) \
bits >>= 1; \
if (bits == 0) { ++pointer; bits=0x80000000L; }
#define UP_CHANGED(pointer, bits) pointer -= changedBitWidth
#define DOWN_CHANGED(pointer, bits) pointer += changedBitWidth
#define LEFT_DEST(pointer) --pointer
#define RIGHT_DEST(pointer) ++pointer
#define UP_DEST(pointer) pointer -= width
#define DOWN_DEST(pointer) pointer += width
#define LEFT_SOURCE(pointer,map) --pointer
#define RIGHT_SOURCE(pointer,map) ++pointer
#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x
#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x
#define LEFT_BITMAP(pointer,bits) \
bits <<= 1; \
if (bits == 0) { --pointer; bits=0x0001; }
#define RIGHT_BITMAP(pointer, bits) \
bits >>= 1; \
if (bits == 0) { ++pointer; bits=0x8000; }
#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords
#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords
//
// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner!
//
void
Video16BitBuffered::MarkChangedLines(
int start,
int stop
)
{
Check(this);
Diag_Tell(
"Video16BitBuffered::MarkChangedLines(" << start <<
", " << stop <<
")\n"
);
if (start > stop)
{
# if defined(DEBUG)
Tell("MarkChangedLines FLIPPING\n");
# endif
int temp;
temp = start;
start = stop;
stop = temp;
}
Verify(start >= 0);
Verify(start <= maximumY);
Verify(stop >= 0);
Verify(stop <= maximumY);
//------------------------------------------------
// Set the flag for each changed line
//------------------------------------------------
Verify(stop >= start);
memset(&changedLine[start], 1, stop-start+1);
Check_Fpu();
}
//===================================================================
// DrawPoint
//===================================================================
void
Video16BitBuffered::DrawPoint(
int color,
int bitmask,
Enumeration operation,
int x, int y
)
{
Check(this);
Verify(x >= bounds.bottomLeft.x);
Verify(x <= bounds.topRight.x);
Verify(y >= bounds.bottomLeft.y);
Verify(y <= bounds.topRight.y);
Word
*dest_pointer;
LWord
*changed_pointer;
LWord
changed_bit;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y = maximumY - y;
# if defined(DEBUG)
Tell("x=" << x << ", y=" << y << "\n");
# endif
Verify(x >= 0);
Verify(x < width);
Verify(y >= 0);
Verify(y < height);
//---------------------------------------------------------
// Update changedLine array
//---------------------------------------------------------
MarkChangedLines(y, y);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Create pointers
//---------------------------------------------------------
buildDestPointer(
x, y,
&dest_pointer,
&changed_pointer,
&changed_bit
);
//---------------------------------------------------------
// Write the point
//---------------------------------------------------------
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
Check_Fpu();
}
//===================================================================
// DrawLine
//===================================================================
void
Video16BitBuffered::DrawLine(
int color,
int bitmask,
Enumeration operation,
int x1, int y1,
int x2, int y2,
Logical include_last_pixel
)
{
# if defined(DEBUG)
Tell(
"Video16BitBuffered::DrawLine(" << color <<
", " << bitmask <<
", " << operation <<
", " << x1 << "," << y1 << "," << x2 << "," << y2 <<
", " << include_last_pixel <<
"\n"
);
# endif
Check(this);
Verify(x1 >= bounds.bottomLeft.x);
Verify(x1 <= bounds.topRight.x);
Verify(y1 >= bounds.bottomLeft.y);
Verify(y1 <= bounds.topRight.y);
Verify(x2 >= bounds.bottomLeft.x);
Verify(x2 <= bounds.topRight.x);
Verify(y2 >= bounds.bottomLeft.y);
Verify(y2 <= bounds.topRight.y);
enum
{
negative_delta_x = 1,
negative_delta_y = 2,
delta_y_greater = 0,
delta_x_greater = 4
};
long
length,
rate,
accumulator;
int
octant,
delta_x,
delta_y;
Word
*dest_pointer;
LWord
*changed_pointer;
LWord
changed_bit;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Route to DrawPoint if single pixel
//---------------------------------------------------------
if (x1 == x2 && y1 == y2)
{
if (include_last_pixel)
{
DrawPoint(color, bitmask, operation, x1, y1);
}
return;
}
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y1 = maximumY - y1;
y2 = maximumY - y2;
//---------------------------------------------------------
// Ensure that endpoints are legitimate
//---------------------------------------------------------
Verify(x1 >= 0);
Verify(x1 < width);
Verify(x2 >= 0);
Verify(x2 < width);
Verify(y1 >= 0);
Verify(y1 < height);
Verify(y2 >= 0);
Verify(y2 < height);
# if defined(DEBUG)
Tell(
"Transformed coordinates=" << x1 << "," << y1 <<
"," << x2 << "," << y2 <<
"\n"
);
# endif
//---------------------------------------------------------
// Update changedLine array
//---------------------------------------------------------
MarkChangedLines(y1, y2);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Determine which octant to use
//---------------------------------------------------------
octant = 0;
delta_x = x2 - x1;
if (delta_x < 0)
{
# if defined(DEBUG)
Tell("negative dx\n");
# endif
octant |= negative_delta_x;
delta_x = - delta_x;
}
delta_y = y2 - y1;
if (delta_y < 0)
{
# if defined(DEBUG)
Tell("negative dy\n");
# endif
octant |= negative_delta_y;
delta_y = - delta_y;
}
if (delta_x > delta_y)
{
# if defined(DEBUG)
Tell("dx > dy\n");
# endif
octant |= delta_x_greater;
}
# if defined(DEBUG)
Tell(
"dx=" << delta_x <<
", dy=" << delta_y <<
", octant=" << octant <<
", color=" << color <<
"\n"
);
# endif
//---------------------------------------------------------
// Prepare to draw line
//---------------------------------------------------------
buildDestPointer(
x1, y1,
&dest_pointer,
&changed_pointer,
&changed_bit
);
accumulator = 1024L; // preset accumulator to 1/2 full
//---------------------------------------------------------
// Draw the line!
//---------------------------------------------------------
switch (octant)
{
case delta_y_greater:
//-------------------------------------
// delta y greater
// positive delta x
// positive delta y
//
// +
// \ &
// \ &
//-------------------------------------
length = delta_y;
if (!include_last_pixel)
{
-- length;
}
Verify(delta_y > 0);
rate = (delta_x*2048L)/delta_y;
# if defined(DEBUG)
Tell(
"delta_y_greater, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
DOWN_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
RIGHT_DEST(dest_pointer);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_y_greater+negative_delta_x:
//-------------------------------------
// delta y greater
// negative delta x
// positive delta y
//
// +
// /
// /
//-------------------------------------
length = delta_y;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_x*2048L)/delta_y;
# if defined(DEBUG)
Tell(
"delta_y_greater+negative_delta_x, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
DOWN_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
LEFT_DEST(dest_pointer);
LEFT_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_y_greater+negative_delta_y:
//-------------------------------------
// delta y greater
// positive delta x
// negative delta y
//
// /
// /
// +
//-------------------------------------
length = delta_y;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_x*2048L)/delta_y;
# if defined(DEBUG)
Tell(
"delta_y_greater+negative_delta_y, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
UP_DEST(dest_pointer);
UP_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
RIGHT_DEST(dest_pointer);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_y_greater+negative_delta_x+negative_delta_y:
//-------------------------------------
// delta y greater
// negative delta x
// negative delta y
//
// \ &
// \ &
// +
//-------------------------------------
length = delta_y;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_x*2048L)/delta_y;
# if defined(DEBUG)
Tell(
"delta_y_greater+negative_delta_x+negative_delta_y, length=" <<
length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
UP_DEST(dest_pointer);
UP_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
LEFT_DEST(dest_pointer);
LEFT_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_x_greater:
//-------------------------------------
// delta x greater
// positive delta x
// positive delta y
//
// +---___
//
//
//-------------------------------------
length = delta_x;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_y*2048L)/delta_x;
# if defined(DEBUG)
Tell(
"delta_x_greater, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
RIGHT_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
DOWN_DEST(dest_pointer);
DOWN_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_x_greater+negative_delta_x:
//-------------------------------------
// delta x greater
// negative delta x
// positive delta y
//
// ___---+
//
//
//-------------------------------------
length = delta_x;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_y*2048L)/delta_x;
# if defined(DEBUG)
Tell(
"delta_x_greater+negative_delta_x, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
LEFT_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
DOWN_DEST(dest_pointer);
DOWN_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_x_greater+negative_delta_y:
//-------------------------------------
// delta x greater
// positive delta x
// negative delta y
//
// +___---
//
//
//-------------------------------------
length = delta_x;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_y*2048L)/delta_x;
# if defined(DEBUG)
Tell(
"delta_x_greater+negative_delta_y, length=" << length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
RIGHT_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
UP_DEST(dest_pointer);
UP_CHANGED(changed_pointer, changed_bit);
}
}
break;
case delta_x_greater+negative_delta_x+negative_delta_y:
//-------------------------------------
// delta x greater
// negative delta x
// negative delta y
//
// ---___+
//
//
//-------------------------------------
length = delta_x;
if (!include_last_pixel)
{
-- length;
}
rate = (delta_y*2048L)/delta_x;
# if defined(DEBUG)
Tell(
"delta_x_greater+negative_delta_x+negative_delta_y, length=" <<
length <<
", rate=" << rate <<
"\n"
);
# endif
Verify(rate >= 0L);
Verify(rate <= 2048L);
Verify(length >= 0);
for ( ; length>0; --length)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
# if defined(DEBUG)
Tell(
length <<
", accum=" << accumulator <<
", dest_pointer=" << dest_pointer <<
"\n"
);
# endif
SET_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
LEFT_CHANGED(changed_pointer, changed_bit);
accumulator += rate;
if (accumulator > 2048L)
{
# if defined(DEBUG)
Tell("OVERFLOW\n");
# endif
accumulator -= 2048L;
UP_DEST(dest_pointer);
UP_CHANGED(changed_pointer, changed_bit);
}
}
break;
}
Check_Fpu();
}
//===================================================================
// DrawFilledRectangle
//===================================================================
void
Video16BitBuffered::DrawFilledRectangle(
int color,
int bitmask,
Enumeration operation,
int x1, int y1,
int x2, int y2
)
{
# if defined(DEBUG)
Tell("Video16BitBuffered::DrawFilledRectangle(" <<
color << ", " <<
hex << bitmask << ", " << dec <<
operation << ", " <<
x1 << ", " <<
y1 << ", " <<
x2 << ", " <<
y2 << ", " <<
")\n");
# endif
Check(this);
Verify(x1 >= bounds.bottomLeft.x);
Verify(x1 <= bounds.topRight.x);
Verify(y1 >= bounds.bottomLeft.y);
Verify(y1 <= bounds.topRight.y);
Verify(x2 >= bounds.bottomLeft.x);
Verify(x2 <= bounds.topRight.x);
Verify(y2 >= bounds.bottomLeft.y);
Verify(y2 <= bounds.topRight.y);
Word
*dest_pointer;
LWord
*init_changed_pointer,
*changed_pointer;
LWord
init_changed_bit,
changed_bit;
int
x,
dest_fixup,
rect_width,
rect_height;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y1 = maximumY - y1;
y2 = maximumY - y2;
//---------------------------------------------------------
// Ensure that rectangle is properly specified
//---------------------------------------------------------
if (x2 < x1)
{
int temp;
temp = x1;
x1 = x2;
x2 = temp;
}
if (y2 < y1)
{
int temp;
temp = y1;
y1 = y2;
y2 = temp;
}
//---------------------------------------------------------
// Verify that values are legitimate
//---------------------------------------------------------
Verify(pixelBuffer.Data.MapPointer != NULL);
Verify(x1 >= 0);
Verify(x1 <= x2);
Verify(x2 < width);
Verify(y1 >= 0);
Verify(y1 <= y2);
Verify(y2 < height);
//---------------------------------------------------------
// Update changedLine array
//---------------------------------------------------------
MarkChangedLines(y1, y2);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Prepare to fill
//---------------------------------------------------------
# if defined(DEBUG)
Tell(
"x1=" << x1 << ", " << "y1=" << y1 << "\n" <<
"x2=" << x2 << ", " << "y2=" << y2 << "\n" <<
flush
);
# endif
buildDestPointer(
x1, y1,
&dest_pointer,
&init_changed_pointer,
&init_changed_bit
);
rect_height = y2 - y1 + 1;
rect_width = x2 - x1 + 1;
dest_fixup = width - rect_width;
# if defined(DEBUG)
Tell(
"rect_height=" << rect_height << "\n" <<
"rect_width=" << rect_width << "\n" <<
"dest_fixup=" << dest_fixup << "\n" <<
flush
);
# endif
//---------------------------------------------------------
// Fill the rectangle
//---------------------------------------------------------
switch(operation)
{
case GraphicsDisplay::Replace:
for( ; rect_height>0; --rect_height)
{
changed_bit = init_changed_bit;
changed_pointer = init_changed_pointer;
DOWN_CHANGED(init_changed_pointer, init_changed_bit);
for(x=rect_width; x>0; --x)
{
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
dest_pointer++;
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
dest_pointer += dest_fixup;
}
break;
case GraphicsDisplay::And:
for( ; rect_height>0; --rect_height)
{
changed_bit = init_changed_bit;
changed_pointer = init_changed_pointer;
DOWN_CHANGED(init_changed_pointer, init_changed_bit);
for(x=rect_width; x>0; --x)
{
*dest_pointer++ &= (Word) color;
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
dest_pointer += dest_fixup;
}
break;
case GraphicsDisplay::Or:
for( ; rect_height>0; --rect_height)
{
changed_bit = init_changed_bit;
changed_pointer = init_changed_pointer;
DOWN_CHANGED(init_changed_pointer, init_changed_bit);
for(x=rect_width; x>0; --x)
{
*dest_pointer++ |= (Word) color;
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
dest_pointer += dest_fixup;
}
break;
case GraphicsDisplay::Xor:
for( ; rect_height>0; --rect_height)
{
changed_bit = init_changed_bit;
changed_pointer = init_changed_pointer;
DOWN_CHANGED(init_changed_pointer, init_changed_bit);
for(x=rect_width; x>0; --x)
{
*dest_pointer++ ^= (Word) color;
SET_CHANGED(changed_pointer, changed_bit);
RIGHT_CHANGED(changed_pointer, changed_bit);
}
dest_pointer += dest_fixup;
}
break;
}
Check_Fpu();
}
void
Video16BitBuffered::DrawText(
int /*color*/,
int /*bitmask*/,
Enumeration /*operation*/,
Logical /*opaque*/,
int /*rotation*/,
Enumeration /*fontNumber*/,
Logical /*vertical*/,
GraphicsDisplay::Justification /*justification*/,
Rectangle2D */*clippingRectanglepointer*/,
char */*stringPointer*/
)
{
# if defined(DEBUG)
Tell("Video16BitBuffered::DrawText()\n");
# endif
Check(this);
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
Check_Fpu();
if (!valid)
{
return;
}
}
//===================================================================
// DrawBitMap
//===================================================================
void
Video16BitBuffered::DrawBitMap(
int color,
int bitmask,
Enumeration operation,
int rotation,
int x, int y,
BitMap *bitmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
# if defined(DEBUG)
Tell(
"Video16BitBuffered::DrawBitMap(<" <<
x << ", " <<
y << ">,<" <<
sLeft << ", " <<
sBottom << ", " <<
sRight << ", " <<
sTop << ">" <<
")\n"
);
# endif
Check(this);
Verify(x >= bounds.bottomLeft.x);
Verify(x <= bounds.topRight.x);
Verify(y >= bounds.bottomLeft.y);
Verify(y <= bounds.topRight.y);
int
map_width,
map_height,
map_max_y,
bits,
bit_test,
first_bit_test;
Word
*source_pointer_begin,
*source_pointer,
*dest_pointer_begin,
*dest_pointer;
LWord
changed_bit_begin,
changed_bit,
*changed_pointer_begin,
*changed_pointer;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Ensure that source rectangle is properly specified
//---------------------------------------------------------
Verify(bitmap != NULL);
Verify(sLeft >= 0);
Verify(sLeft <= sRight);
Verify(sRight < bitmap->Data.Size.x);
Verify(sBottom >= 0);
Verify(sBottom <= sTop);
Verify(sTop < bitmap->Data.Size.y);
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y = maximumY - y;
map_max_y = bitmap->Data.Size.y-1;
sTop = map_max_y - sTop;
sBottom = map_max_y - sBottom;
map_width = sRight - sLeft + 1;
map_height = sBottom - sTop + 1;
# if defined(DEBUG)
Tell("x=" << x << ", y=" << y << "\n");
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
# endif
Verify(map_width > 0);
Verify(map_width <= bitmap->Data.Size.x);
Verify(map_height > 0);
Verify(map_height <= bitmap->Data.Size.y);
Verify(x >= 0);
Verify(x < width);
Verify(y >= 0);
Verify(y < height);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Prepare to draw bitmap
//---------------------------------------------------------
Verify(pixelBuffer.Data.MapPointer != NULL);
source_pointer_begin =
bitmap->Data.MapPointer +
(sLeft >> 4) +
(sBottom * bitmap->Data.WidthInWords);
first_bit_test = 1 << (15-(sLeft & 15));
buildDestPointer(
x, y,
&dest_pointer_begin,
&changed_pointer_begin,
&changed_bit_begin
);
switch (rotation)
{
default:
//--------------------------------------------
// transparent bitmap, zero degrees
// .-----.
// | |
// | |
// Y |
// #X----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"zero: xp=" << (x+map_width-1) <<
", yp=" << (y-map_height+1) <<
"\n"
);
# endif
Verify(x+map_width-1 >= 0);
Verify(x+map_width-1 < width);
Verify(y-map_height+1 >= 0);
Verify(y-map_height+1 < height);
MarkChangedLines(y-map_height+1, y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
UP_CHANGED(changed_pointer_begin, changed_bit_begin);
UP_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
RIGHT_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
}
}
break;
case 90:
//--------------------------------------------
// Transparent bitmap, 90 degrees
// #Y----.
// X |
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n");
# endif
Verify(x+map_height >= 0);
Verify(x+map_height < width);
Verify(y+map_width >= 0);
Verify(y+map_width < height);
MarkChangedLines(y, y+map_width);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin);
RIGHT_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
DOWN_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
}
}
break;
case 180:
//--------------------------------------------
// Transparent bitmap, 180 degrees
// .----X#
// | Y
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n");
# endif
Verify(x-map_width+1 >= 0);
Verify(x-map_width+1 < width);
Verify(y+map_height >= 0);
Verify(y+map_height < height);
MarkChangedLines(y, y+map_height);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
DOWN_CHANGED(changed_pointer_begin, changed_bit_begin);
DOWN_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
LEFT_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
}
}
break;
case 270:
//--------------------------------------------
// Transparent bitmap, 270 degrees
// .-----.
// | |
// | X
// | |
// .--Y--#
//--------------------------------------------
# if defined(DEBUG)
Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n");
# endif
if (x-map_height < 0)
{
Tell("x-map_height = " << (x - map_height) << "\n");
return;
}
Verify(x-map_height >= 0);
Verify(x-map_height < width);
Verify(y-(map_width-1) >= 0);
Verify(y-(map_width-1) < height);
MarkChangedLines(y-(map_width-1), y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
LEFT_CHANGED(changed_pointer_begin, changed_bit_begin);
LEFT_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
Verify(dest_pointer >= pixelBuffer.Data.MapPointer);
Verify(dest_pointer < pixelBuffer.Data.MapPointer+
(width*height));
Verify(changed_pointer >= changedBit);
Verify(changed_pointer < changedBit+(changedBitWidth*height));
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
UP_CHANGED(changed_pointer, changed_bit_begin);
UP_DEST(dest_pointer);
}
}
break;
}
Check_Fpu();
}
//===================================================================
// DrawBitMapOpaque
//===================================================================
void
Video16BitBuffered::DrawBitMapOpaque(
int foreground,
int background,
int bitmask,
Enumeration operation,
int rotation,
int x, int y,
BitMap *bitmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
Check(this);
Diag_on;
Diag_Tell(
"Video16BitBuffered::DrawBitMapOpaque(<" << x <<
", " << y <<
">,<" << sLeft <<
", " << sBottom <<
", " << sRight <<
", " << sTop <<
">)\n"
);
Verify(x >= bounds.bottomLeft.x);
Verify(x <= bounds.topRight.x);
Verify(y >= bounds.bottomLeft.y);
Verify(y <= bounds.topRight.y);
int
map_width,
map_height,
map_max_y,
bits,
bit_test,
first_bit_test;
Word
*source_pointer_begin,
*source_pointer,
*dest_pointer_begin,
*dest_pointer;
LWord
changed_bit_begin,
changed_bit,
*changed_pointer_begin,
*changed_pointer;
Word
color;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Ensure that source rectangle is properly specified
//---------------------------------------------------------
Verify(bitmap != NULL);
Verify(sLeft >= 0);
Verify(sLeft <= sRight);
Verify(sRight < bitmap->Data.Size.x);
Verify(sBottom >= 0);
Verify(sBottom <= sTop);
Verify(sTop < bitmap->Data.Size.y);
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y = maximumY - y;
map_max_y = bitmap->Data.Size.y-1;
sTop = map_max_y - sTop;
sBottom = map_max_y - sBottom;
map_width = sRight - sLeft + 1;
map_height = sBottom - sTop + 1;
Diag_off;
Diag_Tell("x=" << x << ", y=" << y << "\n");
Diag_Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
Diag_Tell(
"map_width=" << map_width <<
", map_height=" << map_height <<
"\n"
);
Diag_on;
Verify(map_width > 0);
Verify(map_width <= bitmap->Data.Size.x);
Verify(map_height > 0);
Verify(map_height <= bitmap->Data.Size.y);
Verify(x >= 0);
Verify(x < width);
Verify(y >= 0);
Verify(y < height);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Prepare to draw bitmap
//---------------------------------------------------------
Verify(pixelBuffer.Data.MapPointer != NULL);
source_pointer_begin =
bitmap->Data.MapPointer +
(sLeft >> 4) +
(sBottom * bitmap->Data.WidthInWords);
first_bit_test = 1 << (15-(sLeft & 15));
buildDestPointer(
x, y,
&dest_pointer_begin,
&changed_pointer_begin,
&changed_bit_begin
);
//---------------------------------------------------------
// The bitmap is always read left-to-right, bottom-to-top.
// We write it to the screen in different directions
// based on the rotation.
//---------------------------------------------------------
switch (rotation)
{
default:
//--------------------------------------------
// opaque bitmap, zero degrees
// .-----.
// | |
// | |
// Y |
// #X----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"zero: xp=" << (x+map_width) <<
", yp=" << (y-map_height+1) <<
"\n"
);
# endif
Verify(x+map_width >= 0);
Verify(x+map_width <= width); // HACK? <, or <=?
Verify(y-map_height+1 >= 0);
Verify(y-map_height+1 < height);
MarkChangedLines(y-map_height+1, y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
UP_CHANGED(changed_pointer_begin, changed_bit_begin);
UP_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
color = (Word) foreground;
}
else
{
color = (Word) background;
}
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
RIGHT_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
}
}
break;
case 90:
//--------------------------------------------
// opaque bitmap, 90 degrees
// #--Y--.
// | |
// X |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n");
# endif
Verify(x+map_height >= 0);
Verify(x+map_height < width);
Verify(y+map_width >= 0);
Verify(y+map_width < height);
MarkChangedLines(y, y+map_width);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin);
RIGHT_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
color = (Word) foreground;
}
else
{
color = (Word) background;
}
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
DOWN_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
}
}
break;
case 180:
//--------------------------------------------
// opaque bitmap, 180 degrees
// .----X#
// | Y
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n");
# endif
Verify(x-map_width+1 >= 0);
Verify(x-map_width+1 < width);
Verify(y+map_height >= 0);
Verify(y+map_height < height);
MarkChangedLines(y, y+map_height);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
DOWN_CHANGED(changed_pointer_begin, changed_bit_begin);
DOWN_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
color = (Word) foreground;
}
else
{
color = (Word) background;
}
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
LEFT_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
}
}
break;
case 270:
//--------------------------------------------
// opaque bitmap, 270 degrees
// .-----.
// | |
// | X
// | |
// .--Y--#
//--------------------------------------------
# if defined(DEBUG)
Tell(
"xp=" << (x-map_height+1) <<
", yp=" << (y-(map_width-1)) <<
"\n"
);
# endif
Verify(x-map_height >= 0);
Verify(x-map_height < width);
Verify(y-(map_width-1) >= 0);
Verify(y-(map_width-1) < height);
Diag_Tell(
"(y-(map_width-1))=" << (y-(map_width-1)) <<
", y=" << y <<
","
);
MarkChangedLines(y-(map_width-1), y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_BITMAP(source_pointer_begin, bitmap);
LEFT_CHANGED(changed_pointer_begin, changed_bit_begin);
LEFT_DEST(dest_pointer_begin);
bit_test = first_bit_test;
bits = *source_pointer++;
for(x=map_width; x>0; --x,bit_test>>=1)
{
Verify(dest_pointer >= pixelBuffer.Data.MapPointer);
Verify(dest_pointer < pixelBuffer.Data.MapPointer+
(width*height));
Verify(changed_pointer >= changedBit);
Verify(changed_pointer < changedBit+(changedBitWidth*height));
if (bit_test == 0)
{
bit_test = 0x8000;
bits = *source_pointer++;
}
if (bits & bit_test)
{
color = (Word) foreground;
}
else
{
color = (Word) background;
}
{
switch (operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
UP_CHANGED(changed_pointer, changed_bit_begin);
UP_DEST(dest_pointer);
}
}
Diag_Tell(
"changed_pointer=" << changed_pointer << dec <<
"\n"
);
break;
}
Check_Fpu();
Diag_off;
}
//===================================================================
// DrawPixelMap8
//===================================================================
void
Video16BitBuffered::DrawPixelMap8(
int *translation_table,
int bitmask,
Enumeration operation,
Logical opaque,
int rotation,
int x, int y,
PixelMap8 *pixelmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
# if defined(DEBUG)
Tell(
"Video16BitBuffered::DrawPixelMap8(<" <<
x << ", " <<
y << ">,<" <<
sLeft << ", " <<
sBottom << ", " <<
sRight << ", " <<
sTop << ">" <<
")\n"
);
# endif
Check(this);
Verify(x >= bounds.bottomLeft.x);
Verify(x <= bounds.topRight.x);
Verify(y >= bounds.bottomLeft.y);
Verify(y <= bounds.topRight.y);
int
map_width,
map_height,
map_max_y;
Byte
source_data,
*source_pointer_begin,
*source_pointer;
Word
*dest_pointer_begin,
*dest_pointer;
LWord
changed_bit_begin,
changed_bit,
*changed_pointer_begin,
*changed_pointer;
Word
color;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Ensure that source rectangle is properly specified
//---------------------------------------------------------
Verify(pixelmap != NULL);
Verify(sLeft >= 0);
Verify(sLeft <= sRight);
Verify(sRight < pixelmap->Data.Size.x);
Verify(sBottom >= 0);
Verify(sBottom <= sTop);
Verify(sTop < pixelmap->Data.Size.y);
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y = maximumY - y;
map_max_y = pixelmap->Data.Size.y-1;
sTop = map_max_y - sTop;
sBottom = map_max_y - sBottom;
map_width = sRight - sLeft + 1;
map_height = sBottom - sTop + 1;
# if defined(DEBUG)
Tell("x=" << x << ", y=" << y << "\n");
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
# endif
Verify(map_width > 0);
Verify(map_width <= pixelmap->Data.Size.x);
Verify(map_height > 0);
Verify(map_height <= pixelmap->Data.Size.y);
Verify(x >= 0);
Verify(x < width);
Verify(y >= 0);
Verify(y < height);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Prepare to draw bitmap
//---------------------------------------------------------
Verify(pixelBuffer.Data.MapPointer != NULL);
source_pointer_begin =
pixelmap->Data.MapPointer +
sLeft +
(sBottom * pixelmap->Data.Size.x);
buildDestPointer(
x, y,
&dest_pointer_begin,
&changed_pointer_begin,
&changed_bit_begin
);
if (opaque)
{
switch (rotation)
{
default:
//--------------------------------------------
// Opaque pixelmap, zero degrees
// .-----.
// | |
// | |
// Y |
// #X----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Opaque zero: xp=" << (x+map_width) <<
", yp=" << (y-map_height+1) <<
"\n"
);
# endif
Verify(x+map_width >= 0);
Verify(x+map_width < width);
Verify(y-map_height+1 >= 0);
Verify(y-map_height+1 < height);
MarkChangedLines(y-map_height+1, y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
UP_CHANGED(changed_pointer_begin, changed_bit_begin);
UP_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
RIGHT_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
}
}
break;
case 90:
//--------------------------------------------
// Opaque pixelmap, 90 degrees
// #Y----.
// X |
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Opaque 90: xp=" << (x+map_height) <<
", yp=" << (y+map_width) <<
"\n"
);
# endif
Verify(x+map_height >= 0);
Verify(x+map_height < width);
Verify(y+map_width >= 0);
Verify(y+map_width < height);
MarkChangedLines(y, y+map_width);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin);
RIGHT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
DOWN_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
}
}
break;
case 180:
//--------------------------------------------
// Opaque pixelmap, 180 degrees
// .----X#
// | Y
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Opaque 180: xp=" << (x-map_width+1) <<
", yp=" << (y+map_height) <<
"\n"
);
# endif
Verify(x-map_width+1 >= 0);
Verify(x-map_width+1 < width);
Verify(y+map_height >= 0);
Verify(y+map_height < height);
MarkChangedLines(y, y+map_height);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
DOWN_CHANGED(changed_pointer_begin, changed_bit_begin);
DOWN_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
LEFT_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
}
}
break;
case 270:
//--------------------------------------------
// Opaque pixelmap, 270 degrees
// .-----.
// | |
// | X
// | |
// .--Y--#
//--------------------------------------------
# if defined(DEBUG)
Tell("Opaque 270: x=" << x << ", y=" << y << "\n");
Tell(
"xp=" << (x-map_height) <<
", yp=" << (y-(map_width-1)) <<
"\n"
);
# endif
Verify(x-map_height-1 >= 0);
Verify(x-map_height-1 < width);
Verify(y-(map_width-1) >= 0);
Verify(y-(map_width-1) < height);
MarkChangedLines(y-(map_width-1), y);
for(y=map_height ; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
LEFT_CHANGED(changed_pointer_begin, changed_bit_begin);
LEFT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
Verify(dest_pointer >= pixelBuffer.Data.MapPointer);
Verify(dest_pointer < pixelBuffer.Data.MapPointer+
(width*height));
Verify(changed_pointer >= changedBit);
Verify(changed_pointer < changedBit+(changedBitWidth*height));
source_data = *source_pointer++; //SOURCE_RIGHT
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
UP_CHANGED(changed_pointer, changed_bit_begin);
UP_DEST(dest_pointer);
}
}
break;
}
}
else
{
switch (rotation)
{
default:
//--------------------------------------------
// Transparent pixelmap, zero degrees
// .-----.
// | |
// | |
// Y |
// #X----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"transparent zero: xp=" << (x+map_width) <<
", yp=" << (y-map_height+1) <<
"\n"
);
# endif
Verify(x+map_width >= 0);
Verify(x+map_width < width);
Verify(y-map_height+1 >= 0);
Verify(y-map_height+1 < height);
MarkChangedLines(y-map_height+1, y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
UP_CHANGED(changed_pointer_begin, changed_bit_begin);
UP_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
RIGHT_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
}
}
break;
case 90:
//--------------------------------------------
// Transparent pixelmap, 90 degrees
// #Y----.
// X |
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"transparent 90: xp=" << (x+map_height) <<
", yp=" << (y+map_width) <<
"\n"
);
# endif
Verify(x+map_height >= 0);
Verify(x+map_height < width);
Verify(y+map_width >= 0);
Verify(y+map_width < height);
MarkChangedLines(y, y+map_width);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin);
RIGHT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
DOWN_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
}
}
break;
case 180:
//--------------------------------------------
// Transparent pixelmap, 180 degrees
// .----X#
// | Y
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"transparent 180: xp=" << (x-map_width+1) <<
", yp=" << (y+map_height) <<
"\n"
);
# endif
Verify(x-map_width+1 >= 0);
Verify(x-map_width+1 < width);
Verify(y+map_height >= 0);
Verify(y+map_height < height);
MarkChangedLines(y, y+map_height);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
DOWN_CHANGED(changed_pointer_begin, changed_bit_begin);
DOWN_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
LEFT_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
}
}
break;
case 270:
//--------------------------------------------
// Transparent pixelmap, 270 degrees
// .-----.
// | |
// | X
// | |
// .--Y--#
//--------------------------------------------
# if defined(DEBUG)
Tell("transparent 270: x=" << x << ", y=" << y << "\n");
Tell(
"xp=" << (x-map_height) <<
", yp=" << (y-(map_width-1)) <<
"\n"
);
# endif
Verify(x-(map_height-1) >= 0);
Verify(x-(map_height-1) < width);
Verify(y-(map_width-1) >= 0);
Verify(y-(map_width-1) < height);
MarkChangedLines(y-(map_width-1), y);
for(y=map_height ; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
LEFT_CHANGED(changed_pointer_begin, changed_bit_begin);
LEFT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
Verify(dest_pointer >= pixelBuffer.Data.MapPointer);
Verify(dest_pointer < pixelBuffer.Data.MapPointer+
(width*height));
Verify(changed_pointer >= changedBit);
Verify(changed_pointer < changedBit+(changedBitWidth*height));
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
color = (Word) translation_table[source_data];
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
UP_CHANGED(changed_pointer, changed_bit_begin);
UP_DEST(dest_pointer);
}
}
break;
}
}
Check_Fpu();
}
//===================================================================
// DrawPixelMap8SingleColor
//===================================================================
void
Video16BitBuffered::DrawPixelMap8SingleColor(
int color,
int bitmask,
Enumeration operation,
int rotation,
int x, int y,
PixelMap8 *pixelmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
# if defined(DEBUG)
Tell(
"Video16BitBuffered::DrawPixelMap8SingleColor(<" <<
x << ", " <<
y << ">,<" <<
sLeft << ", " <<
sBottom << ", " <<
sRight << ", " <<
sTop << ">" <<
")\n"
);
# endif
Check(this);
Verify(x >= bounds.bottomLeft.x);
Verify(x <= bounds.topRight.x);
Verify(y >= bounds.bottomLeft.y);
Verify(y <= bounds.topRight.y);
int
map_width,
map_height,
map_max_y;
Byte
source_data,
*source_pointer_begin,
*source_pointer;
Word
*dest_pointer_begin,
*dest_pointer;
LWord
changed_bit_begin,
changed_bit,
*changed_pointer_begin,
*changed_pointer;
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
Check_Fpu();
return;
}
//---------------------------------------------------------
// Ensure that source rectangle is properly specified
//---------------------------------------------------------
Verify(pixelmap != NULL);
Verify(sLeft >= 0);
Verify(sLeft <= sRight);
Verify(sRight < pixelmap->Data.Size.x);
Verify(sBottom >= 0);
Verify(sBottom <= sTop);
Verify(sTop < pixelmap->Data.Size.y);
//---------------------------------------------------------
// Convert to screen co-ordinates
//---------------------------------------------------------
y = maximumY - y;
map_max_y = pixelmap->Data.Size.y-1;
sTop = map_max_y - sTop;
sBottom = map_max_y - sBottom;
map_width = sRight - sLeft + 1;
map_height = sBottom - sTop + 1;
# if defined(DEBUG)
Tell("x=" << x << ", y=" << y << "\n");
Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n");
Tell("map_width=" << map_width << ", map_height=" << map_height << "\n");
# endif
Verify(map_width > 0);
Verify(map_width <= pixelmap->Data.Size.x);
Verify(map_height > 0);
Verify(map_height <= pixelmap->Data.Size.y);
Verify(x >= 0);
Verify(x < width);
Verify(y >= 0);
Verify(y < height);
//---------------------------------------------------------
// We really need inverse bitmap here
//---------------------------------------------------------
bitmask = ~bitmask;
//---------------------------------------------------------
// Prepare to draw bitmap
//---------------------------------------------------------
Verify(pixelBuffer.Data.MapPointer != NULL);
source_pointer_begin =
pixelmap->Data.MapPointer +
sLeft +
(sBottom * pixelmap->Data.Size.x);
buildDestPointer(
x, y,
&dest_pointer_begin,
&changed_pointer_begin,
&changed_bit_begin
);
{
switch (rotation)
{
default:
//--------------------------------------------
// Single-color pixelmap, zero degrees
// .-----.
// | |
// | |
// Y |
// #X----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Single-color zero: xp=" << (x+map_width) <<
", yp=" << (y-map_height+1) <<
"\n"
);
# endif
Verify(x+map_width >= 0);
Verify(x+map_width < width);
Verify(y-map_height+1 >= 0);
Verify(y-map_height+1 < height);
MarkChangedLines(y-map_height+1, y);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
UP_CHANGED(changed_pointer_begin, changed_bit_begin);
UP_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
RIGHT_CHANGED(changed_pointer, changed_bit);
RIGHT_DEST(dest_pointer);
}
}
break;
case 90:
//--------------------------------------------
// Single-color pixelmap, 90 degrees
// #Y----.
// X |
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Single-color 90: xp=" << (x+map_height) <<
", yp=" << (y+map_width) <<
"\n"
);
# endif
Verify(x+map_height >= 0);
Verify(x+map_height < width);
Verify(y+map_width >= 0);
Verify(y+map_width < height);
MarkChangedLines(y, y+map_width);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin);
RIGHT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word) ((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
DOWN_CHANGED(changed_pointer, changed_bit);
DOWN_DEST(dest_pointer);
}
}
break;
case 180:
//--------------------------------------------
// Single-color pixelmap, 180 degrees
// .----X#
// | Y
// | |
// | |
// .-----.
//--------------------------------------------
# if defined(DEBUG)
Tell(
"Single-color 180: xp=" << (x-map_width+1) <<
", yp=" << (y+map_height) <<
"\n"
);
# endif
Verify(x-map_width+1 >= 0);
Verify(x-map_width+1 < width);
Verify(y+map_height >= 0);
Verify(y+map_height < height);
MarkChangedLines(y, y+map_height);
for(y=map_height; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
DOWN_CHANGED(changed_pointer_begin, changed_bit_begin);
DOWN_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
LEFT_CHANGED(changed_pointer, changed_bit);
LEFT_DEST(dest_pointer);
}
}
break;
case 270:
//--------------------------------------------
// Single-color pixelmap, 270 degrees
// .-----.
// | |
// | X
// | |
// .--Y--#
//--------------------------------------------
# if defined(DEBUG)
Tell("Single-color 270: x=" << x << ", y=" << y << "\n");
Tell(
"xp=" << (x-map_height) <<
", yp=" << (y-map_width) <<
"\n"
);
# endif
Verify(x-map_height >= 0);
Verify(x-map_height < width);
Verify(y-map_width >= 0);
Verify(y-map_width < height);
MarkChangedLines(y-map_width, y);
for(y=map_height ; y>0; --y)
{
source_pointer = source_pointer_begin;
changed_pointer = changed_pointer_begin;
changed_bit = changed_bit_begin;
dest_pointer = dest_pointer_begin;
UP_SOURCE(source_pointer_begin, pixelmap);
LEFT_CHANGED(changed_pointer_begin, changed_bit_begin);
LEFT_DEST(dest_pointer_begin);
for(x=map_width; x>0; --x)
{
Verify(dest_pointer >= pixelBuffer.Data.MapPointer);
Verify(dest_pointer < pixelBuffer.Data.MapPointer+
(width*height));
Verify(changed_pointer >= changedBit);
Verify(changed_pointer < changedBit+(changedBitWidth*height));
source_data = *source_pointer++; //SOURCE_RIGHT
if (source_data)
{
switch(operation)
{
case GraphicsDisplay::Replace:
*dest_pointer = (Word)((*dest_pointer & bitmask) | color);
break;
case GraphicsDisplay::And:
*dest_pointer &= (Word) color;
break;
case GraphicsDisplay::Or:
*dest_pointer |= (Word) color;
break;
case GraphicsDisplay::Xor:
*dest_pointer ^= (Word) color;
break;
}
SET_CHANGED(changed_pointer, changed_bit);
}
UP_CHANGED(changed_pointer, changed_bit_begin);
UP_DEST(dest_pointer);
}
}
break;
}
}
Check_Fpu();
}
//########################################################################
//############################ SVGA640x480x16 ############################
//########################################################################
SVGA16::SVGA16(
int mode,
int init_width,
int init_height,
int mem_page_size,
int mem_granularity,
int bytes_per_line,
int page_function_pointer,
int special_interface
):Video16BitBuffered(init_width, init_height)
{
# if defined(DEBUG)
Tell("SVGA16::SVGA16()\n");
# endif
pageSize = mem_page_size * 1024;
Verify(mem_granularity > 0);
pageDelta = mem_page_size/mem_granularity;
widthInBytes = bytes_per_line;
pageFcnPtr = page_function_pointer;
specialInterface = special_interface; // currently unused
currentPageNumber = -1;
//
// Set video mode
//
SVGASetMode(mode, pageFcnPtr);
//
// Set VWE video splitter clock divider
//
SVGASetSplitterClock(True);
//------------------------------------------------------------------------
// Initialize palettes
//------------------------------------------------------------------------
FadeToWhite(0.0);
//------------------------------------------------------------------------
// Initialize palette data
//------------------------------------------------------------------------
// The +2 causes Adam's decoded Palette addresses to "match up"
// with the address definitions used by the standard VGA palette port.
// Adam's port decoder design uses:
// xx00 = write address port
// xx01 = data port
// xx10 = pixel mask port
// xx11 = read address port
// The standard VGA/SVGA ports are:
// 03C6 = ......0110 = xx10 = pixel mask port
// 03C7 = ......0111 = xx11 = read address port
// 03C8 = ......1000 = xx00 = write address port
// 03C9 = ......1001 = xx01 = data port
// Adam's ports are:
// 0300 = secondary palette
// 0308 = auxiliary palette 1
// 0310 = auxiliary palette 2
// By adding 2 to "Adam's" port assignments, they match with a VGA:
// 0302/030A/0312 = xx10 = pixel mask port
// 0303/030B/0313 = xx11 = read address port
// 0304/030C/0314 = xx00 = write address port
// 0305/030D/0315 = xx01 = data port
// See L4VB16.hpp, class SVGA16 for an enumeration of palettes
// matching this table.
static Word port_addr[PaletteCount] = {
0x3C6, // NativePalette
0x300+2, // SecondaryPalette
0x308+2, // AuxiliaryPalette1
0x310+2 // AuxiliaryPalette2
};
SVGA16Palette
*palette_pointer = &palette[0];
for(int i=0; i<PaletteCount; ++i,++palette_pointer)
{
int j;
palette_pointer->hardwarePort = port_addr[i];
palette_pointer->modified = False;
palette_pointer->flashAccumulator = 0.0;
palette_pointer->flashRate = 0.0;
palette_pointer->previousMaskState = -1;
for(j=0; j<SVGA16Palette::maskStates; ++j)
{
palette_pointer->mask[j] = 0xFF;
}
if (port_addr[i] != 0x3C6)
{
SVGAZeroPalette(port_addr[i]);
}
}
//---------------------------------------------------------
// Prepare update values
//---------------------------------------------------------
currentPageNumber = -1;
ResetUpdatePosition();
# if defined(BLIT_STATISTICS)
dirtyPixelCount = 0;
transferPixelCount = 0;
overflowPixelCount = 0;
# endif
//---------------------------------------------------------
// Clear the display
//---------------------------------------------------------
# if defined(DEBUG)
Tell("Valid, drawing rectangle-\n" << flush);
# endif
DrawFilledRectangle(
0,
0xFFFF,
GraphicsDisplay::Replace,
0, 0,
maximumX, maximumY
);
# if defined(DEBUG)
Tell("About to update-\n" << flush);
# endif
Update(False);
Check_Fpu();
}
SVGA16::~SVGA16()
{
# if defined(DEBUG)
Tell("SVGA16::~SVGA16()\n");
# endif
Check(this);
//---------------------------------------------------------
// Eventually wait for fade (if any) to complete??
//---------------------------------------------------------
//---------------------------------------------------------
// Set video mode
//---------------------------------------------------------
SVGASetMode(3, 0);
# if defined(BLIT_STATISTICS)
double
ratio;
if (transferPixelCount == 0)
{
ratio = (double) 0;
}
else
{
ratio = ((double) dirtyPixelCount) / transferPixelCount;
}
//------------------------------------------------------
// Print statistics
//------------------------------------------------------
DEBUG_STREAM <<
"SVGA16::~SVGA16: pixel management statistics ------------" <<
"\nNumber of dirty pixels =" << dirtyPixelCount <<
"\nNumber of transferred pixels=" << transferPixelCount <<
"\nTimes overflowed =" << overflowPixelCount <<
"\nRatio =" << ratio <<
"\n-------------------------------------------------------\n";
# endif
//---------------------------------------------------------
// Set VWE video splitter clock divider
//---------------------------------------------------------
SVGASetSplitterClock(False);
Check_Fpu();
}
Logical
SVGA16::TestInstance() const
{
return Video16BitBuffered::TestInstance();
}
void
SVGA16::ShowInstance(char *indent)
{
cout << indent << "SVGA16:\n";
char
temp[80];
Str_Copy(temp,indent, 80);
Str_Cat(temp,"...", 80);
cout << temp << "SVGA16:\n";
Video16BitBuffered::ShowInstance(temp);
Check_Fpu();
}
Logical
SVGA16::Update(Logical forceAll)
{
SET_SCREEN_COPY();
Diag_Tell("SVGA16::Update(" << forceAll << ")\n");
Check(this);
//---------------------------------------------------------
// If pixelbuffer is invalid, do nothing
//---------------------------------------------------------
if (!valid)
{
CLEAR_SCREEN_COPY();
return False; // Do no more!
}
//---------------------------------------------------------
// Mark all lines as changed if commanded
//---------------------------------------------------------
if (forceAll)
{
memset(changedLine, 1, height);
}
int
previous_line_number = lineNumber;
long
dest_size,
dest_line_size;
//---------------------------------------------------------
// Calculate sizes based on specialInterface
//---------------------------------------------------------
if (specialInterface)
{
dest_size = 32L; // BYTE offset!
dest_line_size = width;
}
else
{
dest_size = 32L << 1; // WORD offset!
dest_line_size = width << 1;
}
//---------------------------------------------------------
// Process lines for as long as we can
//---------------------------------------------------------
#if 0 // Let's process just a few lines for background loop processing...
while (Get_Frame_Percent_Used() < .65f)
#endif
{
//---------------------------------------------------------
// Do a couple of lines before checking time again
//---------------------------------------------------------
for(int line_limit=15; line_limit > 0; )
{
//---------------------------------------------------------
// Check for changed line, clear the flag
//---------------------------------------------------------
Verify(changedLinePointer < &changedLine[height]);
int
changed_line = *changedLinePointer;
*changedLinePointer++ = 0;
if (changed_line)
{
Diag_Tell(height << ":");
//---------------------------------------------------------
// Pixels on this line have been changed
//---------------------------------------------------------
--line_limit;
//---------------------------------------------------------
// Check 'dirty' LWords: if set, scan for changed pixels
//---------------------------------------------------------
for(int x=0; x<changedBitWidth; ++x)
{
//---------------------------------------------------------
// Check for changed pixels in LWord, clear flag
//---------------------------------------------------------
Verify(
changedBitPointer < &changedBit[height*changedBitWidth]
);
LWord
changed_bits = *changedBitPointer;
*changedBitPointer++ = 0L;
if (changed_bits)
{
Diag_Tell( (changed_bits & 0xFFFF0000L) ? "#" : "." );
Diag_Tell( (changed_bits & 0x0000FFFFL) ? "#" : "." );
//---------------------------------------------------------
// Changed pixels! Make sure display page is correct
//---------------------------------------------------------
if (currentPageNumber != nextPageNumber)
{
SVGASetPage(nextPageNumber);
currentPageNumber = nextPageNumber;
}
//---------------------------------------------------------
// Then transfer changed pixels
//---------------------------------------------------------
if (specialInterface)
{
# if defined(BLIT_STATISTICS)
transferPixelCount +=
# endif
SVGATransfer32x(destOffset, sourcePointer, changed_bits);
}
else
{
# if defined(BLIT_STATISTICS)
transferPixelCount +=
# endif
SVGATransfer32(destOffset, sourcePointer, changed_bits);
}
}
# if defined(DEBUG)
else
{
//---------------------------------------------------------
// No pixels in this LWord, move to next one
//---------------------------------------------------------
Tell("--");
}
# endif
//---------------------------------------------------------
// Update remaining pixel count
//---------------------------------------------------------
sourcePointer += 32;
destOffset += dest_size;
if (destOffset >= pageSize)
{
destOffset -= pageSize;
nextPageNumber += pageDelta;
}
}
Diag_Tell("\n");
}
else
{
//---------------------------------------------------------
// Line has not changed, skip over it
//---------------------------------------------------------
#if defined(CHECK_FOR_DIRT)
Logical
dirty_flag = False;
for(int x=0; x<changedBitWidth; ++x)
{
//---------------------------------------------------------
// Check for changed pixels in LWord
//---------------------------------------------------------
Verify(
changedBitPointer < &changedBit[height*changedBitWidth]
);
LWord
changed_bits = *changedBitPointer;
*changedBitPointer++ = 0L;
if (changed_bits)
{
dirty_flag = True;
}
//---------------------------------------------------------
// Update remaining pixel count
//---------------------------------------------------------
sourcePointer += 32;
destOffset += dest_size;
if (destOffset >= pageSize)
{
destOffset -= pageSize;
nextPageNumber += pageDelta;
}
}
if (dirty_flag)
{
Tell(
"SVGA16::Update: Unexpected dirty bits in line " <<
lineNumber <<
"\n!"
);
}
#else
changedBitPointer += changedBitWidth;
sourcePointer += width;
destOffset += dest_line_size;
if (destOffset >= pageSize)
{
destOffset -= pageSize;
nextPageNumber += pageDelta;
}
#endif
}
# if defined(BLIT_STATISTICS)
//---------------------------------
// Keep values within a sane range
//---------------------------------
if (
(transferPixelCount > 0x10000000)
||
(dirtyPixelCount > 0x10000000)
)
{
transferPixelCount >>= 1;
dirtyPixelCount >>= 1;
++overflowPixelCount;
}
# endif
//---------------------------------------------------------
// Check for wrap
//---------------------------------------------------------
if (++lineNumber >= height)
{
ResetUpdatePosition();
}
//---------------------------------------------------------
// If back to beginning, exit loop
//---------------------------------------------------------
if (lineNumber == previous_line_number)
{
Check_Fpu();
CLEAR_SCREEN_COPY();
return False; // All done
}
}
}
Check_Fpu();
CLEAR_SCREEN_COPY();
return True; // True == 'more to do'
}
void
SVGA16::ResetUpdatePosition()
{
lineNumber = 0;
sourcePointer = pixelBuffer.Data.MapPointer;
changedLinePointer = changedLine;
changedBitPointer = changedBit;
nextPageNumber = 0;
destOffset = 0L;
}
void
SVGA16::FadeToPalettes(Scalar fade_time)
{
Check(this);
previousFadeTime = Now();
paletteFadeState = fadeToColor;
if(Small_Enough(fade_time))
{
fadeUnitsPerSecond = 0.0;
fadeAlpha = 1.0;
}
else
{
fadeUnitsPerSecond = (1.0/fade_time);
}
Check_Fpu();
}
void
SVGA16::FadeToWhite(Scalar fade_time)
{
Check(this);
previousFadeTime = Now();
paletteFadeState = fadeToWhite;
if(Small_Enough(fade_time))
{
fadeUnitsPerSecond = 0.0;
fadeAlpha = 0.0;
}
else
{
fadeUnitsPerSecond = (1.0/fade_time);
}
Check_Fpu();
}
void
generateFade(
SVGA16Palette *source,
Scalar alpha
)
{
Check_Pointer(source);
if (alpha < 0.0)
{
alpha = 0.0;
}
else if (alpha > 1.0)
{
alpha = 1.0;
}
Palette8
temp;
// Scalar
// inverse_alpha = (1.0 - alpha) * 255.0;
int
i;
for(i=0; i<256; ++i)
{
temp.Color[i].Red = (Byte)
// (inverse_alpha + (source->paletteData.Color[i].Red * alpha));
((source->paletteData.Color[i].Red * alpha));
temp.Color[i].Green = (Byte)
// (inverse_alpha + (source->paletteData.Color[i].Green * alpha));
((source->paletteData.Color[i].Green * alpha));
temp.Color[i].Blue = (Byte)
// (inverse_alpha + (source->paletteData.Color[i].Blue * alpha));
((source->paletteData.Color[i].Blue * alpha));
}
SVGAWriteFullPalette( // in L4SVGA16.ASM
&temp.Color[0].Red,
source->hardwarePort
);
Check_Fpu();
}
void
SVGA16::FlashPalette(
int palette_number,
Scalar rate,
unsigned char *stateList
)
{
Check(this);
Verify(palette_number >= 0);
Verify(palette_number < PaletteCount);
SVGA16Palette
*palette_pointer = &palette[palette_number];
//-------------------------------------------------
// Adjust rate so value becomes "cycles per second"
//-------------------------------------------------
palette_pointer->flashRate = rate * (Scalar) SVGA16Palette::maskStates;
//-------------------------------------------------
// Copy the mask values
//-------------------------------------------------
for (int i=0; i<SVGA16Palette::maskStates; ++i)
{
palette_pointer->mask[i] = *stateList++;
}
Check_Fpu();
}
void
SVGA16::UnflashPalette(
int palette_number
)
{
Check(this);
Verify(palette_number >= 0);
Verify(palette_number < PaletteCount);
SVGA16Palette
*palette_pointer = &palette[palette_number];
palette_pointer->flashRate = 0.0;
palette_pointer->flashAccumulator = 0.0;
palette_pointer->previousMaskState = -1;
SVGAWritePaletteMask(palette_pointer->hardwarePort, 0xFF);
Check_Fpu();
}
void
SVGA16::UpdatePalette()
{
Check(this);
int
i,
mask_state;
SVGA16Palette
*palette_pointer;
//--------------------------------------------------------
// Update time values
//--------------------------------------------------------
Time
right_now = Now();
Scalar
delta_t = (Scalar) (right_now - previousFadeTime);
previousFadeTime = right_now;
if (delta_t <= 0.0)
{
return;
}
//--------------------------------------------------------
// Set palette masks
//--------------------------------------------------------
palette_pointer = &palette[0];
for(i=0; i<PaletteCount; ++i,++palette_pointer)
{
if (palette_pointer->flashRate != 0.0)
{
palette_pointer->flashAccumulator +=
palette_pointer->flashRate * delta_t;
while (palette_pointer->flashAccumulator >=
(Scalar) SVGA16Palette::maskStates)
{
palette_pointer->flashAccumulator -=
(Scalar) SVGA16Palette::maskStates;
}
mask_state = (int) palette_pointer->flashAccumulator;
if (mask_state != palette_pointer->previousMaskState)
{
palette_pointer->previousMaskState = mask_state;
SVGAWritePaletteMask(
palette_pointer->hardwarePort,
palette_pointer->mask[mask_state]
);
}
}
}
//--------------------------------------------------------
// Fade palettes
//--------------------------------------------------------
palette_pointer = &palette[0];
for(i=0; i<PaletteCount; ++i,++palette_pointer)
{
//--------------------------------------------------------
// Only the secondary palette (i==1) is allowed to fade!
// All other palettes are merely copied.
//--------------------------------------------------------
if ((i != 1) || (paletteFadeState == staticPalette))
{
if (palette_pointer->modified)
{
palette_pointer->modified = False;
SVGAWriteFullPalette(
&palette_pointer->paletteData.Color[0].Red,
palette_pointer->hardwarePort
);
}
}
else
{
//--------------------------------------------------------
// Discard 'modified' flag (we use the local values for
// fade in/out, and in the 'white' state we don't care,
// because we'll have to fade back in anyway)
//--------------------------------------------------------
palette_pointer->modified = False;
//--------------------------------------------------------
// Perform fade (or stay white)
//--------------------------------------------------------
switch(paletteFadeState)
{
case fadeToWhite:
fadeAlpha -= (delta_t * fadeUnitsPerSecond);
generateFade(palette_pointer, fadeAlpha);
if (fadeAlpha <= 0.0)
{
fadeAlpha = 0.0;
paletteFadeState = whitePalette;
}
break;
case whitePalette:
break;
case fadeToColor:
fadeAlpha += (delta_t * fadeUnitsPerSecond);
generateFade(palette_pointer, fadeAlpha);
if (fadeAlpha >= 1.0)
{
fadeAlpha = 1.0;
paletteFadeState = staticPalette;
}
break;
}
}
}
Check_Fpu();
}
void
SVGA16::FunkyVideo(Logical on_off)
{
Check(this);
SVGAFunkyVideo(on_off);
Check_Fpu();
}
//########################################################################
//########################### L4GraphicsPort #############################
//########################################################################
L4GraphicsPort::L4GraphicsPort(
Video16BitBuffered *graphics_display,
const char *name,
int rotation,
int bit_mask,
SVGA16::PaletteID palette_ID,
L4GraphicsPort::ChannelEnableID channel_enable
):GraphicsPort(graphics_display, name)
{
int
bit_test;
//
// Save the base rotation value
//
baseRotation = rotation;
//
// Save the paletteID and channel enable
//
paletteID = palette_ID;
channelEnable = channel_enable;
//
// Save the bitMask
//
bitMask = bit_mask;
Verify (bitMask != 0);
//
// Count the number of active bits in the bitMask
//
for(bit_test=0x8000,numberOfBits=0; bit_test!=0; bit_test>>=1)
{
if (bit_test & bitMask)
{
++numberOfBits;
}
}
//
// Initialize conversion constants
//
maximumX = bounds.topRight.x - bounds.bottomLeft.x;
maximumY = bounds.topRight.y - bounds.bottomLeft.y;
//
// Overwrite the GraphicsPort::bounds data with rotated values
// for GraphView's benefit
//
switch(baseRotation)
{
default:
// do nothing
break;
case 90:
case 270:
if (graphics_display != NULL)
{
Check(graphics_display);
bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y;
bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x;
bounds.topRight.x = graphics_display->bounds.topRight.y;
bounds.topRight.y = graphics_display->bounds.topRight.x;
}
break;
}
for(int j=0; j<256; ++j)
{
myColor[j] = NULL;
}
Check_Fpu();
}
L4GraphicsPort::~L4GraphicsPort()
{
Check(this);
Check_Fpu();
}
Logical
L4GraphicsPort::TestInstance() const
{
return True;
}
void
L4GraphicsPort::ShowInstance(char *indent)
{
Check(this);
cout << indent << "L4GraphicsPort:\n";
char
temp[80];
Str_Copy(temp,indent, 80);
Str_Cat(temp,"...", 80);
cout << temp << "bitMask =" << bitMask << "\n";
cout << temp << "baseRotation =" << baseRotation << "\n";
cout << temp << "maximumX =" << maximumX << "\n";
cout << temp << "maximumY =" << maximumY << "\n";
cout << temp << "bounds =" << bounds << "\n";
cout << flush;
GraphicsPort::ShowInstance(temp);
Check_Fpu();
}
void
L4GraphicsPort::SetColor(
PaletteTriplet *source_triplet,
int color_index
)
{
Check(this);
Check_Pointer(source_triplet);
Verify(color_index >= 0);
Verify(color_index < 256);
switch(channelEnable)
{
case L4GraphicsPort::DirectColor:
case L4GraphicsPort::BlankColor:
break;
default:
BuildSecondaryColor(source_triplet, color_index);
break;
}
Check_Fpu();
}
void
L4GraphicsPort::SetSecondaryPalette(
Palette8 *source_palette
)
{
Check(this);
Check(source_palette);
if (graphicsDisplay == NULL)
{
return;
}
switch(channelEnable)
{
case L4GraphicsPort::DirectColor:
BuildDirectTranslation(source_palette);
break;
case L4GraphicsPort::BlankColor:
BlankPalette();
BuildSecondaryTranslation();
break;
default:
BuildSecondaryPalette(source_palette);
BuildSecondaryTranslation();
break;
}
Check_Fpu();
}
void
L4GraphicsPort::SetAuxiliaryPalette()
{
Check(this);
if (graphicsDisplay == NULL)
{
return;
}
switch(channelEnable)
{
case L4GraphicsPort::DirectColor:
//---------------------------------------------------------------
// Set translation table for direct color mode
//---------------------------------------------------------------
{
Palette8
monochrome_palette;
PaletteTriplet
black,
white;
black.Red = 0;
black.Green = 0;
black.Blue = 0;
white.Red = 255;
white.Green = 255;
white.Blue = 255;
monochrome_palette.BuildColorRange(0,255,black, white);
BuildDirectTranslation(&monochrome_palette);
}
break;
case L4GraphicsPort::BlankColor:
BlankPalette();
BuildAuxiliaryTranslation();
break;
default:
BuildAuxiliaryPalette();
BuildAuxiliaryTranslation();
break;
}
Check_Fpu();
}
void
L4GraphicsPort::DrawPoint(
int color,
Enumeration operation,
int x, int y
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
int
xp, yp;
convertPortPair(&xp, &yp, x, y);
graphicsDisplay->
DrawPoint(
translationTable[color],
bitMask,
operation,
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y
);
Check_Fpu();
}
void
L4GraphicsPort::DrawLine(
int color,
Enumeration operation,
int x1, int y1,
int x2, int y2,
Logical include_last_pixel
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
int
x1p, y1p,
x2p, y2p;
convertPortPair(&x1p, &y1p, x1, y1);
convertPortPair(&x2p, &y2p, x2, y2);
graphicsDisplay->
DrawLine(
translationTable[color],
bitMask,
operation,
x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y,
x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y,
include_last_pixel
);
Check_Fpu();
}
void
L4GraphicsPort::DrawFilledRectangle(
int color,
Enumeration operation,
int x1, int y1,
int x2, int y2
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
int
x1p, y1p,
x2p, y2p;
convertPortPair(&x1p, &y1p, x1, y1);
convertPortPair(&x2p, &y2p, x2, y2);
graphicsDisplay->
DrawFilledRectangle(
translationTable[color],
bitMask,
operation,
x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y,
x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y
);
Check_Fpu();
}
void
L4GraphicsPort::DrawText(
int /*color*/,
Enumeration /*operation*/,
Logical /*opaque*/,
int /*rotation*/,
Enumeration /*fontNumber*/,
Logical /*vertical*/,
GraphicsDisplay::Justification /*justification*/,
Rectangle2D */*clippingRectanglepointer*/,
char */*stringPointer*/
)
{
}
void
L4GraphicsPort::DrawBitMap(
int color,
Enumeration operation,
int rotation,
int x, int y,
BitMap *bitmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
if (bitmap == NULL)
{
Check_Fpu();
return;
}
if (bitmap->Data.MapPointer == NULL)
{
Check_Fpu();
return;
}
Check(bitmap);
int
xp, yp;
convertPortPair(&xp, &yp, x, y);
rotation += baseRotation;
while (rotation < 0) { rotation += 360; }
while (rotation >= 360) { rotation -= 360; }
graphicsDisplay->
DrawBitMap(
translationTable[color],
bitMask,
operation,
rotation,
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
bitmap,
sLeft, sBottom, sRight, sTop
);
Check_Fpu();
}
void
L4GraphicsPort::DrawBitMapOpaque(
int color,
int background,
Enumeration operation,
int rotation,
int x, int y,
BitMap *bitmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
if (bitmap == NULL)
{
Check_Fpu();
return;
}
if (bitmap->Data.MapPointer == NULL)
{
Check_Fpu();
return;
}
Check(bitmap);
int
xp, yp;
convertPortPair(&xp, &yp, x, y);
rotation += baseRotation;
while (rotation < 0) { rotation += 360; }
while (rotation >= 360) { rotation -= 360; }
graphicsDisplay->
DrawBitMapOpaque(
translationTable[color],
translationTable[background],
bitMask,
operation,
rotation,
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
bitmap,
sLeft, sBottom, sRight, sTop
);
}
void
L4GraphicsPort::DrawPixelMap8(
Enumeration operation,
Logical opaque,
int rotation,
int x, int y,
PixelMap8 *pixelmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
if (pixelmap == NULL)
{
Check_Fpu();
return;
}
if (pixelmap->Data.MapPointer == NULL)
{
Check_Fpu();
return;
}
Check(pixelmap);
int
xp, yp;
convertPortPair(&xp, &yp, x, y);
rotation += baseRotation;
while (rotation < 0) { rotation += 360; }
while (rotation >= 360) { rotation -= 360; }
graphicsDisplay->
DrawPixelMap8(
translationTable,
bitMask,
operation,
opaque,
rotation,
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
pixelmap,
sLeft, sBottom, sRight, sTop
);
Check_Fpu();
}
void
L4GraphicsPort::DrawPixelMap8SingleColor(
int color,
Enumeration operation,
int rotation,
int x, int y,
PixelMap8 *pixelmap,
int sLeft, int sBottom, int sRight, int sTop
)
{
Check(this);
if (graphicsDisplay == NULL)
{
Check_Fpu();
return;
}
Check(graphicsDisplay);
if (pixelmap == NULL)
{
Check_Fpu();
return;
}
if (pixelmap->Data.MapPointer == NULL)
{
Check_Fpu();
return;
}
Check(pixelmap);
int
xp, yp;
convertPortPair(&xp, &yp, x, y);
rotation += baseRotation;
while (rotation < 0) { rotation += 360; }
while (rotation >= 360) { rotation -= 360; }
graphicsDisplay->
DrawPixelMap8SingleColor(
translationTable[color],
bitMask,
operation,
rotation,
xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y,
pixelmap,
sLeft, sBottom, sRight, sTop
);
Check_Fpu();
}
void
L4GraphicsPort::convertPortPair(
int *xp,
int *yp,
int x,
int y
)
{
switch(baseRotation)
{
default:
*xp = x;
*yp = y;
break;
case 90:
*xp = y;
*yp = maximumY - x;
break;
case 180:
*xp = maximumX - x;
*yp = maximumY - y;
break;
case 270:
*xp = maximumX - y;
*yp = x;
break;
}
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method generates a translation table specifically for writing
// to a "direct" color mode display, in which colors are represented
// as 5 red bits, 6 green bits, and 5 blue bits in a display word.
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildDirectTranslation(
Palette8 *source_palette
)
{
PaletteTriplet
*source_data(source_palette->Color);
int
*dest(translationTable);
int
red_bits,
green_bits,
blue_bits,
i;
//
// Force to all bits (just to be sure)
//
bitMask = 0xFFFF;
for(i=256; i>0; --i,++source_data)
{
red_bits = source_data->Red >> 3;
green_bits = source_data->Green >> 2;
blue_bits = source_data->Blue >> 3;
*dest++ = (red_bits << 11)|(green_bits << 5) | blue_bits;
}
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method combines palettes from multiple L4GraphicsPorts.
// If several ports have palettes mapped onto the same RGB display, then
// the most recently built palette has precedence over the previous one(s).
//
// Palettes are assumed to always have 256 colors.
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildSecondaryPalette(
Palette8 *source_palette
)
{
Verify (bitMask != 0);
if (graphicsDisplay == NULL)
{
return;
}
Check(graphicsDisplay);
Check(source_palette);
int
byte_mask(bitMask & 0xFF);
Verify (byte_mask != 0);
BitWrangler
wrangler(byte_mask, 8);
PaletteTriplet
*source_triplet,
*destination_triplet;
SVGA16Palette
*svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]);
source_triplet = &source_palette->Color[0];
//-------------------------------------------
// Clear the 'owned color' flags
//-------------------------------------------
for(int j=0; j<256; ++j)
{
myColor[wrangler.Value] = 0;
}
//
// If any of the ...TransparentZero modes are used,
// leave color zero undefined for this bit group by
// skipping over it
//
if (channelEnable & 0x80)
{
++source_triplet;
wrangler.IncrementActive();
}
//
// Fill in the color table for this palette set
//
do
{
//-------------------------------------------
// Write all destination colors
//-------------------------------------------
do
{
//-------------------------------------------
// Set the 'owned color' flag
//-------------------------------------------
myColor[wrangler.Value] = 1;
//-------------------------------------------
// Get destination pointer
//-------------------------------------------
destination_triplet =
&svga_palette->paletteData.Color[wrangler.Value];
//-------------------------------------------
// Copy color data
//-------------------------------------------
switch(channelEnable)
{
case RedChannel:
case RedChannelTransparentZero:
destination_triplet->Red = source_triplet->Red;
break;
case GreenChannel:
case GreenChannelTransparentZero:
destination_triplet->Green = source_triplet->Green;
break;
case BlueChannel:
case BlueChannelTransparentZero:
destination_triplet->Blue = source_triplet->Blue;
break;
case AllChannels:
case AllChannelsTransparentZero:
*destination_triplet = *source_triplet;
break;
}
}
while (wrangler.IncrementInactive());
//-------------------------------------------
// Bump the source pointer
//-------------------------------------------
++source_triplet;
}
while (wrangler.IncrementActive());
svga_palette->paletteData.Valid = True;
svga_palette->modified = True;
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method combines palettes from multiple L4GraphicsPorts.
// If several ports have palettes mapped onto the same RGB display, then
// the most recently built palette has precedence over the previous one(s).
//
// Palettes are assumed to always have 256 colors.
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildSecondaryColor(
PaletteTriplet *source_triplet,
int dest_color_number
)
{
Verify (bitMask != 0);
if (graphicsDisplay == NULL)
{
return;
}
Check(graphicsDisplay);
Check_Pointer(source_triplet);
int
byte_mask(bitMask & 0xFF);
Verify (byte_mask != 0);
BitWrangler
wrangler(byte_mask, 8);
int
destination_color = 0;
PaletteTriplet
*destination_triplet;
SVGA16Palette
*svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]);
//-------------------------------------------
// If any of the ...TransparentZero modes are used,
// leave color zero undefined for this bit group by
// skipping over it
//-------------------------------------------
if (channelEnable & 0x80)
{
++destination_color;
wrangler.IncrementActive();
}
//-------------------------------------------
// Set the color value
//-------------------------------------------
do
{
//-------------------------------------------
// Write all destination colors
//-------------------------------------------
if (destination_color == dest_color_number)
{
//-------------------------------------------
// Write all destination colors
//-------------------------------------------
do
{
//-------------------------------------------
// Do we own this color? Skip if unowned
//-------------------------------------------
if (myColor[wrangler.Value])
{
//-------------------------------------------
// Copy color data
//-------------------------------------------
destination_triplet =
&svga_palette->paletteData.Color[wrangler.Value];
switch(channelEnable)
{
case RedChannel:
case RedChannelTransparentZero:
destination_triplet->Red = source_triplet->Red;
break;
case GreenChannel:
case GreenChannelTransparentZero:
destination_triplet->Green = source_triplet->Green;
break;
case BlueChannel:
case BlueChannelTransparentZero:
destination_triplet->Blue = source_triplet->Blue;
break;
case AllChannels:
case AllChannelsTransparentZero:
*destination_triplet = *source_triplet;
break;
}
}
}
while (wrangler.IncrementInactive());
//-------------------------------------------
// Only doing one color, so exit the loop
//-------------------------------------------
break;
}
//-------------------------------------------
// Bump the color counter
//-------------------------------------------
++destination_color;
}
while (wrangler.IncrementActive());
svga_palette->paletteData.Valid = True;
svga_palette->modified = True;
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method combines palettes from multiple L4GraphicsPorts.
// If several ports have palettes mapped on top of another, then
// the most recently built palette has precedence over the previous one(s).
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildAuxiliaryPalette()
{
Verify (bitMask != 0);
if (graphicsDisplay == NULL)
{
return;
}
Check(graphicsDisplay);
int
byte_mask((bitMask >> 8) & 0xFF);
Verify (byte_mask != 0);
BitWrangler
wrangler(byte_mask, 8);
int
rate,
accumulator;
Byte
color_value;
PaletteTriplet
*destination_triplet;
SVGA16Palette
*svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]);
Verify(((1<<wrangler.NumberOfActiveBits())-1) > 0);
rate = (255<<5)/((1<<wrangler.NumberOfActiveBits())-1);
accumulator = 0;
//
//-----------------------------------------------------------------------
// Generate palette
//-----------------------------------------------------------------------
//
// If any of the ...TransparentZero modes are used,
// leave color zero undefined for this bit group by
// skipping over it
if (channelEnable & 0x80)
{
accumulator += rate;
wrangler.IncrementActive();
}
do
{
color_value = (Byte) (accumulator >> 5);
accumulator += rate;
do
{
destination_triplet = &svga_palette->paletteData.
Color[wrangler.Value];
switch(channelEnable)
{
case RedChannel:
case RedChannelTransparentZero:
destination_triplet->Red = color_value;
break;
case GreenChannel:
case GreenChannelTransparentZero:
destination_triplet->Green = color_value;
break;
case BlueChannel:
case BlueChannelTransparentZero:
destination_triplet->Blue = color_value;
break;
case AllChannels:
case AllChannelsTransparentZero:
destination_triplet->Red = color_value;
destination_triplet->Green = color_value;
destination_triplet->Blue = color_value;
break;
}
}
while (wrangler.IncrementInactive());
}
while (wrangler.IncrementActive());
svga_palette->paletteData.Valid = True;
svga_palette->modified = True;
# if defined(TESTPALETTE)
cout << "L4GraphicsPort::BuildAuxiliaryPalette for port " <<
hex << svga_palette->hardwarePort << "\n";
for(int i=0; i<256; ++i)
{
if ((i & 0x03) == 0)
{
cout << dec << "\n" << i << ":" << hex;
}
cout << svga_palette->paletteData.Color[i] << " ";
}
cout << "\n";
{
Palette8
temp;
SVGAReadFullPalette(
&temp.Color[0].Red,
svga_palette->hardwarePort
);
cout << "L4GraphicsPort::BuildAuxiliaryPalette, read back\n";
for(int i=0; i<256; ++i)
{
if ((i & 0x03) == 0)
{
cout << dec << "\n" << i << ":" << hex;
}
cout << temp.Color[i] << " ";
}
cout << "\n";
}
# endif
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This sets 'owned' color values in a palette to zero.
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BlankPalette()
{
Verify (bitMask != 0);
if (graphicsDisplay == NULL)
{
return;
}
Check(graphicsDisplay);
int
byte_mask((bitMask >> 8) & 0xFF);
Verify (byte_mask != 0);
BitWrangler
wrangler(byte_mask, 8);
Byte
color_value;
PaletteTriplet
*destination_triplet;
SVGA16Palette
*svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]);
Verify(((1<<wrangler.NumberOfActiveBits())-1) > 0);
color_value = 0;
do
{
do
{
destination_triplet = &svga_palette->paletteData.
Color[wrangler.Value];
switch(channelEnable)
{
case RedChannel:
case RedChannelTransparentZero:
destination_triplet->Red = color_value;
break;
case GreenChannel:
case GreenChannelTransparentZero:
destination_triplet->Green = color_value;
break;
case BlueChannel:
case BlueChannelTransparentZero:
destination_triplet->Blue = color_value;
break;
case AllChannels:
case AllChannelsTransparentZero:
destination_triplet->Red = color_value;
destination_triplet->Green = color_value;
destination_triplet->Blue = color_value;
break;
}
}
while (wrangler.IncrementInactive());
}
while (wrangler.IncrementActive());
svga_palette->paletteData.Valid = True;
svga_palette->modified = True;
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method generates a translation table for the secondary display,
// using a previously set palette and channel.
//
// Palettes are assumed to always have 256 colors.
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildSecondaryTranslation()
{
Verify((bitMask & 0xFF) != 0);
BitWrangler
wrangler(bitMask & 0xFF, 8);
int
*destination(translationTable);
do
{
*destination++ = wrangler.Value;
}
while (wrangler.IncrementActive());
Check_Fpu();
}
//
//---------------------------------------------------------------------------
// This method generates a translation table for the auxiliary displays.
//
// Palettes are assumed to always have 256 colors (0=black, 255=white).
//---------------------------------------------------------------------------
//
void
L4GraphicsPort::BuildAuxiliaryTranslation()
{
Verify(numberOfBits != 0);
Verify(numberOfBits <= 8);
int
byte_mask((bitMask >> 8) & 0xFF);
Verify(byte_mask != 0);
BitWrangler
wrangler(byte_mask, 8);
int
*destination(translationTable);
int
currentValue;
//
// Generate lookup table
//
do
{
currentValue = wrangler.Value << 8;
do
{
*destination++ = currentValue;
}
while (wrangler.IncrementInactive());
}
while (wrangler.IncrementActive());
# if defined(TESTPALETTE)
cout << "L4GraphicsPort::BuildAuxiliaryTranslation\n";
for(int i=0; i<256; ++i)
{
if ((i & 0x07) == 0)
{
cout << "\n" << dec << i << ":" << hex;
}
cout << translationTable[i] << " ";
}
cout << "\n";
# endif
Check_Fpu();
}