mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
288 lines
7.0 KiB
C++
288 lines
7.0 KiB
C++
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#if defined(LOGITECHLCD)
|
|
|
|
#include "resource.h"
|
|
#include "gui.h"
|
|
#include "lcd.h"
|
|
#include "threaddep/thread.h"
|
|
#include "uae.h"
|
|
|
|
#include <LogitechLCDLib.h>
|
|
|
|
extern HINSTANCE hInst;
|
|
|
|
static int inited;
|
|
static uae_u8 *mbitmap, *origmbitmap;
|
|
static uae_u32 *cbitmap;
|
|
static uae_u8 *numbers;
|
|
static int bm_width = LOGI_LCD_MONO_WIDTH;
|
|
static int bm_height = LOGI_LCD_MONO_HEIGHT;
|
|
static const int numbers_width = 7, numbers_height = 10;
|
|
static HMODULE lcdlib;
|
|
static volatile int lcd_thread_active;
|
|
static volatile bool lcd_updated;
|
|
int logitech_lcd = 1;
|
|
|
|
extern unsigned long timeframes;
|
|
|
|
// Do it this way because stupid LogitechLCDLib.lib LogiLcdInit() refuses to link.
|
|
|
|
typedef bool(__cdecl *LOGILCDINIT)(wchar_t*, int);
|
|
static LOGILCDINIT pLogiLcdInit;
|
|
typedef bool(__cdecl *LOGILCDISCONNECTED)(int);
|
|
static LOGILCDISCONNECTED pLogiLcdIsConnected;
|
|
typedef bool(__cdecl *LOGILCDSHUTDOWN)(void);
|
|
static LOGILCDSHUTDOWN pLogiLcdShutdown;
|
|
typedef bool(__cdecl *LOGILCDUPDATE)(void);
|
|
static LOGILCDUPDATE pLogiLcdUpdate;
|
|
typedef bool(__cdecl *LOGILCDSETBACKGROUND)(BYTE[]);
|
|
static LOGILCDSETBACKGROUND pLogiLcdMonoSetBackground, pLogiLcdColorSetBackground;
|
|
|
|
#define LOGITECH_LCD_DLL _T("SOFTWARE\\Classes\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary")
|
|
|
|
static void lcd_thread(void *null);
|
|
|
|
void lcd_close (void)
|
|
{
|
|
if (!lcdlib)
|
|
return;
|
|
if (lcd_thread_active > 0) {
|
|
lcd_thread_active = -1;
|
|
while (lcd_thread_active)
|
|
sleep_millis(10);
|
|
}
|
|
|
|
pLogiLcdShutdown();
|
|
xfree(mbitmap);
|
|
mbitmap = NULL;
|
|
xfree(cbitmap);
|
|
cbitmap = NULL;
|
|
xfree(origmbitmap);
|
|
origmbitmap = NULL;
|
|
inited = 0;
|
|
FreeLibrary(lcdlib);
|
|
lcdlib = NULL;
|
|
}
|
|
|
|
static int lcd_init (void)
|
|
{
|
|
HBITMAP bmp;
|
|
BITMAP binfo;
|
|
HDC dc;
|
|
TCHAR path[MAX_DPATH];
|
|
DWORD ret;
|
|
DWORD type = REG_SZ;
|
|
DWORD size = sizeof(path) / sizeof(TCHAR);
|
|
HKEY key;
|
|
|
|
if (!logitech_lcd)
|
|
return 0;
|
|
|
|
lcdlib = NULL;
|
|
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LOGITECH_LCD_DLL, 0, KEY_READ, &key);
|
|
if (ret != ERROR_SUCCESS)
|
|
return 0;
|
|
if (RegQueryValueEx(key, NULL, 0, &type, (LPBYTE)path, &size) == ERROR_SUCCESS) {
|
|
lcdlib = LoadLibrary(path);
|
|
}
|
|
RegCloseKey(key);
|
|
if (!lcdlib)
|
|
return 0;
|
|
|
|
pLogiLcdInit = (LOGILCDINIT)GetProcAddress(lcdlib, "LogiLcdInit");
|
|
pLogiLcdIsConnected = (LOGILCDISCONNECTED)GetProcAddress(lcdlib, "LogiLcdIsConnected");
|
|
pLogiLcdShutdown = (LOGILCDSHUTDOWN)GetProcAddress(lcdlib, "LogiLcdShutdown");
|
|
pLogiLcdUpdate = (LOGILCDUPDATE)GetProcAddress(lcdlib, "LogiLcdUpdate");
|
|
pLogiLcdMonoSetBackground = (LOGILCDSETBACKGROUND)GetProcAddress(lcdlib, "LogiLcdMonoSetBackground");
|
|
pLogiLcdColorSetBackground = (LOGILCDSETBACKGROUND)GetProcAddress(lcdlib, "LogiLcdColorSetBackground");
|
|
if (!pLogiLcdInit || !pLogiLcdIsConnected || !pLogiLcdShutdown || !pLogiLcdUpdate || (!pLogiLcdMonoSetBackground && !pLogiLcdColorSetBackground))
|
|
goto err;
|
|
|
|
if (!pLogiLcdInit(_T("WinUAE"), LOGI_LCD_TYPE_MONO | LOGI_LCD_TYPE_COLOR))
|
|
goto err;
|
|
|
|
bool lcd_mono = pLogiLcdIsConnected(LOGI_LCD_TYPE_MONO);
|
|
bool lcd_color = pLogiLcdIsConnected(LOGI_LCD_TYPE_COLOR);
|
|
if (!lcd_mono && !lcd_color) {
|
|
pLogiLcdShutdown();
|
|
goto err;
|
|
}
|
|
|
|
bmp = LoadBitmap (hInst, MAKEINTRESOURCE(IDB_LCD160X43));
|
|
dc = CreateCompatibleDC (NULL);
|
|
SelectObject (dc, bmp);
|
|
GetObject (bmp, sizeof (binfo), &binfo);
|
|
|
|
cbitmap = xcalloc(uae_u32, LOGI_LCD_COLOR_WIDTH * LOGI_LCD_COLOR_HEIGHT);
|
|
mbitmap = xcalloc(uae_u8, binfo.bmWidth * binfo.bmHeight);
|
|
origmbitmap = xcalloc(uae_u8, binfo.bmWidth * binfo.bmHeight);
|
|
|
|
for (int y = 0; y < binfo.bmHeight; y++) {
|
|
for (int x = 0; x < binfo.bmWidth; x++) {
|
|
mbitmap[y * binfo.bmWidth + x] = GetPixel (dc, x, y) == 0 ? 0xff : 0;
|
|
}
|
|
}
|
|
numbers = mbitmap + bm_width * bm_height;
|
|
memcpy (origmbitmap, mbitmap, bm_width * bm_height);
|
|
DeleteDC (dc);
|
|
|
|
write_log (_T("LCD enabled. Mono=%d Color=%d\n"), lcd_mono, lcd_color);
|
|
|
|
lcd_thread_active = 1;
|
|
uae_start_thread(_T("lcd"), lcd_thread, 0, NULL);
|
|
return 1;
|
|
|
|
err:
|
|
write_log(_T("LCD: Logitech LCD failed to initialize\n"));
|
|
if (lcdlib) {
|
|
FreeLibrary(lcdlib);
|
|
lcdlib = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void makecolorbm(void)
|
|
{
|
|
int yoff = 16;
|
|
for (int y = 0; y < bm_height; y++) {
|
|
for (int x = 0; x < bm_width; x++) {
|
|
uae_u8 c = mbitmap[y * bm_width + x];
|
|
uae_u32 cc = c >= 0x80 ? 0xffffffff : 0x00000000;
|
|
cbitmap[(y * 3 + yoff + 0) * LOGI_LCD_COLOR_WIDTH + x * 2 + 0] = cc;
|
|
cbitmap[(y * 3 + yoff + 0) * LOGI_LCD_COLOR_WIDTH + x * 2 + 1] = cc;
|
|
cbitmap[(y * 3 + yoff + 1) * LOGI_LCD_COLOR_WIDTH + x * 2 + 0] = cc;
|
|
cbitmap[(y * 3 + yoff + 1) * LOGI_LCD_COLOR_WIDTH + x * 2 + 1] = cc;
|
|
cbitmap[(y * 3 + yoff + 2) * LOGI_LCD_COLOR_WIDTH + x * 2 + 0] = cc;
|
|
cbitmap[(y * 3 + yoff + 2) * LOGI_LCD_COLOR_WIDTH + x * 2 + 1] = cc;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void dorect (const int *crd, int inv)
|
|
{
|
|
int yy, xx;
|
|
int x = crd[0], y = crd[1], w = crd[2], h = crd[3];
|
|
for (yy = y; yy < y + h; yy++) {
|
|
for (xx = x; xx < x + w; xx++) {
|
|
uae_u8 b = origmbitmap[yy * bm_width + xx];
|
|
if (inv)
|
|
b = b == 0 ? 0xff : 0;
|
|
mbitmap[yy * bm_width + xx] = b;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void putnumber (int x, int y, int n, int inv)
|
|
{
|
|
int xx, yy;
|
|
uae_u8 *dst, *src;
|
|
if (n == 0)
|
|
n = 9;
|
|
else
|
|
n--;
|
|
if (n < 0)
|
|
n = 10;
|
|
for (yy = 0; yy < numbers_height; yy++) {
|
|
for (xx = 0; xx < numbers_width; xx++) {
|
|
dst = mbitmap + (yy + y) * bm_width + (xx + x);
|
|
src = numbers + n * numbers_width + yy * bm_width + xx;
|
|
*dst = 0;
|
|
if (*src == 0)
|
|
*dst = 0xff;
|
|
if (inv)
|
|
*dst ^= 0xff;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void putnumbers (int x, int y, int num, int inv)
|
|
{
|
|
putnumber (x, y, num < 0 ? num : ((num / 10) > 0 ? num / 10 : -1), inv);
|
|
putnumber (x + numbers_width, y, num < 0 ? num : num % 10, inv);
|
|
}
|
|
|
|
static const int coords[] = {
|
|
53, 2, 13, 10, // CD
|
|
36, 2, 13, 10, // HD
|
|
2, 2, 30, 10 // POWER
|
|
};
|
|
|
|
void lcd_priority(int priority)
|
|
{
|
|
}
|
|
|
|
void lcd_update(int led, int on)
|
|
{
|
|
int track, x, y;
|
|
|
|
if (!inited)
|
|
return;
|
|
|
|
if (led < 0) {
|
|
lcd_updated = true;
|
|
return;
|
|
}
|
|
if (on < 0)
|
|
return;
|
|
|
|
if (led >= 1 && led <= 4) {
|
|
x = 23 + (led - 1) * 40;
|
|
y = 17;
|
|
track = gui_data.drives[led - 1].drive_track;
|
|
if (gui_data.drives[led - 1].drive_disabled) {
|
|
track = -1;
|
|
on = 0;
|
|
}
|
|
putnumbers (x, y, track, on);
|
|
} else if (led == 0) {
|
|
dorect (&coords[4 * 2], on);
|
|
} else if (led == 5) {
|
|
dorect (&coords[4 * 1], on);
|
|
} else if (led == 6) {
|
|
dorect (&coords[4 * 0], on);
|
|
} else if (led == 7) {
|
|
y = 2;
|
|
x = 125;
|
|
putnumbers (x, y, gui_data.fps <= 999 ? (gui_data.fps + 5) / 10 : 99, 0);
|
|
} else if (led == 8) {
|
|
y = 2;
|
|
x = 98;
|
|
putnumbers (x, y, gui_data.idle <= 999 ? gui_data.idle / 10 : 99, 0);
|
|
}
|
|
lcd_updated = true;
|
|
}
|
|
|
|
static void lcd_thread(void *null)
|
|
{
|
|
while (lcd_thread_active > 0) {
|
|
bool c;
|
|
Sleep(10);
|
|
if (lcd_updated) {
|
|
if (pLogiLcdMonoSetBackground)
|
|
c = pLogiLcdMonoSetBackground(mbitmap);
|
|
if (pLogiLcdColorSetBackground) {
|
|
makecolorbm();
|
|
c = pLogiLcdColorSetBackground((uae_u8*)cbitmap);
|
|
}
|
|
c = pLogiLcdUpdate();
|
|
lcd_updated = false;
|
|
}
|
|
}
|
|
lcd_thread_active = 0;
|
|
}
|
|
|
|
int lcd_open (void)
|
|
{
|
|
if (!inited) {
|
|
if (!lcd_init ())
|
|
return 0;
|
|
inited = 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#endif
|