Sorry about the resend, but I used an old copy of the source
inadvertently.
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 (nLcdDoubled == 2):
#define B 0x00000000
#define W 0x00FFFFFF
#define I 0xFFFFFFFF
static struct
{
BITMAPINFOHEADER Lcd_bmih;
DWORD dwColor[64];
} bmiLcd =
{
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,64,0},
{
W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I
}
};
VOID CreateLcdBitmap(VOID)
{
// create LCD bitmap
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled;
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
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
UpdateContrast(Chipset.contrast);
}
In the new source update contrast doesn't do a SetDIBColorTable
it just plays with the pattern used to write to the dib.
static DWORD Pattern[16];
VOID UpdateContrast(BYTE byContrast)
{
DWORD c = byContrast;
DWORD b = byContrast + 0x20;
if (bmiLcd.dwColor[b] == 0xFFFFFFFF) b = 0;
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 1)
{
WORD i,j;
for (i=0; i<16; ++i)
{
Pattern[i] = 0;
for (j=8; j>0; j>>=1)
{
Pattern[i] = (Pattern[i] << 8) | ((i&j) ? c : b);
}
}
return;
}
c = (c<<8) | c;
b = (b<<8) | b;
if (nLcdDoubled == 2)
{
Pattern[0] = (b<<16)|b;
Pattern[1] = (b<<16)|c;
Pattern[2] = (c<<16)|b;
Pattern[3] = (c<<16)|c;
return;
}
c = (c<<16) | c;
b = (b<<16) | b;
if (nLcdDoubled == 4)
{
Pattern[0] = b;
Pattern[1] = c;
}
return;
}
The BitBlt:
static BYTE Buf[36];
VOID UpdateMainDisplay(VOID)
{
UINT x, y, nLines;
DWORD d = Chipset.start1;
BYTE *p = pbyLcd;
#if defined DEBUG_DISPLAY
{
TCHAR buffer[256];
wsprintf(buffer,_T("%.5lx: Update Main Display\n"),Chipset.pc);
OutputDebugString(buffer);
}
#endif
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (!Chipset.dispon)
{
nLines = 64;
ZeroMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled);
}
else
{
nLines = LINES(Chipset.lcounter); // main display lines
if (nLcdDoubled == 4)
{
for (y = 0; y < nLines; ++y)
{
Npeek(Buf,d,36);
for (x=0; x<36; x++)
{
*(((DWORD*)p)++)=Pattern[Buf[x]&1];
*(((DWORD*)p)++)=Pattern[(Buf[x]>>1) & 1];
*(((DWORD*)p)++)=Pattern[(Buf[x]>>2) & 1];
*(((DWORD*)p)++)=Pattern[(Buf[x]>>3) & 1];
}
CopyMemory(p, p-LCD3_ROW, LCD3_ROW);
p+=LCD3_ROW;
CopyMemory(p, p-LCD3_ROW*2, LCD3_ROW*2);
p+=LCD3_ROW*2;
d+=Chipset.width;
}
}
if (nLcdDoubled == 2)
{
for (y = 0; y < nLines; ++y)
{
Npeek(Buf,d,36);
for (x=0; x<36; x++)
{
*(((DWORD*)p)++)=Pattern[Buf[x]&3];
*(((DWORD*)p)++)=Pattern[Buf[x]>>2];
}
CopyMemory(p, p-LCD2_ROW, LCD2_ROW);
p+=LCD2_ROW;
d+=Chipset.width;
}
}
if (nLcdDoubled == 1)
{
for (y = 0; y < nLines; ++y)
{
Npeek(Buf,d,36);
for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]];
d+=Chipset.width;
}
}
}
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled,
hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY);
GdiFlush();
}
LeaveCriticalSection(&csGDILock);
return;
}
As emu48 still doesn't work I'll probably have more things I find in
likely much different areas later.
Dave