I'm new to wine and relatively new to windows programming being mostly
a unix hack. Just for yucks I thought I'd get a relatively simple app
emu48 to work. Turns out emu48 is not so simple (multi-threaded,
etc.). First task towards functionality is to get the boot up display
to look right and a BitBlt didn't seem to be functioning correctly.
Much investigation later it turns out that in the file dib.c:
/* if the source bitmap is 8bpp or less, we're supposed to use the
* DC's palette for color conversion (not the DIB color table) */
is NOT true at least not for my case where the DC containing the
bitmap has one palette and the colormap for the bitmap is not the
same. If I disable the hPalette tests as I did below and always use
the DIB colormap it boots up with the correct display
otherwise the color mapping doesn't match the DIB bits and I get
garbage.
if (dib.dsBm.bmBitsPixel <= 8) {
HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL
);
if (/*!hPalette || (hPalette ==
GetStockObject(DEFAULT_PALETTE))*/1) {
/* HACK: no palette has been set in the source DC,
* use the DIB colormap instead - this is necessary in some
* cases since we need to do depth conversion in some places
* where real Windows can just copy data straight over */
colorMap = physBitmap->colorMap;
nColorMap = physBitmap->nColorMap;
} else {
colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
dib.dsBm.bmBitsPixel,
(BITMAPINFO*)&dib.dsBmih,
&nColorMap );
if (colorMap) aColorMap = TRUE;
}
}
Not knowing the full ramifications of this code I thought I'd pass
this along so that someone more familiar with it can reassess
it.
The DC and bitmap are created thusly:
#if defined GRAYSCALE
#define NOCOLORS 8
#else
#define NOCOLORS 2
#endif
static struct
{
BITMAPINFOHEADER Lcd_bmih;
RGBQUAD bmiColors[NOCOLORS];
} bmiLcd =
{
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,NOCOLORS,0}
};
VOID CreateLcdBitmap(VOID)
{
// create LCD bitmap
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
bmiLcd.Lcd_bmih.biWidth = LCD_ROW * nLcdDoubled;
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
_ASSERT(hLcdDC == NULL);
hLcdDC = CreateCompatibleDC(hWindowDC);
_ASSERT(hLcdDC != NULL);
hLcdBitmap = CreateDIBSection(hLcdDC,
(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
_ASSERT(hLcdBitmap != NULL);
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
_ASSERT(hPalette != NULL);
SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC
RealizePalette(hLcdDC); // realize palette
BuildPattern(); // build Nibble -> DIB
mask pattern
UpdateContrast(Chipset.contrast);
return;
}
Note that update contrast doe a SetDIBColorTable:
VOID UpdateContrast(BYTE byContrast)
{
#if defined GRAYSCALE
INT i;
RGBQUAD c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
RGBQUAD b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&b)
b = *(RGBQUAD*)&dwKMLColor[0];
// fill color palette of bitmap
for (i = 0; i < ARRAYSIZEOF(bmiLcd.bmiColors); ++i)
{
const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
_ASSERT(i < ARRAYSIZEOF(bmiLcd.bmiColors));
_ASSERT(i < ARRAYSIZEOF(nCAdj));
bmiLcd.bmiColors[i] = b;
bmiLcd.bmiColors[i].rgbRed += (((INT) c.rgbRed - (INT)
b.rgbRed) * nCAdj[i] / 3);
bmiLcd.bmiColors[i].rgbGreen += (((INT) c.rgbGreen - (INT)
b.rgbGreen) * nCAdj[i] / 3);
bmiLcd.bmiColors[i].rgbBlue += (((INT) c.rgbBlue - (INT)
b.rgbBlue) * nCAdj[i] / 3);
}
#else
bmiLcd.bmiColors[1] = *(RGBQUAD*)&dwKMLColor[byContrast]; //
pixel on color
bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[byContrast+32]; //
pixel off color
if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I ==
*(DWORD*)&bmiLcd.bmiColors[0])
bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[0];
#endif
// update palette information
_ASSERT(hLcdDC);
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
return;
}
The BitBlt:
BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled,
hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY);
As emu48 still doesn't work I'll probably have more things I find in
likely much different areas later.
Dave