/* * display.c * * This file is part of Emu48 * * Copyright (C) 1995 Sebastien Carlier * */ #include "pch.h" #include "resource.h" #include "Emu48.h" #include "kml.h" #define LCD1_ROW 144 #define LCD2_ROW 288 UINT nBackgroundX = 0; UINT nBackgroundY = 0; UINT nBackgroundW = 0; UINT nBackgroundH = 0; UINT nLcdX = 0; UINT nLcdY = 0; BOOL bLcdDoubled = FALSE; LPBYTE pbyLcd; HDC hLcdDC; HDC hMainDC; static HBITMAP hLcdBitmap; static HBITMAP hMainBitmap; static HBITMAP hOldLcdBitmap; static HBITMAP hOldMainBitmap; #define B 0xFFFFFF #define W 0x000000 static struct { BITMAPINFOHEADER Lcd_bmih; DWORD dwColor[32]; } bmiLcd = { {0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,32,0}, { B,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W, W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W } }; #undef B #undef W static DWORD Pattern4[16]; static DWORD Pattern2[4]; VOID UpdateContrast(BYTE byContrast) { if (bLcdDoubled) { BYTE c = byContrast; Pattern2[0] = 0; Pattern2[1] = (c<<8)|(c); Pattern2[2] = (c<<24)|(c<<16); Pattern2[3] = (c<<24)|(c<<16)|(c<<8)|(c); } else { DWORD c = (DWORD)byContrast; FillMemory(Pattern4, 16*sizeof(DWORD), 0); Pattern4[0x1] = c; Pattern4[0x3] = c; Pattern4[0x5] = c; Pattern4[0x7] = c; Pattern4[0x9] = c; Pattern4[0xB] = c; Pattern4[0xD] = c; Pattern4[0xF] = c; c<<=8; Pattern4[0x2] |= c; Pattern4[0x3] |= c; Pattern4[0x6] |= c; Pattern4[0x7] |= c; Pattern4[0xA] |= c; Pattern4[0xB] |= c; Pattern4[0xE] |= c; Pattern4[0xF] |= c; c<<=8; Pattern4[0x4] |= c; Pattern4[0x5] |= c; Pattern4[0x6] |= c; Pattern4[0x7] |= c; Pattern4[0xC] |= c; Pattern4[0xD] |= c; Pattern4[0xE] |= c; Pattern4[0xF] |= c; c<<=8; Pattern4[0x8] |= c; Pattern4[0x9] |= c; Pattern4[0xA] |= c; Pattern4[0xB] |= c; Pattern4[0xC] |= c; Pattern4[0xD] |= c; Pattern4[0xE] |= c; Pattern4[0xF] |= c; } return; } VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue) { bmiLcd.dwColor[nId&0x1F] = (nRed&0xFF)|((nGreen&0xFF)<<8)|((nBlue&0xFF)<<16); return; } VOID CreateLcdBitmap() { // create LCD bitmap if (bLcdDoubled) { bmiLcd.Lcd_bmih.biWidth = LCD2_ROW; bmiLcd.Lcd_bmih.biHeight = -128; } else { bmiLcd.Lcd_bmih.biWidth = LCD1_ROW; bmiLcd.Lcd_bmih.biHeight = -64; } hLcdDC = CreateCompatibleDC(hWindowDC); hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd, DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0); hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap); UpdateContrast(0x10); } VOID DestroyLcdBitmap() { if (hLcdDC != NULL) { // destroy LCD bitmap SelectObject(hLcdDC, hOldLcdBitmap); DeleteObject(hLcdBitmap); DeleteDC(hLcdDC); hLcdDC = NULL; hLcdBitmap = NULL; hOldLcdBitmap = NULL; } return; } BOOL CreateMainBitmap(LPSTR szFilename) { hMainDC = CreateCompatibleDC(hWindowDC); hMainBitmap = LoadBitmapFile(szFilename); if (hMainBitmap == NULL) { DeleteDC(hMainDC); return FALSE; } hOldMainBitmap = SelectObject(hMainDC, hMainBitmap); SelectPalette(hMainDC, hPalette, FALSE); return TRUE; } VOID DestroyMainBitmap() { if (hMainDC != NULL) { // destroy Main bitmap SelectObject(hMainDC, hOldMainBitmap); DeleteObject(hMainBitmap); DeleteDC(hMainDC); hMainDC = NULL; hMainBitmap = NULL; hOldMainBitmap = NULL; } return; } //**************** //* //* LCD functions //* //**************** VOID UpdateDisplayPointers() { if (Chipset.boffset&4) { Chipset.width = Chipset.loffset + 36; } else { Chipset.width = Chipset.loffset + 34; } Chipset.end1 = Chipset.start1 + (Chipset.lcounter+1)*Chipset.width; if (Chipset.end1 < Chipset.start1) { Chipset.start12 = Chipset.end1; Chipset.end1 = Chipset.start1; } else { Chipset.start12 = Chipset.start1; } Chipset.end2 = Chipset.start2 + (63 - Chipset.lcounter)*34; } static BYTE Buf[36]; static BOOL bScreenIsClean = FALSE; VOID UpdateMainDisplay() { UINT x, y; DWORD d = Chipset.start1; BYTE *p = pbyLcd; if (!Chipset.dispon) { if (!bScreenIsClean) { bScreenIsClean = TRUE; if (bLcdDoubled) FillMemory(pbyLcd, LCD2_ROW*64, 0); else FillMemory(pbyLcd, LCD1_ROW*64, 0); } return; } bScreenIsClean = FALSE; if (bLcdDoubled) { for (y=0; y<=Chipset.lcounter; y++) { Npeek(Buf,d,36); for (x=0; x<36; x++,p+=8) { *((DWORD*)(p+0))=Pattern2[Buf[x]&3]; *((DWORD*)(p+4))=Pattern2[Buf[x]>>2]; } CopyMemory(p, p-LCD2_ROW, LCD2_ROW); p+=LCD2_ROW; d+=Chipset.width; } BitBlt(hWindowDC, nLcdX, nLcdY, 262, (Chipset.lcounter+1)*2, hLcdDC, Chipset.boffset*2, 0, SRCCOPY); } else { for (y=0; y<=Chipset.lcounter; y++) { Npeek(Buf,d,36); for (x=0; x<36; x++,p+=4) *((DWORD*)p)=Pattern4[Buf[x]]; d+=Chipset.width; } BitBlt(hWindowDC, nLcdX, nLcdY, 131, Chipset.lcounter+1, hLcdDC, Chipset.boffset, 0, SRCCOPY); } } VOID UpdateMenuDisplay() { UINT x, y; DWORD d = Chipset.start2; if (!Chipset.dispon) return; if (Chipset.lcounter==0x3F) return; // menu disabled if (bLcdDoubled) { BYTE *p = pbyLcd + ((Chipset.lcounter+1)*2*LCD2_ROW); for (y=Chipset.lcounter+1; y<64; y++) { Npeek(Buf,d,36); for (x=0; x<36; x++,p+=8) { *((DWORD*)(p+0))=Pattern2[Buf[x]&3]; *((DWORD*)(p+4))=Pattern2[Buf[x]>>2]; } CopyMemory(p, p-LCD2_ROW, LCD2_ROW); p+=LCD2_ROW; d+=34; } BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1)*2, 262, (63-Chipset.lcounter)*2, hLcdDC, 0, (Chipset.lcounter+1)*2, SRCCOPY); } else { BYTE *p = pbyLcd + (Chipset.lcounter+1)*LCD1_ROW; for (y=Chipset.lcounter+1; y<64; y++) { Npeek(Buf,d,36); for (x=0; x<36; x++,p+=4) *((DWORD*)p)=Pattern4[Buf[x]]; d+=34; } BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1), 131, 63-Chipset.lcounter, hLcdDC, 0, Chipset.lcounter+1, SRCCOPY); } return; } VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s) { UINT x0, x; UINT y0, y; DWORD *p; if (Chipset.width<0) return; d -= Chipset.start1; y0 = y = d / Chipset.width; x0 = x = d % Chipset.width; if ((x0*4+Chipset.boffset)>=131) return; if (bLcdDoubled) { p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); while (s--) { if (x<36) { p[72] = p[0] = Pattern2[(*a)&3]; p[73] = p[1] = Pattern2[(*a)>>2]; } a++; x++; if ((x==(UINT)Chipset.width)&&s) { x=0; y++; if (y==(Chipset.lcounter+1)) break; p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); } else p+=2; } if (y0!=y) { y++; y0<<=1; y<<=1; BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0, hLcdDC, Chipset.boffset*2, y0, SRCCOPY); } else { x0<<=3; x<<=3; if (x>262) x=262; y0<<=1; y<<=1; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 2, hLcdDC, x0+Chipset.boffset*2, y0, SRCCOPY); } } else { p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); while (s--) { if (x<36) *p = Pattern4[*a]; a++; x++; if ((x==(UINT)Chipset.width)&&s) { x=0; y++; if (y==(Chipset.lcounter+1)) break; p=(DWORD*)(pbyLcd+y*LCD1_ROW); } else p++; } if (y0!=y) { BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, Chipset.boffset, y0, SRCCOPY); } else { x0<<=2; x<<=2; if (x>131) x=131; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 1, hLcdDC, x0+Chipset.boffset, y0, SRCCOPY); } } return; } VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) { UINT x0, x; UINT y0, y; DWORD *p; if (Chipset.width<0) return; if (Chipset.lcounter==0x3F) return; // menu disabled d -= Chipset.start2; y0 = y = (d / 34) + (Chipset.lcounter+1); x0 = x = d % 34; if ((x0*4)>=131) return; if (bLcdDoubled) { p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); while (s--) { if (x<34) { p[72] = p[0] = Pattern2[(*a)&3]; p[73] = p[1] = Pattern2[(*a)>>2]; } a++; x++; if ((x==34)&&s) { x=0; y++; if (y==64) break; p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); } else p+=2; } if (y0!=y) { y0<<=1; y<<=1; BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0+2, hLcdDC, 0, y0, SRCCOPY); } else { x0<<=3; x<<=3; y0<<=1; y<<=1; if (x>262) x=262; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+2, hLcdDC, x0, y0, SRCCOPY); } } else { p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); while (s--) { if (x<34) *p = Pattern4[*a]; a++; x++; if ((x==34)&&s) { x=0; y++; if (y==64) break; p=(DWORD*)(pbyLcd+y*LCD1_ROW); } else p++; } if (y0!=y) { BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, 0, y0, SRCCOPY); } else { x0<<=2; x<<=2; if (x>131) x=131; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+1, hLcdDC, x0, y0, SRCCOPY); } } return; } VOID UpdateAnnunciators() { BYTE c; c = (BYTE)(Chipset.IORam[0xB] | (Chipset.IORam[0xC]<<4)); if (!(c&0x80)) c=0; DrawAnnunciator(1,c&0x01); DrawAnnunciator(2,c&0x02); DrawAnnunciator(3,c&0x04); DrawAnnunciator(4,c&0x08); DrawAnnunciator(5,c&0x10); DrawAnnunciator(6,c&0x20); return; } VOID ResizeWindow() { RECT rectWindow; RECT rectClient; rectWindow.left = 0; rectWindow.top = 0; rectWindow.right = nBackgroundW; rectWindow.bottom = nBackgroundH; AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); SetWindowPos (hWnd, (HWND)NULL, 0, 0, rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, SWP_NOMOVE | SWP_NOZORDER); GetClientRect(hWnd, &rectClient); AdjustWindowRect(&rectClient, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); if (rectClient.bottom < rectWindow.bottom) { rectWindow.bottom += (rectWindow.bottom - rectClient.bottom); SetWindowPos (hWnd, (HWND)NULL, 0, 0, rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, SWP_NOMOVE | SWP_NOZORDER); } InvalidateRect(hWnd,NULL,TRUE); return; }