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