/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OVGABUF.CPP
//Description : OVGABUF direct draw surface class
#include
#include
#include
#include
#include
#include
#include
//-------- Begin of function VgaBuf::VgaBuf ----------//
VgaBuf::VgaBuf()
{
memset( this, 0, sizeof(VgaBuf) );
}
//-------- End of function VgaBuf::VgaBuf ----------//
//-------- Begin of function VgaBuf::~VgaBuf ----------//
VgaBuf::~VgaBuf()
{
deinit();
}
//-------- End of function VgaBuf::~VgaBuf ----------//
//-------- Begin of function VgaBuf::init_front ----------//
//
// Create a direct draw front buffer.
//
void VgaBuf::init_front(LPDIRECTDRAW2 ddPtr)
{
DDSURFACEDESC ddsd;
HRESULT rc;
DDCAPS ddcaps;
//------ Get Direct Draw capacity info --------//
ddcaps.dwSize = sizeof( ddcaps );
if( ddPtr->GetCaps( &ddcaps, NULL ) != DD_OK )
err.run( "Error creating Direct Draw front surface!" );
//---------------------------------------------//
// Create the Front Buffer
//---------------------------------------------//
ZeroMemory( &ddsd, sizeof(ddsd) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
LPDIRECTDRAWSURFACE dd1Buf;
rc = ddPtr->CreateSurface( &ddsd, &dd1Buf, NULL );
if( rc != DD_OK )
err.run( "Error creating Direct Draw front surface!" );
rc = dd1Buf->QueryInterface(IID_IDirectDrawSurface2, (void **)&dd_buf);
if( rc != DD_OK )
{
dd1Buf->Release();
err.run ( "Error creating Direct Draw front surface!!" );
}
dd1Buf->Release();
is_front = 1;
}
//-------- End of function VgaBuf::init_front ----------//
//-------- Begin of function VgaBuf::init_back ----------//
//
// Create a direct draw back buffer.
//
// [DWORD] w : width of the surface [default 0 : VGA_WIDTH]
// [DWORD] h : height of the surface [default 0 : VGA_HEIGHT]
//
void VgaBuf::init_back( LPDIRECTDRAW2 ddPtr, DWORD w, DWORD h )
{
DDSURFACEDESC ddsd;
HRESULT rc;
//--------- fill in surface desc -----------//
memset( &ddsd, 0, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = w ? w : VGA_WIDTH;
ddsd.dwHeight = h ? h : VGA_HEIGHT;
LPDIRECTDRAWSURFACE dd1Buf;
rc = ddPtr->CreateSurface( &ddsd, &dd1Buf, NULL );
if( rc != DD_OK )
err.run( "Error creating direct draw back surface!" );
rc = dd1Buf->QueryInterface(IID_IDirectDrawSurface2, (void **)&dd_buf);
if( rc != DD_OK )
{
dd1Buf->Release();
err.run( "Error creating direct draw back surface!!" );
}
dd1Buf->Release();
}
//-------- End of function VgaBuf::init_back ----------//
//------ Begin of function VgaBuf::deinit --------//
void VgaBuf::deinit()
{
if( dd_buf )
{
dd_buf->Release();
dd_buf = NULL;
}
}
//-------- End of function VgaBuf::deinit ----------//
//-------- Begin of function VgaBuf::activate_pal ----------//
//
// Activate a palette to the current direct draw surface buffer.
//
void VgaBuf::activate_pal(LPDIRECTDRAWPALETTE ddPalPtr)
{
err_when(!ddPalPtr || !dd_buf);
HRESULT rc = dd_buf->SetPalette(ddPalPtr);
if( rc == DDERR_SURFACELOST )
{
dd_buf->Restore();
rc = dd_buf->SetPalette(ddPalPtr);
}
#ifdef DEBUG
if( rc != DD_OK )
debug_msg( "VgaBuf::activate_pal(), failed activating the palette" );
#endif
}
//--------- End of function VgaBuf::activate_pal ----------//
//-------- Begin of function VgaBuf::color_match ----------//
DWORD VgaBuf::color_match(COLORREF rgb)
{
COLORREF rgbT;
HDC hdc;
DWORD dw = CLR_INVALID;
DDSURFACEDESC ddsd;
HRESULT hres;
if( dd_buf->GetDC(&hdc) == DD_OK )
{
rgbT = GetPixel(hdc, 0, 0);
SetPixel(hdc, 0, 0, rgb);
dd_buf->ReleaseDC(hdc);
}
ddsd.dwSize = sizeof(ddsd);
hres = dd_buf->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
if (hres == DD_OK)
{
dw = *(DWORD *)ddsd.lpSurface;
dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
dd_buf->Unlock(NULL);
}
if (dd_buf->GetDC(&hdc) == DD_OK)
{
SetPixel(hdc, 0, 0, rgbT);
dd_buf->ReleaseDC(hdc);
}
return dw;
}
//-------- End Endof function VgaBuf::color_match ----------//
//-------- Begin of function VgaBuf::is_buf_lost ----------//
//
BOOL VgaBuf::is_buf_lost()
{
return dd_buf && dd_buf->IsLost() == DDERR_SURFACELOST;
}
//--------- End of function VgaBuf::is_buf_lost ----------//
//-------- Begin of function VgaBuf::restore_buf ----------//
//
// Restore buffers that have been lost.
//
BOOL VgaBuf::restore_buf()
{
if( dd_buf == NULL || dd_buf->Restore() != DD_OK )
{
#ifdef DEBUG
debug_msg("Error restoring direct draw buffer");
#endif
return FALSE;
}
return TRUE;
}
//--------- End of function VgaBuf::restore_buf ----------//
//------------- Begin of function VgaBuf::lock_buf --------------//
void VgaBuf::lock_buf()
{
err_if( buf_locked )
err_now( "VgaBuf::lock_buf() error, buffer already locked." );
memset( &buf_des, 0, sizeof(buf_des) );
buf_des.dwSize = sizeof(buf_des);
int rc = dd_buf->Lock(NULL, &buf_des, DDLOCK_WAIT, NULL);
cur_buf_ptr = (char*) buf_des.lpSurface;
//--------------------------------------//
if( rc==DD_OK )
buf_locked = TRUE;
else
{
if( is_front )
err_now( "VgaBuf::lock_buf() locking front buffer failed." );
else
err_now( "VgaBuf::lock_buf() locking back buffer failed." );
#ifdef DEBUG
debug_msg( "Failed to lock the buffer." );
#endif
}
}
//--------------- End of function VgaBuf::lock_buf --------------//
//------------- Begin of function VgaBuf::unlock_buf --------------//
void VgaBuf::unlock_buf()
{
// ####### begin Gilbert 16/9 #####//
if( !dd_buf )
return;
// ####### end Gilbert 16/9 #####//
err_when( !buf_locked );
int rc = dd_buf->Unlock(NULL);
if( rc==DD_OK )
buf_locked = FALSE;
else
{
switch(rc)
{
case DDERR_INVALIDOBJECT:
err_now( "VgaBuf::unlock_buf error: DDERR_INVALIDOBJECT" );
case DDERR_INVALIDPARAMS:
err_now( "VgaBuf::unlock_buf error: DDERR_INVALIDPARAMS" );
case DDERR_INVALIDRECT:
err_now( "VgaBuf::unlock_buf error: DDERR_INVALIDRECT" );
case DDERR_NOTLOCKED:
err_now( "VgaBuf::unlock_buf error: DDERR_NOTLOCKED" );
case DDERR_SURFACELOST:
err_now( "VgaBuf::unlock_buf error: DDERR_SURFACELOST" );
}
if( is_front )
err_now( "VgaBuf::unlock_buf() unlocking front buffer failed." );
else
err_now( "VgaBuf::unlock_buf() unlocking back buffer failed." );
#ifdef DEBUG
debug_msg( "Failed to unlock the buffer." );
#endif
}
}
//--------------- End of function VgaBuf::unlock_buf --------------//
//------------- Begin of function VgaBuf::temp_unlock --------------//
//
// Unlock the Vga buffer temporarily.
//
void VgaBuf::temp_unlock()
{
// ######### begin Gilbert 16/9 ########//
save_locked_flag = buf_locked;
if( buf_locked )
unlock_buf();
// ######### end Gilbert 16/9 ########//
}
//--------------- End of function VgaBuf::temp_unlock --------------//
//------------- Begin of function VgaBuf::temp_restore_lock --------------//
//
// Restore the previous lock stage.
//
void VgaBuf::temp_restore_lock()
{
if( save_locked_flag )
lock_buf();
}
//--------------- End of function VgaBuf::temp_restore_lock --------------//
//------------- Begin of function VgaBuf::put_bitmap --------------//
//
// Put a bitmap on the surface buffer
//
void VgaBuf::put_bitmap(int x,int y,char* bitmapPtr)
{
err_when( !buf_locked );
if( is_front )
mouse.hide_area( x, y, x+*((short*)bitmapPtr)-1, y+*(((short*)bitmapPtr)+1)-1 );
IMGblt(buf_ptr(), buf_pitch(), x, y, bitmapPtr);
if( is_front )
mouse.show_area();
}
//--------------- End of function VgaBuf::put_bitmap --------------//
//------- Begin of function VgaBuf::put_bitmap_trans --------//
//
// Put a bitmap on the surface buffer and hide the mouse cursor while displaying
//
void VgaBuf::put_bitmap_trans(int x,int y,char* bitmapPtr)
{
err_when( !buf_locked );
if( is_front )
mouse.hide_area( x, y, x+*((short*)bitmapPtr)-1, y+*(((short*)bitmapPtr)+1)-1 );
IMGbltTrans(buf_ptr(), buf_pitch(), x, y, bitmapPtr);
if( is_front )
mouse.show_area();
}
//--------- End of function VgaBuf::put_bitmap_trans --------//
//------- Begin of function VgaBuf::put_bitmap_remap --------//
//
// Put a bitmap on the surface buffer and hide the mouse cursor while displaying
//
void VgaBuf::put_bitmap_remap(int x,int y,char* bitmapPtr,char *colorTable)
{
err_when( !buf_locked );
if( is_front )
mouse.hide_area( x, y, x+*((short*)bitmapPtr)-1, y+*(((short*)bitmapPtr)+1)-1 );
IMGbltRemap(buf_ptr(), buf_pitch(), x, y, bitmapPtr, colorTable);
if( is_front )
mouse.show_area();
}
//--------- End of function VgaBuf::put_bitmap_remap --------//
//---------- Begin of function VgaBuf::save_area_common_buf ----------//
//
// Save screen area to sys.common_data_buf.
//
void VgaBuf::save_area_common_buf(int x1, int y1, int x2, int y2)
{
err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
long saveSize = sizeof(short)*6 + (x2-x1+1) * (y2-y1+1);
err_if( saveSize > COMMON_DATA_BUF_SIZE )
err_now( "VgaBuf::save_area_common_buf()" );
short* shortPtr = (short*) sys.common_data_buf;
*shortPtr++ = x1;
*shortPtr++ = y1;
*shortPtr++ = x2;
*shortPtr++ = y2;
//-------- read screen ---------//
if( is_front )
mouse.hide_area( x1,y1,x2,y2 ); // if the mouse cursor is in that area, hide it
read_bitmap( x1,y1,x2,y2, (char*) shortPtr );
if( is_front )
mouse.show_area();
}
//------------ End of function VgaBuf::save_area_common_buf ----------//
//---------- Begin of function VgaBuf::rest_area_common_buf ----------//
//
// Restore screen area to the screen from Vga image buffer.
// This screen should be previously saved by save_area()
//
void VgaBuf::rest_area_common_buf()
{
short* shortPtr = (short*) sys.common_data_buf;
int x1 = *shortPtr++;
int y1 = *shortPtr++;
int x2 = *shortPtr++;
int y2 = *shortPtr++;
put_bitmap( x1, y1, (char*) shortPtr );
}
//------------ End of function VgaBuf::rest_area_common_buf ----------//
//---------- Begin of function VgaBuf::save_area ---------//
//
// save_area() differs from save_area() as :
//
// save_area() save the screen to a user-defined buffer.
// save_area() save the screen to the global screen saving buffer in Vga object
//
// x1,y1,x2,y2 = the area of the screen
// [char*] saveScr = the pointer to the previous saved buffer
// (default : initialize a new buffer)
//
char* VgaBuf::save_area(int x1, int y1, int x2, int y2, char* saveScr )
{
err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
long newSize = sizeof(short)*6 + (x2-x1+1) * (y2-y1+1);
saveScr = mem_resize( saveScr, newSize );
short* shortPtr = (short*) saveScr;
*shortPtr++ = x1;
*shortPtr++ = y1;
*shortPtr++ = x2;
*shortPtr++ = y2;
if( is_front )
mouse.hide_area( x1,y1,x2,y2 ); // if the mouse cursor is in that area, hide it
read_bitmap( x1,y1,x2,y2, (char*) shortPtr );
if( is_front )
mouse.show_area();
return saveScr;
}
//------------ End of function VgaBuf::save_area ---------//
//----------- Begin of function VgaBuf::rest_area --------//
//
// Restore previously saved screen
//
// char* saveScr = the previously saved screen
// [int] releaseFlag = whether release the buffer of the saved screen or not
// (default : 1)
//
void VgaBuf::rest_area(char* saveScr, int releaseFlag)
{
int x1,y1,x2,y2;
if( saveScr == NULL )
return;
short* shortPtr = (short*) saveScr;
x1 = *shortPtr++;
y1 = *shortPtr++;
x2 = *shortPtr++;
y2 = *shortPtr++;
err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
put_bitmap( x1, y1, (char*) shortPtr );
if( releaseFlag )
mem_del( saveScr );
}
//------------ End of function VgaBuf::rest_area ----------//
//------------ Begin of function VgaBuf::write_bmp_file --------------//
//
// Load a BMP file into the current VgaBuf DIB object.
//
// fileName - the name of the BMP file.
//
// return : 1-succeeded, 0-failed.
//
int VgaBuf::write_bmp_file(char* fileName)
{
File bmpFile;
bmpFile.file_create(fileName, 1, 0); // 1-handle error, 0-disable variable file size
//------------ Write the file header ------------//
BITMAPFILEHEADER bmpFileHdr;
bmpFileHdr.bfType = 0x4D42; // set the type to "BM"
bmpFileHdr.bfReserved1 = 0;
bmpFileHdr.bfReserved2 = 0;
bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
bmpFileHdr.bfSize = buf_size() + bmpFileHdr.bfOffBits;
bmpFile.file_write(&bmpFileHdr, sizeof(bmpFileHdr));
//------------ Write in the info header -----------//
BITMAPINFOHEADER bmpInfoHdr;
bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biWidth = buf_des.dwWidth;
bmpInfoHdr.biHeight = buf_des.dwHeight;
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = 8;
bmpInfoHdr.biCompression = BI_RGB;
bmpInfoHdr.biSizeImage = buf_size();
bmpInfoHdr.biXPelsPerMeter = 0;
bmpInfoHdr.biYPelsPerMeter = 0;
bmpInfoHdr.biClrUsed = 0;
bmpInfoHdr.biClrImportant = 0;
bmpFile.file_write(&bmpInfoHdr, sizeof(bmpInfoHdr));
//------------ write the color table -----------//
LPDIRECTDRAWPALETTE ddPalettePtr; // get the direct draw surface's palette
dd_buf->GetPalette(&ddPalettePtr);
PALETTEENTRY *palEntries = (PALETTEENTRY*) mem_add( sizeof(PALETTEENTRY)*256 );
ddPalettePtr->GetEntries(0, 0, 256, palEntries);
RGBQUAD *colorTable = (RGBQUAD*) mem_add( sizeof(RGBQUAD)*256 ); // allocate a color table with 256 entries
for( int i=0 ; i<256 ; i++ )
{
colorTable[i].rgbBlue = palEntries[i].peBlue;
colorTable[i].rgbGreen = palEntries[i].peGreen;
colorTable[i].rgbRed = palEntries[i].peRed;
colorTable[i].rgbReserved = 0;
}
bmpFile.file_write(colorTable, sizeof(RGBQUAD)*256);
mem_del(palEntries);
mem_del(colorTable);
//----------- write the bitmap ----------//
for( int y=buf_height()-1 ; y>=0 ; y-- ) // write in reversed order as DIB's vertical order is reversed
bmpFile.file_write(buf_ptr(0,y), buf_width());
//------------ close the file -----------//
bmpFile.file_close();
return 1;
}
//------------ End of function VgaBuf::write_bmp_file --------------//
int VgaBuf::write_bmp_file(char * fileName, int offset_x, int offset_y, int width, int height)
{
if (!width || !height || !offset_x || !offset_y) return 0;
if (offset_x + width > buf_des.dwWidth) return 0;
if (offset_y + width > buf_des.dwHeight) return 0;
File bmpFile;
bmpFile.file_create(fileName, 1, 0); // 1-handle error, 0-disable variable file size
//------------ Write the file header ------------//
BITMAPFILEHEADER bmpFileHdr;
bmpFileHdr.bfType = 0x4D42; // set the type to "BM"
bmpFileHdr.bfReserved1 = 0;
bmpFileHdr.bfReserved2 = 0;
bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256;
bmpFileHdr.bfSize = bmpFileHdr.bfOffBits + width * height;
bmpFile.file_write(&bmpFileHdr, sizeof(bmpFileHdr));
//------------ Write in the info header -----------//
BITMAPINFOHEADER bmpInfoHdr;
bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biWidth = width;
bmpInfoHdr.biHeight = height;
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = 8;
bmpInfoHdr.biCompression = BI_RGB;
bmpInfoHdr.biSizeImage = width * height;
bmpInfoHdr.biXPelsPerMeter = 0;
bmpInfoHdr.biYPelsPerMeter = 0;
bmpInfoHdr.biClrUsed = 0;
bmpInfoHdr.biClrImportant = 0;
bmpFile.file_write(&bmpInfoHdr, sizeof(bmpInfoHdr));
//------------ write the color table -----------//
LPDIRECTDRAWPALETTE ddPalettePtr; // get the direct draw surface's palette
dd_buf->GetPalette(&ddPalettePtr);
PALETTEENTRY *palEntries = (PALETTEENTRY*) mem_add(sizeof(PALETTEENTRY) * 256);
ddPalettePtr->GetEntries(0, 0, 256, palEntries);
RGBQUAD *colorTable = (RGBQUAD*) mem_add(sizeof(RGBQUAD) * 256); // allocate a color table with 256 entries
for (int i = 0; i < 256; i++)
{
colorTable[i].rgbBlue = palEntries[i].peBlue;
colorTable[i].rgbGreen = palEntries[i].peGreen;
colorTable[i].rgbRed = palEntries[i].peRed;
colorTable[i].rgbReserved = 0;
}
bmpFile.file_write(colorTable, sizeof(RGBQUAD) * 256);
mem_del(palEntries);
mem_del(colorTable);
//----------- write the bitmap ----------//
char paddingBytes[4];
for (int y = offset_y + height - 1; y >= offset_y; y--) // write in reversed order as DIB's vertical order is reversed
{
bmpFile.file_write(buf_ptr(offset_x, y), width);
if (width % 4 != 0) bmpFile.file_write(paddingBytes, 4 - (width % 4));
}
//------------ close the file -----------//
bmpFile.file_close();
return 1;
}
//---------- Begin of function VgaBuf::put_large_bitmap ---------//
//
// Put a picture on the screen, when a picture's size is > 64K
// Pass a file pointer to put_large_bitmap() for continously reading the file
//
// Syntax
//
// x, y = the location of the picture on the screen
// filePtr = pointer to the
//
//--------- Format of Picture buffer -------//
//
// int = whether this picture buffer contains the palette or not
// -1 (0xFF) if has, otherwise not
// char[256][3] = VGA color palette
//
// = picture width
// = picture height
//
// char[...] = non-compressed flat picture bitmap
//
//---------------------------------------------//
void VgaBuf::put_large_bitmap(int x1, int y1, File* filePtr)
{
if( filePtr == NULL )
return;
int pictWidth = filePtr->file_get_short();
int hasPalette=0;
//------- read in color palette if this picture has one -----//
/*
if( pictWidth == -1 ) // if the has palette in it
{
//------- set all palette to dark black ------//
ColorPal colorPal;
colorPal.red=0;
colorPal.green=0;
colorPal.blue=0;
palette.set_single(colorPal);
//-------- get the palette of the picture --------//
ColorPal palBuf[256];
filePtr->file_read( palBuf, sizeof(ColorPal)*256 );
palette.set_fade_in(0, 255, palBuf, 15 ); // 15 steps for the whole fade in process, each step 0.01 seconds, 10 steps = 0.1 second
hasPalette=1;
pictWidth = filePtr->file_get_short();
}
*/
//------ read in bitmap and display it --------//
int pictHeight = filePtr->file_get_short();
int x2 = x1 + pictWidth - 1;
int y2 = y1 + pictHeight - 1;
long pictSize = (long) x2 * y2;
err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
//---- if pict size less than 64K, read in the picture in one step ----//
if( pictSize <= COMMON_DATA_BUF_SIZE )
{
filePtr->file_read( sys.common_data_buf, pictSize );
if( is_front )
mouse.hide_area( x1,y1,x2,y2 ); // if the mouse cursor is in that area, hide it
put_bitmap2( x1, y1, pictWidth, pictHeight, sys.common_data_buf );
if( is_front )
mouse.show_area();
}
else //----- if the picture size > 64K, read in line by line -----//
{
int bufferLine = COMMON_DATA_BUF_SIZE / pictWidth; // max. no. of lines can be in the buffer
int ty=y1+bufferLine-1;
if( ty> y2 )
ty=y2;
while( y1<=y2 )
{
filePtr->file_read( sys.common_data_buf, (unsigned)pictWidth * (ty-y1+1) );
if( is_front )
mouse.hide_area( x1,y1,x2,ty ); // if the mouse cursor is in that area, hide it
put_bitmap2( x1, y1, pictWidth, ty-y1+1, sys.common_data_buf );
if( is_front )
mouse.show_area();
y1 += bufferLine;
if( (ty+=bufferLine) > y2 )
ty=y2;
}
}
/*
if( hasPalette )
while( !palette.fade_in() );
*/
}
//----------- End of function VgaBuf::put_large_bitmap --------//
//----------- Begin of function VgaBuf::convert_gray ----------//
//
// Convert an specified area of the bitmap from color to gray-scale.
//
void VgaBuf::convert_gray(int x1, int y1, int x2, int y2)
{
remap_bar(x1, y1, x2, y2, vga.gray_remap_table);
}
//--------- End of function VgaBuf::convert_gray -----------//