From: Toni Wilen Date: Sat, 26 Nov 2011 12:18:54 +0000 (+0200) Subject: 2400b1 X-Git-Tag: 2400~28 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=7bc7fa1a414a35884bec076d8f3f74b06a84c3d7;p=francis%2Fwinuae.git 2400b1 --- diff --git a/specialmonitors.cpp b/specialmonitors.cpp new file mode 100755 index 00000000..1533e370 --- /dev/null +++ b/specialmonitors.cpp @@ -0,0 +1,391 @@ +#include "sysconfig.h" +#include "sysdeps.h" + +#include +#include + +#include "options.h" +#include "xwin.h" +#include "custom.h" + +static bool automatic; +static int monitor; + +extern unsigned int bplcon0; + +static uae_u8 graffiti_palette[256 * 4]; + +static bool graffiti(struct vidbuffer *src, struct vidbuffer *dst) +{ + int y, x; + int ystart, yend, isntsc; + int xstart, xend; + uae_u8 *srcbuf, *srcend; + uae_u8 *dstbuf; + bool command, hires, found; + int xadd, xpixadd, extrapix; + int waitline = 0, dbl; + uae_u8 read_mask = 0xff, color = 0, color2 = 0; + + if (!(bplcon0 & 0x0100)) // GAUD + return false; + + command = true; + found = false; + isntsc = (beamcon0 & 0x20) ? 0 : 1; + if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + isntsc = currprefs.ntscmode ? 1 : 0; + + dbl = gfxvidinfo.ychange == 1 ? 2 : 1; + + ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL; + yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL; + if (src->yoffset >= (ystart << VRES_MAX)) + ystart = src->yoffset >> VRES_MAX; + + xadd = gfxvidinfo.xchange == 1 ? src->pixbytes * 2 : src->pixbytes; + xpixadd = gfxvidinfo.xchange == 1 ? 4 : 2; + + xstart = 0x1c * 2 + 1; + xend = 0xf0 * 2 + 1; + + srcbuf = src->bufmem + (((ystart << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((xstart << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes; + srcend = src->bufmem + (((yend << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes; + extrapix = 0; + + dstbuf = dst->bufmem + (((ystart << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * dst->rowbytes + (((xstart << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * dst->pixbytes; + + y = 0; + while (srcend > srcbuf) { + uae_u8 *srcp = srcbuf + extrapix; + uae_u8 *dstp = dstbuf; + + x = xstart; + while (x < xend) { + + uae_u8 mask = 0x80; + uae_u8 chunky[4] = { 0, 0, 0, 0 }; + while (mask) { + if (srcp[2] & 0x80) // R + chunky[3] |= mask; + if (srcp[1] & 0x80) // G + chunky[2] |= mask; + if (srcp[0] & 0x80) // B + chunky[1] |= mask; + if (srcp[0] & 0x10) // I + chunky[0] |= mask; + srcp += xadd; + mask >>= 1; + } + + if (command) { + if (chunky[0] || chunky[1] || chunky[2] || chunky[3] || found) { + for (int pix = 0; pix < 2; pix++) { + uae_u8 cmd = chunky[pix * 2 + 0]; + uae_u8 parm = chunky[pix * 2 + 1]; + +#if 0 + //if (cmd != 0) + write_log(L"X=%d Y=%d %02x = %02x (%d %d)\n", x, y, cmd, parm, color, color2); +#endif + + if (automatic && cmd >= 0x40) + return false; + if (cmd != 0) + found = true; + if (cmd & 8) { + command = false; + dbl = 1; + waitline = 2; + if (cmd & 16) { + hires = true; + xadd /= 2; + xpixadd /= 2; + extrapix = -4 * src->pixbytes; + } else { + hires = false; + } + } else if (cmd & 4) { + if ((cmd & 3) == 1) { + read_mask = parm; + } else if ((cmd & 3) == 2) { + graffiti_palette[color * 4 + color2] = (parm << 2) | (parm & 3); + color2++; + if (color2 == 3) { + color2 = 0; + color++; + } + } else if ((cmd & 3) == 0) { + color = parm; + color2 = 0; + } + } + } + } + + memset(dstp, 0, dst->pixbytes * 4 * 2); + dstp += dst->pixbytes * 4 * 2; + + } else if (waitline) { + + memset(dstp, 0, dst->pixbytes * 4 * 2); + dstp += dst->pixbytes * 4 * 2; + + } else { + + for (int pix = 0; pix < 4; pix++) { + uae_u8 r, g, b, c; + + c = chunky[pix] & read_mask; + r = graffiti_palette[c * 4 + 0]; + g = graffiti_palette[c * 4 + 1]; + b = graffiti_palette[c * 4 + 2]; + dstp[2] = r; + dstp[1] = g; + dstp[0] = b; + dstp += dst->pixbytes; + dstp[2] = r; + dstp[1] = g; + dstp[0] = b; + dstp += dst->pixbytes; + + if (gfxvidinfo.xchange == 1 && !hires) { + dstp[2] = r; + dstp[1] = g; + dstp[0] = b; + dstp += dst->pixbytes; + dstp[2] = r; + dstp[1] = g; + dstp[0] = b; + dstp += dst->pixbytes; + } + } + + } + + x += xpixadd; + } + + y++; + srcbuf += src->rowbytes * dbl; + dstbuf += dst->rowbytes * dbl; + if (waitline > 0) + waitline--; + } + + dst->nativepositioning = true; + + if (monitor != MONITOREMU_GRAFFITI) { + monitor = MONITOREMU_GRAFFITI; + write_log (L"GRAFFITI %s mode\n", hires ? L"hires" : L"lores"); + } + + return true; +} + +/* A2024 information comes from US patent 4851826 */ + +static bool a2024(struct vidbuffer *src, struct vidbuffer *dst) +{ + int y; + uae_u8 *srcbuf, *dstbuf; + uae_u8 *dataline; + int px, py, doff, pxcnt, dbl; + int panel_width, panel_width_draw, panel_height, srcxoffset; + bool f64, interlace, expand, wpb, less16; + uae_u8 enp, dpl; + bool hires; + int idline; + int total_width, total_height; + + idline = currprefs.ntscmode ? 21 : 29; + + if (src->yoffset > (idline << VRES_MAX)) + return false; + + dbl = gfxvidinfo.ychange == 1 ? 2 : 1; + doff = (128 * 2 / gfxvidinfo.xchange) * src->pixbytes; + // min 178 max 234 + dataline = src->bufmem + (((idline << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((200 << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes; + +#if 0 + write_log (L"%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x\n", + dataline[0 * doff + 0], dataline[0 * doff + 1], dataline[0 * doff + 2], + dataline[1 * doff + 0], dataline[1 * doff + 1], dataline[1 * doff + 2], + dataline[2 * doff + 0], dataline[2 * doff + 1], dataline[2 * doff + 2], + dataline[3 * doff + 0], dataline[3 * doff + 1], dataline[3 * doff + 2]); +#endif + + px = py = 0; + if (dataline[1 * doff + 0] & 0x80) // 1:B FN2 + px |= 2; + if (dataline[1 * doff + 1] & 0x80) // 1:G FN1 + px |= 1; + if (dataline[1 * doff + 2] & 0x80) // 1:R FN0 + py |= 1; + + f64 = (dataline[0 * doff + 2] & 0x80) != 0; // 0:R + interlace = (dataline[0 * doff + 1] & 0x80) != 0; // 0:G (*Always zero) + if ((dataline[0 * doff + 0] & 0x80) != 0) // 0:B = 0 + return false; + if ((dataline[0 * doff + 0] & 0x10) == 0) // 0:I = 1 + return false; + expand = (dataline[1 * doff + 0] & 0x10) != 0; // 1:I (*Always set) + enp = (dataline[2 * doff + 2] & 0x80) ? 1 : 0; // 2:R (*ENP=3) + enp |= (dataline[2 * doff + 1] & 0x80) ? 2 : 0; // 2:G + wpb = (dataline[2 * doff + 0] & 0x80) != 0; // 2:B (*Always zero) + if ((dataline[2 * doff + 0] & 0x10) != 0) // 2:I = 0 + return false; + dpl = (dataline[3 * doff + 2] & 0x80) ? 1 : 0; // 3:R (*DPL=3) + dpl |= (dataline[3 * doff + 1] & 0x80) ? 2 : 0; // 3:G + less16 = (dataline[3 * doff + 0] & 0x80) != 0; // 3:B + if ((dataline[3 * doff + 0] & 0x10) == 0) // 3:I = 1 + return false; + + /* (*) = AOS A2024 driver static bits. Not yet implemented in emulation. */ + + if (f64) { + panel_width = 336; + panel_width_draw = 352; + pxcnt = 3; + hires = false; + srcxoffset = 113; + if (px > 2) + return false; + } else { + panel_width = 512; + panel_width_draw = 512; + pxcnt = 2; + hires = true; + srcxoffset = 129; + if (px > 1) + return false; + } + panel_height = currprefs.ntscmode ? 400 : 512; + + +#if 0 + write_log (L"0 = F6-4:%d INTERLACE:%d\n", f64, interlace); + write_log (L"1 = FN:%d EXPAND:%d\n", py + px *2, expand); + write_log (L"2 = ENP:%d WPB=%d\n", enp, wpb); + write_log (L"3 = DPL:%d LESS16=%d\n", dpl, less16); +#endif +#if 0 + write_log (L"%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %dx%d\n", + dataline[0 * doff + 0], dataline[0 * doff + 1], dataline[0 * doff + 2], + dataline[1 * doff + 0], dataline[1 * doff + 1], dataline[1 * doff + 2], + dataline[2 * doff + 0], dataline[2 * doff + 1], dataline[2 * doff + 2], + dataline[3 * doff + 0], dataline[3 * doff + 1], dataline[3 * doff + 2], + px, py); +#endif + + total_width = panel_width * (pxcnt - 1) + panel_width_draw; + if (total_width > 1024) + total_width = 1024; + if (less16) { + total_width -= 16; + if (px == pxcnt - 1) + panel_width_draw -= 16; + } + total_height = panel_height * dbl; + + srcbuf = src->bufmem + (((44 << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((srcxoffset << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes; + dstbuf = dst->bufmem + py * (panel_height / gfxvidinfo.ychange) * dst->rowbytes + px * ((panel_width * 2) / gfxvidinfo.xchange) * dst->pixbytes; + + for (y = 0; y < (panel_height / (dbl == 1 ? 1 : 2)) / gfxvidinfo.ychange; y++) { +#if 0 + memcpy (dstbuf, srcbuf, ((panel_width * 2) / gfxvidinfo.xchange) * dst->pixbytes); +#else + uae_u8 *srcp = srcbuf; + uae_u8 *dstp1 = dstbuf; + uae_u8 *dstp2 = dstbuf + dst->rowbytes; + int x; + for (x = 0; x < (panel_width_draw * 2) / gfxvidinfo.xchange; x++) { + uae_u8 c1 = 0, c2 = 0; + if (srcp[2] & 0x80) // R + c1 |= 2; + if (srcp[1] & 0x80) // G + c2 |= 2; + if (srcp[0] & 0x80) // B + c1 |= 1; + if (srcp[0] & 0x10) // I + c2 |= 1; + if (dbl == 1) { + c1 = (c1 + c2 + 1) / 2; + c1 = (c1 << 6) | (c1 << 4) | (c1 << 2); + dstp1[0] = c1; + dstp1[1] = c1; + dstp1[2] = c1; + } else { + c1 = (c1 << 6) | (c1 << 4) | (c1 << 2); + c2 = (c2 << 6) | (c2 << 4) | (c2 << 2); + dstp1[0] = c1; + dstp1[1] = c1; + dstp1[2] = c1; + dstp2[0] = c2; + dstp2[1] = c2; + dstp2[2] = c2; + dstp2 += dst->pixbytes; + } + srcp += src->pixbytes; + if (!hires) + srcp += src->pixbytes; + dstp1 += dst->pixbytes; + } +#endif + srcbuf += src->rowbytes * dbl; + dstbuf += dst->rowbytes * dbl; + } + + total_width /= 2; + total_width <<= currprefs.gfx_resolution; + + dst->outwidth = total_width; + dst->outheight = total_height; + dst->inwidth = total_width; + dst->inheight = total_height; + dst->inwidth2 = total_width; + dst->inheight2 = total_height; + dst->nativepositioning = false; + + if (monitor != MONITOREMU_A2024) { + monitor = MONITOREMU_A2024; + write_log (L"A2024 %dHz mode\n", hires ? 10 : 15); + } + + return true; +} + +static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *dst) +{ + if (src->pixbytes != 4) + return false; + + if (currprefs.monitoremu == MONITOREMU_AUTO) { + automatic = true; + bool v = a2024(src, dst); + if (!v) + v = graffiti(src, dst); + return v; + } else if (currprefs.monitoremu == MONITOREMU_A2024) { + automatic = false; + return a2024(src, dst); + } else if (currprefs.monitoremu == MONITOREMU_GRAFFITI) { + automatic = false; + return graffiti(src, dst); + } + return false; +} + + +bool emulate_specialmonitors(struct vidbuffer *src, struct vidbuffer *dst) +{ + if (!emulate_specialmonitors2(src, dst)) { + if (monitor) { + monitor = 0; + write_log (L"Native mode\n"); + } + return false; + } + return true; +}