From 77966a45f28ab8cbef979dab13d2cf2e155ffc27 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 7 Mar 2024 19:26:29 +0200 Subject: [PATCH] LDP-1450 character generator emulation. Platoon (Nova) LDP generated message(s?) are now visible. --- arcadia.cpp | 95 ++++++++++++++++- cfgfile.cpp | 3 + include/options.h | 1 + include/specialmonitors.h | 1 + include/statusline.h | 1 + od-win32/statusline_win32.cpp | 189 +++++++++++++++++++++++++++++++++- specialmonitors.cpp | 12 +++ 7 files changed, 298 insertions(+), 4 deletions(-) diff --git a/arcadia.cpp b/arcadia.cpp index 184f860c..ffe9184f 100644 --- a/arcadia.cpp +++ b/arcadia.cpp @@ -717,6 +717,60 @@ static int ld_audio, ld_audio_mute; static bool ld_video; static int ld_vsync; static int alg_hsync_delay; +static uae_u8 ld_uidx_config[3], ld_uidx_offset, ld_uidx_offsetd; +static char ld_uidx_data[32]; +static uae_u8 ld_user_index; + +void genlock_infotext(uae_u8 *d, struct vidbuffer *dst) +{ + if (!ld_user_index) { +#if 0 + int x = 26; + int y = 12; + x -= 12; + y -= 10; + int dx = dst->inwidth * x / (86 - 12); + int dy = dst->inheight * y / (59 - 10); + int mx = 1, my = 1; + mx <<= currprefs.gfx_resolution; + my <<= currprefs.gfx_vresolution; + ldp_render("ABCDE12345ABCDE12345", 20, d, dst, dx, dy, mx ,my); + y += 4; + dy = dst->inheight * y / (59 - 10); + ldp_render("ABCDE12345ABCDE12345", 20, d, dst, dx, dy, mx, my); +#endif + return; + } + int x = ld_uidx_config[0] & 63; + int y = ld_uidx_config[1] & 63; + int mx = (ld_uidx_config[2] & 3) + 1; + int my = ((ld_uidx_config[2] >> 2) & 3) + 1; + bool dm = (ld_uidx_config[2] & 0x10) != 0; + int offset = ld_uidx_offsetd & 31; + int len = 32 - offset; + + x -= 12; + y -= 10; + + int dx = dst->inwidth * x / (86 - 12); + int dy = dst->inheight * y / (59 - 10); + + mx <<= currprefs.gfx_resolution; + my <<= currprefs.gfx_vresolution; + + if (dm) { + ldp_render(ld_uidx_data, 10, d, dst, dx, dy, mx, my); + y += 4; + dy = dst->inheight * y / (59 - 10); + ldp_render(ld_uidx_data + 10, 10, d, dst, dx, dy, mx, my); + y += 4; + dy = dst->inheight * y / (59 - 10); + ldp_render(ld_uidx_data + 20, 10, d, dst, dx, dy, mx, my); + } else { + ldp_render(ld_uidx_data, 20, d, dst, dx, dy, mx, my); + } + +} static void sb(uae_u8 v) { @@ -735,16 +789,27 @@ static void sony_serial_read(uae_u16 w) w &= 0xff; if (ld_ui >= 0 && ld_ui_cnt >= 0) { - ld_ui_cnt++; if (ld_ui == 0) { + ld_uidx_config[ld_ui_cnt] = (uae_u8)w; + ld_ui_cnt++; if (ld_ui_cnt == 3) { ld_ui = -1; } } else if (ld_ui == 1) { + if (ld_ui_cnt == 0) { + ld_uidx_offset = (uae_u8)w; + } else { + int idx = ld_uidx_offset & 31; + ld_uidx_data[idx] = (uae_u8)w; + ld_uidx_offset++; + } + ld_ui_cnt++; if (ld_ui_cnt >= 34 || (ld_ui_cnt > 1 && w == 0x1a)) { ld_ui = -1; } } else if (ld_ui == 2) { + ld_uidx_offsetd = (uae_u8)w; + ld_ui_cnt++; ld_ui = -1; } ack(); @@ -1039,11 +1104,13 @@ static void sony_serial_read(uae_u16 w) write_log("LD: USER INDEX\n"); break; case 0x81: // USER INDEX ON + ld_user_index = 1; ack(); if (log_ld) write_log("LD: USER INDEX ON\n"); break; case 0x82: // USER INDEX OFF + ld_user_index = 0; ack(); if (log_ld) write_log(_T("LD: USER INDEX OFF\n")); @@ -1452,6 +1519,13 @@ void alg_map_banks(void) alg_hsync_delay = 0; arcadia_hsync_cnt = 0; ld_ui = -1; + ld_user_index = 0; + ld_uidx_config[0] = 0; + ld_uidx_config[1] = 0; + ld_uidx_config[2] = 0; + ld_uidx_offset = 0; + ld_uidx_offsetd = 0; + memset(ld_uidx_data, 0, sizeof(ld_uidx_data)); } } @@ -1483,6 +1557,15 @@ uae_u8 *restore_alg(uae_u8 *src) alg_ser_buf[i] = restore_u8(); } ld_vsync = restore_u32(); + ld_user_index = restore_u8(); + ld_uidx_config[0] = restore_u8(); + ld_uidx_config[1] = restore_u8(); + ld_uidx_config[2] = restore_u8(); + ld_uidx_offset = restore_u8(); + ld_uidx_offsetd = restore_u8(); + for (int i = 0; i < 32; i++) { + ld_uidx_data[i] = restore_u8(); + } return src; } @@ -1520,7 +1603,15 @@ uae_u8 *save_alg(size_t *len) save_u8(alg_ser_buf[i]); } save_u32(ld_vsync); - + save_u8(ld_user_index); + save_u8(ld_uidx_config[0]); + save_u8(ld_uidx_config[1]); + save_u8(ld_uidx_config[2]); + save_u8(ld_uidx_offset); + save_u8(ld_uidx_offsetd); + for (int i = 0; i < 32; i++) { + save_u8(ld_uidx_data[i]); + } *len = dst - dstbak; return dstbak; } diff --git a/cfgfile.cpp b/cfgfile.cpp index 3a9f8447..33e4b56c 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -2561,6 +2561,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_dwrite_strarr(f, _T("genlockmode"), genlockmodes, p->genlock_image); cfgfile_dwrite_str(f, _T("genlock_image"), p->genlock_image_file); cfgfile_dwrite_str(f, _T("genlock_video"), p->genlock_video_file); + cfgfile_dwrite_str(f, _T("genlock_font"), p->genlock_font); cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix); cfgfile_dwrite(f, _T("genlock_scale"), _T("%d"), p->genlock_scale); cfgfile_dwrite(f, _T("genlock_offset_x"), _T("%d"), p->genlock_offset_x); @@ -6028,6 +6029,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH || cfgfile_path(option, value, _T("picassoiv_rom_file"), p->picassoivromfile, sizeof p->picassoivromfile / sizeof(TCHAR), &p->path_rom) || cfgfile_string(option, value, _T("genlock_image"), p->genlock_image_file, sizeof p->genlock_image_file / sizeof(TCHAR)) || cfgfile_string(option, value, _T("genlock_video"), p->genlock_video_file, sizeof p->genlock_video_file / sizeof(TCHAR)) + || cfgfile_string(option, value, _T("genlock_font"), p->genlock_font, sizeof p->genlock_font / sizeof(TCHAR)) || cfgfile_string(option, value, _T ("pci_devices"), p->pci_devices, sizeof p->pci_devices / sizeof(TCHAR)) || cfgfile_string (option, value, _T("ghostscript_parameters"), p->ghostscript_parameters, sizeof p->ghostscript_parameters / sizeof (TCHAR))) return 1; @@ -8808,6 +8810,7 @@ static void buildin_default_prefs (struct uae_prefs *p) p->genlock = 0; p->genlock_image = 0; p->genlock_image_file[0] = 0; + p->genlock_font[0] = 0; p->ne2000pciname[0] = 0; p->ne2000pcmcianame[0] = 0; diff --git a/include/options.h b/include/options.h index 06da514a..6cbdaddd 100644 --- a/include/options.h +++ b/include/options.h @@ -634,6 +634,7 @@ struct uae_prefs { bool genlock_alpha; TCHAR genlock_image_file[MAX_DPATH]; TCHAR genlock_video_file[MAX_DPATH]; + TCHAR genlock_font[MAX_DPATH]; int monitoremu; int monitoremu_mon; float chipset_refreshrate; diff --git a/include/specialmonitors.h b/include/specialmonitors.h index 7afc98b3..e67e3f02 100644 --- a/include/specialmonitors.h +++ b/include/specialmonitors.h @@ -13,6 +13,7 @@ bool specialmonitor_autoconfig_init(struct autoconfig_info*); bool emulate_genlock(struct vidbuffer*, struct vidbuffer*, bool); bool emulate_grayscale(struct vidbuffer*, struct vidbuffer*); bool specialmonitor_linebased(void); +void genlock_infotext(uae_u8*, struct vidbuffer*); const TCHAR *specialmonitorfriendlynames[]; const TCHAR *specialmonitormanufacturernames[]; diff --git a/include/statusline.h b/include/statusline.h index 48f9790c..21cf9eee 100644 --- a/include/statusline.h +++ b/include/statusline.h @@ -54,5 +54,6 @@ const TCHAR *statusline_fetch(void); int statusline_set_multiplier(int, int, int); int statusline_get_multiplier(int monid); void statusline_set_font(const char *newnumbers, int width, int height); +void ldp_render(const char *txt, int len, uae_u8 *buf, struct vidbuffer*, int x, int y, int mx, int my); #endif /* UAE_STATUSLINE_H */ diff --git a/od-win32/statusline_win32.cpp b/od-win32/statusline_win32.cpp index 703e5f7d..123049dd 100644 --- a/od-win32/statusline_win32.cpp +++ b/od-win32/statusline_win32.cpp @@ -49,6 +49,144 @@ void deletestatusline(int monid) statusline_palette = NULL; } + +static char *ldp_font_bitmap; +static int ldp_font_width, ldp_font_height; + +static void create_ldp_font(HWND parent) +{ + HDC hdc; + LPLOGPALETTE lp; + HPALETTE hpal; + BITMAPINFO *bi; + BITMAPINFOHEADER *bih; + HBITMAP bitmap = NULL; + int width = 128; + int height = 128; + int fontsize, fontweight; + void *bm; + const TCHAR *fn; + + xfree(ldp_font_bitmap); + + if (currprefs.genlock_image != 6 && currprefs.genlock_image != 7 && currprefs.genlock_image != 8) { + return; + } + + fontsize = 20; + fontweight = FW_NORMAL; + fn = statusline_fontname; + if (currprefs.genlock_font[0]) { + fn = currprefs.genlock_font; + } + + hdc = CreateCompatibleDC(NULL); + if (hdc) { + lp = (LOGPALETTE *)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY)); + if (lp) { + lp->palNumEntries = 4; + lp->palVersion = 0x300; + lp->palPalEntry[1].peBlue = lp->palPalEntry[1].peGreen = lp->palPalEntry[0].peRed = 0x10; + lp->palPalEntry[2].peBlue = lp->palPalEntry[2].peGreen = lp->palPalEntry[2].peRed = 0xff; + lp->palPalEntry[3].peBlue = lp->palPalEntry[3].peGreen = lp->palPalEntry[3].peRed = 0x7f; + hpal = CreatePalette(lp); + if (hpal) { + SelectPalette(hdc, hpal, FALSE); + bi = (BITMAPINFO *)xcalloc(uae_u8, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD)); + if (bi) { + bih = &bi->bmiHeader; + bih->biSize = sizeof(BITMAPINFOHEADER); + bih->biWidth = width; + bih->biHeight = -height; + bih->biPlanes = 1; + bih->biBitCount = 8; + bih->biCompression = BI_RGB; + bih->biClrUsed = 4; + bih->biClrImportant = 4; + bi->bmiColors[1].rgbBlue = bi->bmiColors[1].rgbGreen = bi->bmiColors[1].rgbRed = 0x10; + bi->bmiColors[2].rgbBlue = bi->bmiColors[2].rgbGreen = bi->bmiColors[2].rgbRed = 0xff; + bi->bmiColors[3].rgbBlue = bi->bmiColors[3].rgbGreen = bi->bmiColors[3].rgbRed = 0x7f; + bitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bm, NULL, 0); + if (bitmap) { + SelectObject(hdc, bitmap); + RealizePalette(hdc); + HFONT font = CreateFont(-fontsize, 0, + 0, 0, + fontweight, + 0, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_TT_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH | FF_DONTCARE, + statusline_fontname); + if (font) { + SelectObject(hdc, font); + SetTextColor(hdc, PALETTEINDEX(2)); + SetBkColor(hdc, PALETTEINDEX(1)); + TEXTMETRIC tm; + GetTextMetrics(hdc, &tm); + int w = 0; + int h = tm.tmAscent + 2; + int total = 128 - 32; + for (int i = 32; i < 128; i++) { + SIZE sz; + TCHAR ch = i; + if (GetTextExtentPoint32(hdc,&ch, 1, &sz)) { + if (sz.cx > w) + w = sz.cx; + } + } + int offsetx = 10; + int offsety = 10 - 1; + int fxd = fontsize - w; + if (fxd >= 1) { + fxd -= 1; + offsetx -= fxd / 2; + w += fxd / 2; + if (offsetx < 0) { + offsetx = 0; + } + } + ldp_font_bitmap = xcalloc(char, w * h * total); + if (ldp_font_bitmap) { + for (int i = 32; i < 128; i++) { + TCHAR ch = i; + SetBkMode(hdc, OPAQUE); + BitBlt(hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS); + TextOut(hdc, 10, 10, &ch, 1); + char *dst = ldp_font_bitmap + (i - 32) * w * h; + for (int y = 0; y < h; y++) { + uae_u8 *src = (uae_u8 *)bm + (y + offsety) * width + offsetx; + for (int x = 0; x < w; x++) { + uae_u8 b = *src++; + if (b == 2) { + *dst = 'x'; + } + dst++; + } + } + } + ldp_font_width = w; + ldp_font_height = h; + } + DeleteObject(font); + } + DeleteObject(bitmap); + } + xfree(bi); + } + DeleteObject(hpal); + } + xfree(lp); + } + ReleaseDC(NULL, hdc); + } +} + + static void create_led_font(HWND parent, int monid) { HDC hdc; @@ -204,6 +342,7 @@ bool createstatusline(HWND parentHwnd, int monid) return false; create_led_font(parentHwnd, monid); + create_ldp_font(parentHwnd); lp = (LOGPALETTE*)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY)); if (!lp) @@ -275,7 +414,7 @@ void statusline_render(int monid, uae_u8 *buf, int bpp, int pitch, int width, in { struct AmigaMonitor *mon = &AMonitors[monid]; uae_u32 white = rc[0xff] | gc[0xff] | bc[0xff] | (alpha ? alpha[0xff] : 0); - uae_u32 back = rc[0x00] | gc[0x00] | bc[0x00] | (alpha ? alpha[0xa0] : 0); + uae_u32 black = rc[0x00] | gc[0x00] | bc[0x00] | (alpha ? alpha[0xa0] : 0); const TCHAR *text; int y = 0, x = 10, textwidth = 0; int bar_xstart; @@ -316,9 +455,55 @@ void statusline_render(int monid, uae_u8 *buf, int bpp, int pitch, int width, in if (b == 2) *dst2 = white; else if (b == 1) - *dst2 = back; + *dst2 = black; } dst2++; } } } + +void ldp_render(const char *txt, int len, uae_u8 *buf, struct vidbuffer *vd, int dx, int dy, int mx, int my) +{ + if (!ldp_font_bitmap) { + return; + } + int bpp = vd->pixbytes; + uae_u32 white = 0xffffff; + uae_u8 *dbuf2 = buf + dy * vd->rowbytes + dx * bpp; + for (int i = 0; i < len; i++) { + uae_u8 *dbuf = dbuf2 + i * ldp_font_width * mx * bpp; + char ch = *txt++; + if (ch >= 32) { + ch -= 32; + } else { + ch = 0; + } + char *font = ldp_font_bitmap + ch * ldp_font_width * ldp_font_height; + for (int y = 0; y < ldp_font_height; y++) { + for (int mmy = 0; mmy < my; mmy++) { + char *font2 = font; + for (int x = 0; x < ldp_font_width; x++) { + if (*font2) { + for (int mmx = 0; mmx < mx; mmx++) { + int xx = x * mx + mmx; + if (dy + y * my + mmy >= 0 && dy + y * my + mmy < vd->inheight) { + if (dx + xx >= 0 && dx + xx < vd->inwidth) { + dbuf[xx * bpp + 0] = 0xff; + dbuf[xx * bpp + 1] = 0xff; + if (bpp == 4) { + dbuf[xx * bpp + 2] = 0xff; + dbuf[xx * bpp + 3] = 0xff; + } + } + } + } + } + font2++; + } + dbuf += vd->rowbytes; + } + font += ldp_font_width; + } + dx += ldp_font_width; + } +} diff --git a/specialmonitors.cpp b/specialmonitors.cpp index 302b5e45..ed7b02c7 100755 --- a/specialmonitors.cpp +++ b/specialmonitors.cpp @@ -2615,6 +2615,9 @@ skip: vblank_bottom_stop <<= vdbl; vblank_top_start <<= vdbl; + bool first = true; + uae_u8 *firstdstline = NULL; + uae_u8 r = 0, g = 0, b = 0, a = 0; for (y = ystart; y < yend; y++) { int yoff = ((y * 2 + oddlines) - src->yoffset) >> vdbl; @@ -2640,6 +2643,10 @@ skip: uae_u8 *s = line; uae_u8 *d = dstline; uae_u8 *s_genlock = line_genlock; + if (first) { + firstdstline = dstline; + first = false; + } int hwidth = 0; for (x = 0; x < src->inwidth; x++) { uae_u8 *s2 = s + src->rowbytes; @@ -2687,6 +2694,11 @@ skip: } } } + + if (firstdstline) { + firstdstline += hblank_left_start * dst->pixbytes; + genlock_infotext(firstdstline, dst); + } dst->nativepositioning = true; return true; -- 2.47.3