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