From: Toni Wilen Date: Sat, 1 Oct 2022 16:46:49 +0000 (+0300) Subject: Genlock and screenshot updates. X-Git-Tag: 41000~134 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=f02ee341b4099d3b56ffcecc014ac853cf8ecc66;p=francis%2Fwinuae.git Genlock and screenshot updates. --- diff --git a/custom.cpp b/custom.cpp index 15e4e10e..69cb6807 100644 --- a/custom.cpp +++ b/custom.cpp @@ -9046,6 +9046,29 @@ static void checkautoscalecol0(void) } } +bool get_custom_color_reg(int colreg, uae_u8 *r, uae_u8 *g, uae_u8 *b) +{ + if (colreg >= 32 && !aga_mode) { + return false; + } + if (colreg >= 256 || colreg < 0) { + return false; + } + if (aga_mode) { + *r = (current_colors.color_regs_aga[colreg] >> 16) & 0xFF; + *g = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; + *b = current_colors.color_regs_aga[colreg] & 0xFF; + } else { + *r = (current_colors.color_regs_ecs[colreg] >> 8) & 15; + *r |= (*r) << 4; + *g = (current_colors.color_regs_ecs[colreg] >> 4) & 15; + *g |= (*g) << 4; + *b = (current_colors.color_regs_ecs[colreg] >> 0) & 15; + *b |= (*b) << 4; + } + return true; +} + static void COLOR_WRITE(int hpos, uae_u16 v, int num) { bool colzero = false; diff --git a/drawing.cpp b/drawing.cpp index 77138594..3319581b 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -284,6 +284,7 @@ static int hposblank; static bool ecs_genlock_features_active; static uae_u8 ecs_genlock_features_mask; static bool ecs_genlock_features_colorkey; +static bool aga_genlock_features_zdclken; static int hsync_shift_hack; static bool sprite_smaller_than_64, sprite_smaller_than_64_inuse; static bool full_blank; @@ -3311,18 +3312,22 @@ static void pfield_expand_dp_bplcon(void) sprite_smaller_than_64_inuse = true; sprite_smaller_than_64 = (dp_for_drawing->fmode & 0x0c) != 0x0c; #endif - ecs_genlock_features_active = (ecs_denise && ((dp_for_drawing->bplcon2 & 0x0c00) || ce_is_borderntrans(colors_for_drawing.extra))) || (currprefs.genlock_effects ? 1 : 0); + ecs_genlock_features_active = (ecs_denise && ((dp_for_drawing->bplcon2 & 0x0c00) || ce_is_borderntrans(colors_for_drawing.extra))) || + (currprefs.genlock_effects ? 1 : 0) || (aga_mode && (dp_for_drawing->bplcon3 & 0x004) && (dp_for_drawing->bplcon0 & 1)); if (ecs_genlock_features_active) { - uae_u16 bc2 = dp_for_drawing->bplcon2; ecs_genlock_features_colorkey = currprefs.ecs_genlock_features_colorkey_mask[0] || currprefs.ecs_genlock_features_colorkey_mask[1] || currprefs.ecs_genlock_features_colorkey_mask[2] || currprefs.ecs_genlock_features_colorkey_mask[3]; ecs_genlock_features_mask = currprefs.ecs_genlock_features_plane_mask; - if (bc2 & 0x0800) { - ecs_genlock_features_mask = 1 << ((bc2 >> 12) & 7); + aga_genlock_features_zdclken = false; + if (dp_for_drawing->bplcon2 & 0x0800) { + ecs_genlock_features_mask = 1 << ((dp_for_drawing->bplcon2 >> 12) & 7); } - if (bc2 & 0x0400) { + if (dp_for_drawing->bplcon2 & 0x0400) { ecs_genlock_features_colorkey = true; } + if ((dp_for_drawing->bplcon3 & 0x0004) && (dp_for_drawing->bplcon0 & 1)) { + aga_genlock_features_zdclken = true; + } } if (pfield_mode_changed) @@ -4779,7 +4784,7 @@ static void finish_drawing_frame(bool drawlines) init_row_map(); pfield_set_linetoscr(); } - emulate_genlock(vb, &vidinfo->tempbuffer); + emulate_genlock(vb, &vidinfo->tempbuffer, aga_genlock_features_zdclken); vb = vidinfo->outbuffer = &vidinfo->tempbuffer; if (vb->nativepositioning) setnativeposition(vb); @@ -5189,6 +5194,9 @@ void reset_drawing(void) ad->specialmonitoron = false; bplcolorburst_field = 1; hsync_shift_hack = 0; + ecs_genlock_features_active = false; + aga_genlock_features_zdclken = false; + ecs_genlock_features_colorkey = false; } static void gen_direct_drawing_table(void) diff --git a/include/specialmonitors.h b/include/specialmonitors.h index 90719406..7afc98b3 100644 --- a/include/specialmonitors.h +++ b/include/specialmonitors.h @@ -10,7 +10,7 @@ void specialmonitor_reset(void); bool specialmonitor_need_genlock(void); bool specialmonitor_uses_control_lines(void); bool specialmonitor_autoconfig_init(struct autoconfig_info*); -bool emulate_genlock(struct vidbuffer*, struct vidbuffer*); +bool emulate_genlock(struct vidbuffer*, struct vidbuffer*, bool); bool emulate_grayscale(struct vidbuffer*, struct vidbuffer*); bool specialmonitor_linebased(void); diff --git a/od-win32/avioutput.h b/od-win32/avioutput.h index 52aa8663..bf9713b5 100644 --- a/od-win32/avioutput.h +++ b/od-win32/avioutput.h @@ -12,6 +12,7 @@ extern int avioutput_width, avioutput_height, avioutput_bits; extern int avioutput_framelimiter, avioutput_nosoundoutput; extern int avioutput_nosoundsync, avioutput_originalsize; extern int screenshot_originalsize; +extern int screenshot_paletteindexed; extern int screenshot_clipmode; extern int screenshot_multi; diff --git a/od-win32/clipboard_win32.cpp b/od-win32/clipboard_win32.cpp index 1c5e388c..43901f61 100644 --- a/od-win32/clipboard_win32.cpp +++ b/od-win32/clipboard_win32.cpp @@ -383,7 +383,7 @@ static void to_iff_ilbm(TrapContext *ctx, HBITMAP hbmp) for (y = 0; y < h; y++) { uae_u8 *s = (uae_u8*)(((uae_u8*)bmp.bmBits) + y * bmpw); int b; - for (b = 0; b < 8; b++) { + for (b = 0; b < iffbpp; b++) { int mask2 = 1 << b; for (x = 0; x < w; x++) { int off = x / 8; diff --git a/od-win32/resources/resource.h b/od-win32/resources/resource.h index e481d94c..3c48e294 100644 --- a/od-win32/resources/resource.h +++ b/od-win32/resources/resource.h @@ -972,7 +972,6 @@ #define IDC_UPBM 1650 #define IDC_DISKLISTINSERT 1650 #define IDC_DF1QENABLE 1650 -#define IDC_AVIOUTPUT_ORIGINALSIZE2 1650 #define IDC_SCREENSHOT_ORIGINALSIZE 1650 #define IDC_SOUNDCARDLIST 1651 #define IDC_STATE_BUFFERSIZE2 1651 @@ -981,9 +980,9 @@ #define IDC_SOUNDFREQ 1652 #define IDC_STATEREC_AUTOPLAY 1652 #define IDC_SOUNDFREQTXT 1653 -#define IDC_SCREENSHOT_ORIGINALSIZE2 1653 #define IDC_SCREENSHOT_CLIP 1653 #define IDC_SOUNDFILTERTXT 1654 +#define IDC_SCREENSHOT_PALETTED 1654 #define IDC_SOUNDSTEREO 1655 #define IDC_CONFIGTYPE 1655 #define IDC_SOUNDDRIVETXT 1656 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 0028f7e9..c27bc141 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -877,22 +877,24 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,114,176,10 CONTROL "Disable sound sync",IDC_AVIOUTPUT_NOSOUNDSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,114,171,10 CONTROL "AVI output enabled",IDC_AVIOUTPUT_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,15,129,144,14 - GROUPBOX "Ripper",IDC_STATIC,1,155,393,53 + GROUPBOX "Ripper",IDC_STATIC,1,155,393,65 PUSHBUTTON "Save screenshot",IDC_SCREENSHOT,28,169,87,14 PUSHBUTTON "Pro Wizard 1.62",IDC_PROWIZARD,162,169,87,14,WS_DISABLED CONTROL "Take screenshot before filtering",IDC_SCREENSHOT_ORIGINALSIZE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,192,144,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,192,130,10 CONTROL "Sample ripper",IDC_SAMPLERIPPER_ACTIVATED,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,280,169,87,14 - GROUPBOX "Re-recorder",IDC_STATIC,1,211,393,70 - CONTROL "Play recording",IDC_STATEREC_PLAY,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,53,223,87,14 - CONTROL "Re-recording enabled",IDC_STATEREC_RECORD,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,214,223,118,14 - CONTROL "Automatic replay",IDC_STATEREC_AUTOPLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,246,129,10 - PUSHBUTTON "Save recording",IDC_STATEREC_SAVE,214,241,118,14 - RTEXT "Recording rate (seconds):",IDC_STATIC,15,264,121,10,SS_CENTERIMAGE | WS_TABSTOP - COMBOBOX IDC_STATEREC_RATE,141,262,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - RTEXT "Recording buffers:",IDC_STATIC,195,264,91,10,SS_CENTERIMAGE | WS_TABSTOP - COMBOBOX IDC_STATEREC_BUFFERSIZE,291,262,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - CONTROL "Autoclip screenshot",IDC_SCREENSHOT_CLIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,192,144,10 + GROUPBOX "Re-recorder",IDC_STATIC,1,227,393,70 + CONTROL "Play recording",IDC_STATEREC_PLAY,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,53,239,87,14 + CONTROL "Re-recording enabled",IDC_STATEREC_RECORD,"Button",BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_FLAT,214,239,118,14 + CONTROL "Automatic replay",IDC_STATEREC_AUTOPLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,262,129,10 + PUSHBUTTON "Save recording",IDC_STATEREC_SAVE,214,257,118,14 + RTEXT "Recording rate (seconds):",IDC_STATIC,15,280,121,10,SS_CENTERIMAGE | WS_TABSTOP + COMBOBOX IDC_STATEREC_RATE,141,278,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + RTEXT "Recording buffers:",IDC_STATIC,195,280,91,10,SS_CENTERIMAGE | WS_TABSTOP + COMBOBOX IDC_STATEREC_BUFFERSIZE,291,278,38,65,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "Autoclip screenshot",IDC_SCREENSHOT_CLIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,192,97,10 + CONTROL "Create 256 color palette indexed screenshot if possible",IDC_SCREENSHOT_PALETTED, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,206,231,10 END IDD_INPUT DIALOGEX 0, 0, 396, 316 diff --git a/od-win32/screenshot.cpp b/od-win32/screenshot.cpp index aa2c2d7e..01997513 100644 --- a/od-win32/screenshot.cpp +++ b/od-win32/screenshot.cpp @@ -1,5 +1,6 @@ #define PNG_SCREENSHOTS 1 +#define IFF_SCREENSHOTS 2 #include @@ -25,6 +26,7 @@ int screenshotmode = PNG_SCREENSHOTS; int screenshot_originalsize = 0; +int screenshot_paletteindexed = 0; int screenshot_clipmode = 0; int screenshot_multi = 0; @@ -123,7 +125,9 @@ static int screenshot_prepare(int monid, int imagemode, struct vidbuffer *vb, bo if (!standard) { regqueryint(NULL, _T("Screenshot_Original"), &screenshot_originalsize); + regqueryint(NULL, _T("Screenshot_PaletteIndexed"), &screenshot_paletteindexed); regqueryint(NULL, _T("Screenshot_ClipMode"), &screenshot_clipmode); + regqueryint(NULL, _T("Screenshot_Mode"), &screenshotmode); } else { screenshot_originalsize = 1; screenshot_clipmode = 0; @@ -624,6 +628,168 @@ void Screenshot_RGBinfo (int rb, int gb, int bb, int ab, int rs, int gs, int bs, rgb_as = as; } +extern bool get_custom_color_reg(int colreg, uae_u8 *r, uae_u8 *g, uae_u8 *b); + +static uae_u32 uniquecolors[256] = { 0 }; +static int uniquecolorcount, uniquecolordepth; +static uae_u8 *palettebm; + +static void count_colors(bool alpha) +{ + int h = bi->bmiHeader.biHeight; + int w = bi->bmiHeader.biWidth; + int d = bi->bmiHeader.biBitCount; + uae_u32 customcolors[256] = { 0 }; + bool uniquecolorsa[256] = { 0 }; + bool palettea[256] = { 0 }; + uae_u32 palette[256] = { 0 }; + uae_u8 indextab[256] = { 0 }; + int palettecount = 0; + + uniquecolorcount = 0; + if (d <= 8 || !screenshot_paletteindexed) { + return; + } + if (alpha) { + uniquecolorcount = -1; + return; + } + palettebm = xcalloc(uae_u8, w * h); + if (!palettebm) { + return; + } + for (int i = 0; i < h; i++) { + uae_u8 *p = (uae_u8*)lpvBits + i * ((((w * 24) + 31) & ~31) / 8); + for (int j = 0; j < w; j++) { + uae_u32 co = (p[0] << 16) | (p[1] << 8) | (p[2] << 0); + p += 3; + int c = 0; + if (palettecount >= 1 && co == palette[palettecount - 1]) { + c = palettecount - 1; + } else { + for (c = 0; c < palettecount; c++) { + if (palette[c] == co) { + break; + } + } + } + if (c >= palettecount) { + if (palettecount >= 256) { + // run out of palette slots + write_log("Run out of palette slots when counting colors."); + uniquecolorcount = -1; + xfree(palettebm); + palettebm = NULL; + return; + } + palettea[palettecount] = true; + c = palettecount++; + palette[c] = co; + } + } + } + write_log("Screenshot color count: %d\n", palettecount); + + // get custom colors + int customcolorcnt = 0; + for (int i = 0; i < 256; i++) { + uniquecolors[i] = 0; + uniquecolorsa[i] = false; + uae_u8 r, g, b; + if (get_custom_color_reg(i, &r, &g, &b)) { + uniquecolors[i] = (b << 16) | (g << 8) | r; + customcolorcnt = i + 1; + } + } + // find matching colors from bitmap and allocate colors + int match = 0; + for (int i = 0; i < palettecount; i++) { + if (palettea[i]) { + uae_u32 cc = palette[i]; + for (int j = 0; j < customcolorcnt; j++) { + uae_u32 cc2 = uniquecolors[j]; + if (!uniquecolorsa[i] && cc == cc2) { + uniquecolorsa[i] = true; + if (i >= uniquecolorcount) { + uniquecolorcount = i + 1; + } + palettea[i] = false; + match++; + break; + } + } + } + } + write_log("Screenshot custom register color matches: %d\n", match); + // add remaining colors not yet matched + match = 0; + // use all unused colors if IFF mode to keep total colors as small as possible + // if not iff: try to preserve first 32 colors. + int safecolors = screenshotmode == 2 ? 0 : 32; + if (uniquecolorcount < safecolors) { + uniquecolorcount = safecolors; + } + for (int i = 0; i < 256; i++) { + if (palettea[i]) { + int j = 0; + for (j = safecolors; j < 256 + safecolors; j++) { + int jj = j & 255; + if (!uniquecolorsa[jj]) { + uniquecolors[jj] = palette[i]; + uniquecolorsa[jj] = true; + palettea[i] = false; + if (jj > uniquecolorcount) { + uniquecolorcount = jj + 1; + } + match++; + break; + } + } + if (j >= 256 + safecolors) { + // run out of palette slots + write_log("Run out of palette slots when adding remaining colors."); + uniquecolorcount = -1; + xfree(palettebm); + palettebm = NULL; + return; + } + } + } + write_log("Screenshot non-custom register matched colors: %d\n", match); + // create image + int prevc = -1; + for (int i = 0; i < h; i++) { + uae_u8 *p = (uae_u8 *)lpvBits + i * ((((w * 24) + 31) & ~31) / 8); + uae_u8 *dp = palettebm + w * i; + for (int j = 0; j < w; j++) { + uae_u32 co = (p[0] << 16) | (p[1] << 8) | (p[2] << 0); + p += 3; + int c = 0; + if (prevc >= 0 && co == uniquecolors[prevc]) { + c = prevc; + } else { + for (c = 0; c < uniquecolorcount; c++) { + if (uniquecolors[c] == co) { + prevc = c; + break; + } + } + if (c >= uniquecolorcount) { + c++; + } + } + *dp++ = (uae_u8)c; + } + } + // select depth + uniquecolordepth = 1; + for (int i = 0; i < 8; i++) { + if (uniquecolorcount > (1 << i)) { + uniquecolordepth = i + 1; + } + } +} + #if PNG_SCREENSHOTS > 0 static void _cdecl pngtest_blah (png_structp png_ptr, png_const_charp message) @@ -661,28 +827,44 @@ static int savepng(FILE *fp, bool alpha) return 3; } + count_colors(alpha); png_init_io (png_ptr, fp); png_set_filter (png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR (png_ptr, info_ptr, - w, h, 8, d <= 8 ? PNG_COLOR_TYPE_PALETTE : (alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB), + w, h, 8, uniquecolorcount <= 256 && uniquecolorcount >= 0 ? PNG_COLOR_TYPE_PALETTE : (alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB), PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - if (d <= 8) { - for (i = 0; i < (1 << d); i++) { - pngpal[i].red = bi->bmiColors[i].rgbRed; - pngpal[i].green = bi->bmiColors[i].rgbGreen; - pngpal[i].blue = bi->bmiColors[i].rgbBlue; - } - png_set_PLTE (png_ptr, info_ptr, pngpal, 1 << d); - } row_pointers = xmalloc (png_bytep, h); - for (i = 0; i < h; i++) { - int j = h - i - 1; - row_pointers[i] = (uae_u8*)lpvBits + j * (((w * (d <= 8 ? 8 : (alpha ? 32 : 24)) + 31) & ~31) / 8); + if (palettebm) { + for (i = 0; i < (1 << uniquecolordepth); i++) { + pngpal[i].red = (uniquecolors[i] >> 0) & 0xff; + pngpal[i].green = (uniquecolors[i] >> 8) & 0xff; + pngpal[i].blue = (uniquecolors[i] >> 16) & 0xff; + } + png_set_PLTE(png_ptr, info_ptr, pngpal, 1 << uniquecolordepth); + for (i = 0; i < h; i++) { + int j = h - i - 1; + row_pointers[i] = palettebm + j * w; + } + } else { + if (d <= 8) { + for (i = 0; i < (1 << d); i++) { + pngpal[i].red = bi->bmiColors[i].rgbRed; + pngpal[i].green = bi->bmiColors[i].rgbGreen; + pngpal[i].blue = bi->bmiColors[i].rgbBlue; + } + png_set_PLTE(png_ptr, info_ptr, pngpal, 1 << d); + } + for (i = 0; i < h; i++) { + int j = h - i - 1; + row_pointers[i] = (uae_u8 *)lpvBits + j * (((w * (d <= 8 ? 8 : (alpha ? 32 : 24)) + 31) & ~31) / 8); + } } png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr,info_ptr, PNG_TRANSFORM_BGR, NULL); png_destroy_write_struct (&png_ptr, &info_ptr); xfree (row_pointers); + xfree(palettebm); + palettebm = NULL; return 0; } @@ -695,6 +877,123 @@ static void __cdecl output_flush_fn(png_structp p) { } +static int saveiff(FILE *fp, bool alpha) +{ + const uae_u8 iffilbm[] = { + 'F','O','R','M',0,0,0,0,'I','L','B','M', + 'B','M','H','D',0,0,0,20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 'C','A','M','G',0,0,0, 4, 0,0,0,0, + }; + + count_colors(alpha); + + int h = bi->bmiHeader.biHeight; + int w = bi->bmiHeader.biWidth; + int iffbpp = uniquecolordepth; + if (uniquecolorcount < 0 || uniquecolorcount > 256) { + iffbpp = 24; + } + + int bodysize = (((w + 15) & ~15) / 8) * h * iffbpp; + + int iffsize = sizeof(iffilbm) + (8 + 256 * 3 + 1) + (4 + 4) + bodysize; + uae_u8 *iff = xcalloc(uae_u8, iffsize); + memcpy(iff, iffilbm, sizeof(iffilbm)); + if (!iff) { + return 1; + } + uae_u8 *p = iff + 5 * 4; + // BMHD + p[0] = w >> 8; + p[1] = w; + p[2] = h >> 8; + p[3] = h; + p[8] = iffbpp; + p[14] = 1; + p[15] = 1; + p[16] = w >> 8; + p[17] = w; + p[18] = h >> 8; + p[19] = h; + p = iff + sizeof iffilbm - 4; + // CAMG + if (w > 400) + p[2] |= 0x80; // HIRES + if (h > 300) + p[3] |= 0x04; // LACE + p += 4; + if (iffbpp <= 8) { + int cols = 1 << iffbpp; + int cnt = 0; + memcpy(p, "CMAP", 4); + p[4] = 0; + p[5] = 0; + p[6] = (cols * 3) >> 8; + p[7] = (cols * 3); + p += 8; + for (int i = 0; i < cols; i++) { + *p++ = uniquecolors[i] >> 0; + *p++ = uniquecolors[i] >> 8; + *p++ = uniquecolors[i] >> 16; + cnt += 3; + } + if (cnt & 1) + *p++ = 0; + } + memcpy(p, "BODY", 4); + p[4] = bodysize >> 24; + p[5] = bodysize >> 16; + p[6] = bodysize >> 8; + p[7] = bodysize >> 0; + p += 8; + + if (iffbpp <= 8) { + for (int y = 0; y < h; y++) { + uae_u8 *s = palettebm + ((h - 1) - y) * w; + int b; + for (b = 0; b < iffbpp; b++) { + int mask2 = 1 << b; + for (int x = 0; x < w; x++) { + int off = x / 8; + int mask = 1 << (7 - (x & 7)); + uae_u8 v = s[x]; + if (v & mask2) + p[off] |= mask; + } + p += ((w + 15) & ~15) / 8; + } + } + } else { + for (int y = 0; y < h; y++) { + uae_u32 *s = (uae_u32*)(((uae_u8*)lpvBits) + ((h - 1) - y) * ((w * (alpha ? 32 : 24) + 31) & ~31) / 8); + int b, bb; + for (bb = 0; bb < 3; bb++) { + for (b = 0; b < 8; b++) { + int mask2 = 1 << (((2 - bb) * 8) + b); + for (int x = 0; x < w; x++) { + int off = x / 8; + int mask = 1 << (7 - (x & 7)); + uae_u32 v = s[x]; + if (v & mask2) + p[off] |= mask; + } + p += ((w + 15) & ~15) / 8; + } + } + } + } + + int tsize = (int)(p - iff - 8); + p = iff + 4; + p[0] = tsize >> 24; + p[1] = tsize >> 16; + p[2] = tsize >> 8; + p[3] = tsize >> 0; + fwrite(iff, 1, 8 + tsize + (tsize & 1), fp); + xfree(iff); + return 0; +} + static struct zfile *savepngzfile(bool alpha) { png_structp png_ptr; @@ -726,10 +1025,11 @@ static struct zfile *savepngzfile(bool alpha) return NULL; } + count_colors(alpha); png_set_write_fn(png_ptr, zf, write_data_fn, output_flush_fn); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR(png_ptr, info_ptr, - w, h, 8, d <= 8 ? PNG_COLOR_TYPE_PALETTE : (alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB), + w, h, 8, uniquecolorcount <= 256 && uniquecolorcount >= 0 ? PNG_COLOR_TYPE_PALETTE : (alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB), PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (d <= 8) { for (i = 0; i < (1 << d); i++) { @@ -740,14 +1040,37 @@ static struct zfile *savepngzfile(bool alpha) png_set_PLTE(png_ptr, info_ptr, pngpal, 1 << d); } row_pointers = xmalloc(png_bytep, h); - for (i = 0; i < h; i++) { - int j = h - i - 1; - row_pointers[i] = (uae_u8*)lpvBits + j * (((w * (d <= 8 ? 8 : (alpha ? 32 : 24)) + 31) & ~31) / 8); + if (palettebm) { + for (i = 0; i < (1 << uniquecolordepth); i++) { + pngpal[i].red = (uniquecolors[i] >> 0) & 0xff; + pngpal[i].green = (uniquecolors[i] >> 8) & 0xff; + pngpal[i].blue = (uniquecolors[i] >> 16) & 0xff; + } + png_set_PLTE(png_ptr, info_ptr, pngpal, 1 << uniquecolordepth); + for (i = 0; i < h; i++) { + int j = h - i - 1; + row_pointers[i] = palettebm + j * w; + } + } else { + if (d <= 8) { + for (i = 0; i < (1 << d); i++) { + pngpal[i].red = bi->bmiColors[i].rgbRed; + pngpal[i].green = bi->bmiColors[i].rgbGreen; + pngpal[i].blue = bi->bmiColors[i].rgbBlue; + } + png_set_PLTE(png_ptr, info_ptr, pngpal, 1 << d); + } + for (i = 0; i < h; i++) { + int j = h - i - 1; + row_pointers[i] = (uae_u8 *)lpvBits + j * (((w * (d <= 8 ? 8 : (alpha ? 32 : 24)) + 31) & ~31) / 8); + } } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); xfree(row_pointers); + xfree(palettebm); + palettebm = NULL; return zf; } @@ -823,10 +1146,12 @@ int screenshotf(int monid, const TCHAR *spath, int mode, int doprepare, int imag fp = _tfopen (spath, _T("wb")); if (fp) { #if PNG_SCREENSHOTS > 0 - if (screenshotmode) + if (screenshotmode == 1) failed = savepng (fp, alpha); - else #endif + if (screenshotmode == 2) + failed = saveiff(fp, alpha); + if (screenshotmode == 0) failed = savebmp (fp, alpha); fclose(fp); fp = NULL; @@ -872,7 +1197,7 @@ int screenshotf(int monid, const TCHAR *spath, int mode, int doprepare, int imag while(++filenumber < screenshot_max) { - _stprintf (filename, format, path, name, underline, filenumber, screenshotmode ? _T("png") : _T("bmp")); + _stprintf (filename, format, path, name, underline, filenumber, screenshotmode == 2 ? _T("iff") : (screenshotmode ? _T("png") : _T("bmp"))); if ((fp = _tfopen (filename, _T("rb"))) == NULL) // does file not exist? { int nok = 0; @@ -881,10 +1206,12 @@ int screenshotf(int monid, const TCHAR *spath, int mode, int doprepare, int imag goto oops; // error } #if PNG_SCREENSHOTS > 0 - if (screenshotmode) + if (screenshotmode == 1) nok = savepng (fp, alpha); - else #endif + if (screenshotmode == 2) + nok = saveiff(fp, alpha); + if (screenshotmode == 0) nok = savebmp (fp, alpha); fclose(fp); if (nok && fp) { diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index b4394bfd..71fe152c 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -6567,6 +6567,10 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2) screenshotmode = 0; return 1; } + if (!_tcscmp(arg, _T("screenshotiff"))) { + screenshotmode = 2; + return 1; + } if (!_tcscmp(arg, _T("psprintdebug"))) { postscript_print_debugging = 1; return 1; diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 271a1961..fd5cd910 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -7933,6 +7933,7 @@ static void enable_for_displaydlg (HWND hDlg) static void enable_for_chipsetdlg (HWND hDlg) { int enable = workprefs.cpu_memory_cycle_exact ? FALSE : TRUE; + int genlock = workprefs.genlock || workprefs.genlock_effects; #if !defined (CPUEMU_13) ew (hDlg, IDC_CYCLEEXACT, FALSE); @@ -7945,12 +7946,12 @@ static void enable_for_chipsetdlg (HWND hDlg) } ew(hDlg, IDC_BLITIMM, !workprefs.cpu_cycle_exact); - ew(hDlg, IDC_GENLOCKMODE, workprefs.genlock ? TRUE : FALSE); - ew(hDlg, IDC_GENLOCKMIX, workprefs.genlock ? TRUE : FALSE); - ew(hDlg, IDC_GENLOCK_ALPHA, workprefs.genlock ? TRUE : FALSE); - ew(hDlg, IDC_GENLOCK_KEEP_ASPECT, workprefs.genlock ? TRUE : FALSE); - ew(hDlg, IDC_GENLOCKFILE, workprefs.genlock && (workprefs.genlock_image >= 6 || (workprefs.genlock_image >= 3 && workprefs.genlock_image < 5)) ? TRUE : FALSE); - ew(hDlg, IDC_GENLOCKFILESELECT, workprefs.genlock && (workprefs.genlock_image >= 6 || (workprefs.genlock_image >= 3 && workprefs.genlock_image < 5)) ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCKMODE, genlock ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCKMIX, genlock ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCK_ALPHA, genlock ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCK_KEEP_ASPECT, genlock ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCKFILE, genlock && (workprefs.genlock_image >= 6 || (workprefs.genlock_image >= 3 && workprefs.genlock_image < 5)) ? TRUE : FALSE); + ew(hDlg, IDC_GENLOCKFILESELECT, genlock && (workprefs.genlock_image >= 6 || (workprefs.genlock_image >= 3 && workprefs.genlock_image < 5)) ? TRUE : FALSE); ew(hDlg, IDC_MONITOREMU_MON, workprefs.monitoremu != 0); } @@ -20775,6 +20776,7 @@ static void values_to_avioutputdlg (HWND hDlg) CheckDlgButton (hDlg, IDC_AVIOUTPUT_ORIGINALSIZE, avioutput_originalsize ? TRUE : FALSE); CheckDlgButton (hDlg, IDC_AVIOUTPUT_ACTIVATED, avioutput_requested ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_SCREENSHOT_ORIGINALSIZE, screenshot_originalsize ? TRUE : FALSE); + CheckDlgButton(hDlg, IDC_SCREENSHOT_PALETTED, screenshot_paletteindexed ? TRUE : FALSE); CheckDlgButton(hDlg, IDC_SCREENSHOT_CLIP, screenshot_clipmode ? TRUE : FALSE); CheckDlgButton (hDlg, IDC_SAMPLERIPPER_ACTIVATED, sampleripper_enabled ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton (hDlg, IDC_STATEREC_RECORD, input_record ? BST_CHECKED : BST_UNCHECKED); @@ -20911,6 +20913,7 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP currentpage = AVIOUTPUT_ID; AVIOutput_GetSettings (); regqueryint(NULL, _T("Screenshot_Original"), &screenshot_originalsize); + regqueryint(NULL, _T("Screenshot_PaletteIndexed"), &screenshot_paletteindexed); regqueryint(NULL, _T("Screenshot_ClipMode"), &screenshot_clipmode); enable_for_avioutputdlg (hDlg); if (!avioutput_filename_gui[0]) { @@ -20988,6 +20991,11 @@ static INT_PTR CALLBACK AVIOutputDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LP regsetint(NULL, _T("Screenshot_Original"), screenshot_originalsize); screenshot_reset(); break; + case IDC_SCREENSHOT_PALETTED: + screenshot_paletteindexed = ischecked(hDlg, IDC_SCREENSHOT_PALETTED) ? 1 : 0; + regsetint(NULL, _T("Screenshot_PaletteIndexed"), screenshot_paletteindexed); + screenshot_reset(); + break; case IDC_SCREENSHOT_CLIP: screenshot_clipmode = ischecked(hDlg, IDC_SCREENSHOT_CLIP) ? 1 : 0; regsetint(NULL, _T("Screenshot_ClipMode"), screenshot_clipmode); diff --git a/specialmonitors.cpp b/specialmonitors.cpp index 2feba598..bf2e3472 100755 --- a/specialmonitors.cpp +++ b/specialmonitors.cpp @@ -2397,7 +2397,7 @@ end: return ok; } -static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines) +static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines, bool zclken) { struct vidbuf_description *avidinfo = &adisplays[dst->monitor_id].gfxvidinfo; @@ -2590,6 +2590,7 @@ skip: if (yoff >= src->inheight) continue; + bool ztoggle = false; uae_u8 *line = src->bufmem + yoff * src->rowbytes; uae_u8 *lineprev = yoff > 0 ? src->bufmem + (yoff - 1) * src->rowbytes : NULL; uae_u8 *dstline = dst->bufmem + ((y * 2 + oddlines) - dst->yoffset) * dst->rowbytes; @@ -2604,10 +2605,11 @@ skip: uae_u8 *s = line; uae_u8 *d = dstline; uae_u8 *s_genlock = line_genlock; + int hwidth = 0; for (x = 0; x < src->inwidth; x++) { uae_u8 *s2 = s + src->rowbytes; uae_u8 *d2 = d + dst->rowbytes; - if (is_transparent(*s_genlock)) { + if ((!zclken && is_transparent(*s_genlock)) || (zclken && ztoggle)) { a = amix2; if (genlock_error) { r = 0x00; @@ -2640,6 +2642,12 @@ skip: s += src->pixbytes; d += dst->pixbytes; s_genlock++; + // ZCLKEN hires pixel clock + hwidth += 1 << currprefs.gfx_resolution; + if (hwidth >= 2) { + hwidth = 0; + ztoggle = !ztoggle; + } } } @@ -2647,25 +2655,25 @@ skip: return true; } -bool emulate_genlock(struct vidbuffer *src, struct vidbuffer *dst) +bool emulate_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool zclken) { bool v; if (interlace_seen) { if (currprefs.gfx_iscanlines) { - v = do_genlock(src, dst, false, lof_store ? 0 : 1); + v = do_genlock(src, dst, false, lof_store ? 0 : 1, zclken); if (v && currprefs.gfx_iscanlines > 1) blank_generic(src, dst, lof_store ? 1 : 0); } else { - v = do_genlock(src, dst, false, 0); - v |= do_genlock(src, dst, false, 1); + v = do_genlock(src, dst, false, 0, zclken); + v |= do_genlock(src, dst, false, 1, zclken); } } else { if (currprefs.gfx_pscanlines) { - v = do_genlock(src, dst, false, lof_store ? 0 : 1); + v = do_genlock(src, dst, false, lof_store ? 0 : 1, zclken); if (v && currprefs.gfx_pscanlines >= 2) - do_genlock(src, dst, false, lof_store ? 1 : 0); + do_genlock(src, dst, false, lof_store ? 1 : 0, zclken); } else { - v = do_genlock(src, dst, true, 0); + v = do_genlock(src, dst, true, 0, zclken); } } return v;