The pod stacks its displays vertically - upper MFDs above the viewscreen, weapon MFDs + secondary below. Default grid now places the lower row (MFD LL / Map / MFD LR) at the main screen's bottom edge instead of directly under the upper row, so the main screen reads as the middle band, with the plasma glass at its lower-left. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6130 lines
140 KiB
C++
6130 lines
140 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "l4vb16.h"
|
|
#include "l4mfdview.h"
|
|
#include "../munga/gaugrend.h"
|
|
#include "L4VIDEO.h"
|
|
#include "DXUtils.h"
|
|
|
|
#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){std::cout << stuff;}
|
|
#else
|
|
# define Diag_on
|
|
# define Diag_off
|
|
# define Diag_Tell(n)
|
|
#endif
|
|
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
//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
|
|
// );
|
|
|
|
|
|
void SVGA16::BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index)
|
|
{
|
|
NUMGAUGEWINDOWS = 0;
|
|
|
|
if (secondaryIndex != NULL)
|
|
{
|
|
NUMGAUGEWINDOWS++;
|
|
}
|
|
|
|
if (aux1Index != NULL)
|
|
{
|
|
NUMGAUGEWINDOWS++;
|
|
}
|
|
|
|
if (aux2Index != NULL)
|
|
{
|
|
NUMGAUGEWINDOWS++;
|
|
}
|
|
|
|
if (NUMGAUGEWINDOWS == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
gaugeWindows = new HWND[NUMGAUGEWINDOWS];
|
|
mDevice = new LPDIRECT3DDEVICE9[NUMGAUGEWINDOWS];
|
|
mVertBuffers = new LPDIRECT3DVERTEXBUFFER9[NUMGAUGEWINDOWS];
|
|
mSurfaces = new LPDIRECT3DTEXTURE9[NUMGAUGEWINDOWS * 2];
|
|
mLockFlags = new DWORD[NUMGAUGEWINDOWS];
|
|
mPresentParams = new D3DPRESENT_PARAMETERS[NUMGAUGEWINDOWS];
|
|
mSurfaceRects = new RECT[NUMGAUGEWINDOWS];
|
|
for (int j=0; j < NUMGAUGEWINDOWS; j++)
|
|
{
|
|
int desiredAdapter = -1;
|
|
|
|
int adapterIndex = j;
|
|
|
|
if (secondaryIndex != NULL && adapterIndex >= 0)
|
|
{
|
|
desiredAdapter = *secondaryIndex;
|
|
adapterIndex--;
|
|
}
|
|
|
|
if (aux1Index != NULL && adapterIndex >= 0)
|
|
{
|
|
desiredAdapter = *aux1Index;
|
|
adapterIndex--;
|
|
}
|
|
|
|
if (aux2Index != NULL && adapterIndex >= 0)
|
|
{
|
|
desiredAdapter = *aux2Index;
|
|
adapterIndex--;
|
|
}
|
|
|
|
if (adapterIndex >= 0 || desiredAdapter < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
RECT r;
|
|
|
|
MONITORINFO info;
|
|
info.cbSize = sizeof(MONITORINFO);
|
|
GetMonitorInfo(gD3D->GetAdapterMonitor(desiredAdapter),&info);
|
|
r = info.rcMonitor;
|
|
|
|
mSurfaceRects[j].left = r.left;
|
|
mSurfaceRects[j].top = r.top;
|
|
mSurfaceRects[j].right = r.left + ((j==0 || aux2Index != NULL)?width:width*2);
|
|
mSurfaceRects[j].bottom = r.top + height;
|
|
|
|
RECT surfaceWindowRect = mSurfaceRects[j];
|
|
AdjustWindowRectEx(&surfaceWindowRect, WS_BORDER, false, 0);
|
|
|
|
gaugeWindows[j] = CreateWindowEx(0, L"MainWndClass", L"RPL4", WS_BORDER, surfaceWindowRect.left, surfaceWindowRect.top, surfaceWindowRect.right-surfaceWindowRect.left, surfaceWindowRect.bottom-surfaceWindowRect.top, (HWND)NULL, (HMENU)NULL, L4Application::GetAppInstance(), (LPVOID)NULL);
|
|
if (gaugeWindows[j])
|
|
{
|
|
// In split-view mode the packed windows are only kept as D3D
|
|
// device targets; the split windows are what the player sees.
|
|
if (!splitViews)
|
|
{
|
|
ShowWindow(gaugeWindows[j], SW_SHOW);
|
|
}
|
|
|
|
memset(&mPresentParams[j], 0, sizeof(D3DPRESENT_PARAMETERS));
|
|
|
|
mPresentParams[j].BackBufferCount = 1;
|
|
mPresentParams[j].SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
mPresentParams[j].hDeviceWindow = gaugeWindows[j];
|
|
mPresentParams[j].Flags = 0;
|
|
mPresentParams[j].FullScreen_RefreshRateInHz = (windowed)?D3DPRESENT_RATE_DEFAULT:60;
|
|
mPresentParams[j].PresentationInterval = D3DPRESENT_RATE_DEFAULT;
|
|
mPresentParams[j].BackBufferFormat = D3DFMT_R5G6B5;
|
|
//pp.EnableAutoDepthStencil = TRUE;
|
|
//pp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
|
mPresentParams[j].Windowed = windowed;
|
|
if (!windowed)
|
|
{
|
|
mPresentParams[j].BackBufferWidth = mSurfaceRects[j].right - mSurfaceRects[j].left;
|
|
mPresentParams[j].BackBufferHeight = mSurfaceRects[j].bottom - mSurfaceRects[j].top;
|
|
}
|
|
|
|
|
|
HRESULT hr = gD3D->CreateDevice(desiredAdapter, D3DDEVTYPE_HAL, ghWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams[j], &mDevice[j]);
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUG_STREAM<<"Couldn't create Direct3D device!"<<std::endl<<std::flush;
|
|
PostQuitMessage(1);
|
|
}
|
|
|
|
D3DCAPS9 caps;
|
|
DWORD usage = 0;
|
|
D3DPOOL pool = D3DPOOL_MANAGED;
|
|
hr = mDevice[j]->GetDeviceCaps(&caps);
|
|
mLockFlags[j] = 0;
|
|
|
|
hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &mSurfaces[j * 2], NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush;
|
|
PostQuitMessage(1);
|
|
}
|
|
|
|
hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush;
|
|
PostQuitMessage(1);
|
|
}
|
|
|
|
hr = mDevice[j]->CreateVertexBuffer(sizeof(float) * 6 * 4, NULL, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &mVertBuffers[j], NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUG_STREAM << "Couldn't create vertex buffer for display " << j << "!" << std::endl << std::flush;
|
|
PostQuitMessage(1);
|
|
}
|
|
|
|
float *buffer;
|
|
hr = mVertBuffers[j]->Lock(0, 0, (void**)&buffer, 0);
|
|
|
|
buffer[0] = 0.0f; // top left, x
|
|
buffer[1] = 0.0f; // y
|
|
buffer[2] = 0.0f; // z
|
|
buffer[3] = 1.0f; // rhw
|
|
buffer[4] = 0.0f; // u
|
|
buffer[5] = 0.0f; // v
|
|
|
|
buffer[6] = mSurfaceRects[j].right - mSurfaceRects[j].left; // top right, x
|
|
buffer[7] = 0.0f; // y
|
|
buffer[8] = 0.0f; // z
|
|
buffer[9] = 1.0f; // rhw
|
|
buffer[10] = 1.0f; // u
|
|
buffer[11] = 0.0f; // v
|
|
|
|
buffer[12] = mSurfaceRects[j].right - mSurfaceRects[j].left; // bottom right, x
|
|
buffer[13] = height; // y
|
|
buffer[14] = 0.0f; // z
|
|
buffer[15] = 1.0f; // rhw
|
|
buffer[16] = 1.0f; // u
|
|
buffer[17] = 1.0f, // v
|
|
|
|
buffer[18] = 0.0f; // bottom left, x
|
|
buffer[19] = height; // y
|
|
buffer[20] = 0.0f; // z
|
|
buffer[21] = 1.0f; // rhw
|
|
buffer[22] = 0.0f; // u
|
|
buffer[23] = 1.0f; // v
|
|
|
|
hr = mVertBuffers[j]->Unlock();
|
|
|
|
mDevice[j]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
|
mDevice[j]->SetStreamSource(0, mVertBuffers[j], 0, sizeof(float) * 6);
|
|
mDevice[j]->SetTexture(0, mSurfaces[j * 2 + 1]);
|
|
|
|
mDevice[j]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0.0f, 0);
|
|
V( mDevice[j]->Present(NULL, NULL, NULL, NULL) );
|
|
if (hr == D3DERR_DEVICELOST)
|
|
{
|
|
int bbCount = mPresentParams[j].BackBufferCount;
|
|
int bbWidth = mPresentParams[j].BackBufferWidth;
|
|
int bbHeight = mPresentParams[j].BackBufferHeight;
|
|
|
|
mSurfaces[j * 2 + 1]->Release();
|
|
V(mDevice[j]->Reset(&mPresentParams[j]));
|
|
V(mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL));
|
|
|
|
mPresentParams[j].BackBufferCount = bbCount;
|
|
mPresentParams[j].BackBufferWidth = bbWidth;
|
|
mPresentParams[j].BackBufferHeight = bbHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//########################################################################
|
|
//############################# 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
|
|
)
|
|
{
|
|
std::cout << indent << "Video16BitBuffered:\n";
|
|
|
|
Check(this);
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "width =" << width << "\n";
|
|
std::cout << temp << "height =" << height << "\n";
|
|
std::cout << temp << "maximumX =" << maximumX << "\n";
|
|
std::cout << temp << "maximumY =" << maximumY << "\n";
|
|
std::cout << temp << "changedLine=" << changedLine << "\n";
|
|
std::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 << std::hex <<
|
|
") = pix " << *pixel_pointer <<
|
|
", cbp " << *changed_bit_pointer <<
|
|
", cb " << *changed_bit << std::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 << ", " <<
|
|
std::hex << bitmask << ", " << std::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" <<
|
|
std::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" <<
|
|
std::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 << std::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,
|
|
bool windowed,
|
|
int *secondaryIndex,
|
|
int *aux1Index,
|
|
int *aux2Index
|
|
):Video16BitBuffered(init_width, init_height)
|
|
{
|
|
//------------------------------------------------------------------
|
|
// Split-view mode: decide before BuildWindows so the packed gauge
|
|
// windows can stay hidden.
|
|
//------------------------------------------------------------------
|
|
splitViews = False;
|
|
{
|
|
const char *split_string = getenv("L4MFDSPLIT");
|
|
if (split_string != NULL && atoi(split_string) != 0)
|
|
{
|
|
splitViews = True;
|
|
}
|
|
}
|
|
for (int view = 0; view < SplitViewCount; ++view)
|
|
{
|
|
splitView[view] = NULL;
|
|
}
|
|
|
|
BuildWindows(init_width,init_height,windowed, secondaryIndex, aux1Index, aux2Index);
|
|
|
|
if (splitViews)
|
|
{
|
|
//---------------------------------------------------------------
|
|
// One window per cockpit display. L4MFDSCALE is the view size in
|
|
// percent of the gauge canvas (default 50). Default layout is the
|
|
// pod grid to the right of the main view:
|
|
// [ main ] [ UL ] [ C ] [ UR ]
|
|
// [ LL ] [ map ] [ LR ]
|
|
//---------------------------------------------------------------
|
|
int scale_percent = 50;
|
|
const char *scale_string = getenv("L4MFDSCALE");
|
|
if (scale_string != NULL)
|
|
{
|
|
int requested = atoi(scale_string);
|
|
if (requested >= 10 && requested <= 200)
|
|
{
|
|
scale_percent = requested;
|
|
}
|
|
}
|
|
|
|
int cell_w = (init_width * scale_percent) / 100;
|
|
int cell_h = (init_height * scale_percent) / 100;
|
|
int frame_h = GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFIXEDFRAME);
|
|
int frame_w = 2 * GetSystemMetrics(SM_CXFIXEDFRAME);
|
|
int grid_x = init_width + frame_w;
|
|
|
|
// The pod stacks its displays vertically: upper MFDs above the
|
|
// viewscreen, weapon MFDs + secondary below it. On the desktop
|
|
// the upper row sits level with the main screen's top and the
|
|
// lower row drops below its bottom edge, so the main screen
|
|
// reads as the middle band.
|
|
int row2_y = (int) L4Application::GetScreenHeight();
|
|
|
|
//---------------------------------------------------------------
|
|
// Button banks per display (addresses per vRIO CockpitLayout,
|
|
// bank-to-display placement per the pod cockpit):
|
|
// upper left MFD 0x2F.. / upper center 0x27.. / upper right
|
|
// 0x37.. / lower left 0x0F.. / lower right 0x07.. and the map
|
|
// flanked by Secondary 0x10-0x15 / Screen 0x18-0x1D.
|
|
//---------------------------------------------------------------
|
|
splitView[SplitMFDUpperLeft] = new MFDSplitView(
|
|
"MFD upper left", init_width, init_height,
|
|
cell_w, cell_h, grid_x, 0,
|
|
MFDSplitView::MFDStrips, 0x2F);
|
|
splitView[SplitMFDUpperCenter] = new MFDSplitView(
|
|
"MFD upper center", init_width, init_height,
|
|
cell_w, cell_h, grid_x + (cell_w + frame_w), 0,
|
|
MFDSplitView::MFDStrips, 0x27);
|
|
splitView[SplitMFDUpperRight] = new MFDSplitView(
|
|
"MFD upper right", init_width, init_height,
|
|
cell_w, cell_h, grid_x + 2 * (cell_w + frame_w), 0,
|
|
MFDSplitView::MFDStrips, 0x37);
|
|
splitView[SplitMFDLowerLeft] = new MFDSplitView(
|
|
"MFD lower left", init_width, init_height,
|
|
cell_w, cell_h, grid_x, row2_y,
|
|
MFDSplitView::MFDStrips, 0x0F);
|
|
splitView[SplitMFDLowerRight] = new MFDSplitView(
|
|
"MFD lower right", init_width, init_height,
|
|
cell_w, cell_h, grid_x + 2 * (cell_w + frame_w), row2_y,
|
|
MFDSplitView::MFDStrips, 0x07);
|
|
// map is portrait: source rotated 90 degrees clockwise; shift left
|
|
// by one side-button column so the GLASS (not the window) centers
|
|
// under the upper-center MFD
|
|
int map_col_w = cell_h / 8;
|
|
if (map_col_w < 20) map_col_w = 20;
|
|
if (map_col_w > 40) map_col_w = 40;
|
|
splitView[SplitMap] = new MFDSplitView(
|
|
"Map", init_height, init_width,
|
|
cell_h, cell_w,
|
|
grid_x + (cell_w + frame_w) + (cell_w - cell_h) / 2 - (map_col_w + 8), row2_y,
|
|
MFDSplitView::SideColumns, 0x10, 0x18);
|
|
|
|
DEBUG_STREAM << "SVGA16: split views active - 5 MFD windows + rotated map, cockpit buttons on (scale "
|
|
<< scale_percent << "%)\n" << std::flush;
|
|
}
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
# 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 std::decoded Palette addresses to "match up"
|
|
// with the address definitions used by the standard VGA palette port.
|
|
// Adam's port std::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" << std::flush);
|
|
# endif
|
|
DrawFilledRectangle(
|
|
0,
|
|
0xFFFF,
|
|
GraphicsDisplay::Replace,
|
|
0, 0,
|
|
maximumX, maximumY
|
|
);
|
|
# if defined(DEBUG)
|
|
Tell("About to update-\n" << std::flush);
|
|
# endif
|
|
Update(False);
|
|
Check_Fpu();
|
|
|
|
mDisplayToUpdate = 0;
|
|
}
|
|
|
|
SVGA16::~SVGA16()
|
|
{
|
|
for (int i=0; i < NUMGAUGEWINDOWS; i++)
|
|
{
|
|
if (mSurfaces[i * 2] != NULL)
|
|
{
|
|
mSurfaces[i * 2]->Release();
|
|
mSurfaces[i * 2] = NULL;
|
|
}
|
|
if (mSurfaces[i * 2 + 1] != NULL)
|
|
{
|
|
mSurfaces[i * 2 + 1]->Release();
|
|
mSurfaces[i * 2 + 1] = NULL;
|
|
}
|
|
|
|
if (mDevice[i] != NULL)
|
|
{
|
|
mDevice[i]->Release();
|
|
mSurfaces[i] = NULL;
|
|
}
|
|
|
|
DestroyWindow(gaugeWindows[i]);
|
|
}
|
|
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
# 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);
|
|
|
|
for (int view = 0; view < SplitViewCount; ++view)
|
|
{
|
|
delete splitView[view];
|
|
splitView[view] = NULL;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
SVGA16::TestInstance() const
|
|
{
|
|
return Video16BitBuffered::TestInstance();
|
|
}
|
|
|
|
void
|
|
SVGA16::ShowInstance(char *indent)
|
|
{
|
|
std::cout << indent << "SVGA16:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "SVGA16:\n";
|
|
Video16BitBuffered::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
int GetShiftAmount(DWORD mask)
|
|
{
|
|
int amount = -1;
|
|
while (mask)
|
|
{
|
|
mask >>= 1;
|
|
amount++;
|
|
}
|
|
return amount;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Render one MFD's bit-slice of the shared canvas into its split-view
|
|
// window as a green screen. The mask arrives in the duplicated
|
|
// (mask | mask<<16) form the packed path uses.
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
void SVGA16::FillSplitMFD(
|
|
SplitViewID view,
|
|
DWORD mask,
|
|
int shift
|
|
)
|
|
{
|
|
if (splitView[view] == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Word mask16 = (Word)(mask & 0xFFFF);
|
|
Word max_value = (Word)(mask16 >> shift);
|
|
if (max_value == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Word *source = pixelBuffer.Data.MapPointer;
|
|
unsigned long *dest = splitView[view]->Pixels();
|
|
int count = pixelBuffer.Data.Size.x * pixelBuffer.Data.Size.y;
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
unsigned long value = (unsigned long)((*source++ & mask16) >> shift);
|
|
unsigned long green = (value * 255ul) / max_value;
|
|
*dest++ = green << 8;
|
|
}
|
|
|
|
splitView[view]->Repaint();
|
|
}
|
|
|
|
Logical SVGA16::Update(Logical forceAll)
|
|
{
|
|
HRESULT hr;
|
|
|
|
GaugeRenderer *renderer = application->GetGaugeRenderer();
|
|
if (!valid || renderer == NULL)
|
|
{
|
|
CLEAR_SCREEN_COPY();
|
|
return False; // Do no more!
|
|
}
|
|
|
|
if (++mDisplayToUpdate >= NUMGAUGEWINDOWS)
|
|
mDisplayToUpdate = 0;
|
|
|
|
//Top MFD's
|
|
L4GraphicsPort *UL = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("auxUL2"));
|
|
L4GraphicsPort *Cent = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("auxC"));
|
|
L4GraphicsPort *UR = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("auxUR2"));
|
|
//Bottom MFD's
|
|
L4GraphicsPort *LL = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("auxLL"));
|
|
L4GraphicsPort *LR = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("auxLR"));
|
|
//Secondary
|
|
L4GraphicsPort *secPort = static_cast<L4GraphicsPort*>(renderer->GetGraphicsPort("sec"));
|
|
|
|
DWORD ulMask = 0, ucMask = 0, urMask = 0, llMask = 0, lrMask = 0;
|
|
int ulMask_sh = 0, ucMask_sh = 0, urMask_sh = 0, llMask_sh = 0, lrMask_sh = 0;
|
|
int secMask = 0;
|
|
SVGA16Palette *secPalette = NULL;
|
|
|
|
if (this->mDisplayToUpdate == 1 || this->mDisplayToUpdate == 2)
|
|
{
|
|
//Drawing MFD's... make sure we have MFDs to draw
|
|
if (UL != NULL && Cent != NULL && UR != NULL && LL != NULL && LR != NULL)
|
|
{
|
|
ulMask = UL->GetBitMask();
|
|
ulMask_sh = GetShiftAmount(ulMask);
|
|
ulMask |= (ulMask << 16);
|
|
|
|
ucMask = Cent->GetBitMask();
|
|
ucMask_sh = GetShiftAmount(ucMask);
|
|
ucMask |= (ucMask << 16);
|
|
|
|
urMask = UR->GetBitMask();
|
|
urMask_sh = GetShiftAmount(urMask);
|
|
urMask |= (urMask << 16);
|
|
|
|
llMask = LL->GetBitMask();
|
|
llMask_sh = GetShiftAmount(llMask);
|
|
llMask |= (llMask << 16);
|
|
|
|
lrMask = LR->GetBitMask();
|
|
lrMask_sh = GetShiftAmount(lrMask);
|
|
lrMask |= (lrMask << 16);
|
|
} else
|
|
{
|
|
//No MFDs to draw, break out early
|
|
return False;
|
|
}
|
|
} else
|
|
{
|
|
//Drawing secondary, make sure we got secondary
|
|
if (secPort != NULL)
|
|
{
|
|
secMask = secPort->GetBitMask();
|
|
secPalette = &((SVGA16 *) secPort->graphicsDisplay)->palette[secPort->paletteID];
|
|
} else
|
|
{
|
|
//No secondary, skip
|
|
return False;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Split views: render this window's displays into their own desktop
|
|
// windows, straight from the shared canvas (CPU-side, no D3D).
|
|
//------------------------------------------------------------------
|
|
if (splitViews)
|
|
{
|
|
if (mDisplayToUpdate == 0)
|
|
{
|
|
if (splitView[SplitMap] != NULL)
|
|
{
|
|
// Map is portrait-mounted: rotate 90 degrees clockwise.
|
|
// dest(x,y) = source(row = srcH-1-x, col = y)
|
|
Word *source_base = pixelBuffer.Data.MapPointer;
|
|
unsigned long *dest = splitView[SplitMap]->Pixels();
|
|
int src_w = pixelBuffer.Data.Size.x;
|
|
int src_h = pixelBuffer.Data.Size.y;
|
|
|
|
for (int dy = 0; dy < src_w; ++dy)
|
|
{
|
|
for (int dx = 0; dx < src_h; ++dx)
|
|
{
|
|
Word pixel = source_base[(src_h - 1 - dx) * src_w + dy];
|
|
PaletteTriplet *entry =
|
|
&secPalette->paletteData.Color[pixel & secMask];
|
|
*dest++ = ((unsigned long) entry->Red << 16) |
|
|
((unsigned long) entry->Green << 8) |
|
|
((unsigned long) entry->Blue);
|
|
}
|
|
}
|
|
splitView[SplitMap]->Repaint();
|
|
}
|
|
}
|
|
else if (mDisplayToUpdate == 1)
|
|
{
|
|
FillSplitMFD(SplitMFDUpperLeft, ulMask, ulMask_sh);
|
|
FillSplitMFD(SplitMFDUpperCenter, ucMask, ucMask_sh);
|
|
FillSplitMFD(SplitMFDUpperRight, urMask, urMask_sh);
|
|
if (NUMGAUGEWINDOWS < 3)
|
|
{
|
|
// spanning mode: the lower MFDs ride this window too
|
|
FillSplitMFD(SplitMFDLowerLeft, llMask, llMask_sh);
|
|
FillSplitMFD(SplitMFDLowerRight, lrMask, lrMask_sh);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FillSplitMFD(SplitMFDLowerLeft, llMask, llMask_sh);
|
|
FillSplitMFD(SplitMFDLowerRight, lrMask, lrMask_sh);
|
|
}
|
|
}
|
|
|
|
Word *data = pixelBuffer.Data.MapPointer;
|
|
|
|
D3DLOCKED_RECT rect;
|
|
if (FAILED(mSurfaces[mDisplayToUpdate * 2]->LockRect(0, &rect, NULL, mLockFlags[mDisplayToUpdate])))
|
|
{
|
|
DEBUG_STREAM << "Failed to lock texture for display " << mDisplayToUpdate << "!" << std::endl << std::flush;
|
|
}
|
|
else
|
|
{
|
|
switch(mDisplayToUpdate)
|
|
{
|
|
case 0:
|
|
{
|
|
//Secondary
|
|
Word *source = data;
|
|
Word *dest = (Word*)rect.pBits;
|
|
|
|
int postRowIncrement = (rect.Pitch / 2) - pixelBuffer.Data.Size.x;
|
|
for (int y = 0; y < pixelBuffer.Data.Size.y; y++)
|
|
{
|
|
for (int x = 0; x < pixelBuffer.Data.Size.x; x++)
|
|
{
|
|
PaletteTriplet *paletteEntry = &(secPalette->paletteData.Color[*source & secMask]);
|
|
|
|
*dest = ((paletteEntry->Red >> 3) << 11) |
|
|
((paletteEntry->Green >> 2) << 5) |
|
|
((paletteEntry->Blue >> 3));
|
|
|
|
dest++;
|
|
source++;
|
|
}
|
|
|
|
dest += postRowIncrement;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
//HACK - set the upper mask to be the lower mask (so that we draw the lower MFDs to the window)
|
|
//and then drop through and draw like the upper stuff
|
|
ulMask = llMask;
|
|
ucMask = lrMask;
|
|
urMask = 0;
|
|
ulMask_sh = llMask_sh;
|
|
ucMask_sh = lrMask_sh;
|
|
urMask_sh = 0;
|
|
}
|
|
case 1:
|
|
{
|
|
DWORD *sourceData = (DWORD*)data;
|
|
DWORD *destData = (DWORD*)rect.pBits;
|
|
|
|
int leftWidth = pixelBuffer.Data.Size.x/2;
|
|
|
|
int postRowIncrement = (rect.Pitch / sizeof(DWORD)) - leftWidth;
|
|
for (int y = 0; y < pixelBuffer.Data.Size.y; y++)
|
|
{
|
|
for (int x=0; x < leftWidth; x++)
|
|
{
|
|
*destData = (((*sourceData & ulMask) >> ulMask_sh) * 0xF800) |
|
|
(((*sourceData & ucMask) >> ucMask_sh) * 0x07E0) |
|
|
(((*sourceData & urMask) >> urMask_sh) * 0x001F);
|
|
|
|
if (NUMGAUGEWINDOWS < 3)
|
|
{
|
|
//Only draw if we are in spanning mode
|
|
*(destData + leftWidth) = (((*sourceData & llMask) >> llMask_sh) * 0xF800) |
|
|
(((*sourceData & lrMask) >> lrMask_sh) * 0x07E0);
|
|
}
|
|
sourceData++;
|
|
destData++;
|
|
}
|
|
|
|
destData += postRowIncrement;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
V( mSurfaces[mDisplayToUpdate * 2]->UnlockRect(0) );
|
|
|
|
V( mDevice[mDisplayToUpdate]->UpdateTexture(mSurfaces[mDisplayToUpdate * 2], mSurfaces[mDisplayToUpdate * 2 + 1]) );
|
|
}
|
|
|
|
V( mDevice[mDisplayToUpdate]->BeginScene() );
|
|
V( mDevice[mDisplayToUpdate]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1) );
|
|
V( mDevice[mDisplayToUpdate]->SetStreamSource(0, mVertBuffers[mDisplayToUpdate], 0, sizeof(float) * 6) );
|
|
V( mDevice[mDisplayToUpdate]->SetTexture(0, mSurfaces[mDisplayToUpdate * 2 + 1]) );
|
|
V( mDevice[mDisplayToUpdate]->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) );
|
|
V( mDevice[mDisplayToUpdate]->EndScene() );
|
|
|
|
V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) );
|
|
if (hr == D3DERR_DEVICELOST)
|
|
{
|
|
int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount;
|
|
int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth;
|
|
int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight;
|
|
|
|
mSurfaces[mDisplayToUpdate * 2 + 1]->Release();
|
|
V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate]));
|
|
hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL);
|
|
|
|
|
|
mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount;
|
|
mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth;
|
|
mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight;
|
|
}
|
|
|
|
// Time end = Now();
|
|
|
|
// if (end.ticks - start.ticks > 100)
|
|
// end = start;
|
|
|
|
return False; // True == 'more to do'
|
|
}
|
|
|
|
|
|
void SVGA16::Refresh()
|
|
{
|
|
HRESULT hr;
|
|
V( mDevice[mDisplayToUpdate]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0) );
|
|
|
|
V( mDevice[mDisplayToUpdate]->BeginScene() );
|
|
|
|
V( mDevice[mDisplayToUpdate]->EndScene() );
|
|
|
|
V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) );
|
|
if (hr == D3DERR_DEVICELOST)
|
|
{
|
|
int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount;
|
|
int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth;
|
|
int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight;
|
|
|
|
mSurfaces[mDisplayToUpdate * 2 + 1]->Release();
|
|
V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate]));
|
|
hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL);
|
|
|
|
V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL));
|
|
|
|
mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount;
|
|
mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth;
|
|
mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight;
|
|
}
|
|
|
|
mDisplayToUpdate++;
|
|
|
|
if (mDisplayToUpdate >= NUMGAUGEWINDOWS)
|
|
{
|
|
mDisplayToUpdate = 0;
|
|
}
|
|
}
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
// 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();
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
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
|
|
)
|
|
{
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
//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()
|
|
{
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
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)
|
|
{
|
|
//STUBBED: VIDEO RB 1/15/07
|
|
//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);
|
|
|
|
std::cout << indent << "L4GraphicsPort:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "bitMask =" << bitMask << "\n";
|
|
std::cout << temp << "baseRotation =" << baseRotation << "\n";
|
|
std::cout << temp << "maximumX =" << maximumX << "\n";
|
|
std::cout << temp << "maximumY =" << maximumY << "\n";
|
|
std::cout << temp << "bounds =" << bounds << "\n";
|
|
std::cout << std::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)
|
|
std::cout << "L4GraphicsPort::BuildAuxiliaryPalette for port " <<
|
|
std::hex << svga_palette->hardwarePort << "\n";
|
|
for(int i=0; i<256; ++i)
|
|
{
|
|
if ((i & 0x03) == 0)
|
|
{
|
|
std::cout << std::dec << "\n" << i << ":" << std::hex;
|
|
}
|
|
std::cout << svga_palette->paletteData.Color[i] << " ";
|
|
}
|
|
std::cout << "\n";
|
|
{
|
|
Palette8
|
|
temp;
|
|
|
|
SVGAReadFullPalette(
|
|
&temp.Color[0].Red,
|
|
svga_palette->hardwarePort
|
|
);
|
|
|
|
std::cout << "L4GraphicsPort::BuildAuxiliaryPalette, read back\n";
|
|
for(int i=0; i<256; ++i)
|
|
{
|
|
if ((i & 0x03) == 0)
|
|
{
|
|
std::cout << std::dec << "\n" << i << ":" << std::hex;
|
|
}
|
|
std::cout << temp.Color[i] << " ";
|
|
}
|
|
std::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)
|
|
std::cout << "L4GraphicsPort::BuildAuxiliaryTranslation\n";
|
|
for(int i=0; i<256; ++i)
|
|
{
|
|
if ((i & 0x07) == 0)
|
|
{
|
|
std::cout << "\n" << std::dec << i << ":" << std::hex;
|
|
}
|
|
std::cout << translationTable[i] << " ";
|
|
}
|
|
std::cout << "\n";
|
|
# endif
|
|
Check_Fpu();
|
|
}
|