2024-03-19 22:24:30 +01:00
|
|
|
/*
|
|
|
|
* display.c
|
|
|
|
*
|
|
|
|
* This file is part of Emu48
|
|
|
|
*
|
|
|
|
* Copyright (C) 1995 Sebastien Carlier
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "Emu48.h"
|
2024-03-19 22:36:03 +01:00
|
|
|
#include "io.h"
|
2024-03-19 22:24:30 +01:00
|
|
|
#include "kml.h"
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
// #define DEBUG_DISPLAY // switch for DISPLAY debug purpose
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
#define LCD1_ROW 144
|
|
|
|
#define LCD2_ROW 288
|
2024-03-19 22:25:45 +01:00
|
|
|
#define LCD3_ROW 576
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
// main display lines, handle zero lines exception
|
|
|
|
#define LINES(n) ((n == 0) ? 64 : (n+1))
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
UINT nBackgroundX = 0;
|
|
|
|
UINT nBackgroundY = 0;
|
|
|
|
UINT nBackgroundW = 0;
|
|
|
|
UINT nBackgroundH = 0;
|
|
|
|
UINT nLcdX = 0;
|
|
|
|
UINT nLcdY = 0;
|
2024-03-19 22:25:45 +01:00
|
|
|
UINT nLcdDoubled = 1;
|
2024-03-19 22:24:30 +01:00
|
|
|
LPBYTE pbyLcd;
|
2024-03-19 22:25:45 +01:00
|
|
|
HDC hLcdDC = NULL;
|
|
|
|
HDC hMainDC = NULL;
|
2024-03-19 22:24:30 +01:00
|
|
|
static HBITMAP hLcdBitmap;
|
|
|
|
static HBITMAP hMainBitmap;
|
|
|
|
static HBITMAP hOldLcdBitmap;
|
|
|
|
static HBITMAP hOldMainBitmap;
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
#define B 0x00000000
|
|
|
|
#define W 0x00FFFFFF
|
2024-03-19 22:24:30 +01:00
|
|
|
#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
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#undef B
|
|
|
|
#undef W
|
|
|
|
#undef I
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static DWORD Pattern[16];
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
VOID UpdateContrast(BYTE byContrast)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:37:03 +01:00
|
|
|
return;
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2024-03-19 22:37:03 +01:00
|
|
|
return;
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
c = (c<<16) | c;
|
|
|
|
b = (b<<16) | b;
|
|
|
|
|
|
|
|
if (nLcdDoubled == 4)
|
|
|
|
{
|
|
|
|
Pattern[0] = b;
|
|
|
|
Pattern[1] = c;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
|
|
|
|
{
|
|
|
|
bmiLcd.dwColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID CreateLcdBitmap(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
// 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);
|
2024-03-19 22:36:03 +01:00
|
|
|
_ASSERT(hLcdDC != NULL);
|
2024-03-19 22:24:30 +01:00
|
|
|
hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
|
2024-03-19 22:36:03 +01:00
|
|
|
_ASSERT(hLcdBitmap != NULL);
|
2024-03-19 22:24:30 +01:00
|
|
|
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
|
2024-03-19 22:36:03 +01:00
|
|
|
_ASSERT(hPalette != NULL);
|
|
|
|
SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC
|
|
|
|
RealizePalette(hLcdDC); // realize palette
|
2024-03-19 22:25:45 +01:00
|
|
|
UpdateContrast(Chipset.contrast);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID DestroyLcdBitmap(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
WORD i;
|
2024-03-19 22:25:45 +01:00
|
|
|
// clear background colors
|
2024-03-19 22:24:30 +01:00
|
|
|
for (i=32; i< 64; ++i) bmiLcd.dwColor[i] = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
if (hLcdDC != NULL)
|
|
|
|
{
|
|
|
|
// destroy LCD bitmap
|
|
|
|
SelectObject(hLcdDC, hOldLcdBitmap);
|
|
|
|
DeleteObject(hLcdBitmap);
|
|
|
|
DeleteDC(hLcdDC);
|
|
|
|
hLcdDC = NULL;
|
|
|
|
hLcdBitmap = NULL;
|
|
|
|
hOldLcdBitmap = NULL;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
BOOL CreateMainBitmap(LPCTSTR szFilename)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:36:03 +01:00
|
|
|
HPALETTE hAssertPalette;
|
|
|
|
|
|
|
|
_ASSERT(hWindowDC != NULL);
|
2024-03-19 22:24:30 +01:00
|
|
|
hMainDC = CreateCompatibleDC(hWindowDC);
|
2024-03-19 22:36:03 +01:00
|
|
|
_ASSERT(hMainDC != NULL);
|
|
|
|
if (hMainDC == NULL) return FALSE; // quit if failed
|
2024-03-19 22:24:30 +01:00
|
|
|
hMainBitmap = LoadBitmapFile(szFilename);
|
|
|
|
if (hMainBitmap == NULL)
|
|
|
|
{
|
|
|
|
DeleteDC(hMainDC);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
hOldMainBitmap = SelectObject(hMainDC, hMainBitmap);
|
2024-03-19 22:36:03 +01:00
|
|
|
_ASSERT(hPalette != NULL);
|
|
|
|
hAssertPalette = SelectPalette(hMainDC, hPalette, FALSE);
|
|
|
|
_ASSERT(hAssertPalette != NULL);
|
|
|
|
RealizePalette(hMainDC);
|
2024-03-19 22:24:30 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID DestroyMainBitmap(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
if (hMainDC != NULL)
|
|
|
|
{
|
|
|
|
// destroy Main bitmap
|
|
|
|
SelectObject(hMainDC, hOldMainBitmap);
|
|
|
|
DeleteObject(hMainBitmap);
|
|
|
|
DeleteDC(hMainDC);
|
|
|
|
hMainDC = NULL;
|
|
|
|
hMainBitmap = NULL;
|
|
|
|
hOldMainBitmap = NULL;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//****************
|
|
|
|
//*
|
|
|
|
//* LCD functions
|
|
|
|
//*
|
|
|
|
//****************
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID UpdateDisplayPointers(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
UINT nLines = LINES(Chipset.lcounter);
|
|
|
|
|
|
|
|
#if defined DEBUG_DISPLAY
|
|
|
|
{
|
|
|
|
TCHAR buffer[256];
|
|
|
|
wsprintf(buffer,_T("%.5lx: Update Display Pointer\n"),Chipset.pc);
|
|
|
|
OutputDebugString(buffer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
// calculate display width
|
2024-03-19 22:24:30 +01:00
|
|
|
Chipset.width = (34 + Chipset.loffset + (Chipset.boffset / 4) * 2) & 0xFFFFFFFE;
|
2024-03-19 22:37:03 +01:00
|
|
|
Chipset.end1 = Chipset.start1 + nLines * Chipset.width;
|
2024-03-19 22:24:30 +01:00
|
|
|
if (Chipset.end1 < Chipset.start1)
|
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
// calculate first address of main display
|
2024-03-19 22:24:30 +01:00
|
|
|
Chipset.start12 = Chipset.end1 - Chipset.width;
|
2024-03-19 22:25:45 +01:00
|
|
|
// calculate last address of main display
|
2024-03-19 22:24:30 +01:00
|
|
|
Chipset.end1 = Chipset.start1 - Chipset.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Chipset.start12 = Chipset.start1;
|
|
|
|
}
|
2024-03-19 22:37:03 +01:00
|
|
|
Chipset.end2 = Chipset.start2 + (64 - nLines) * 34;
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static BYTE Buf[36];
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID UpdateMainDisplay(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
UINT x, y, nLines;
|
2024-03-19 22:24:30 +01:00
|
|
|
DWORD d = Chipset.start1;
|
|
|
|
BYTE *p = pbyLcd;
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
#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);
|
2024-03-19 22:24:30 +01:00
|
|
|
if (!Chipset.dispon)
|
|
|
|
{
|
|
|
|
nLines = 64;
|
2024-03-19 22:37:03 +01:00
|
|
|
ZeroMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
nLines = LINES(Chipset.lcounter); // main display lines
|
2024-03-19 22:24:30 +01:00
|
|
|
if (nLcdDoubled == 4)
|
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = 0; y < nLines; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 2)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = 0; y < nLines; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 1)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = 0; y < nLines; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
Npeek(Buf,d,36);
|
|
|
|
for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]];
|
|
|
|
d+=Chipset.width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled,
|
|
|
|
hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY);
|
2024-03-19 22:25:45 +01:00
|
|
|
GdiFlush();
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
LeaveCriticalSection(&csGDILock);
|
2024-03-19 22:24:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID UpdateMenuDisplay(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
UINT x, y, nLines;
|
2024-03-19 22:24:30 +01:00
|
|
|
BYTE *p;
|
|
|
|
DWORD d = Chipset.start2;
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
#if defined DEBUG_DISPLAY
|
|
|
|
{
|
|
|
|
TCHAR buffer[256];
|
|
|
|
wsprintf(buffer,_T("%.5lx: Update Menu Display\n"),Chipset.pc);
|
|
|
|
OutputDebugString(buffer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nLines = LINES(Chipset.lcounter);
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
if (!Chipset.dispon) return;
|
2024-03-19 22:37:03 +01:00
|
|
|
if (nLines == 64) return; // menu disabled
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
|
2024-03-19 22:37:03 +01:00
|
|
|
// calculate bitmap offset
|
|
|
|
p = pbyLcd + (nLines*nLcdDoubled*LCD1_ROW*nLcdDoubled);
|
2024-03-19 22:24:30 +01:00
|
|
|
if (nLcdDoubled == 4)
|
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = nLines; y < 64; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
Npeek(Buf,d,34); // 34 nibbles are viewed
|
2024-03-19 22:37:03 +01:00
|
|
|
for (x = 0; x < 36; ++x)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
*(((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+=34;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 2)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = nLines; y < 64; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
Npeek(Buf,d,34); // 34 nibbles are viewed
|
2024-03-19 22:37:03 +01:00
|
|
|
for (x = 0; x < 36; ++x)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
*(((DWORD*)p)++)=Pattern[Buf[x]&3];
|
|
|
|
*(((DWORD*)p)++)=Pattern[Buf[x]>>2];
|
|
|
|
}
|
|
|
|
CopyMemory(p, p-LCD2_ROW, LCD2_ROW);
|
|
|
|
p+=LCD2_ROW;
|
|
|
|
d+=34;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 1)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
for (y = nLines; y < 64; ++y)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
Npeek(Buf,d,34); // 34 nibbles are viewed
|
2024-03-19 22:37:03 +01:00
|
|
|
for (x = 0; x < 36; ++x) *(((DWORD*)p)++)=Pattern[Buf[x]];
|
2024-03-19 22:24:30 +01:00
|
|
|
d+=34;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
BitBlt(hWindowDC, nLcdX, nLcdY+nLines*nLcdDoubled,
|
|
|
|
131*nLcdDoubled, (64-nLines)*nLcdDoubled,
|
|
|
|
hLcdDC, 0, nLines*nLcdDoubled, SRCCOPY);
|
2024-03-19 22:25:45 +01:00
|
|
|
GdiFlush();
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
LeaveCriticalSection(&csGDILock);
|
2024-03-19 22:24:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
|
|
|
{
|
2024-03-19 22:37:03 +01:00
|
|
|
INT x0, x;
|
|
|
|
INT y0, y;
|
|
|
|
DWORD *p;
|
|
|
|
|
|
|
|
INT lWidth = abs(Chipset.width); // display width
|
|
|
|
UINT nLines = LINES(Chipset.lcounter); // main display lines
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
#if defined DEBUG_DISPLAY
|
|
|
|
{
|
|
|
|
TCHAR buffer[256];
|
|
|
|
wsprintf(buffer,_T("%.5lx: Write Main Display %x,%u\n"),Chipset.pc,d,s);
|
|
|
|
OutputDebugString(buffer);
|
|
|
|
}
|
|
|
|
#endif
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
d -= Chipset.start1; // nibble offset to DISPADDR (start of display)
|
|
|
|
d += 64 * lWidth; // make positive offset
|
|
|
|
y0 = abs((INT) d / lWidth - 64); // bitmap row
|
|
|
|
x0 = (INT) d % lWidth; // bitmap coloumn
|
|
|
|
y = y0; x = x0; // load loop variables
|
|
|
|
|
|
|
|
// outside main display area
|
2024-03-19 22:37:03 +01:00
|
|
|
_ASSERT(y0 >= 0 && y0 < (INT) nLines);
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
// illegal zoom factor
|
|
|
|
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
|
|
|
|
|
|
|
|
// calculate memory position in LCD bitmap
|
|
|
|
p = (DWORD*) (pbyLcd + y0*LCD1_ROW*nLcdDoubled*nLcdDoubled
|
|
|
|
+ x0*sizeof(bmiLcd.dwColor[0])*nLcdDoubled);
|
|
|
|
|
|
|
|
while (s--) // loop for nibbles to write
|
|
|
|
{
|
|
|
|
if (x<36) // only fill visible area
|
|
|
|
{
|
|
|
|
if (nLcdDoubled == 4)
|
|
|
|
{
|
|
|
|
p[432] = p[288] = p[144] = p[0] = Pattern[(*a)&1];
|
|
|
|
p[433] = p[289] = p[145] = p[1] = Pattern[((*a)>>1) &1];
|
|
|
|
p[434] = p[290] = p[146] = p[2] = Pattern[((*a)>>2) &1];
|
|
|
|
p[435] = p[291] = p[147] = p[3] = Pattern[((*a)>>3) &1];
|
|
|
|
}
|
|
|
|
if (nLcdDoubled == 2)
|
|
|
|
{
|
|
|
|
p[72] = p[0] = Pattern[(*a)&3];
|
|
|
|
p[73] = p[1] = Pattern[(*a)>>2];
|
|
|
|
}
|
|
|
|
if (nLcdDoubled == 1)
|
|
|
|
{
|
|
|
|
*p = Pattern[*a];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++a; // next value to write
|
|
|
|
++x; // next x position
|
|
|
|
if ((x==lWidth)&&s) // end of display line
|
|
|
|
{
|
|
|
|
// end of main display area
|
2024-03-19 22:37:03 +01:00
|
|
|
if (y == (INT) nLines - 1) break;
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
x = 0; // first coloumn
|
|
|
|
++y; // next row
|
|
|
|
// recalculate bitmap memory position of new line
|
|
|
|
p = (DWORD*) (pbyLcd+y*LCD1_ROW*nLcdDoubled*nLcdDoubled);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
p += nLcdDoubled; // next x position in bitmap
|
|
|
|
}
|
|
|
|
|
|
|
|
// update window region
|
|
|
|
if (y0 != y) // changed more than one line
|
|
|
|
{
|
|
|
|
x0 = 0; // no x-position offset
|
|
|
|
x = 131; // redraw complete lines
|
|
|
|
|
|
|
|
++y; // redraw this line as well
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x0 <<= 2; x <<= 2; // x-position in pixel
|
|
|
|
_ASSERT(x >= x0); // can't draw negative number of pixel
|
|
|
|
x -= x0; // number of pixels to update
|
|
|
|
|
|
|
|
x0 -= Chipset.boffset; // adjust x-position with left margin
|
|
|
|
if (x0 < 0) x0 = 0;
|
|
|
|
|
|
|
|
if (x0 > 131) x0 = 131; // cut right borders
|
|
|
|
if (x+x0 > 131) x = 131 - x0;
|
|
|
|
|
|
|
|
y = y0 + 1; // draw one line
|
|
|
|
}
|
|
|
|
|
|
|
|
x0 <<= nLcdDoubled / 2; // adjust dimensions to pixel size
|
|
|
|
x <<= nLcdDoubled / 2;
|
|
|
|
y0 <<= nLcdDoubled / 2;
|
|
|
|
y <<= nLcdDoubled / 2;
|
|
|
|
|
|
|
|
EnterCriticalSection(&csGDILock);
|
|
|
|
{
|
|
|
|
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x, y-y0, hLcdDC, x0+Chipset.boffset*nLcdDoubled, y0, SRCCOPY);
|
|
|
|
GdiFlush();
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&csGDILock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
|
|
|
{
|
|
|
|
UINT x0, x;
|
|
|
|
UINT y0, y;
|
|
|
|
DWORD *p;
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
UINT nLines = LINES(Chipset.lcounter); // main display lines
|
|
|
|
|
|
|
|
#if defined DEBUG_DISPLAY
|
|
|
|
{
|
|
|
|
TCHAR buffer[256];
|
|
|
|
wsprintf(buffer,_T("%.5lx: Write Menu Display %x,%u\n"),Chipset.pc,d,s);
|
|
|
|
OutputDebugString(buffer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (nLines == 64) return; // menu disabled
|
2024-03-19 22:24:30 +01:00
|
|
|
d -= Chipset.start2;
|
2024-03-19 22:37:03 +01:00
|
|
|
y0 = y = (d / 34) + nLines;
|
2024-03-19 22:24:30 +01:00
|
|
|
x0 = x = d % 34;
|
2024-03-19 22:25:45 +01:00
|
|
|
if (x0 > 32) return; // position out of viewed area
|
2024-03-19 22:24:30 +01:00
|
|
|
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
|
|
|
|
if (nLcdDoubled == 4)
|
|
|
|
{
|
|
|
|
p = (DWORD*)(pbyLcd + y0*LCD3_ROW*4 + x0*16);
|
|
|
|
while (s--)
|
|
|
|
{
|
|
|
|
if (x<34)
|
|
|
|
{
|
|
|
|
p[432] = p[288] = p[144] = p[0] = Pattern[(*a)&1];
|
|
|
|
p[433] = p[289] = p[145] = p[1] = Pattern[((*a)>>1) &1];
|
|
|
|
p[434] = p[290] = p[146] = p[2] = Pattern[((*a)>>2) &1];
|
|
|
|
p[435] = p[291] = p[147] = p[3] = Pattern[((*a)>>3) &1];
|
|
|
|
}
|
|
|
|
a++;
|
|
|
|
x++;
|
|
|
|
if ((x==34)&&s)
|
|
|
|
{
|
|
|
|
x=0;
|
|
|
|
y++;
|
|
|
|
if (y==64) break;
|
|
|
|
p=(DWORD*)(pbyLcd+y*LCD3_ROW*4);
|
|
|
|
} else p+=4;
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
if (y0!=y)
|
|
|
|
{
|
|
|
|
y0<<=2; y<<=2;
|
|
|
|
BitBlt(hWindowDC, nLcdX, nLcdY+y0, 524, y-y0+4, hLcdDC, 0, y0, SRCCOPY);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x0<<=4; x<<=4;
|
|
|
|
y0<<=2; y<<=2;
|
|
|
|
if (x>524) x=524;
|
|
|
|
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+4, hLcdDC, x0, y0, SRCCOPY);
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
GdiFlush();
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
LeaveCriticalSection(&csGDILock);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 2)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8);
|
|
|
|
while (s--)
|
|
|
|
{
|
|
|
|
if (x<34)
|
|
|
|
{
|
|
|
|
p[72] = p[0] = Pattern[(*a)&3];
|
|
|
|
p[73] = p[1] = Pattern[(*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;
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
GdiFlush();
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
LeaveCriticalSection(&csGDILock);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
if (nLcdDoubled == 1)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4);
|
|
|
|
while (s--)
|
|
|
|
{
|
|
|
|
if (x<34) *p = Pattern[*a];
|
|
|
|
a++;
|
|
|
|
x++;
|
|
|
|
if ((x==34)&&s)
|
|
|
|
{
|
|
|
|
x=0;
|
|
|
|
y++;
|
|
|
|
if (y==64) break;
|
|
|
|
p=(DWORD*)(pbyLcd+y*LCD1_ROW);
|
|
|
|
} else p++;
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
GdiFlush();
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
LeaveCriticalSection(&csGDILock);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID UpdateAnnunciators(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
BYTE c;
|
|
|
|
|
2024-03-19 22:36:03 +01:00
|
|
|
c = (BYTE)(Chipset.IORam[ANNCTRL] | (Chipset.IORam[ANNCTRL+1]<<4));
|
|
|
|
// switch annunciators off if timer stopped
|
|
|
|
if ((c & AON) == 0 || (Chipset.IORam[TIMER2_CTRL] & RUN) == 0)
|
2024-03-19 22:37:03 +01:00
|
|
|
c = 0;
|
2024-03-19 22:36:03 +01:00
|
|
|
|
|
|
|
DrawAnnunciator(1,c&LA1);
|
|
|
|
DrawAnnunciator(2,c&LA2);
|
|
|
|
DrawAnnunciator(3,c&LA3);
|
|
|
|
DrawAnnunciator(4,c&LA4);
|
|
|
|
DrawAnnunciator(5,c&LA5);
|
|
|
|
DrawAnnunciator(6,c&LA6);
|
2024-03-19 22:24:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:37:03 +01:00
|
|
|
VOID ResizeWindow(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
RECT rectWindow;
|
|
|
|
RECT rectClient;
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
if (hWnd == NULL) return; // return if window closed
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|