Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5936 lines
134 KiB
C++
5936 lines
134 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "l4vb16.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])
|
|
{
|
|
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)
|
|
{
|
|
BuildWindows(init_width,init_height,windowed, secondaryIndex, aux1Index, aux2Index);
|
|
//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);
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|