Genlock transparency emulation.

This commit is contained in:
Toni Wilen 2015-06-18 20:29:05 +03:00
parent 5e80df2c32
commit 4d65ec3b06
8 changed files with 2499 additions and 89 deletions

View File

@ -158,8 +158,8 @@ static uae_u32 sprite_ab_merge[256];
/* Tables for collision detection. */
static uae_u32 sprclx[16], clxmask[16];
/* AGA T genlock bit in color registers */
static uae_u8 color_regs_aga_genlock[256];
/* T genlock bit in ECS Denise and AGA color registers */
static uae_u8 color_regs_genlock[256];
/*
* Hardware registers of all sorts.
@ -2909,15 +2909,18 @@ static void record_color_change (int hpos, int regno, unsigned long value)
static bool isbrdblank (int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
{
bool brdblank;
bool brdblank, brdntrans;
#ifdef ECS_DENISE
brdblank = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x20);
brdntrans = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x10);
#else
brdblank = false;
brdntrans = false;
#endif
if (hpos >= 0 && current_colors.borderblank != brdblank) {
record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (current_colors.bordersprite ? 2 : 0));
if (hpos >= 0 && (current_colors.borderblank != brdblank || current_colors.borderntrans != brdntrans)) {
record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (current_colors.bordersprite ? 2 : 0) | (brdntrans ? 4 : 0));
current_colors.borderblank = brdblank;
current_colors.borderblank = brdntrans;
remembered_color_entry = -1;
}
return brdblank;
@ -2933,7 +2936,7 @@ static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
brdsprt = false;
#endif
if (hpos >= 0 && current_colors.bordersprite != brdsprt) {
record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (current_colors.borderblank ? 1 : 0) | (brdsprt ? 2 : 0));
record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (current_colors.borderblank ? 1 : 0) | (current_colors.borderntrans ? 4 : 0) | (brdsprt ? 2 : 0));
current_colors.bordersprite = brdsprt;
remembered_color_entry = -1;
if (brdsprt && !current_colors.borderblank)
@ -3363,7 +3366,7 @@ static void decide_sprites (int hpos, bool usepointx)
{
int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2];
int count, i;
int point = hpos * 2 + 0;
int point;
int width = sprite_width;
int sscanmask = 0x100 << sprite_buffer_res;
int gotdata = 0;
@ -3371,6 +3374,12 @@ static void decide_sprites (int hpos, bool usepointx)
if (thisline_decision.plfleft < 0 && !(bplcon3 & 2))
return;
// let sprite shift register empty completely
// if sprite is at the very edge of right border
point = hpos * 2;
if (hpos >= maxhpos)
point += ((9 - 2) * 2) * sprite_buffer_res;
if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
return;
@ -3393,6 +3402,9 @@ static void decide_sprites (int hpos, bool usepointx)
if (! spr[i].armed)
continue;
// if (sprxp > ((maxhpos * 2) << sprite_buffer_res))
// write_log(_T("*"));
if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
add_sprite (&count, i, sprxp, posns, nrs);
}
@ -5652,6 +5664,10 @@ static void SPRxCTLPOS(int num)
sprstartstop (s);
sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1);
if (!(fmode & 0x80) && sprxp >= 2 && sprxp <= 9) {
// right border wrap around
sprxp += maxhpos * 2;
}
sprxp <<= sprite_buffer_res;
/* Quite a bit salad in this register... */
if (0) {
@ -5873,10 +5889,10 @@ void dump_aga_custom (void)
c2 = c1 + 64;
c3 = c2 + 64;
c4 = c3 + 64;
rgb1 = current_colors.color_regs_aga[c1] | (color_regs_aga_genlock[c1] << 31);
rgb2 = current_colors.color_regs_aga[c2] | (color_regs_aga_genlock[c2] << 31);
rgb3 = current_colors.color_regs_aga[c3] | (color_regs_aga_genlock[c3] << 31);
rgb4 = current_colors.color_regs_aga[c4] | (color_regs_aga_genlock[c4] << 31);
rgb1 = current_colors.color_regs_aga[c1];
rgb2 = current_colors.color_regs_aga[c2];
rgb3 = current_colors.color_regs_aga[c3];
rgb4 = current_colors.color_regs_aga[c4];
console_out_f (_T("%3d %08X %3d %08X %3d %08X %3d %08X\n"),
c1, rgb1, c2, rgb2, c3, rgb3, c4, rgb4);
}
@ -5891,14 +5907,14 @@ static uae_u16 COLOR_READ (int num)
return 0xffff;
colreg = ((bplcon3 >> 13) & 7) * 32 + num;
cr = current_colors.color_regs_aga[colreg] >> 16;
cr = (current_colors.color_regs_aga[colreg] >> 16) & 0xFF;
cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
cb = current_colors.color_regs_aga[colreg] & 0xFF;
if (bplcon3 & 0x200) {
cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0);
} else {
cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
if (color_regs_aga_genlock[num])
if (color_regs_genlock[num])
cval |= 0x8000;
}
return cval;
@ -5931,7 +5947,6 @@ static void checkautoscalecol0 (void)
static void COLOR_WRITE (int hpos, uae_u16 v, int num)
{
bool colzero = false;
v &= 0xFFF;
#ifdef AGA
if (currprefs.chipset_mask & CSMASK_AGA) {
int r,g,b;
@ -5947,7 +5962,7 @@ static void COLOR_WRITE (int hpos, uae_u16 v, int num)
r = (v & 0xF00) >> 8;
g = (v & 0xF0) >> 4;
b = (v & 0xF) >> 0;
cr = current_colors.color_regs_aga[colreg] >> 16;
cr = (current_colors.color_regs_aga[colreg] >> 16) & 0xFF;
cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
cb = current_colors.color_regs_aga[colreg] & 0xFF;
@ -5959,9 +5974,9 @@ static void COLOR_WRITE (int hpos, uae_u16 v, int num)
cr = r + (r << 4);
cg = g + (g << 4);
cb = b + (b << 4);
color_regs_aga_genlock[colreg] = v >> 15;
color_regs_genlock[colreg] = v >> 15;
}
cval = (cr << 16) | (cg << 8) | cb;
cval = (cr << 16) | (cg << 8) | cb | (color_regs_genlock[colreg] ? 0x80000000 : 0);
if (cval && colreg == 0)
colzero = true;
@ -5979,6 +5994,10 @@ static void COLOR_WRITE (int hpos, uae_u16 v, int num)
} else {
#endif
v &= 0x8fff;
if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE))
v &= 0xfff;
color_regs_genlock[num] = v >> 15;
if (num && v == 0)
colzero = true;
if (current_colors.color_regs_ecs[num] == v)
@ -9111,8 +9130,11 @@ uae_u8 *restore_custom (uae_u8 *src)
clxcon2 = RW; /* 10E CLXCON2* */
for(i = 0; i < 8; i++)
fetched[i] = RW; /* BPLXDAT */
for(i = 0; i < 32; i++)
current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */
for(i = 0; i < 32; i++) {
uae_u16 v = RW;
color_regs_genlock[i] = (v & 0x8000) != 0;
current_colors.color_regs_ecs[i] = v & 0xfff; /* 180 COLORxx */
}
htotal = RW; /* 1C0 HTOTAL */
hsstop = RW; /* 1C2 HSTOP ? */
hbstrt = RW; /* 1C4 HBSTRT ? */
@ -9288,7 +9310,10 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
v2 |= ((v >> 20) & 15) << 8;
SW (v2);
} else {
SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */
uae_u16 v = current_colors.color_regs_ecs[i];
if (color_regs_genlock[i])
v |= 0x8000;
SW (v); /* 180-1BE COLORxx */
}
}
SW (htotal); /* 1C0 HTOTAL */
@ -9339,10 +9364,10 @@ uae_u8 *restore_custom_agacolors (uae_u8 *src)
for (i = 0; i < 256; i++) {
#ifdef AGA
uae_u32 v = RL;
color_regs_aga_genlock[i] = 0;
color_regs_genlock[i] = 0;
if (v & 0x80000000)
color_regs_aga_genlock[i] = 1;
v &= 0x00ffffff;
color_regs_genlock[i] = 1;
v &= 0x80ffffff;
current_colors.color_regs_aga[i] = v;
#else
RL;
@ -9362,7 +9387,7 @@ uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr)
dstbak = dst = xmalloc (uae_u8, 256 * 4);
for (i = 0; i < 256; i++)
#ifdef AGA
SL (current_colors.color_regs_aga[i] | (color_regs_aga_genlock[i] ? 0x80000000 : 0));
SL (current_colors.color_regs_aga[i] | (color_regs_genlock[i] ? 0x80000000 : 0));
#else
SL (0);
#endif

View File

@ -230,6 +230,9 @@ static uae_u32 plf_sprite_mask;
static int sbasecol[2] = { 16, 16 };
static int hposblank;
static bool specialmonitoron;
static bool ecs_genlock_features_active;
static uae_u8 ecs_genlock_features_mask;
static bool ecs_genlock_features_colorkey;
bool picasso_requested_on;
bool picasso_on;
@ -1219,6 +1222,38 @@ static uae_u8 render_sprites (int pos, int dualpf, uae_u8 apixel, int aga)
return 0;
}
static bool get_genlock_very_rare_and_complex_case(uae_u8 v)
{
// border color without BRDNTRAN bit set = transparent
if (v == 0 && !colors_for_drawing.borderntrans)
return false;
if (ecs_genlock_features_colorkey) {
// color key match?
if (currprefs.chipset_mask & CSMASK_AGA) {
if (colors_for_drawing.color_regs_aga[v] & 0x80000000)
return false;
} else {
if (colors_for_drawing.color_regs_ecs[v] & 0x8000)
return false;
}
}
// plane mask match?
if (v & ecs_genlock_features_mask)
return false;
return true;
}
// false = transparent
STATIC_INLINE bool get_genlock_transparency(uae_u8 v)
{
if (!ecs_genlock_features_active) {
if (v == 0)
return false;
return true;
} else {
return get_genlock_very_rare_and_complex_case(v);
}
}
#include "linetoscr.cpp"
#define LTPARMS src_pixel, start, stop
@ -1882,10 +1917,10 @@ static void init_ham_decoding (void)
int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1];
#ifdef AGA
if (currprefs.chipset_mask & CSMASK_AGA)
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor] & 0xffffff;
else
#endif
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv] & 0xfff;
}
#ifdef AGA
} else if (currprefs.chipset_mask & CSMASK_AGA) {
@ -1894,7 +1929,7 @@ static void init_ham_decoding (void)
int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor;
switch (pv & 0x3)
{
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2] & 0xffffff; break;
case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
@ -1905,7 +1940,7 @@ static void init_ham_decoding (void)
int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor;
switch (pv & 0x30)
{
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv] & 0xffffff; break;
case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
@ -1919,7 +1954,7 @@ static void init_ham_decoding (void)
int pv = pixdata.apixels[ham_decode_pixel++];
switch (pv & 0x30)
{
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv] & 0xfff; break;
case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
@ -1937,10 +1972,10 @@ static void decode_ham (int pix, int stoppos, bool blank)
int pv = pixdata.apixels[ham_decode_pixel];
#ifdef AGA
if (currprefs.chipset_mask & CSMASK_AGA)
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor] & 0xffffff;
else
#endif
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
ham_lastcolor = colors_for_drawing.color_regs_ecs[pv] & 0xfff;
ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
}
@ -1951,7 +1986,7 @@ static void decode_ham (int pix, int stoppos, bool blank)
int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor;
switch (pv & 0x3)
{
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2] & 0xffffff; break;
case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
@ -1963,7 +1998,7 @@ static void decode_ham (int pix, int stoppos, bool blank)
int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor;
switch (pv & 0x30)
{
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv] & 0xffffff; break;
case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
@ -1978,7 +2013,7 @@ static void decode_ham (int pix, int stoppos, bool blank)
int pv = pixdata.apixels[ham_decode_pixel];
switch (pv & 0x30)
{
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv] & 0xfff; break;
case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
@ -2464,6 +2499,17 @@ static void pfield_expand_dp_bplcon (void)
sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4;
bplxor = dp_for_drawing->bplcon4 >> 8;
#endif
ecs_genlock_features_active = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && ((dp_for_drawing->bplcon2 & 0x0c00) || colors_for_drawing.borderntrans) ? 1 : 0;
if (ecs_genlock_features_active) {
ecs_genlock_features_colorkey = false;
ecs_genlock_features_mask = 0;
if (dp_for_drawing->bplcon3 & 0x0800) {
ecs_genlock_features_mask = 1 << ((dp_for_drawing->bplcon2 >> 12) & 7);
}
if (dp_for_drawing->bplcon3 & 0x0400) {
ecs_genlock_features_colorkey = true;
}
}
}
static bool isham (uae_u16 bplcon0)
@ -2626,6 +2672,7 @@ static void do_color_changes (line_draw_func worker_border, line_draw_func worke
if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK)) {
colors_for_drawing.borderblank = (value & 1) != 0;
colors_for_drawing.bordersprite = (value & 3) == 2;
colors_for_drawing.borderntrans = (value & 5) == 4;
} else {
color_reg_set (&colors_for_drawing, regno, value);
colors_for_drawing.acolors[regno] = getxcolor (value);
@ -3495,6 +3542,21 @@ static void finish_drawing_frame (void)
}
}
if (currprefs.genlock_image && !currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated && currprefs.genlock) {
setspecialmonitorpos(&gfxvidinfo.tempbuffer);
if (init_genlock_data != specialmonitor_need_genlock()) {
need_genlock_data = init_genlock_data = specialmonitor_need_genlock();
init_row_map();
}
emulate_genlock(vb, &gfxvidinfo.tempbuffer);
vb = gfxvidinfo.outbuffer = &gfxvidinfo.tempbuffer;
if (vb->nativepositioning)
setnativeposition(vb);
gfxvidinfo.drawbuffer.tempbufferinuse = true;
do_flush_screen(vb, 0, vb->outheight);
didflush = true;
}
if (!currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated && currprefs.cs_cd32fmv) {
if (cd32_fmv_active) {
cd32_fmv_genlock(vb, &gfxvidinfo.tempbuffer);

View File

@ -98,20 +98,30 @@ int set_indent (int indent)
return old_indent;
}
void outln (const char *s)
void outindent(void)
{
unsigned int i;
for (i = 0; i < outfile_indent; i++)
fputc(' ', outfile);
}
void outf(const char *s, ...)
{
va_list ap;
va_start(ap, s);
vfprintf(outfile, s, ap);
}
void outln (const char *s)
{
outindent();
fprintf (outfile, "%s\n", s);
}
void outlnf (const char *s, ...)
{
va_list ap;
unsigned int i;
for (i = 0; i < outfile_indent; i++)
fputc (' ', outfile);
outindent();
va_start (ap, s);
vfprintf (outfile, s, ap);
fputc ('\n', outfile);
@ -221,12 +231,50 @@ static void out_linetoscr_do_incspix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE
}
}
static void put_dpix (const char *var, int genlock, const char *var2)
static void put_dpixsprgenlock(int offset, int genlock)
{
if (genlock) {
outlnf(" genlock_buf[dpix] = %s;", var2 ? var2 : "spix_val");
if (genlock!)
return;
if (offset)
outlnf(" genlock_buf[dpix + %d] = get_genlock_transparency(sprcol);", offset);
else
outlnf(" genlock_buf[dpix] = get_genlock_transparency(sprcol);");
}
static void put_dpixgenlock(int offset, CMODE_T cmode, int aga, int genlock, const char *var2)
{
if (!genlock)
return;
outindent();
if (offset)
outf(" genlock_buf[dpix + %d] = get_genlock_transparency(", offset);
else
outf(" genlock_buf[dpix] = get_genlock_transparency(");
if (genlock) {
if (cmode == CMODE_EXTRAHB) {
outf("%s", var2 ? var2 : "spix_val & 31");
}
else if (cmode == CMODE_DUALPF) {
outf("%s", var2 ? var2 : "lookup[spix_val]");
}
else if (cmode == CMODE_HAM) {
if (aga) {
outf("%s", var2 ? var2 : "(spix_val >> 2) & 63");
}
else {
outf("%s", var2 ? var2 : "spix_val & 15");
}
}
else {
outf("%s", var2 ? var2 : "spix_val");
}
}
outf(");\n");
}
static void put_dpix (const char *var)
{
outlnf(" buf[dpix++] = %s;", var);
}
@ -238,37 +286,30 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int
outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf(" if (sprcol) {");
outlnf ( " out_val = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val = sprcol;");
put_dpixsprgenlock(0, genlock);
outlnf(" }");
outlnf(" }");
put_dpix("out_val", genlock, NULL);
put_dpix("out_val");
} else if (cnt == 2) {
outlnf ( " {");
outlnf ( " uae_u32 out_val1 = out_val;");
outlnf ( " uae_u32 out_val2 = out_val;");
if (genlock) {
outlnf(" uae_u32 spix_val1 = spix_val;");
outlnf(" uae_u32 spix_val2 = spix_val;");
}
outlnf(" if (spritepixels[dpix + 0].data) {");
outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val1 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val1 = sprcol;");
put_dpixsprgenlock(0, genlock);
outlnf(" }");
outlnf(" }");
outlnf ( " if (spritepixels[dpix + 1].data) {");
outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val2 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val2 = sprcol;");
put_dpixsprgenlock(1, genlock);
outlnf(" }");
outlnf(" }");
put_dpix("out_val1", genlock, "spix_val1");
put_dpix("out_val2", genlock, "spix_val2");
put_dpix("out_val1");
put_dpix("out_val2");
outlnf ( " }");
} else if (cnt == 4) {
outlnf ( " {");
@ -276,62 +317,51 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int
outlnf ( " uae_u32 out_val2 = out_val;");
outlnf ( " uae_u32 out_val3 = out_val;");
outlnf ( " uae_u32 out_val4 = out_val;");
if (genlock) {
outlnf(" uae_u32 spix_val1 = spix_val;");
outlnf(" uae_u32 spix_val2 = spix_val;");
outlnf(" uae_u32 spix_val3 = spix_val;");
outlnf(" uae_u32 spix_val4 = spix_val;");
}
outlnf(" if (spritepixels[dpix + 0].data) {");
outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val1 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val1 = sprcol;");
put_dpixsprgenlock(0, genlock);
outlnf(" }");
outlnf(" }");
outlnf ( " if (spritepixels[dpix + 1].data) {");
outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val2 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val2 = sprcol;");
put_dpixsprgenlock(1, genlock);
outlnf(" }");
outlnf(" }");
outlnf ( " if (spritepixels[dpix + 2].data) {");
outlnf ( " sprcol = render_sprites (dpix + 2, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val3 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val3 = sprcol;");
put_dpixsprgenlock(2, genlock);
outlnf(" }");
outlnf(" }");
outlnf ( " if (spritepixels[dpix + 3].data) {");
outlnf ( " sprcol = render_sprites (dpix + 3, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
outlnf ( " if (sprcol) {");
outlnf ( " out_val4 = colors_for_drawing.acolors[sprcol];");
if (genlock)
outlnf(" spix_val4 = sprcol;");
put_dpixsprgenlock(3, genlock);
outlnf(" }");
outlnf(" }");
put_dpix("out_val1", genlock, "spix_val1");
put_dpix("out_val2", genlock, "spix_val2");
put_dpix("out_val3", genlock, "spix_val3");
put_dpix("out_val4", genlock, "spix_val4");
put_dpix("out_val1");
put_dpix("out_val2");
put_dpix("out_val3");
put_dpix("out_val4");
outlnf ( " }");
}
} else {
outlnf ( " if (spritepixels[dpix].data) {");
outlnf ( " sprcol = render_sprites (dpix, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga);
if (genlock)
outlnf(" spix_val = sprcol;");
put_dpixsprgenlock(0, genlock);
outlnf(" if (sprcol) {");
outlnf ( " uae_u32 spcol = colors_for_drawing.acolors[sprcol];");
outlnf ( " out_val = spcol;");
outlnf ( " }");
outlnf ( " }");
while (cnt-- > 0)
put_dpix("out_val", genlock, NULL);
put_dpix("out_val");
}
}
@ -356,7 +386,7 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
put_dpix("dpix_val", genlock, NULL);
put_dpix("dpix_val");
outln ( "}");
outln ( "if (dpix >= dpix_end)");
outln ( " return spix;");
@ -384,6 +414,18 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
else
outln ( " out_val = colors_for_drawing.acolors[0];");
if (hmode == HMODE_DOUBLE) {
put_dpixgenlock(0, cmode, aga, genlock, NULL);
put_dpixgenlock(1, cmode, aga, genlock, NULL);
} else if (hmode == HMODE_DOUBLE2X) {
put_dpixgenlock(0, cmode, aga, genlock, NULL);
put_dpixgenlock(1, cmode, aga, genlock, NULL);
put_dpixgenlock(2, cmode, aga, genlock, NULL);
put_dpixgenlock(3, cmode, aga, genlock, NULL);
} else {
put_dpixgenlock(0, cmode, aga, genlock, NULL);
}
if (hmode != HMODE_DOUBLE && hmode != HMODE_DOUBLE2X && bpp == DEPTH_16BPP && spr == 0) {
out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
@ -410,8 +452,8 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
if (spr) {
out_sprite(bpp, hmode, cmode, aga, 2, spr, genlock);
} else {
put_dpix("out_val", genlock, NULL);
put_dpix("out_val", genlock, NULL);
put_dpix("out_val");
put_dpix("out_val");
}
}
} else if (hmode == HMODE_DOUBLE2X) {
@ -431,10 +473,10 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
if (spr) {
out_sprite(bpp, hmode, cmode, aga, 4, spr, genlock);
} else {
put_dpix("out_val", genlock, NULL);
put_dpix("out_val", genlock, NULL);
put_dpix("out_val", genlock, NULL);
put_dpix("out_val", genlock, NULL);
put_dpix("out_val");
put_dpix("out_val");
put_dpix("out_val");
put_dpix("out_val");
}
}
} else {
@ -449,7 +491,7 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
if (spr) {
out_sprite(bpp, hmode, cmode, aga, 1, spr, genlock);
} else {
put_dpix("out_val", genlock, NULL);
put_dpix("out_val");
}
}
}
@ -466,7 +508,7 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM
out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
put_dpix("dpix_val", genlock, NULL);
put_dpix("dpix_val");
outln ( "}");
}

View File

@ -86,7 +86,7 @@ struct color_entry {
xcolnr acolors[256];
uae_u32 color_regs_aga[256];
#endif
bool borderblank, bordersprite;
bool borderblank, borderntrans, bordersprite;
};
#ifdef AGA

View File

@ -4,3 +4,4 @@ void specialmonitor_store_fmode(int vpos, int hpos, uae_u16 fmode);
void specialmonitor_reset(void);
bool specialmonitor_need_genlock(void);
addrbank *specialmonitor_autoconfig_init(int devnum);
bool emulate_genlock(struct vidbuffer*, struct vidbuffer*);

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -11,6 +11,7 @@
#include "memory.h"
#include "specialmonitors.h"
#include "debug.h"
#include "zfile.h"
static bool automatic;
static int monitor;
@ -20,6 +21,11 @@ extern uae_u8 **row_map_genlock;
static uae_u8 graffiti_palette[256 * 4];
STATIC_INLINE bool is_transparent(uae_u8 v)
{
return v == 0;
}
STATIC_INLINE uae_u8 FVR(struct vidbuffer *src, uae_u8 *dataline)
{
if (src->pixbytes == 4)
@ -382,7 +388,7 @@ static bool firecracker24(struct vidbuffer *src, struct vidbuffer *dst, bool dou
b = vramptr[3];
}
}
if (!(fc24_cr0 & 1) && (!(fc24_cr1 & 1) || (s_genlock[0] != 0))) {
if (!(fc24_cr0 & 1) && (!(fc24_cr1 & 1) || (!is_transparent(s_genlock[0])))) {
uae_u8 *s2 = s + src->rowbytes;
uae_u8 *d2 = d + dst->rowbytes;
PUT_AMIGARGB(d, s, d2, s2, dst, xadd, doublelines, false);
@ -598,7 +604,7 @@ static void REGPARAM2 sm_bput(uaecptr addr, uae_u32 b)
if (!sm_configured) {
switch (addr) {
case 0x48:
map_banks(&specialmonitors_bank, expamem_z2_pointer >> 16, 65536 >> 16, 0);
map_banks_z2(&specialmonitors_bank, expamem_z2_pointer >> 16, 65536 >> 16);
sm_configured = 1;
expamem_next(&specialmonitors_bank, NULL);
break;
@ -1821,5 +1827,264 @@ bool specialmonitor_need_genlock(void)
case MONITOREMU_HAM_E_PLUS:
return true;
}
if (currprefs.genlock_image && currprefs.genlock)
return true;
return false;
}
static uae_u8 *genlock_image;
static int genlock_image_width, genlock_image_height, genlock_image_pitch;
static uae_u8 noise_buffer[1024];
static uae_u32 noise_seed, noise_add, noise_index;
static uae_u32 quickrand(void)
{
noise_seed = (noise_seed >> 1) ^ (0 - (noise_seed & 1) & 0xd0000001);
return noise_seed;
}
static void init_noise(void)
{
noise_seed++;
for (int i = 0; i < sizeof noise_buffer; i++) {
noise_buffer[i] = quickrand();
}
}
static uae_u8 get_noise(void)
{
noise_index += noise_add;
noise_index &= 1023;
return noise_buffer[noise_index];
}
#include "png.h"
struct png_cb
{
uae_u8 *ptr;
int size;
};
static void __cdecl readcallback(png_structp png_ptr, png_bytep out, png_size_t count)
{
png_voidp io_ptr = png_get_io_ptr(png_ptr);
if (!io_ptr)
return;
struct png_cb *cb = (struct png_cb*)io_ptr;
if (count > cb->size)
count = cb->size;
memcpy(out, cb->ptr, count);
cb->ptr += count;
cb->size -= count;
}
static void load_genlock_image(void)
{
extern unsigned char test_card_png[];
extern unsigned int test_card_png_len;
uae_u8 *b = test_card_png;
uae_u8 *bfree = NULL;
int file_size = test_card_png_len;
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int depth, color_type;
struct png_cb cb;
xfree(genlock_image);
genlock_image = NULL;
if (currprefs.genlock_image == 3) {
int size;
uae_u8 *bb = zfile_load_file(currprefs.genlock_image_file, &size);
if (bb) {
file_size = size;
b = bb;
bfree = bb;
}
}
if (!png_check_sig(b, 8))
goto end;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (!png_ptr)
goto end;
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, 0, 0);
goto end;
}
cb.ptr = b;
cb.size = file_size;
png_set_read_fn(png_ptr, &cb, readcallback);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
png_set_expand(png_ptr);
if (depth > 8)
png_set_strip_16(png_ptr);
if (depth < 8)
png_set_packing(png_ptr);
if (!(color_type & PNG_COLOR_MASK_ALPHA))
png_set_add_alpha(png_ptr, 0, PNG_FILLER_AFTER);
png_size_t cols = png_get_rowbytes(png_ptr, info_ptr);
genlock_image_pitch = width * 4;
genlock_image_width = width;
genlock_image_height = height;
png_bytepp row_pp = new png_bytep[height];
genlock_image = xcalloc(uae_u8, width * height * 4);
for (int i = 0; i < height; i++) {
row_pp[i] = (png_bytep) &genlock_image[i * genlock_image_pitch];
}
png_read_image(png_ptr, row_pp);
png_read_end(png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
delete[] row_pp;
end:
xfree(bfree);
}
static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
{
int y, x, vdbl, hdbl;
int ystart, yend, isntsc;
int gl_vdbl_l, gl_vdbl_r;
int gl_hdbl_l, gl_hdbl_r, gl_hdbl;
int gl_hcenter, gl_vcenter;
isntsc = (beamcon0 & 0x20) ? 0 : 1;
if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
isntsc = currprefs.ntscmode ? 1 : 0;
if (!genlock_image && currprefs.genlock_image == 2) {
load_genlock_image();
}
if (genlock_image && currprefs.genlock_image != 2) {
xfree(genlock_image);
genlock_image = NULL;
}
if (gfxvidinfo.xchange == 1)
hdbl = 0;
else if (gfxvidinfo.xchange == 2)
hdbl = 1;
else
hdbl = 2;
gl_hdbl_l = gl_hdbl_r = 0;
if (genlock_image_width < 600) {
gl_hdbl = 0;
} else if (genlock_image_width < 1000) {
gl_hdbl = 1;
} else {
gl_hdbl = 2;
}
if (hdbl >= gl_hdbl) {
gl_hdbl_l = hdbl - gl_hdbl;
} else {
gl_hdbl_r = gl_hdbl - hdbl;
}
if (gfxvidinfo.ychange == 1)
vdbl = 0;
else
vdbl = 1;
gl_vdbl_l = gl_vdbl_r = 0;
gl_hcenter = (genlock_image_width - ((src->inwidth << hdbl) >> gl_hdbl)) / 2;
ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
gl_vcenter = (((genlock_image_height << gl_vdbl_l) >> gl_vdbl_r) - (((yend - ystart) * 2))) / 2;
init_noise();
uae_u8 r = 0, g = 0, b = 0;
for (y = ystart; y < yend; y++) {
int yoff = (((y * 2 + oddlines) - src->yoffset) >> vdbl);
if (yoff < 0)
continue;
if (yoff >= src->inheight)
continue;
uae_u8 *line = src->bufmem + yoff * src->rowbytes;
uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) >> vdbl) * dst->rowbytes;
uae_u8 *line_genlock = row_map_genlock[yoff];
int gy = ((((y * 2 + oddlines) - dst->yoffset) << gl_vdbl_l) >> gl_vdbl_r) + gl_vcenter;
uae_u8 *image_genlock = genlock_image + gy * genlock_image_pitch;
r = g = b = 0;
noise_add = (quickrand() & 15) | 1;
for (x = 0; x < src->inwidth; x++) {
uae_u8 *s = line + x * src->pixbytes;
uae_u8 *d = dstline + x * dst->pixbytes;
uae_u8 *s_genlock = line_genlock + x;
uae_u8 *s2 = s + src->rowbytes;
uae_u8 *d2 = d + dst->rowbytes;
if (is_transparent(*s_genlock)) {
if (genlock_image) {
int gx = (((x + gl_hcenter) << gl_hdbl_l) >> gl_hdbl_r);
if (gx >= 0 && gx < genlock_image_width && gy >= 0 && gy < genlock_image_height) {
uae_u8 *s_genlock_image = image_genlock + gx * 4;
r = s_genlock_image[0];
g = s_genlock_image[1];
b = s_genlock_image[2];
} else {
r = g = b = 0;
}
} else {
r = g = b = get_noise();
}
PUT_PRGB(d, d2, dst, r, g, b, 0, doublelines, false);
} else {
PUT_AMIGARGB(d, s, d2, s2, dst, 0, doublelines, false);
}
}
}
dst->nativepositioning = true;
return true;
}
bool emulate_genlock(struct vidbuffer *src, struct vidbuffer *dst)
{
bool v;
if (interlace_seen) {
if (currprefs.gfx_iscanlines) {
v = do_genlock(src, dst, false, lof_store ? 0 : 1);
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);
}
} else {
if (currprefs.gfx_pscanlines) {
v = do_genlock(src, dst, false, lof_store ? 0 : 1);
if (v && currprefs.gfx_pscanlines > 1)
blank_generic(src, dst, lof_store ? 1 : 0);
} else {
v = do_genlock(src, dst, true, 0);
}
}
return v;
}

2015
test_card.cpp Normal file

File diff suppressed because it is too large Load Diff