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