#include "mungal4.h" #pragma hdrstop #include "l4vb16.h" #include "l4mfdview.h" #include "l4plasmascreen.h" #include "../munga/gaugrend.h" #include "L4VIDEO.h" #include "DXUtils.h" #if defined(TRACE_SCREEN_COPY) static BitTrace Screen_Copy("Screen Copy"); #define SET_SCREEN_COPY() Screen_Copy.Set() #define CLEAR_SCREEN_COPY() Screen_Copy.Clear() #else #define SET_SCREEN_COPY() #define CLEAR_SCREEN_COPY() #endif #define BLIT_STATISTICS #if defined(BLIT_STATISTICS) static int dirtyPixelCount, transferPixelCount, overflowPixelCount; #endif //#define DEBUG #if defined(DEBUG) static Logical printFlag=True; # define Diag_on printFlag=True # define Diag_off printFlag=False # define Diag_Tell(stuff) if(printFlag){std::cout << stuff;} #else # define Diag_on # define Diag_off # define Diag_Tell(n) #endif //STUBBED: VIDEO RB 1/15/07 //extern "C" void // SVGASetMode( // int mode, // LWord pageFlipFcnpointer // ); // //extern "C" void // SVGASetPage( // int page // ); // //extern "C" int // SVGATransfer32( // int dest_offset, // Word *source_pointer, // LWord changed_bits // ); // //extern "C" int // SVGATransfer32x( // int dest_offset, // Word *source_pointer, // LWord changed_bits // ); // //extern "C" void // SVGASetSplitterClock( // Logical state // ); // //extern "C" void // SVGAZeroPalette( // Word DAC_port // ); // //extern "C" void // SVGAWriteFullPalette( // Byte *firstColorByte, // Word DAC_port // ); // //extern "C" void // SVGAReadFullPalette( // Byte *firstColorByte, // Word DAC_port // ); // //extern "C" void // SVGAWritePaletteMask( // Word DAC_port, // Byte new_mask // ); // //extern "C" void // SVGAFunkyVideo( // Logical on_off // ); void SVGA16::BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index) { NUMGAUGEWINDOWS = 0; if (secondaryIndex != NULL) { NUMGAUGEWINDOWS++; } if (aux1Index != NULL) { NUMGAUGEWINDOWS++; } if (aux2Index != NULL) { NUMGAUGEWINDOWS++; } if (NUMGAUGEWINDOWS == 0) { return; } gaugeWindows = new HWND[NUMGAUGEWINDOWS]; mDevice = new LPDIRECT3DDEVICE9[NUMGAUGEWINDOWS]; mVertBuffers = new LPDIRECT3DVERTEXBUFFER9[NUMGAUGEWINDOWS]; mSurfaces = new LPDIRECT3DTEXTURE9[NUMGAUGEWINDOWS * 2]; mLockFlags = new DWORD[NUMGAUGEWINDOWS]; mPresentParams = new D3DPRESENT_PARAMETERS[NUMGAUGEWINDOWS]; mSurfaceRects = new RECT[NUMGAUGEWINDOWS]; for (int j=0; j < NUMGAUGEWINDOWS; j++) { int desiredAdapter = -1; int adapterIndex = j; if (secondaryIndex != NULL && adapterIndex >= 0) { desiredAdapter = *secondaryIndex; adapterIndex--; } if (aux1Index != NULL && adapterIndex >= 0) { desiredAdapter = *aux1Index; adapterIndex--; } if (aux2Index != NULL && adapterIndex >= 0) { desiredAdapter = *aux2Index; adapterIndex--; } if (adapterIndex >= 0 || desiredAdapter < 0) { break; } RECT r; MONITORINFO info; info.cbSize = sizeof(MONITORINFO); GetMonitorInfo(gD3D->GetAdapterMonitor(desiredAdapter),&info); r = info.rcMonitor; mSurfaceRects[j].left = r.left; mSurfaceRects[j].top = r.top; mSurfaceRects[j].right = r.left + ((j==0 || aux2Index != NULL)?width:width*2); mSurfaceRects[j].bottom = r.top + height; RECT surfaceWindowRect = mSurfaceRects[j]; AdjustWindowRectEx(&surfaceWindowRect, WS_BORDER, false, 0); gaugeWindows[j] = CreateWindowEx(0, L"MainWndClass", L"RPL4", WS_BORDER, surfaceWindowRect.left, surfaceWindowRect.top, surfaceWindowRect.right-surfaceWindowRect.left, surfaceWindowRect.bottom-surfaceWindowRect.top, (HWND)NULL, (HMENU)NULL, L4Application::GetAppInstance(), (LPVOID)NULL); if (gaugeWindows[j]) { // In split-view mode the packed windows are only kept as D3D // device targets; the split windows are what the player sees. if (!splitViews) { ShowWindow(gaugeWindows[j], SW_SHOW); } memset(&mPresentParams[j], 0, sizeof(D3DPRESENT_PARAMETERS)); mPresentParams[j].BackBufferCount = 1; mPresentParams[j].SwapEffect = D3DSWAPEFFECT_DISCARD; mPresentParams[j].hDeviceWindow = gaugeWindows[j]; mPresentParams[j].Flags = 0; mPresentParams[j].FullScreen_RefreshRateInHz = (windowed)?D3DPRESENT_RATE_DEFAULT:60; mPresentParams[j].PresentationInterval = D3DPRESENT_RATE_DEFAULT; mPresentParams[j].BackBufferFormat = D3DFMT_R5G6B5; //pp.EnableAutoDepthStencil = TRUE; //pp.AutoDepthStencilFormat = D3DFMT_D24X8; mPresentParams[j].Windowed = windowed; if (!windowed) { mPresentParams[j].BackBufferWidth = mSurfaceRects[j].right - mSurfaceRects[j].left; mPresentParams[j].BackBufferHeight = mSurfaceRects[j].bottom - mSurfaceRects[j].top; } HRESULT hr = gD3D->CreateDevice(desiredAdapter, D3DDEVTYPE_HAL, ghWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams[j], &mDevice[j]); if (FAILED(hr)) { DEBUG_STREAM<<"Couldn't create Direct3D device!"<GetDeviceCaps(&caps); mLockFlags[j] = 0; hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &mSurfaces[j * 2], NULL); if (FAILED(hr)) { DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush; PostQuitMessage(1); } hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL); if (FAILED(hr)) { DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush; PostQuitMessage(1); } hr = mDevice[j]->CreateVertexBuffer(sizeof(float) * 6 * 4, NULL, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &mVertBuffers[j], NULL); if (FAILED(hr)) { DEBUG_STREAM << "Couldn't create vertex buffer for display " << j << "!" << std::endl << std::flush; PostQuitMessage(1); } float *buffer; hr = mVertBuffers[j]->Lock(0, 0, (void**)&buffer, 0); buffer[0] = 0.0f; // top left, x buffer[1] = 0.0f; // y buffer[2] = 0.0f; // z buffer[3] = 1.0f; // rhw buffer[4] = 0.0f; // u buffer[5] = 0.0f; // v buffer[6] = mSurfaceRects[j].right - mSurfaceRects[j].left; // top right, x buffer[7] = 0.0f; // y buffer[8] = 0.0f; // z buffer[9] = 1.0f; // rhw buffer[10] = 1.0f; // u buffer[11] = 0.0f; // v buffer[12] = mSurfaceRects[j].right - mSurfaceRects[j].left; // bottom right, x buffer[13] = height; // y buffer[14] = 0.0f; // z buffer[15] = 1.0f; // rhw buffer[16] = 1.0f; // u buffer[17] = 1.0f, // v buffer[18] = 0.0f; // bottom left, x buffer[19] = height; // y buffer[20] = 0.0f; // z buffer[21] = 1.0f; // rhw buffer[22] = 0.0f; // u buffer[23] = 1.0f; // v hr = mVertBuffers[j]->Unlock(); mDevice[j]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); mDevice[j]->SetStreamSource(0, mVertBuffers[j], 0, sizeof(float) * 6); mDevice[j]->SetTexture(0, mSurfaces[j * 2 + 1]); mDevice[j]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0.0f, 0); V( mDevice[j]->Present(NULL, NULL, NULL, NULL) ); if (hr == D3DERR_DEVICELOST) { int bbCount = mPresentParams[j].BackBufferCount; int bbWidth = mPresentParams[j].BackBufferWidth; int bbHeight = mPresentParams[j].BackBufferHeight; mSurfaces[j * 2 + 1]->Release(); V(mDevice[j]->Reset(&mPresentParams[j])); V(mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL)); mPresentParams[j].BackBufferCount = bbCount; mPresentParams[j].BackBufferWidth = bbWidth; mPresentParams[j].BackBufferHeight = bbHeight; } } } } //######################################################################## //############################# BitWrangler ############################## //######################################################################## // // A "bitwrangler" manages a group of bits by segregating them into two groups: // "active", and "inactive". Active bits are those specified within a given // bit mask as "ones", and inactive bits are those specified as "zeros". // // Once initialized, the bitwrangler may be requested to increment either // the active bit field or the inactive bit field: the "carry" is propagated // from the least significant bit through the most significant bit, and if // an overflow is generated it is returned as "False". // // Why in the world would anyone want such a bizarre object? // It's used here to generate palettes and translation tables according // to bit allocations for a GraphicsPort. "Unused" colors are easily // found and set to proper values. // class BitWrangler { public: BitWrangler(int bit_mask, int total_length); ~BitWrangler() {} void ResetActive(); void ResetInactive(); Logical IncrementActive(); Logical IncrementInactive(); int NumberOfActiveBits(); int NumberOfInactiveBits(); int Value; protected: int length; int bitMask; }; // // Bitwrangler initialization // BitWrangler::BitWrangler(int bit_mask, int total_length) { Verify(bit_mask != 0); bitMask = bit_mask; length = total_length; Value = 0; Check_Fpu(); } // // Reset all "active" bits to zero // void BitWrangler::ResetActive() { Value &= ~ bitMask; Check_Fpu(); } // // Reset all "inactive" bits to zero // void BitWrangler::ResetInactive() { Value &= bitMask; Check_Fpu(); } // // Increment the "active" bit field, and return "false" if overflow // Logical BitWrangler::IncrementActive() { int single_bit; int count(length); for(single_bit=1; count>0; --count, single_bit <<= 1) { // // If it's an active bit, process it // if (bitMask & single_bit) { // // Invert the bit // Value ^= single_bit; // // If the bit is now set, it was zero, so exit // if (Value & single_bit) { Check_Fpu(); return True; } } } // // All the active bits are set, so return false // Check_Fpu(); return False; } // // Increment the "inactive" bit field, and return "false" if overflow // Logical BitWrangler::IncrementInactive() { int single_bit; int count(length); int inverse_mask(~bitMask); for(single_bit=1; count>0; --count, single_bit <<= 1) { // // If it's an inactive bit, process it // if (inverse_mask & single_bit) { // // Invert the bit // Value ^= single_bit; // // If the bit is now set, it was zero, so exit // if (Value & single_bit) { Check_Fpu(); return True; } } } // // All the inactive bits are set, so return false // Check_Fpu(); return False; } // // Return the number of "active" bits // int BitWrangler::NumberOfActiveBits() { int count(0), temp(bitMask); while(temp != 0) { ++count; temp = temp & (temp-1); } Check_Fpu(); return count; } // // Return the number of "inactive" bits // int BitWrangler::NumberOfInactiveBits() { Check_Fpu(); return length-NumberOfActiveBits(); } //######################################################################## //######################### Video16BitBuffered ########################### //######################################################################## // //NOTE: the application assumes that the origin is in the lower left // corner of the display, and all parameters passed to these routines // use the application's coordinate system. // // All of the methods here convert these values to the SCREEN // coordinate system, with the origin in the UPPER LEFT corner of // the display. // //=================================================================== // Creator //=================================================================== Video16BitBuffered::Video16BitBuffered(int x, int y): GraphicsDisplay(x, y), pixelBuffer(x, y) { # if defined(DEBUG) Tell( "Video16BitBuffered::Video16BitBuffered()\n" ); # endif int i, changed_size; Verify(pixelBuffer.Data.MapPointer != NULL); height = y; width = x; changedBitWidth = (width >> 5); changed_size = height * changedBitWidth; maximumY = height-1; maximumX = width-1; //--------------------------------------------------------- // Create 'changedLine' and 'changedBit' arrays //--------------------------------------------------------- changedLine = new Byte[height]; changedBit = new LWord[changed_size]; if (changedLine == NULL || changedBit == NULL) { # if defined(DEBUG) Tell("INVALID!\n"); # endif valid = False; return; } else { Register_Pointer(changedLine); Register_Pointer(changedBit); valid = True; } # if defined(DEBUG) Tell("changedLine=" << changedLine << "\n"); Tell("changedBit=" << changedBit << "\n"); # endif //--------------------------------------------------------- // Clear the 'changedBit' array //--------------------------------------------------------- memset(changedLine, 0, height); //--------------------------------------------------------- // Clear the 'changedBit' array //--------------------------------------------------------- LWord *bit_dest; for (i=changed_size,bit_dest=changedBit; i>0; --i,++bit_dest) { *bit_dest = (LWord) 0; } Check_Fpu(); } //=================================================================== // Destructor //=================================================================== Video16BitBuffered::~Video16BitBuffered() { Check(this); if (changedLine != NULL) { Unregister_Pointer(changedLine); delete changedLine; changedLine = NULL; } if (changedBit != NULL) { Unregister_Pointer(changedBit); delete changedBit; changedBit = NULL; } Check_Fpu(); } //=================================================================== // TestInstance //=================================================================== Logical Video16BitBuffered::TestInstance() const { return True; } //=================================================================== // ShowInstance //=================================================================== void Video16BitBuffered::ShowInstance( char *indent ) { std::cout << indent << "Video16BitBuffered:\n"; Check(this); char temp[80]; Str_Copy(temp,indent, 80); Str_Cat(temp,"...", 80); std::cout << temp << "width =" << width << "\n"; std::cout << temp << "height =" << height << "\n"; std::cout << temp << "maximumX =" << maximumX << "\n"; std::cout << temp << "maximumY =" << maximumY << "\n"; std::cout << temp << "changedLine=" << changedLine << "\n"; std::cout << temp << "changedBit =" << changedBit << "\n"; pixelBuffer.ShowInstance(temp); GraphicsDisplay::ShowInstance(temp); Check_Fpu(); } //=================================================================== // buildDestPointer //=================================================================== void Video16BitBuffered::buildDestPointer( int screenX, int screenY, Word **pixel_pointer, LWord **changed_bit_pointer, LWord *changed_bit ) { Verify(valid); Verify(pixel_pointer != NULL); Verify(changed_bit_pointer != NULL); Verify(changed_bit != NULL); Verify(screenX >= 0); Verify(screenX < width); Verify(screenY >= 0); Verify(screenY < height); *pixel_pointer = pixelBuffer.Data.MapPointer + screenX + (screenY * width); Verify(*pixel_pointer >= pixelBuffer.Data.MapPointer); Verify(*pixel_pointer < &pixelBuffer.Data.MapPointer[height*width]); *changed_bit_pointer = changedBit + (screenX >> 5) + (screenY * changedBitWidth); Verify(*changed_bit_pointer >= changedBit); Verify(*changed_bit_pointer < &changedBit[height*changedBitWidth]); *changed_bit = 1L << (0x1F - (screenX & 0x1F)); Verify(*changed_bit != 0L); Diag_Tell( "Video16BitBuffered::buildDestPointer(" << screenX << ", " << screenY << std::hex << ") = pix " << *pixel_pointer << ", cbp " << *changed_bit_pointer << ", cb " << *changed_bit << std::dec << "\n" ); Diag_Tell("changedBitWidth=" << changedBitWidth << "\n"); Check_Fpu(); } //=================================================================== // MarkChangedLines //=================================================================== #if defined(BLIT_STATISTICS) # define SET_CHANGED(pointer, bits) *pointer |= bits; ++dirtyPixelCount #else # define SET_CHANGED(pointer, bits) *pointer |= bits #endif #define LEFT_CHANGED(pointer, bits) \ bits <<= 1; \ if (bits == 0) { --pointer; bits=0x00000001L; } #define RIGHT_CHANGED(pointer, bits) \ bits >>= 1; \ if (bits == 0) { ++pointer; bits=0x80000000L; } #define UP_CHANGED(pointer, bits) pointer -= changedBitWidth #define DOWN_CHANGED(pointer, bits) pointer += changedBitWidth #define LEFT_DEST(pointer) --pointer #define RIGHT_DEST(pointer) ++pointer #define UP_DEST(pointer) pointer -= width #define DOWN_DEST(pointer) pointer += width #define LEFT_SOURCE(pointer,map) --pointer #define RIGHT_SOURCE(pointer,map) ++pointer #define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x #define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x #define LEFT_BITMAP(pointer,bits) \ bits <<= 1; \ if (bits == 0) { --pointer; bits=0x0001; } #define RIGHT_BITMAP(pointer, bits) \ bits >>= 1; \ if (bits == 0) { ++pointer; bits=0x8000; } #define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords #define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords // // Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner! // void Video16BitBuffered::MarkChangedLines( int start, int stop ) { Check(this); Diag_Tell( "Video16BitBuffered::MarkChangedLines(" << start << ", " << stop << ")\n" ); if (start > stop) { # if defined(DEBUG) Tell("MarkChangedLines FLIPPING\n"); # endif int temp; temp = start; start = stop; stop = temp; } Verify(start >= 0); Verify(start <= maximumY); Verify(stop >= 0); Verify(stop <= maximumY); //------------------------------------------------ // Set the flag for each changed line //------------------------------------------------ Verify(stop >= start); memset(&changedLine[start], 1, stop-start+1); Check_Fpu(); } //=================================================================== // DrawPoint //=================================================================== void Video16BitBuffered::DrawPoint( int color, int bitmask, Enumeration operation, int x, int y ) { Check(this); Verify(x >= bounds.bottomLeft.x); Verify(x <= bounds.topRight.x); Verify(y >= bounds.bottomLeft.y); Verify(y <= bounds.topRight.y); Word *dest_pointer; LWord *changed_pointer; LWord changed_bit; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y = maximumY - y; # if defined(DEBUG) Tell("x=" << x << ", y=" << y << "\n"); # endif Verify(x >= 0); Verify(x < width); Verify(y >= 0); Verify(y < height); //--------------------------------------------------------- // Update changedLine array //--------------------------------------------------------- MarkChangedLines(y, y); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Create pointers //--------------------------------------------------------- buildDestPointer( x, y, &dest_pointer, &changed_pointer, &changed_bit ); //--------------------------------------------------------- // Write the point //--------------------------------------------------------- switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); Check_Fpu(); } //=================================================================== // DrawLine //=================================================================== void Video16BitBuffered::DrawLine( int color, int bitmask, Enumeration operation, int x1, int y1, int x2, int y2, Logical include_last_pixel ) { # if defined(DEBUG) Tell( "Video16BitBuffered::DrawLine(" << color << ", " << bitmask << ", " << operation << ", " << x1 << "," << y1 << "," << x2 << "," << y2 << ", " << include_last_pixel << "\n" ); # endif Check(this); Verify(x1 >= bounds.bottomLeft.x); Verify(x1 <= bounds.topRight.x); Verify(y1 >= bounds.bottomLeft.y); Verify(y1 <= bounds.topRight.y); Verify(x2 >= bounds.bottomLeft.x); Verify(x2 <= bounds.topRight.x); Verify(y2 >= bounds.bottomLeft.y); Verify(y2 <= bounds.topRight.y); enum { negative_delta_x = 1, negative_delta_y = 2, delta_y_greater = 0, delta_x_greater = 4 }; long length, rate, accumulator; int octant, delta_x, delta_y; Word *dest_pointer; LWord *changed_pointer; LWord changed_bit; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Route to DrawPoint if single pixel //--------------------------------------------------------- if (x1 == x2 && y1 == y2) { if (include_last_pixel) { DrawPoint(color, bitmask, operation, x1, y1); } return; } //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y1 = maximumY - y1; y2 = maximumY - y2; //--------------------------------------------------------- // Ensure that endpoints are legitimate //--------------------------------------------------------- Verify(x1 >= 0); Verify(x1 < width); Verify(x2 >= 0); Verify(x2 < width); Verify(y1 >= 0); Verify(y1 < height); Verify(y2 >= 0); Verify(y2 < height); # if defined(DEBUG) Tell( "Transformed coordinates=" << x1 << "," << y1 << "," << x2 << "," << y2 << "\n" ); # endif //--------------------------------------------------------- // Update changedLine array //--------------------------------------------------------- MarkChangedLines(y1, y2); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Determine which octant to use //--------------------------------------------------------- octant = 0; delta_x = x2 - x1; if (delta_x < 0) { # if defined(DEBUG) Tell("negative dx\n"); # endif octant |= negative_delta_x; delta_x = - delta_x; } delta_y = y2 - y1; if (delta_y < 0) { # if defined(DEBUG) Tell("negative dy\n"); # endif octant |= negative_delta_y; delta_y = - delta_y; } if (delta_x > delta_y) { # if defined(DEBUG) Tell("dx > dy\n"); # endif octant |= delta_x_greater; } # if defined(DEBUG) Tell( "dx=" << delta_x << ", dy=" << delta_y << ", octant=" << octant << ", color=" << color << "\n" ); # endif //--------------------------------------------------------- // Prepare to draw line //--------------------------------------------------------- buildDestPointer( x1, y1, &dest_pointer, &changed_pointer, &changed_bit ); accumulator = 1024L; // preset accumulator to 1/2 full //--------------------------------------------------------- // Draw the line! //--------------------------------------------------------- switch (octant) { case delta_y_greater: //------------------------------------- // delta y greater // positive delta x // positive delta y // // + // \ & // \ & //------------------------------------- length = delta_y; if (!include_last_pixel) { -- length; } Verify(delta_y > 0); rate = (delta_x*2048L)/delta_y; # if defined(DEBUG) Tell( "delta_y_greater, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); DOWN_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; RIGHT_DEST(dest_pointer); RIGHT_CHANGED(changed_pointer, changed_bit); } } break; case delta_y_greater+negative_delta_x: //------------------------------------- // delta y greater // negative delta x // positive delta y // // + // / // / //------------------------------------- length = delta_y; if (!include_last_pixel) { -- length; } rate = (delta_x*2048L)/delta_y; # if defined(DEBUG) Tell( "delta_y_greater+negative_delta_x, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); DOWN_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; LEFT_DEST(dest_pointer); LEFT_CHANGED(changed_pointer, changed_bit); } } break; case delta_y_greater+negative_delta_y: //------------------------------------- // delta y greater // positive delta x // negative delta y // // / // / // + //------------------------------------- length = delta_y; if (!include_last_pixel) { -- length; } rate = (delta_x*2048L)/delta_y; # if defined(DEBUG) Tell( "delta_y_greater+negative_delta_y, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); UP_DEST(dest_pointer); UP_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; RIGHT_DEST(dest_pointer); RIGHT_CHANGED(changed_pointer, changed_bit); } } break; case delta_y_greater+negative_delta_x+negative_delta_y: //------------------------------------- // delta y greater // negative delta x // negative delta y // // \ & // \ & // + //------------------------------------- length = delta_y; if (!include_last_pixel) { -- length; } rate = (delta_x*2048L)/delta_y; # if defined(DEBUG) Tell( "delta_y_greater+negative_delta_x+negative_delta_y, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); UP_DEST(dest_pointer); UP_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; LEFT_DEST(dest_pointer); LEFT_CHANGED(changed_pointer, changed_bit); } } break; case delta_x_greater: //------------------------------------- // delta x greater // positive delta x // positive delta y // // +---___ // // //------------------------------------- length = delta_x; if (!include_last_pixel) { -- length; } rate = (delta_y*2048L)/delta_x; # if defined(DEBUG) Tell( "delta_x_greater, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); RIGHT_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; DOWN_DEST(dest_pointer); DOWN_CHANGED(changed_pointer, changed_bit); } } break; case delta_x_greater+negative_delta_x: //------------------------------------- // delta x greater // negative delta x // positive delta y // // ___---+ // // //------------------------------------- length = delta_x; if (!include_last_pixel) { -- length; } rate = (delta_y*2048L)/delta_x; # if defined(DEBUG) Tell( "delta_x_greater+negative_delta_x, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); LEFT_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; DOWN_DEST(dest_pointer); DOWN_CHANGED(changed_pointer, changed_bit); } } break; case delta_x_greater+negative_delta_y: //------------------------------------- // delta x greater // positive delta x // negative delta y // // +___--- // // //------------------------------------- length = delta_x; if (!include_last_pixel) { -- length; } rate = (delta_y*2048L)/delta_x; # if defined(DEBUG) Tell( "delta_x_greater+negative_delta_y, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); RIGHT_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; UP_DEST(dest_pointer); UP_CHANGED(changed_pointer, changed_bit); } } break; case delta_x_greater+negative_delta_x+negative_delta_y: //------------------------------------- // delta x greater // negative delta x // negative delta y // // ---___+ // // //------------------------------------- length = delta_x; if (!include_last_pixel) { -- length; } rate = (delta_y*2048L)/delta_x; # if defined(DEBUG) Tell( "delta_x_greater+negative_delta_x+negative_delta_y, length=" << length << ", rate=" << rate << "\n" ); # endif Verify(rate >= 0L); Verify(rate <= 2048L); Verify(length >= 0); for ( ; length>0; --length) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } # if defined(DEBUG) Tell( length << ", accum=" << accumulator << ", dest_pointer=" << dest_pointer << "\n" ); # endif SET_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); LEFT_CHANGED(changed_pointer, changed_bit); accumulator += rate; if (accumulator > 2048L) { # if defined(DEBUG) Tell("OVERFLOW\n"); # endif accumulator -= 2048L; UP_DEST(dest_pointer); UP_CHANGED(changed_pointer, changed_bit); } } break; } Check_Fpu(); } //=================================================================== // DrawFilledRectangle //=================================================================== void Video16BitBuffered::DrawFilledRectangle( int color, int bitmask, Enumeration operation, int x1, int y1, int x2, int y2 ) { # if defined(DEBUG) Tell("Video16BitBuffered::DrawFilledRectangle(" << color << ", " << std::hex << bitmask << ", " << std::dec << operation << ", " << x1 << ", " << y1 << ", " << x2 << ", " << y2 << ", " << ")\n"); # endif Check(this); Verify(x1 >= bounds.bottomLeft.x); Verify(x1 <= bounds.topRight.x); Verify(y1 >= bounds.bottomLeft.y); Verify(y1 <= bounds.topRight.y); Verify(x2 >= bounds.bottomLeft.x); Verify(x2 <= bounds.topRight.x); Verify(y2 >= bounds.bottomLeft.y); Verify(y2 <= bounds.topRight.y); Word *dest_pointer; LWord *init_changed_pointer, *changed_pointer; LWord init_changed_bit, changed_bit; int x, dest_fixup, rect_width, rect_height; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y1 = maximumY - y1; y2 = maximumY - y2; //--------------------------------------------------------- // Ensure that rectangle is properly specified //--------------------------------------------------------- if (x2 < x1) { int temp; temp = x1; x1 = x2; x2 = temp; } if (y2 < y1) { int temp; temp = y1; y1 = y2; y2 = temp; } //--------------------------------------------------------- // Verify that values are legitimate //--------------------------------------------------------- Verify(pixelBuffer.Data.MapPointer != NULL); Verify(x1 >= 0); Verify(x1 <= x2); Verify(x2 < width); Verify(y1 >= 0); Verify(y1 <= y2); Verify(y2 < height); //--------------------------------------------------------- // Update changedLine array //--------------------------------------------------------- MarkChangedLines(y1, y2); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Prepare to fill //--------------------------------------------------------- # if defined(DEBUG) Tell( "x1=" << x1 << ", " << "y1=" << y1 << "\n" << "x2=" << x2 << ", " << "y2=" << y2 << "\n" << std::flush ); # endif buildDestPointer( x1, y1, &dest_pointer, &init_changed_pointer, &init_changed_bit ); rect_height = y2 - y1 + 1; rect_width = x2 - x1 + 1; dest_fixup = width - rect_width; # if defined(DEBUG) Tell( "rect_height=" << rect_height << "\n" << "rect_width=" << rect_width << "\n" << "dest_fixup=" << dest_fixup << "\n" << std::flush ); # endif //--------------------------------------------------------- // Fill the rectangle //--------------------------------------------------------- switch(operation) { case GraphicsDisplay::Replace: for( ; rect_height>0; --rect_height) { changed_bit = init_changed_bit; changed_pointer = init_changed_pointer; DOWN_CHANGED(init_changed_pointer, init_changed_bit); for(x=rect_width; x>0; --x) { *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); dest_pointer++; SET_CHANGED(changed_pointer, changed_bit); RIGHT_CHANGED(changed_pointer, changed_bit); } dest_pointer += dest_fixup; } break; case GraphicsDisplay::And: for( ; rect_height>0; --rect_height) { changed_bit = init_changed_bit; changed_pointer = init_changed_pointer; DOWN_CHANGED(init_changed_pointer, init_changed_bit); for(x=rect_width; x>0; --x) { *dest_pointer++ &= (Word) color; SET_CHANGED(changed_pointer, changed_bit); RIGHT_CHANGED(changed_pointer, changed_bit); } dest_pointer += dest_fixup; } break; case GraphicsDisplay::Or: for( ; rect_height>0; --rect_height) { changed_bit = init_changed_bit; changed_pointer = init_changed_pointer; DOWN_CHANGED(init_changed_pointer, init_changed_bit); for(x=rect_width; x>0; --x) { *dest_pointer++ |= (Word) color; SET_CHANGED(changed_pointer, changed_bit); RIGHT_CHANGED(changed_pointer, changed_bit); } dest_pointer += dest_fixup; } break; case GraphicsDisplay::Xor: for( ; rect_height>0; --rect_height) { changed_bit = init_changed_bit; changed_pointer = init_changed_pointer; DOWN_CHANGED(init_changed_pointer, init_changed_bit); for(x=rect_width; x>0; --x) { *dest_pointer++ ^= (Word) color; SET_CHANGED(changed_pointer, changed_bit); RIGHT_CHANGED(changed_pointer, changed_bit); } dest_pointer += dest_fixup; } break; } Check_Fpu(); } void Video16BitBuffered::DrawText( int /*color*/, int /*bitmask*/, Enumeration /*operation*/, Logical /*opaque*/, int /*rotation*/, Enumeration /*fontNumber*/, Logical /*vertical*/, GraphicsDisplay::Justification /*justification*/, Rectangle2D */*clippingRectanglepointer*/, char */*stringPointer*/ ) { # if defined(DEBUG) Tell("Video16BitBuffered::DrawText()\n"); # endif Check(this); //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- Check_Fpu(); if (!valid) { return; } } //=================================================================== // DrawBitMap //=================================================================== void Video16BitBuffered::DrawBitMap( int color, int bitmask, Enumeration operation, int rotation, int x, int y, BitMap *bitmap, int sLeft, int sBottom, int sRight, int sTop ) { # if defined(DEBUG) Tell( "Video16BitBuffered::DrawBitMap(<" << x << ", " << y << ">,<" << sLeft << ", " << sBottom << ", " << sRight << ", " << sTop << ">" << ")\n" ); # endif Check(this); Verify(x >= bounds.bottomLeft.x); Verify(x <= bounds.topRight.x); Verify(y >= bounds.bottomLeft.y); Verify(y <= bounds.topRight.y); int map_width, map_height, map_max_y, bits, bit_test, first_bit_test; Word *source_pointer_begin, *source_pointer, *dest_pointer_begin, *dest_pointer; LWord changed_bit_begin, changed_bit, *changed_pointer_begin, *changed_pointer; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Ensure that source rectangle is properly specified //--------------------------------------------------------- Verify(bitmap != NULL); Verify(sLeft >= 0); Verify(sLeft <= sRight); Verify(sRight < bitmap->Data.Size.x); Verify(sBottom >= 0); Verify(sBottom <= sTop); Verify(sTop < bitmap->Data.Size.y); //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y = maximumY - y; map_max_y = bitmap->Data.Size.y-1; sTop = map_max_y - sTop; sBottom = map_max_y - sBottom; map_width = sRight - sLeft + 1; map_height = sBottom - sTop + 1; # if defined(DEBUG) Tell("x=" << x << ", y=" << y << "\n"); Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); # endif Verify(map_width > 0); Verify(map_width <= bitmap->Data.Size.x); Verify(map_height > 0); Verify(map_height <= bitmap->Data.Size.y); Verify(x >= 0); Verify(x < width); Verify(y >= 0); Verify(y < height); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Prepare to draw bitmap //--------------------------------------------------------- Verify(pixelBuffer.Data.MapPointer != NULL); source_pointer_begin = bitmap->Data.MapPointer + (sLeft >> 4) + (sBottom * bitmap->Data.WidthInWords); first_bit_test = 1 << (15-(sLeft & 15)); buildDestPointer( x, y, &dest_pointer_begin, &changed_pointer_begin, &changed_bit_begin ); switch (rotation) { default: //-------------------------------------------- // transparent bitmap, zero degrees // .-----. // | | // | | // Y | // #X----. //-------------------------------------------- # if defined(DEBUG) Tell( "zero: xp=" << (x+map_width-1) << ", yp=" << (y-map_height+1) << "\n" ); # endif Verify(x+map_width-1 >= 0); Verify(x+map_width-1 < width); Verify(y-map_height+1 >= 0); Verify(y-map_height+1 < height); MarkChangedLines(y-map_height+1, y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); UP_CHANGED(changed_pointer_begin, changed_bit_begin); UP_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } RIGHT_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); } } break; case 90: //-------------------------------------------- // Transparent bitmap, 90 degrees // #Y----. // X | // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); # endif Verify(x+map_height >= 0); Verify(x+map_height < width); Verify(y+map_width >= 0); Verify(y+map_width < height); MarkChangedLines(y, y+map_width); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); RIGHT_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } DOWN_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); } } break; case 180: //-------------------------------------------- // Transparent bitmap, 180 degrees // .----X# // | Y // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); # endif Verify(x-map_width+1 >= 0); Verify(x-map_width+1 < width); Verify(y+map_height >= 0); Verify(y+map_height < height); MarkChangedLines(y, y+map_height); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); DOWN_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } LEFT_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); } } break; case 270: //-------------------------------------------- // Transparent bitmap, 270 degrees // .-----. // | | // | X // | | // .--Y--# //-------------------------------------------- # if defined(DEBUG) Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n"); # endif if (x-map_height < 0) { Tell("x-map_height = " << (x - map_height) << "\n"); return; } Verify(x-map_height >= 0); Verify(x-map_height < width); Verify(y-(map_width-1) >= 0); Verify(y-(map_width-1) < height); MarkChangedLines(y-(map_width-1), y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); LEFT_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { Verify(dest_pointer >= pixelBuffer.Data.MapPointer); Verify(dest_pointer < pixelBuffer.Data.MapPointer+ (width*height)); Verify(changed_pointer >= changedBit); Verify(changed_pointer < changedBit+(changedBitWidth*height)); if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } UP_CHANGED(changed_pointer, changed_bit_begin); UP_DEST(dest_pointer); } } break; } Check_Fpu(); } //=================================================================== // DrawBitMapOpaque //=================================================================== void Video16BitBuffered::DrawBitMapOpaque( int foreground, int background, int bitmask, Enumeration operation, int rotation, int x, int y, BitMap *bitmap, int sLeft, int sBottom, int sRight, int sTop ) { Check(this); Diag_on; Diag_Tell( "Video16BitBuffered::DrawBitMapOpaque(<" << x << ", " << y << ">,<" << sLeft << ", " << sBottom << ", " << sRight << ", " << sTop << ">)\n" ); Verify(x >= bounds.bottomLeft.x); Verify(x <= bounds.topRight.x); Verify(y >= bounds.bottomLeft.y); Verify(y <= bounds.topRight.y); int map_width, map_height, map_max_y, bits, bit_test, first_bit_test; Word *source_pointer_begin, *source_pointer, *dest_pointer_begin, *dest_pointer; LWord changed_bit_begin, changed_bit, *changed_pointer_begin, *changed_pointer; Word color; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Ensure that source rectangle is properly specified //--------------------------------------------------------- Verify(bitmap != NULL); Verify(sLeft >= 0); Verify(sLeft <= sRight); Verify(sRight < bitmap->Data.Size.x); Verify(sBottom >= 0); Verify(sBottom <= sTop); Verify(sTop < bitmap->Data.Size.y); //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y = maximumY - y; map_max_y = bitmap->Data.Size.y-1; sTop = map_max_y - sTop; sBottom = map_max_y - sBottom; map_width = sRight - sLeft + 1; map_height = sBottom - sTop + 1; Diag_off; Diag_Tell("x=" << x << ", y=" << y << "\n"); Diag_Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); Diag_Tell( "map_width=" << map_width << ", map_height=" << map_height << "\n" ); Diag_on; Verify(map_width > 0); Verify(map_width <= bitmap->Data.Size.x); Verify(map_height > 0); Verify(map_height <= bitmap->Data.Size.y); Verify(x >= 0); Verify(x < width); Verify(y >= 0); Verify(y < height); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Prepare to draw bitmap //--------------------------------------------------------- Verify(pixelBuffer.Data.MapPointer != NULL); source_pointer_begin = bitmap->Data.MapPointer + (sLeft >> 4) + (sBottom * bitmap->Data.WidthInWords); first_bit_test = 1 << (15-(sLeft & 15)); buildDestPointer( x, y, &dest_pointer_begin, &changed_pointer_begin, &changed_bit_begin ); //--------------------------------------------------------- // The bitmap is always read left-to-right, bottom-to-top. // We write it to the screen in different directions // based on the rotation. //--------------------------------------------------------- switch (rotation) { default: //-------------------------------------------- // opaque bitmap, zero degrees // .-----. // | | // | | // Y | // #X----. //-------------------------------------------- # if defined(DEBUG) Tell( "zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n" ); # endif Verify(x+map_width >= 0); Verify(x+map_width <= width); // HACK? <, or <=? Verify(y-map_height+1 >= 0); Verify(y-map_height+1 < height); MarkChangedLines(y-map_height+1, y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); UP_CHANGED(changed_pointer_begin, changed_bit_begin); UP_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { color = (Word) foreground; } else { color = (Word) background; } { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } RIGHT_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); } } break; case 90: //-------------------------------------------- // opaque bitmap, 90 degrees // #--Y--. // | | // X | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); # endif Verify(x+map_height >= 0); Verify(x+map_height < width); Verify(y+map_width >= 0); Verify(y+map_width < height); MarkChangedLines(y, y+map_width); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); RIGHT_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { color = (Word) foreground; } else { color = (Word) background; } { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } DOWN_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); } } break; case 180: //-------------------------------------------- // opaque bitmap, 180 degrees // .----X# // | Y // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); # endif Verify(x-map_width+1 >= 0); Verify(x-map_width+1 < width); Verify(y+map_height >= 0); Verify(y+map_height < height); MarkChangedLines(y, y+map_height); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); DOWN_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { color = (Word) foreground; } else { color = (Word) background; } { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } LEFT_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); } } break; case 270: //-------------------------------------------- // opaque bitmap, 270 degrees // .-----. // | | // | X // | | // .--Y--# //-------------------------------------------- # if defined(DEBUG) Tell( "xp=" << (x-map_height+1) << ", yp=" << (y-(map_width-1)) << "\n" ); # endif Verify(x-map_height >= 0); Verify(x-map_height < width); Verify(y-(map_width-1) >= 0); Verify(y-(map_width-1) < height); Diag_Tell( "(y-(map_width-1))=" << (y-(map_width-1)) << ", y=" << y << "," ); MarkChangedLines(y-(map_width-1), y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_BITMAP(source_pointer_begin, bitmap); LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); LEFT_DEST(dest_pointer_begin); bit_test = first_bit_test; bits = *source_pointer++; for(x=map_width; x>0; --x,bit_test>>=1) { Verify(dest_pointer >= pixelBuffer.Data.MapPointer); Verify(dest_pointer < pixelBuffer.Data.MapPointer+ (width*height)); Verify(changed_pointer >= changedBit); Verify(changed_pointer < changedBit+(changedBitWidth*height)); if (bit_test == 0) { bit_test = 0x8000; bits = *source_pointer++; } if (bits & bit_test) { color = (Word) foreground; } else { color = (Word) background; } { switch (operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } UP_CHANGED(changed_pointer, changed_bit_begin); UP_DEST(dest_pointer); } } Diag_Tell( "changed_pointer=" << changed_pointer << std::dec << "\n" ); break; } Check_Fpu(); Diag_off; } //=================================================================== // DrawPixelMap8 //=================================================================== void Video16BitBuffered::DrawPixelMap8( int *translation_table, int bitmask, Enumeration operation, Logical opaque, int rotation, int x, int y, PixelMap8 *pixelmap, int sLeft, int sBottom, int sRight, int sTop ) { # if defined(DEBUG) Tell( "Video16BitBuffered::DrawPixelMap8(<" << x << ", " << y << ">,<" << sLeft << ", " << sBottom << ", " << sRight << ", " << sTop << ">" << ")\n" ); # endif Check(this); Verify(x >= bounds.bottomLeft.x); Verify(x <= bounds.topRight.x); Verify(y >= bounds.bottomLeft.y); Verify(y <= bounds.topRight.y); int map_width, map_height, map_max_y; Byte source_data, *source_pointer_begin, *source_pointer; Word *dest_pointer_begin, *dest_pointer; LWord changed_bit_begin, changed_bit, *changed_pointer_begin, *changed_pointer; Word color; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Ensure that source rectangle is properly specified //--------------------------------------------------------- Verify(pixelmap != NULL); Verify(sLeft >= 0); Verify(sLeft <= sRight); Verify(sRight < pixelmap->Data.Size.x); Verify(sBottom >= 0); Verify(sBottom <= sTop); Verify(sTop < pixelmap->Data.Size.y); //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y = maximumY - y; map_max_y = pixelmap->Data.Size.y-1; sTop = map_max_y - sTop; sBottom = map_max_y - sBottom; map_width = sRight - sLeft + 1; map_height = sBottom - sTop + 1; # if defined(DEBUG) Tell("x=" << x << ", y=" << y << "\n"); Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); # endif Verify(map_width > 0); Verify(map_width <= pixelmap->Data.Size.x); Verify(map_height > 0); Verify(map_height <= pixelmap->Data.Size.y); Verify(x >= 0); Verify(x < width); Verify(y >= 0); Verify(y < height); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Prepare to draw bitmap //--------------------------------------------------------- Verify(pixelBuffer.Data.MapPointer != NULL); source_pointer_begin = pixelmap->Data.MapPointer + sLeft + (sBottom * pixelmap->Data.Size.x); buildDestPointer( x, y, &dest_pointer_begin, &changed_pointer_begin, &changed_bit_begin ); if (opaque) { switch (rotation) { default: //-------------------------------------------- // Opaque pixelmap, zero degrees // .-----. // | | // | | // Y | // #X----. //-------------------------------------------- # if defined(DEBUG) Tell( "Opaque zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n" ); # endif Verify(x+map_width >= 0); Verify(x+map_width < width); Verify(y-map_height+1 >= 0); Verify(y-map_height+1 < height); MarkChangedLines(y-map_height+1, y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); UP_CHANGED(changed_pointer_begin, changed_bit_begin); UP_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } RIGHT_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); } } break; case 90: //-------------------------------------------- // Opaque pixelmap, 90 degrees // #Y----. // X | // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "Opaque 90: xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n" ); # endif Verify(x+map_height >= 0); Verify(x+map_height < width); Verify(y+map_width >= 0); Verify(y+map_width < height); MarkChangedLines(y, y+map_width); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); RIGHT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } DOWN_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); } } break; case 180: //-------------------------------------------- // Opaque pixelmap, 180 degrees // .----X# // | Y // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "Opaque 180: xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n" ); # endif Verify(x-map_width+1 >= 0); Verify(x-map_width+1 < width); Verify(y+map_height >= 0); Verify(y+map_height < height); MarkChangedLines(y, y+map_height); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); DOWN_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } LEFT_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); } } break; case 270: //-------------------------------------------- // Opaque pixelmap, 270 degrees // .-----. // | | // | X // | | // .--Y--# //-------------------------------------------- # if defined(DEBUG) Tell("Opaque 270: x=" << x << ", y=" << y << "\n"); Tell( "xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n" ); # endif Verify(x-map_height-1 >= 0); Verify(x-map_height-1 < width); Verify(y-(map_width-1) >= 0); Verify(y-(map_width-1) < height); MarkChangedLines(y-(map_width-1), y); for(y=map_height ; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); LEFT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { Verify(dest_pointer >= pixelBuffer.Data.MapPointer); Verify(dest_pointer < pixelBuffer.Data.MapPointer+ (width*height)); Verify(changed_pointer >= changedBit); Verify(changed_pointer < changedBit+(changedBitWidth*height)); source_data = *source_pointer++; //SOURCE_RIGHT { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } UP_CHANGED(changed_pointer, changed_bit_begin); UP_DEST(dest_pointer); } } break; } } else { switch (rotation) { default: //-------------------------------------------- // Transparent pixelmap, zero degrees // .-----. // | | // | | // Y | // #X----. //-------------------------------------------- # if defined(DEBUG) Tell( "transparent zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n" ); # endif Verify(x+map_width >= 0); Verify(x+map_width < width); Verify(y-map_height+1 >= 0); Verify(y-map_height+1 < height); MarkChangedLines(y-map_height+1, y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); UP_CHANGED(changed_pointer_begin, changed_bit_begin); UP_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } RIGHT_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); } } break; case 90: //-------------------------------------------- // Transparent pixelmap, 90 degrees // #Y----. // X | // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "transparent 90: xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n" ); # endif Verify(x+map_height >= 0); Verify(x+map_height < width); Verify(y+map_width >= 0); Verify(y+map_width < height); MarkChangedLines(y, y+map_width); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); RIGHT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } DOWN_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); } } break; case 180: //-------------------------------------------- // Transparent pixelmap, 180 degrees // .----X# // | Y // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "transparent 180: xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n" ); # endif Verify(x-map_width+1 >= 0); Verify(x-map_width+1 < width); Verify(y+map_height >= 0); Verify(y+map_height < height); MarkChangedLines(y, y+map_height); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); DOWN_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } LEFT_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); } } break; case 270: //-------------------------------------------- // Transparent pixelmap, 270 degrees // .-----. // | | // | X // | | // .--Y--# //-------------------------------------------- # if defined(DEBUG) Tell("transparent 270: x=" << x << ", y=" << y << "\n"); Tell( "xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n" ); # endif Verify(x-(map_height-1) >= 0); Verify(x-(map_height-1) < width); Verify(y-(map_width-1) >= 0); Verify(y-(map_width-1) < height); MarkChangedLines(y-(map_width-1), y); for(y=map_height ; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); LEFT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { Verify(dest_pointer >= pixelBuffer.Data.MapPointer); Verify(dest_pointer < pixelBuffer.Data.MapPointer+ (width*height)); Verify(changed_pointer >= changedBit); Verify(changed_pointer < changedBit+(changedBitWidth*height)); source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { color = (Word) translation_table[source_data]; switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= color; break; case GraphicsDisplay::Or: *dest_pointer |= color; break; case GraphicsDisplay::Xor: *dest_pointer ^= color; break; } SET_CHANGED(changed_pointer, changed_bit); } UP_CHANGED(changed_pointer, changed_bit_begin); UP_DEST(dest_pointer); } } break; } } Check_Fpu(); } //=================================================================== // DrawPixelMap8SingleColor //=================================================================== void Video16BitBuffered::DrawPixelMap8SingleColor( int color, int bitmask, Enumeration operation, int rotation, int x, int y, PixelMap8 *pixelmap, int sLeft, int sBottom, int sRight, int sTop ) { # if defined(DEBUG) Tell( "Video16BitBuffered::DrawPixelMap8SingleColor(<" << x << ", " << y << ">,<" << sLeft << ", " << sBottom << ", " << sRight << ", " << sTop << ">" << ")\n" ); # endif Check(this); Verify(x >= bounds.bottomLeft.x); Verify(x <= bounds.topRight.x); Verify(y >= bounds.bottomLeft.y); Verify(y <= bounds.topRight.y); int map_width, map_height, map_max_y; Byte source_data, *source_pointer_begin, *source_pointer; Word *dest_pointer_begin, *dest_pointer; LWord changed_bit_begin, changed_bit, *changed_pointer_begin, *changed_pointer; //--------------------------------------------------------- // If pixelbuffer is invalid, do nothing //--------------------------------------------------------- if (!valid) { Check_Fpu(); return; } //--------------------------------------------------------- // Ensure that source rectangle is properly specified //--------------------------------------------------------- Verify(pixelmap != NULL); Verify(sLeft >= 0); Verify(sLeft <= sRight); Verify(sRight < pixelmap->Data.Size.x); Verify(sBottom >= 0); Verify(sBottom <= sTop); Verify(sTop < pixelmap->Data.Size.y); //--------------------------------------------------------- // Convert to screen co-ordinates //--------------------------------------------------------- y = maximumY - y; map_max_y = pixelmap->Data.Size.y-1; sTop = map_max_y - sTop; sBottom = map_max_y - sBottom; map_width = sRight - sLeft + 1; map_height = sBottom - sTop + 1; # if defined(DEBUG) Tell("x=" << x << ", y=" << y << "\n"); Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); # endif Verify(map_width > 0); Verify(map_width <= pixelmap->Data.Size.x); Verify(map_height > 0); Verify(map_height <= pixelmap->Data.Size.y); Verify(x >= 0); Verify(x < width); Verify(y >= 0); Verify(y < height); //--------------------------------------------------------- // We really need inverse bitmap here //--------------------------------------------------------- bitmask = ~bitmask; //--------------------------------------------------------- // Prepare to draw bitmap //--------------------------------------------------------- Verify(pixelBuffer.Data.MapPointer != NULL); source_pointer_begin = pixelmap->Data.MapPointer + sLeft + (sBottom * pixelmap->Data.Size.x); buildDestPointer( x, y, &dest_pointer_begin, &changed_pointer_begin, &changed_bit_begin ); { switch (rotation) { default: //-------------------------------------------- // Single-color pixelmap, zero degrees // .-----. // | | // | | // Y | // #X----. //-------------------------------------------- # if defined(DEBUG) Tell( "Single-color zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n" ); # endif Verify(x+map_width >= 0); Verify(x+map_width < width); Verify(y-map_height+1 >= 0); Verify(y-map_height+1 < height); MarkChangedLines(y-map_height+1, y); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); UP_CHANGED(changed_pointer_begin, changed_bit_begin); UP_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } RIGHT_CHANGED(changed_pointer, changed_bit); RIGHT_DEST(dest_pointer); } } break; case 90: //-------------------------------------------- // Single-color pixelmap, 90 degrees // #Y----. // X | // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "Single-color 90: xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n" ); # endif Verify(x+map_height >= 0); Verify(x+map_height < width); Verify(y+map_width >= 0); Verify(y+map_width < height); MarkChangedLines(y, y+map_width); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); RIGHT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } DOWN_CHANGED(changed_pointer, changed_bit); DOWN_DEST(dest_pointer); } } break; case 180: //-------------------------------------------- // Single-color pixelmap, 180 degrees // .----X# // | Y // | | // | | // .-----. //-------------------------------------------- # if defined(DEBUG) Tell( "Single-color 180: xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n" ); # endif Verify(x-map_width+1 >= 0); Verify(x-map_width+1 < width); Verify(y+map_height >= 0); Verify(y+map_height < height); MarkChangedLines(y, y+map_height); for(y=map_height; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); DOWN_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } LEFT_CHANGED(changed_pointer, changed_bit); LEFT_DEST(dest_pointer); } } break; case 270: //-------------------------------------------- // Single-color pixelmap, 270 degrees // .-----. // | | // | X // | | // .--Y--# //-------------------------------------------- # if defined(DEBUG) Tell("Single-color 270: x=" << x << ", y=" << y << "\n"); Tell( "xp=" << (x-map_height) << ", yp=" << (y-map_width) << "\n" ); # endif Verify(x-map_height >= 0); Verify(x-map_height < width); Verify(y-map_width >= 0); Verify(y-map_width < height); MarkChangedLines(y-map_width, y); for(y=map_height ; y>0; --y) { source_pointer = source_pointer_begin; changed_pointer = changed_pointer_begin; changed_bit = changed_bit_begin; dest_pointer = dest_pointer_begin; UP_SOURCE(source_pointer_begin, pixelmap); LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); LEFT_DEST(dest_pointer_begin); for(x=map_width; x>0; --x) { Verify(dest_pointer >= pixelBuffer.Data.MapPointer); Verify(dest_pointer < pixelBuffer.Data.MapPointer+ (width*height)); Verify(changed_pointer >= changedBit); Verify(changed_pointer < changedBit+(changedBitWidth*height)); source_data = *source_pointer++; //SOURCE_RIGHT if (source_data) { switch(operation) { case GraphicsDisplay::Replace: *dest_pointer = (Word)((*dest_pointer & bitmask) | color); break; case GraphicsDisplay::And: *dest_pointer &= (Word) color; break; case GraphicsDisplay::Or: *dest_pointer |= (Word) color; break; case GraphicsDisplay::Xor: *dest_pointer ^= (Word) color; break; } SET_CHANGED(changed_pointer, changed_bit); } UP_CHANGED(changed_pointer, changed_bit_begin); UP_DEST(dest_pointer); } } break; } } Check_Fpu(); } //######################################################################## //############################ SVGA640x480x16 ############################ //######################################################################## SVGA16::SVGA16( int mode, int init_width, int init_height, int mem_page_size, int mem_granularity, int bytes_per_line, int page_function_pointer, int special_interface, bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index ):Video16BitBuffered(init_width, init_height) { //------------------------------------------------------------------ // Split-view mode: decide before BuildWindows so the packed gauge // windows can stay hidden. //------------------------------------------------------------------ splitViews = False; cockpitViewscreen = NULL; { const char *split_string = getenv("L4MFDSPLIT"); if (split_string != NULL && atoi(split_string) != 0) { splitViews = True; } } for (int view = 0; view < SplitViewCount; ++view) { splitView[view] = NULL; } BuildWindows(init_width,init_height,windowed, secondaryIndex, aux1Index, aux2Index); if (splitViews) { //--------------------------------------------------------------- // The 1920x1080 internal cockpit canvas. // // [ MFD UL 640 ][ MFD UC 640 ][ MFD UR 640 ] <- native glass, // exactly 1920 // [ viewscreen 800x600, centered ] // [ MFD LL ] [ Map ] [ MFD LR ] <- bottom edge // // The panes layer OVER the viewscreen like the pod's bezels - // the MFDs partially occlude the main display by design, just // as in the original cockpit. The whole canvas scales down // uniformly on monitors smaller than 1920x1080. //--------------------------------------------------------------- const int canvas_w = 1920; const int canvas_h = 1080; HWND cockpit = ApplicationManager::GetCurrentManager()->GetHWnd(); int chrome_w = 16, chrome_h = 40; if (cockpit != NULL) { RECT outer, inner; GetWindowRect(cockpit, &outer); GetClientRect(cockpit, &inner); chrome_w = (outer.right - outer.left) - inner.right; chrome_h = (outer.bottom - outer.top) - inner.bottom; } RECT work; work.left = 0; work.top = 0; work.right = 1920; work.bottom = 1080; SystemParametersInfoA(SPI_GETWORKAREA, 0, &work, 0); int avail_w = (work.right - work.left) - chrome_w; int avail_h = (work.bottom - work.top) - chrome_h; int scale_num = 100; if (avail_w < canvas_w || avail_h < canvas_h) { int fit_w = (avail_w * 100) / canvas_w; int fit_h = (avail_h * 100) / canvas_h; scale_num = (fit_w < fit_h) ? fit_w : fit_h; if (scale_num < 25) scale_num = 25; DEBUG_STREAM << "SVGA16: cockpit canvas scaled to " << scale_num << "% for the " << (work.right - work.left) << "x" << (work.bottom - work.top) << " work area\n" << std::flush; } #define COCKPIT_CANVAS(v) (((v) * scale_num) / 100) int client_w = COCKPIT_CANVAS(canvas_w); int client_h = COCKPIT_CANVAS(canvas_h); //--------------------------------------------------------------- // Grow the main window into the cockpit shell //--------------------------------------------------------------- if (cockpit != NULL) { SetWindowLongPtrA(cockpit, GWL_STYLE, GetWindowLongPtrA(cockpit, GWL_STYLE) | WS_CLIPCHILDREN); SetWindowPos(cockpit, NULL, work.left, work.top, client_w + chrome_w, client_h + chrome_h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); } //--------------------------------------------------------------- // The viewscreen: created FIRST so every pane sits above it in // the z-order, and clipped by those siblings so the 3D present // never draws over them. STATIC hit-tests transparent, so mouse // input over the 3D view reaches the game window as before. // 800x600 (the -res native size), centered on the canvas. //--------------------------------------------------------------- int view_w = COCKPIT_CANVAS(800); int view_h = COCKPIT_CANVAS(600); if (cockpit != NULL) { cockpitViewscreen = CreateWindowExA( 0, "STATIC", "", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_BLACKRECT, (client_w - view_w) / 2, (client_h - view_h) / 2, view_w, view_h, cockpit, NULL, GetModuleHandleA(NULL), NULL); if (cockpitViewscreen != NULL) { gMainPresentWindow = cockpitViewscreen; } } //--------------------------------------------------------------- // Button banks per display (addresses per vRIO CockpitLayout, // bank-to-display placement per the pod cockpit): // upper left MFD 0x2F.. / upper center 0x27.. / upper right // 0x37.. / lower left 0x0F.. / lower right 0x07.. and the map // flanked by Secondary 0x10-0x15 / Screen 0x18-0x1D. //--------------------------------------------------------------- int top_glass_w = COCKPIT_CANVAS(640); int top_glass_h = COCKPIT_CANVAS(480); int bot_glass_w = COCKPIT_CANVAS(320); int bot_glass_h = COCKPIT_CANVAS(240); int map_glass_w = COCKPIT_CANVAS(240); int map_glass_h = COCKPIT_CANVAS(320); splitView[SplitMFDUpperLeft] = new MFDSplitView( "MFD upper left", init_width, init_height, top_glass_w, top_glass_h, 0, 0, MFDSplitView::MFDStrips, 0x2F, 0, cockpit); splitView[SplitMFDUpperCenter] = new MFDSplitView( "MFD upper center", init_width, init_height, top_glass_w, top_glass_h, 0, 0, MFDSplitView::MFDStrips, 0x27, 0, cockpit); splitView[SplitMFDUpperRight] = new MFDSplitView( "MFD upper right", init_width, init_height, top_glass_w, top_glass_h, 0, 0, MFDSplitView::MFDStrips, 0x37, 0, cockpit); splitView[SplitMFDLowerLeft] = new MFDSplitView( "MFD lower left", init_width, init_height, bot_glass_w, bot_glass_h, 0, 0, MFDSplitView::MFDStrips, 0x0F, 0, cockpit); splitView[SplitMFDLowerRight] = new MFDSplitView( "MFD lower right", init_width, init_height, bot_glass_w, bot_glass_h, 0, 0, MFDSplitView::MFDStrips, 0x07, 0, cockpit); // map is portrait: source rotated 90 degrees clockwise splitView[SplitMap] = new MFDSplitView( "Map", init_height, init_width, map_glass_w, map_glass_h, 0, 0, MFDSplitView::SideColumns, 0x10, 0x18, cockpit); //--------------------------------------------------------------- // Place the panes from their measured sizes: top row edge to // edge across the canvas, bottom cluster on the bottom edge. //--------------------------------------------------------------- if (splitView[SplitMFDUpperLeft] != NULL) { splitView[SplitMFDUpperLeft]->SetPosition(0, 0); } if (splitView[SplitMFDUpperCenter] != NULL) { splitView[SplitMFDUpperCenter]->SetPosition( (client_w - splitView[SplitMFDUpperCenter]->ClientWidth()) / 2, 0); } if (splitView[SplitMFDUpperRight] != NULL) { splitView[SplitMFDUpperRight]->SetPosition( client_w - splitView[SplitMFDUpperRight]->ClientWidth(), 0); } if (splitView[SplitMFDLowerLeft] != NULL) { splitView[SplitMFDLowerLeft]->SetPosition( 0, client_h - splitView[SplitMFDLowerLeft]->ClientHeight()); } if (splitView[SplitMFDLowerRight] != NULL) { splitView[SplitMFDLowerRight]->SetPosition( client_w - splitView[SplitMFDLowerRight]->ClientWidth(), client_h - splitView[SplitMFDLowerRight]->ClientHeight()); } if (splitView[SplitMap] != NULL) { splitView[SplitMap]->SetPosition( (client_w - splitView[SplitMap]->ClientWidth()) / 2, client_h - splitView[SplitMap]->ClientHeight()); } // The panes go OVER the main display (pod bezel occlusion): pin // the viewscreen to the bottom of the sibling z-order so the 3D // present clips around every pane. if (cockpitViewscreen != NULL) { SetWindowPos(cockpitViewscreen, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } // the plasma glass sits out for now PlasmaScreen::Hide(); DEBUG_STREAM << "SVGA16: single-window cockpit assembled (" << client_w << "x" << client_h << " canvas at " << scale_num << "%, viewscreen " << view_w << "x" << view_h << " centered)\n" << std::flush; #undef COCKPIT_CANVAS } //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; ihardwarePort = port_addr[i]; palette_pointer->modified = False; palette_pointer->flashAccumulator = 0.0; palette_pointer->flashRate = 0.0; palette_pointer->previousMaskState = -1; for(j=0; jmask[j] = 0xFF; } /*if (port_addr[i] != 0x3C6) { SVGAZeroPalette(port_addr[i]); }*/ } //--------------------------------------------------------- // Prepare update values //--------------------------------------------------------- currentPageNumber = -1; ResetUpdatePosition(); # if defined(BLIT_STATISTICS) dirtyPixelCount = 0; transferPixelCount = 0; overflowPixelCount = 0; # endif //--------------------------------------------------------- // Clear the display //--------------------------------------------------------- # if defined(DEBUG) Tell("Valid, drawing rectangle-\n" << std::flush); # endif DrawFilledRectangle( 0, 0xFFFF, GraphicsDisplay::Replace, 0, 0, maximumX, maximumY ); # if defined(DEBUG) Tell("About to update-\n" << std::flush); # endif Update(False); Check_Fpu(); mDisplayToUpdate = 0; } SVGA16::~SVGA16() { for (int i=0; i < NUMGAUGEWINDOWS; i++) { if (mSurfaces[i * 2] != NULL) { mSurfaces[i * 2]->Release(); mSurfaces[i * 2] = NULL; } if (mSurfaces[i * 2 + 1] != NULL) { mSurfaces[i * 2 + 1]->Release(); mSurfaces[i * 2 + 1] = NULL; } if (mDevice[i] != NULL) { mDevice[i]->Release(); mSurfaces[i] = NULL; } DestroyWindow(gaugeWindows[i]); } //STUBBED: VIDEO RB 1/15/07 # if defined(DEBUG) Tell("SVGA16::~SVGA16()\n"); # endif Check(this); //--------------------------------------------------------- // Eventually wait for fade (if any) to complete?? //--------------------------------------------------------- //--------------------------------------------------------- // Set video mode //--------------------------------------------------------- //SVGASetMode(3, 0); # if defined(BLIT_STATISTICS) double ratio; if (transferPixelCount == 0) { ratio = (double) 0; } else { ratio = ((double) dirtyPixelCount) / transferPixelCount; } //------------------------------------------------------ // Print statistics //------------------------------------------------------ DEBUG_STREAM << "SVGA16::~SVGA16: pixel management statistics ------------" << "\nNumber of dirty pixels =" << dirtyPixelCount << "\nNumber of transferred pixels=" << transferPixelCount << "\nTimes overflowed =" << overflowPixelCount << "\nRatio =" << ratio << "\n-------------------------------------------------------\n"; # endif //--------------------------------------------------------- // Set VWE video splitter clock divider //--------------------------------------------------------- //SVGASetSplitterClock(False); for (int view = 0; view < SplitViewCount; ++view) { delete splitView[view]; splitView[view] = NULL; } if (cockpitViewscreen != NULL) { if (gMainPresentWindow == cockpitViewscreen) { gMainPresentWindow = NULL; } DestroyWindow(cockpitViewscreen); cockpitViewscreen = NULL; } Check_Fpu(); } Logical SVGA16::TestInstance() const { return Video16BitBuffered::TestInstance(); } void SVGA16::ShowInstance(char *indent) { std::cout << indent << "SVGA16:\n"; char temp[80]; Str_Copy(temp,indent, 80); Str_Cat(temp,"...", 80); std::cout << temp << "SVGA16:\n"; Video16BitBuffered::ShowInstance(temp); Check_Fpu(); } int GetShiftAmount(DWORD mask) { int amount = -1; while (mask) { mask >>= 1; amount++; } return amount; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Render one MFD's bit-slice of the shared canvas into its split-view // window as a green screen. The mask arrives in the duplicated // (mask | mask<<16) form the packed path uses. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void SVGA16::FillSplitMFD( SplitViewID view, DWORD mask, int shift ) { if (splitView[view] == NULL) { return; } Word mask16 = (Word)(mask & 0xFFFF); Word max_value = (Word)(mask16 >> shift); if (max_value == 0) { return; } Word *source = pixelBuffer.Data.MapPointer; unsigned long *dest = splitView[view]->Pixels(); int count = pixelBuffer.Data.Size.x * pixelBuffer.Data.Size.y; for (int i = 0; i < count; ++i) { unsigned long value = (unsigned long)((*source++ & mask16) >> shift); unsigned long green = (value * 255ul) / max_value; *dest++ = green << 8; } splitView[view]->Repaint(); } Logical SVGA16::Update(Logical forceAll) { HRESULT hr; GaugeRenderer *renderer = application->GetGaugeRenderer(); if (!valid || renderer == NULL) { CLEAR_SCREEN_COPY(); return False; // Do no more! } if (++mDisplayToUpdate >= NUMGAUGEWINDOWS) mDisplayToUpdate = 0; //Top MFD's L4GraphicsPort *UL = static_cast(renderer->GetGraphicsPort("auxUL2")); L4GraphicsPort *Cent = static_cast(renderer->GetGraphicsPort("auxC")); L4GraphicsPort *UR = static_cast(renderer->GetGraphicsPort("auxUR2")); //Bottom MFD's L4GraphicsPort *LL = static_cast(renderer->GetGraphicsPort("auxLL")); L4GraphicsPort *LR = static_cast(renderer->GetGraphicsPort("auxLR")); //Secondary L4GraphicsPort *secPort = static_cast(renderer->GetGraphicsPort("sec")); DWORD ulMask = 0, ucMask = 0, urMask = 0, llMask = 0, lrMask = 0; int ulMask_sh = 0, ucMask_sh = 0, urMask_sh = 0, llMask_sh = 0, lrMask_sh = 0; int secMask = 0; SVGA16Palette *secPalette = NULL; if (this->mDisplayToUpdate == 1 || this->mDisplayToUpdate == 2) { //Drawing MFD's... make sure we have MFDs to draw if (UL != NULL && Cent != NULL && UR != NULL && LL != NULL && LR != NULL) { ulMask = UL->GetBitMask(); ulMask_sh = GetShiftAmount(ulMask); ulMask |= (ulMask << 16); ucMask = Cent->GetBitMask(); ucMask_sh = GetShiftAmount(ucMask); ucMask |= (ucMask << 16); urMask = UR->GetBitMask(); urMask_sh = GetShiftAmount(urMask); urMask |= (urMask << 16); llMask = LL->GetBitMask(); llMask_sh = GetShiftAmount(llMask); llMask |= (llMask << 16); lrMask = LR->GetBitMask(); lrMask_sh = GetShiftAmount(lrMask); lrMask |= (lrMask << 16); } else { //No MFDs to draw, break out early return False; } } else { //Drawing secondary, make sure we got secondary if (secPort != NULL) { secMask = secPort->GetBitMask(); secPalette = &((SVGA16 *) secPort->graphicsDisplay)->palette[secPort->paletteID]; } else { //No secondary, skip return False; } } //------------------------------------------------------------------ // Split views: render this window's displays into their own desktop // windows, straight from the shared canvas (CPU-side, no D3D). //------------------------------------------------------------------ if (splitViews) { if (mDisplayToUpdate == 0) { if (splitView[SplitMap] != NULL) { // Map is portrait-mounted: rotate 90 degrees clockwise. // dest(x,y) = source(row = srcH-1-x, col = y) Word *source_base = pixelBuffer.Data.MapPointer; unsigned long *dest = splitView[SplitMap]->Pixels(); int src_w = pixelBuffer.Data.Size.x; int src_h = pixelBuffer.Data.Size.y; for (int dy = 0; dy < src_w; ++dy) { for (int dx = 0; dx < src_h; ++dx) { Word pixel = source_base[(src_h - 1 - dx) * src_w + dy]; PaletteTriplet *entry = &secPalette->paletteData.Color[pixel & secMask]; *dest++ = ((unsigned long) entry->Red << 16) | ((unsigned long) entry->Green << 8) | ((unsigned long) entry->Blue); } } splitView[SplitMap]->Repaint(); } } else if (mDisplayToUpdate == 1) { FillSplitMFD(SplitMFDUpperLeft, ulMask, ulMask_sh); FillSplitMFD(SplitMFDUpperCenter, ucMask, ucMask_sh); FillSplitMFD(SplitMFDUpperRight, urMask, urMask_sh); if (NUMGAUGEWINDOWS < 3) { // spanning mode: the lower MFDs ride this window too FillSplitMFD(SplitMFDLowerLeft, llMask, llMask_sh); FillSplitMFD(SplitMFDLowerRight, lrMask, lrMask_sh); } } else { FillSplitMFD(SplitMFDLowerLeft, llMask, llMask_sh); FillSplitMFD(SplitMFDLowerRight, lrMask, lrMask_sh); } } Word *data = pixelBuffer.Data.MapPointer; D3DLOCKED_RECT rect; if (FAILED(mSurfaces[mDisplayToUpdate * 2]->LockRect(0, &rect, NULL, mLockFlags[mDisplayToUpdate]))) { DEBUG_STREAM << "Failed to lock texture for display " << mDisplayToUpdate << "!" << std::endl << std::flush; } else { switch(mDisplayToUpdate) { case 0: { //Secondary Word *source = data; Word *dest = (Word*)rect.pBits; int postRowIncrement = (rect.Pitch / 2) - pixelBuffer.Data.Size.x; for (int y = 0; y < pixelBuffer.Data.Size.y; y++) { for (int x = 0; x < pixelBuffer.Data.Size.x; x++) { PaletteTriplet *paletteEntry = &(secPalette->paletteData.Color[*source & secMask]); *dest = ((paletteEntry->Red >> 3) << 11) | ((paletteEntry->Green >> 2) << 5) | ((paletteEntry->Blue >> 3)); dest++; source++; } dest += postRowIncrement; } } break; case 2: { //HACK - set the upper mask to be the lower mask (so that we draw the lower MFDs to the window) //and then drop through and draw like the upper stuff ulMask = llMask; ucMask = lrMask; urMask = 0; ulMask_sh = llMask_sh; ucMask_sh = lrMask_sh; urMask_sh = 0; } case 1: { DWORD *sourceData = (DWORD*)data; DWORD *destData = (DWORD*)rect.pBits; int leftWidth = pixelBuffer.Data.Size.x/2; int postRowIncrement = (rect.Pitch / sizeof(DWORD)) - leftWidth; for (int y = 0; y < pixelBuffer.Data.Size.y; y++) { for (int x=0; x < leftWidth; x++) { *destData = (((*sourceData & ulMask) >> ulMask_sh) * 0xF800) | (((*sourceData & ucMask) >> ucMask_sh) * 0x07E0) | (((*sourceData & urMask) >> urMask_sh) * 0x001F); if (NUMGAUGEWINDOWS < 3) { //Only draw if we are in spanning mode *(destData + leftWidth) = (((*sourceData & llMask) >> llMask_sh) * 0xF800) | (((*sourceData & lrMask) >> lrMask_sh) * 0x07E0); } sourceData++; destData++; } destData += postRowIncrement; } break; } } V( mSurfaces[mDisplayToUpdate * 2]->UnlockRect(0) ); V( mDevice[mDisplayToUpdate]->UpdateTexture(mSurfaces[mDisplayToUpdate * 2], mSurfaces[mDisplayToUpdate * 2 + 1]) ); } V( mDevice[mDisplayToUpdate]->BeginScene() ); V( mDevice[mDisplayToUpdate]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1) ); V( mDevice[mDisplayToUpdate]->SetStreamSource(0, mVertBuffers[mDisplayToUpdate], 0, sizeof(float) * 6) ); V( mDevice[mDisplayToUpdate]->SetTexture(0, mSurfaces[mDisplayToUpdate * 2 + 1]) ); V( mDevice[mDisplayToUpdate]->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) ); V( mDevice[mDisplayToUpdate]->EndScene() ); V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) ); if (hr == D3DERR_DEVICELOST) { int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount; int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth; int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight; mSurfaces[mDisplayToUpdate * 2 + 1]->Release(); V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate])); hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL); mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount; mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth; mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight; } // Time end = Now(); // if (end.ticks - start.ticks > 100) // end = start; return False; // True == 'more to do' } void SVGA16::Refresh() { HRESULT hr; V( mDevice[mDisplayToUpdate]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0) ); V( mDevice[mDisplayToUpdate]->BeginScene() ); V( mDevice[mDisplayToUpdate]->EndScene() ); V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) ); if (hr == D3DERR_DEVICELOST) { int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount; int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth; int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight; mSurfaces[mDisplayToUpdate * 2 + 1]->Release(); V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate])); hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL); V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL)); mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount; mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth; mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight; } mDisplayToUpdate++; if (mDisplayToUpdate >= NUMGAUGEWINDOWS) { mDisplayToUpdate = 0; } } //STUBBED: VIDEO RB 1/15/07 // SET_SCREEN_COPY(); // Diag_Tell("SVGA16::Update(" << forceAll << ")\n"); // Check(this); // // //--------------------------------------------------------- // // If pixelbuffer is invalid, do nothing // //--------------------------------------------------------- // if (!valid) // { // CLEAR_SCREEN_COPY(); // return False; // Do no more! // } // //--------------------------------------------------------- // // Mark all lines as changed if commanded // //--------------------------------------------------------- // if (forceAll) // { // memset(changedLine, 1, height); // } // // int // previous_line_number = lineNumber; // // long // dest_size, // dest_line_size; // // //--------------------------------------------------------- // // Calculate sizes based on specialInterface // //--------------------------------------------------------- // if (specialInterface) // { // dest_size = 32L; // BYTE offset! // dest_line_size = width; // } // else // { // dest_size = 32L << 1; // WORD offset! // dest_line_size = width << 1; // } // //--------------------------------------------------------- // // Process lines for as long as we can // //--------------------------------------------------------- //#if 0 // Let's process just a few lines for background loop processing... // while (Get_Frame_Percent_Used() < .65f) //#endif // { // //--------------------------------------------------------- // // Do a couple of lines before checking time again // //--------------------------------------------------------- // for(int line_limit=15; line_limit > 0; ) // { // //--------------------------------------------------------- // // Check for changed line, clear the flag // //--------------------------------------------------------- // Verify(changedLinePointer < &changedLine[height]); // // int // changed_line = *changedLinePointer; // *changedLinePointer++ = 0; // // if (changed_line) // { // Diag_Tell(height << ":"); // //--------------------------------------------------------- // // Pixels on this line have been changed // //--------------------------------------------------------- // --line_limit; // //--------------------------------------------------------- // // Check 'dirty' LWords: if set, scan for changed pixels // //--------------------------------------------------------- // for(int x=0; x= 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= 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; imask[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; iflashRate != 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; imodified) { 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< 0); rate = (255<<5)/((1<> 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< 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(); }