1 #include "sysconfig.h"
2 #include "sysdeps.h"
3 
4 #include <ctype.h>
5 #include <assert.h>
6 
7 #include "options.h"
8 #include "xwin.h"
9 #include "custom.h"
10 #include "drawing.h"
11 #include "memory.h"
12 #include "specialmonitors.h"
13 #include "debug.h"
14 #include "zfile.h"
15 
16 static bool automatic;
17 static int monitor;
18 
19 extern unsigned int bplcon0;
20 extern uae_u8 **row_map_genlock;
21 
22 static uae_u8 graffiti_palette[256 * 4];
23 
is_transparent(uae_u8 v)24 STATIC_INLINE bool is_transparent(uae_u8 v)
25 {
26 	return v == 0;
27 }
28 
FVR(struct vidbuffer * src,uae_u8 * dataline)29 STATIC_INLINE uae_u8 FVR(struct vidbuffer *src, uae_u8 *dataline)
30 {
31 	if (src->pixbytes == 4)
32 		return dataline[2];
33 	else
34 		return ((((uae_u16*)dataline)[0] >> 11) & 31) << 3;
35 }
FVG(struct vidbuffer * src,uae_u8 * dataline)36 STATIC_INLINE uae_u8 FVG(struct vidbuffer *src, uae_u8 *dataline)
37 {
38 	if (src->pixbytes == 4)
39 		return dataline[1];
40 	else
41 		return ((((uae_u16*)dataline)[0] >> 5) & 63) << 2;
42 }
FVB(struct vidbuffer * src,uae_u8 * dataline)43 STATIC_INLINE uae_u8 FVB(struct vidbuffer *src, uae_u8 *dataline)
44 {
45 	if (src->pixbytes == 4)
46 		return dataline[0];
47 	else
48 		return ((((uae_u16*)dataline)[0] >> 0) & 31) << 2;
49 }
50 
FR(struct vidbuffer * src,uae_u8 * dataline)51 STATIC_INLINE bool FR(struct vidbuffer *src, uae_u8 *dataline)
52 {
53 	if (src->pixbytes == 4)
54 		return (dataline[2] & 0x80) != 0;
55 	else
56 		return ((dataline[1] >> 7) & 1) != 0;
57 }
FG(struct vidbuffer * src,uae_u8 * dataline)58 STATIC_INLINE bool FG(struct vidbuffer *src, uae_u8 *dataline)
59 {
60 	if (src->pixbytes == 4)
61 		return (dataline[1] & 0x80) != 0;
62 	else
63 		return ((dataline[1] >> 2) & 1) != 0;
64 }
FB(struct vidbuffer * src,uae_u8 * dataline)65 STATIC_INLINE bool FB(struct vidbuffer *src, uae_u8 *dataline)
66 {
67 	if (src->pixbytes == 4)
68 		return (dataline[0] & 0x80) != 0;
69 	else
70 		return ((dataline[0] >> 4) & 1) != 0;
71 }
FI(struct vidbuffer * src,uae_u8 * dataline)72 STATIC_INLINE bool FI(struct vidbuffer *src, uae_u8 *dataline)
73 {
74 	if (src->pixbytes == 4)
75 		return (dataline[0] & 0x10) != 0;
76 	else
77 		return ((dataline[0] >> 1) & 1) != 0;
78 }
79 
FIRGB(struct vidbuffer * src,uae_u8 * dataline)80 STATIC_INLINE uae_u8 FIRGB(struct vidbuffer *src, uae_u8 *dataline)
81 {
82 	uae_u8 v = 0;
83 #if 1
84 	if (FI(src, dataline))
85 		v |= 1;
86 	if (FR(src, dataline))
87 		v |= 8;
88 	if (FG(src, dataline))
89 		v |= 4;
90 	if (FB(src, dataline))
91 		v |= 2;
92 #else
93 	if (FI(src, dataline))
94 		v |= 1 << scramble[scramble_counter * 4 + 0];
95 	if (FR(src, dataline))
96 		v |= 1 << scramble[scramble_counter * 4 + 1];
97 	if (FG(src, dataline))
98 		v |= 1 << scramble[scramble_counter * 4 + 2];
99 	if (FB(src, dataline))
100 		v |= 1 << scramble[scramble_counter * 4 + 3];
101 #endif
102 	return v;
103 }
104 
DCTV_FIRBG(struct vidbuffer * src,uae_u8 * dataline)105 STATIC_INLINE uae_u8 DCTV_FIRBG(struct vidbuffer *src, uae_u8 *dataline)
106 {
107 	uae_u8 v = 0;
108 	if (FI(src, dataline))
109 		v |= 0x40;
110 	if (FR(src, dataline))
111 		v |= 0x10;
112 	if (FB(src, dataline))
113 		v |= 0x04;
114 	if (FG(src, dataline))
115 		v |= 0x01;
116 	return v;
117 }
118 
PRGB(struct vidbuffer * dst,uae_u8 * dataline,uae_u8 r,uae_u8 g,uae_u8 b)119 STATIC_INLINE void PRGB(struct vidbuffer *dst, uae_u8 *dataline, uae_u8 r, uae_u8 g, uae_u8 b)
120 {
121 	if (dst->pixbytes == 4) {
122 		dataline[0] = b;
123 		dataline[1] = g;
124 		dataline[2] = r;
125 	} else {
126 		r >>= 3;
127 		g >>= 2;
128 		b >>= 3;
129 		((uae_u16*)dataline)[0] = (r << 11) | (g << 5) | b;
130 	}
131 }
132 
PUT_PRGB(uae_u8 * d,uae_u8 * d2,struct vidbuffer * dst,uae_u8 r,uae_u8 g,uae_u8 b,int xadd,int doublelines,bool hdouble)133 STATIC_INLINE void PUT_PRGB(uae_u8 *d, uae_u8 *d2, struct vidbuffer *dst, uae_u8 r, uae_u8 g, uae_u8 b, int xadd, int doublelines, bool hdouble)
134 {
135 	if (hdouble)
136 		PRGB(dst, d - dst->pixbytes, r, g, b);
137 	PRGB(dst, d, r, g, b);
138 	if (xadd >= 2) {
139 		PRGB(dst, d + 1 * dst->pixbytes, r, g, b);
140 		if (hdouble)
141 			PRGB(dst, d + 2 * dst->pixbytes, r, g, b);
142 	}
143 	if (doublelines) {
144 		if (hdouble)
145 			PRGB(dst, d2 - dst->pixbytes, r, g, b);
146 		PRGB(dst, d2, r, g, b);
147 		if (xadd >= 2) {
148 			PRGB(dst, d2 + 1 * dst->pixbytes, r, g, b);
149 			if (hdouble)
150 				PRGB(dst, d2 + 2 * dst->pixbytes, r, g, b);
151 		}
152 	}
153 }
154 
PUT_AMIGARGB(uae_u8 * d,uae_u8 * s,uae_u8 * d2,uae_u8 * s2,struct vidbuffer * dst,int xadd,int doublelines,bool hdouble)155 STATIC_INLINE void PUT_AMIGARGB(uae_u8 *d, uae_u8 *s, uae_u8 *d2, uae_u8 *s2, struct vidbuffer *dst, int xadd, int doublelines, bool hdouble)
156 {
157 	if (dst->pixbytes == 4) {
158 		if (hdouble)
159 			((uae_u32*)d)[-1] = ((uae_u32*)s)[-1];
160 		((uae_u32*)d)[0] = ((uae_u32*)s)[0];
161 	} else {
162 		if (hdouble)
163 			((uae_u16*)d)[-1] = ((uae_u16*)s)[-1];
164 		((uae_u16*)d)[0] = ((uae_u16*)s)[0];
165 	}
166 	if (doublelines) {
167 		if (dst->pixbytes == 4) {
168 			if (hdouble)
169 				((uae_u32*)d2)[-1] = ((uae_u32*)s2)[-1];
170 			((uae_u32*)d2)[0] = ((uae_u32*)s2)[0];
171 		} else {
172 			if (hdouble)
173 				((uae_u16*)d2)[-1] = ((uae_u16*)s2)[-1];
174 			((uae_u16*)d2)[0] = ((uae_u16*)s2)[0];
175 		}
176 	}
177 }
178 
clearmonitor(struct vidbuffer * dst)179 static void clearmonitor(struct vidbuffer *dst)
180 {
181 	uae_u8 *p = dst->bufmem;
182 	for (int y = 0; y < dst->height_allocated; y++) {
183 		memset(p, 0, dst->width_allocated * dst->pixbytes);
184 		p += dst->rowbytes;
185 	}
186 }
187 
blank_generic(struct vidbuffer * src,struct vidbuffer * dst,int oddlines)188 static void blank_generic(struct vidbuffer *src, struct vidbuffer *dst, int oddlines)
189 {
190 	int y, vdbl;
191 	int ystart, yend, isntsc;
192 
193 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
194 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
195 		isntsc = currprefs.ntscmode ? 1 : 0;
196 
197 	vdbl = gfxvidinfo.ychange;
198 
199 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
200 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
201 
202 	for (y = ystart; y < yend; y++) {
203 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
204 		if (yoff < 0)
205 			continue;
206 		if (yoff >= src->inheight)
207 			continue;
208 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
209 		memset(dstline, 0, dst->inwidth * dst->pixbytes);
210 	}
211 }
212 
213 static const uae_u8 dctv_signature[] = {
214 	0x93,0x0e,0x51,0xbc,0x22,0x17,0xdf,0xa4,0x19,0x1d,0x16,0x6a,0xb6,0xeb,0xd9,0x70,
215 	0x52,0xd6,0x07,0xf2,0x57,0x68,0x69,0xdc,0xce,0x3c,0xf8,0x9e,0xa6,0xc6,0x2a
216 };
217 
218 static const uae_u16 dctv_tables[] = {
219 	0xF9AF, 0xF9C9, 0xF9E2, 0xF9FC, 0xFA15, 0xFA2F, 0xFA48, 0xFA62,
220 	0xFA7B, 0xFA95, 0xFAAE, 0xFAC8, 0xFAE1, 0xFAFB, 0xFB14, 0xFB2E,
221 	0xFB47, 0xFB61, 0xFB7A, 0xFB94, 0xFBAD, 0xFBC7, 0xFBE0, 0xFBFA,
222 	0xFC13, 0xFC2D, 0xFC46, 0xFC60, 0xFC79, 0xFC93, 0xFCAC, 0xFCC6,
223 	0xFCDF, 0xFCF9, 0xFD12, 0xFD2C, 0xFD45, 0xFD5F, 0xFD78, 0xFD92,
224 	0xFDAB, 0xFDC5, 0xFDDE, 0xFDF8, 0xFE11, 0xFE2B, 0xFE44, 0xFE5E,
225 	0xFE77, 0xFE91, 0xFEAA, 0xFEC4, 0xFEDD, 0xFEF7, 0xFF10, 0xFF2A,
226 	0xFF43, 0xFF5D, 0xFF76, 0xFF90, 0xFFA9, 0xFFC3, 0xFFDC, 0xFFF6,
227 	0x000F, 0x0029, 0x0042, 0x005C, 0x0075, 0x008F, 0x00A8, 0x00C2,
228 	0x00DB, 0x00F5, 0x010E, 0x0128, 0x0141, 0x015B, 0x0174, 0x018E,
229 	0x01A7, 0x01C1, 0x01DA, 0x01F4, 0x020D, 0x0227, 0x0240, 0x025A,
230 	0x0273, 0x028D, 0x02A6, 0x02C0, 0x02D9, 0x02F3, 0x030C, 0x0326,
231 	0x033F, 0x0359, 0x0372, 0x038C, 0x03A5, 0x03BF, 0x03D8, 0x03F2,
232 	0x040B, 0x0425, 0x043E, 0x0458, 0x0471, 0x048B, 0x04A4, 0x04BE,
233 	0x04D7, 0x04F1, 0x050A, 0x0524, 0x053D, 0x0557, 0x0570, 0x058A,
234 	0x05A3, 0x05BD, 0x05D6, 0x05F0, 0x0609, 0x0623, 0x063C, 0x0656,
235 	0x066F, 0x0689, 0x06A2, 0x06BC, 0x06D5, 0x06EF, 0x0708, 0x0722,
236 	0x073B, 0x0755, 0x076E, 0x0788, 0x07A1, 0x07BB, 0x07D4, 0x07EE,
237 	0x0807, 0x0821, 0x083A, 0x0854, 0x086D, 0x0887, 0x08A0, 0x08BA,
238 	0x08D3, 0x08ED, 0x0906, 0x0920, 0x0939, 0x0953, 0x096C, 0x0986,
239 	0x099F, 0x09B9, 0x09D2, 0x09EC, 0x0A05, 0x0A1F, 0x0A38, 0x0A52,
240 	0x0A6B, 0x0A85, 0x0A9E, 0x0AB8, 0x0AD1, 0x0AEB, 0x0B04, 0x0B1E,
241 	0x0B37, 0x0B51, 0x0B6A, 0x0B84, 0x0B9D, 0x0BB7, 0x0BD0, 0x0BEA,
242 	0x0C03, 0x0C1D, 0x0C36, 0x0C50, 0x0C69, 0x0C83, 0x0C9C, 0x0CB6,
243 	0x0CCF, 0x0CE9, 0x0D02, 0x0D1C, 0x0D35, 0x0D4F, 0x0D68, 0x0D82,
244 	0x0D9B, 0x0DB5, 0x0DCE, 0x0DE8, 0x0E01, 0x0E1B, 0x0E34, 0x0E4E,
245 	0x0E67, 0x0E81, 0x0E9A, 0x0EB4, 0x0ECD, 0x0EE7, 0x0F00, 0x0F1A,
246 	0x0F33, 0x0F4D, 0x0F66, 0x0F80, 0x0F99, 0x0FB3, 0x0FCC, 0x0FE6,
247 	0x0FFF, 0x1019, 0x1032, 0x104C, 0x1065, 0x107F, 0x1098, 0x10B2,
248 	0x10CB, 0x10E5, 0x10FE, 0x1118, 0x1131, 0x114B, 0x1164, 0x117E,
249 	0x1197, 0x11B1, 0x11CA, 0x11E4, 0x11FD, 0x1217, 0x1230, 0x124A,
250 	0x1263, 0x127D, 0x1296, 0x12B0, 0x12C9, 0x12E3, 0x12FC, 0x1316,
251 
252 	0xF174, 0xF191, 0xF1AE, 0xF1CB, 0xF1E8, 0xF205, 0xF222, 0xF23F,
253 	0xF25C, 0xF279, 0xF296, 0xF2B4, 0xF2D1, 0xF2EE, 0xF30B, 0xF328,
254 	0xF345, 0xF362, 0xF37F, 0xF39C, 0xF3B9, 0xF3D6, 0xF3F4, 0xF411,
255 	0xF42E, 0xF44B, 0xF468, 0xF485, 0xF4A2, 0xF4BF, 0xF4DC, 0xF4F9,
256 	0xF517, 0xF534, 0xF551, 0xF56E, 0xF58B, 0xF5A8, 0xF5C5, 0xF5E2,
257 	0xF5FF, 0xF61C, 0xF639, 0xF657, 0xF674, 0xF691, 0xF6AE, 0xF6CB,
258 	0xF6E8, 0xF705, 0xF722, 0xF73F, 0xF75C, 0xF779, 0xF797, 0xF7B4,
259 	0xF7D1, 0xF7EE, 0xF80B, 0xF828, 0xF845, 0xF862, 0xF87F, 0xF89C,
260 	0xF8BA, 0xF8D7, 0xF8F4, 0xF911, 0xF92E, 0xF94B, 0xF968, 0xF985,
261 	0xF9A2, 0xF9BF, 0xF9DC, 0xF9FA, 0xFA17, 0xFA34, 0xFA51, 0xFA6E,
262 	0xFA8B, 0xFAA8, 0xFAC5, 0xFAE2, 0xFAFF, 0xFB1C, 0xFB3A, 0xFB57,
263 	0xFB74, 0xFB91, 0xFBAE, 0xFBCB, 0xFBE8, 0xFC05, 0xFC22, 0xFC3F,
264 	0xFC5D, 0xFC7A, 0xFC97, 0xFCB4, 0xFCD1, 0xFCEE, 0xFD0B, 0xFD28,
265 	0xFD45, 0xFD62, 0xFD7F, 0xFD9D, 0xFDBA, 0xFDD7, 0xFDF4, 0xFE11,
266 	0xFE2E, 0xFE4B, 0xFE68, 0xFE85, 0xFEA2, 0xFEBF, 0xFEDD, 0xFEFA,
267 	0xFF17, 0xFF34, 0xFF51, 0xFF6E, 0xFF8B, 0xFFA8, 0xFFC5, 0xFFE2,
268 	//0x180
269 	0x0000, 0x001D, 0x003A, 0x0057, 0x0074, 0x0091, 0x00AE, 0x00CB,
270 	0x00E8, 0x0105, 0x0122, 0x0140, 0x015D, 0x017A, 0x0197, 0x01B4,
271 	0x01D1, 0x01EE, 0x020B, 0x0228, 0x0245, 0x0262, 0x0280, 0x029D,
272 	0x02BA, 0x02D7, 0x02F4, 0x0311, 0x032E, 0x034B, 0x0368, 0x0385,
273 	0x03A3, 0x03C0, 0x03DD, 0x03FA, 0x0417, 0x0434, 0x0451, 0x046E,
274 	0x048B, 0x04A8, 0x04C5, 0x04E3, 0x0500, 0x051D, 0x053A, 0x0557,
275 	0x0574, 0x0591, 0x05AE, 0x05CB, 0x05E8, 0x0605, 0x0623, 0x0640,
276 	0x065D, 0x067A, 0x0697, 0x06B4, 0x06D1, 0x06EE, 0x070B, 0x0728,
277 	0x0746, 0x0763, 0x0780, 0x079D, 0x07BA, 0x07D7, 0x07F4, 0x0811,
278 	0x082E, 0x084B, 0x0868, 0x0886, 0x08A3, 0x08C0, 0x08DD, 0x08FA,
279 	0x0917, 0x0934, 0x0951, 0x096E, 0x098B, 0x09A8, 0x09C6, 0x09E3,
280 	0x0A00, 0x0A1D, 0x0A3A, 0x0A57, 0x0A74, 0x0A91, 0x0AAE, 0x0ACB,
281 	0x0AE9, 0x0B06, 0x0B23, 0x0B40, 0x0B5D, 0x0B7A, 0x0B97, 0x0BB4,
282 	0x0BD1, 0x0BEE, 0x0C0B, 0x0C29, 0x0C46, 0x0C63, 0x0C80, 0x0C9D,
283 	0x0CBA, 0x0CD7, 0x0CF4, 0x0D11, 0x0D2E, 0x0D4B, 0x0D69, 0x0D86,
284 	0x0DA3, 0x0DC0, 0x0DDD, 0x0DFA, 0x0E17, 0x0E34, 0x0E51, 0x0E6E,
285 
286 	0xE61B, 0xE64E, 0xE682, 0xE6B6, 0xE6EA, 0xE71E, 0xE751, 0xE785,
287 	0xE7B9, 0xE7ED, 0xE821, 0xE854, 0xE888, 0xE8BC, 0xE8F0, 0xE924,
288 	0xE957, 0xE98B, 0xE9BF, 0xE9F3, 0xEA26, 0xEA5A, 0xEA8E, 0xEAC2,
289 	0xEAF6, 0xEB29, 0xEB5D, 0xEB91, 0xEBC5, 0xEBF9, 0xEC2C, 0xEC60,
290 	0xEC94, 0xECC8, 0xECFB, 0xED2F, 0xED63, 0xED97, 0xEDCB, 0xEDFE,
291 	0xEE32, 0xEE66, 0xEE9A, 0xEECE, 0xEF01, 0xEF35, 0xEF69, 0xEF9D,
292 	0xEFD1, 0xF004, 0xF038, 0xF06C, 0xF0A0, 0xF0D3, 0xF107, 0xF13B,
293 	0xF16F, 0xF1A3, 0xF1D6, 0xF20A, 0xF23E, 0xF272, 0xF2A6, 0xF2D9,
294 	0xF30D, 0xF341, 0xF375, 0xF3A8, 0xF3DC, 0xF410, 0xF444, 0xF478,
295 	0xF4AB, 0xF4DF, 0xF513, 0xF547, 0xF57B, 0xF5AE, 0xF5E2, 0xF616,
296 	0xF64A, 0xF67D, 0xF6B1, 0xF6E5, 0xF719, 0xF74D, 0xF780, 0xF7B4,
297 	0xF7E8, 0xF81C, 0xF850, 0xF883, 0xF8B7, 0xF8EB, 0xF91F, 0xF953,
298 	0xF986, 0xF9BA, 0xF9EE, 0xFA22, 0xFA55, 0xFA89, 0xFABD, 0xFAF1,
299 	0xFB25, 0xFB58, 0xFB8C, 0xFBC0, 0xFBF4, 0xFC28, 0xFC5B, 0xFC8F,
300 	0xFCC3, 0xFCF7, 0xFD2A, 0xFD5E, 0xFD92, 0xFDC6, 0xFDFA, 0xFE2D,
301 	0xFE61, 0xFE95, 0xFEC9, 0xFEFD, 0xFF30, 0xFF64, 0xFF98, 0xFFCC,
302 	//0x280
303 	0x0000, 0x0033, 0x0067, 0x009B, 0x00CF, 0x0102, 0x0136, 0x016A,
304 	0x019E, 0x01D2, 0x0205, 0x0239, 0x026D, 0x02A1, 0x02D5, 0x0308,
305 	0x033C, 0x0370, 0x03A4, 0x03D7, 0x040B, 0x043F, 0x0473, 0x04A7,
306 	0x04DA, 0x050E, 0x0542, 0x0576, 0x05AA, 0x05DD, 0x0611, 0x0645,
307 	0x0679, 0x06AC, 0x06E0, 0x0714, 0x0748, 0x077C, 0x07AF, 0x07E3,
308 	0x0817, 0x084B, 0x087F, 0x08B2, 0x08E6, 0x091A, 0x094E, 0x0982,
309 	0x09B5, 0x09E9, 0x0A1D, 0x0A51, 0x0A84, 0x0AB8, 0x0AEC, 0x0B20,
310 	0x0B54, 0x0B87, 0x0BBB, 0x0BEF, 0x0C23, 0x0C57, 0x0C8A, 0x0CBE,
311 	0x0CF2, 0x0D26, 0x0D59, 0x0D8D, 0x0DC1, 0x0DF5, 0x0E29, 0x0E5C,
312 	0x0E90, 0x0EC4, 0x0EF8, 0x0F2C, 0x0F5F, 0x0F93, 0x0FC7, 0x0FFB,
313 	0x102F, 0x1062, 0x1096, 0x10CA, 0x10FE, 0x1131, 0x1165, 0x1199,
314 	0x11CD, 0x1201, 0x1234, 0x1268, 0x129C, 0x12D0, 0x1304, 0x1337,
315 	0x136B, 0x139F, 0x13D3, 0x1406, 0x143A, 0x146E, 0x14A2, 0x14D6,
316 	0x1509, 0x153D, 0x1571, 0x15A5, 0x15D9, 0x160C, 0x1640, 0x1674,
317 	0x16A8, 0x16DB, 0x170F, 0x1743, 0x1777, 0x17AB, 0x17DE, 0x1812,
318 	0x1846, 0x187A, 0x18AE, 0x18E1, 0x1915, 0x1949, 0x197D, 0x19B1,
319 
320 	0x0769, 0x075A, 0x074B, 0x073D, 0x072E, 0x071F, 0x0710, 0x0701,
321 	0x06F3, 0x06E4, 0x06D5, 0x06C6, 0x06B7, 0x06A8, 0x069A, 0x068B,
322 	0x067C, 0x066D, 0x065E, 0x064F, 0x0641, 0x0632, 0x0623, 0x0614,
323 	0x0605, 0x05F6, 0x05E8, 0x05D9, 0x05CA, 0x05BB, 0x05AC, 0x059E,
324 	0x058F, 0x0580, 0x0571, 0x0562, 0x0553, 0x0545, 0x0536, 0x0527,
325 	0x0518, 0x0509, 0x04FA, 0x04EC, 0x04DD, 0x04CE, 0x04BF, 0x04B0,
326 	0x04A2, 0x0493, 0x0484, 0x0475, 0x0466, 0x0457, 0x0449, 0x043A,
327 	0x042B, 0x041C, 0x040D, 0x03FE, 0x03F0, 0x03E1, 0x03D2, 0x03C3,
328 	0x03B4, 0x03A5, 0x0397, 0x0388, 0x0379, 0x036A, 0x035B, 0x034D,
329 	0x033E, 0x032F, 0x0320, 0x0311, 0x0302, 0x02F4, 0x02E5, 0x02D6,
330 	0x02C7, 0x02B8, 0x02A9, 0x029B, 0x028C, 0x027D, 0x026E, 0x025F,
331 	0x0251, 0x0242, 0x0233, 0x0224, 0x0215, 0x0206, 0x01F8, 0x01E9,
332 	0x01DA, 0x01CB, 0x01BC, 0x01AD, 0x019F, 0x0190, 0x0181, 0x0172,
333 	0x0163, 0x0154, 0x0146, 0x0137, 0x0128, 0x0119, 0x010A, 0x00FC,
334 	0x00ED, 0x00DE, 0x00CF, 0x00C0, 0x00B1, 0x00A3, 0x0094, 0x0085,
335 	0x0076, 0x0067, 0x0058, 0x004A, 0x003B, 0x002C, 0x001D, 0x000E,
336 	//0x380
337 	0x0000, 0xFFF1, 0xFFE2, 0xFFD3, 0xFFC4, 0xFFB5, 0xFFA7, 0xFF98,
338 	0xFF89, 0xFF7A, 0xFF6B, 0xFF5C, 0xFF4E, 0xFF3F, 0xFF30, 0xFF21,
339 	0xFF12, 0xFF03, 0xFEF5, 0xFEE6, 0xFED7, 0xFEC8, 0xFEB9, 0xFEAB,
340 	0xFE9C, 0xFE8D, 0xFE7E, 0xFE6F, 0xFE60, 0xFE52, 0xFE43, 0xFE34,
341 	0xFE25, 0xFE16, 0xFE07, 0xFDF9, 0xFDEA, 0xFDDB, 0xFDCC, 0xFDBD,
342 	0xFDAF, 0xFDA0, 0xFD91, 0xFD82, 0xFD73, 0xFD64, 0xFD56, 0xFD47,
343 	0xFD38, 0xFD29, 0xFD1A, 0xFD0B, 0xFCFD, 0xFCEE, 0xFCDF, 0xFCD0,
344 	0xFCC1, 0xFCB2, 0xFCA4, 0xFC95, 0xFC86, 0xFC77, 0xFC68, 0xFC5A,
345 	0xFC4B, 0xFC3C, 0xFC2D, 0xFC1E, 0xFC0F, 0xFC01, 0xFBF2, 0xFBE3,
346 	0xFBD4, 0xFBC5, 0xFBB6, 0xFBA8, 0xFB99, 0xFB8A, 0xFB7B, 0xFB6C,
347 	0xFB5E, 0xFB4F, 0xFB40, 0xFB31, 0xFB22, 0xFB13, 0xFB05, 0xFAF6,
348 	0xFAE7, 0xFAD8, 0xFAC9, 0xFABA, 0xFAAC, 0xFA9D, 0xFA8E, 0xFA7F,
349 	0xFA70, 0xFA61, 0xFA53, 0xFA44, 0xFA35, 0xFA26, 0xFA17, 0xFA09,
350 	0xF9FA, 0xF9EB, 0xF9DC, 0xF9CD, 0xF9BE, 0xF9B0, 0xF9A1, 0xF992,
351 	0xF983, 0xF974, 0xF965, 0xF957, 0xF948, 0xF939, 0xF92A, 0xF91B,
352 	0xF90D, 0xF8FE, 0xF8EF, 0xF8E0, 0xF8D1, 0xF8C2, 0xF8B4, 0xF8A5,
353 
354 	0x050C, 0x0502, 0x04F8, 0x04EE, 0x04E4, 0x04DA, 0x04D0, 0x04C6,
355 	0x04BC, 0x04B1, 0x04A7, 0x049D, 0x0493, 0x0489, 0x047F, 0x0475,
356 	0x046B, 0x0461, 0x0457, 0x044C, 0x0442, 0x0438, 0x042E, 0x0424,
357 	0x041A, 0x0410, 0x0406, 0x03FC, 0x03F2, 0x03E7, 0x03DD, 0x03D3,
358 	0x03C9, 0x03BF, 0x03B5, 0x03AB, 0x03A1, 0x0397, 0x038D, 0x0382,
359 	0x0378, 0x036E, 0x0364, 0x035A, 0x0350, 0x0346, 0x033C, 0x0332,
360 	0x0328, 0x031D, 0x0313, 0x0309, 0x02FF, 0x02F5, 0x02EB, 0x02E1,
361 	0x02D7, 0x02CD, 0x02C3, 0x02B8, 0x02AE, 0x02A4, 0x029A, 0x0290,
362 	0x0286, 0x027C, 0x0272, 0x0268, 0x025E, 0x0253, 0x0249, 0x023F,
363 	0x0235, 0x022B, 0x0221, 0x0217, 0x020D, 0x0203, 0x01F9, 0x01EE,
364 	0x01E4, 0x01DA, 0x01D0, 0x01C6, 0x01BC, 0x01B2, 0x01A8, 0x019E,
365 	0x0194, 0x0189, 0x017F, 0x0175, 0x016B, 0x0161, 0x0157, 0x014D,
366 	0x0143, 0x0139, 0x012F, 0x0124, 0x011A, 0x0110, 0x0106, 0x00FC,
367 	0x00F2, 0x00E8, 0x00DE, 0x00D4, 0x00CA, 0x00BF, 0x00B5, 0x00AB,
368 	0x00A1, 0x0097, 0x008D, 0x0083, 0x0079, 0x006F, 0x0065, 0x005A,
369 	0x0050, 0x0046, 0x003C, 0x0032, 0x0028, 0x001E, 0x0014, 0x000A,
370 	//0x480
371 	0x0000, 0xFFF5, 0xFFEB, 0xFFE1, 0xFFD7, 0xFFCD, 0xFFC3, 0xFFB9,
372 	0xFFAF, 0xFFA5, 0xFF9B, 0xFF90, 0xFF86, 0xFF7C, 0xFF72, 0xFF68,
373 	0xFF5E, 0xFF54, 0xFF4A, 0xFF40, 0xFF36, 0xFF2B, 0xFF21, 0xFF17,
374 	0xFF0D, 0xFF03, 0xFEF9, 0xFEEF, 0xFEE5, 0xFEDB, 0xFED1, 0xFEC6,
375 	0xFEBC, 0xFEB2, 0xFEA8, 0xFE9E, 0xFE94, 0xFE8A, 0xFE80, 0xFE76,
376 	0xFE6C, 0xFE61, 0xFE57, 0xFE4D, 0xFE43, 0xFE39, 0xFE2F, 0xFE25,
377 	0xFE1B, 0xFE11, 0xFE07, 0xFDFC, 0xFDF2, 0xFDE8, 0xFDDE, 0xFDD4,
378 	0xFDCA, 0xFDC0, 0xFDB6, 0xFDAC, 0xFDA2, 0xFD97, 0xFD8D, 0xFD83,
379 	0xFD79, 0xFD6F, 0xFD65, 0xFD5B, 0xFD51, 0xFD47, 0xFD3D, 0xFD32,
380 	0xFD28, 0xFD1E, 0xFD14, 0xFD0A, 0xFD00, 0xFCF6, 0xFCEC, 0xFCE2,
381 	0xFCD8, 0xFCCD, 0xFCC3, 0xFCB9, 0xFCAF, 0xFCA5, 0xFC9B, 0xFC91,
382 	0xFC87, 0xFC7D, 0xFC73, 0xFC68, 0xFC5E, 0xFC54, 0xFC4A, 0xFC40,
383 	0xFC36, 0xFC2C, 0xFC22, 0xFC18, 0xFC0E, 0xFC03, 0xFBF9, 0xFBEF,
384 	0xFBE5, 0xFBDB, 0xFBD1, 0xFBC7, 0xFBBD, 0xFBB3, 0xFBA9, 0xFB9E,
385 	0xFB94, 0xFB8A, 0xFB80, 0xFB76, 0xFB6C, 0xFB62, 0xFB58, 0xFB4E,
386 	0xFB44, 0xFB39, 0xFB2F, 0xFB25, 0xFB1B, 0xFB11, 0xFB07, 0xFAFD
387 };
388 
389 #define DCTV_BUFFER_SIZE 1000
390 static uae_s8 dctv_chroma[2 * DCTV_BUFFER_SIZE];
391 static uae_u8 dctv_luma[2 * DCTV_BUFFER_SIZE];
392 
393 
minmax(int v,int min,int max)394 STATIC_INLINE int minmax(int v, int min, int max)
395 {
396 	if (v < min)
397 		v = min;
398 	if (v > max)
399 		v = max;
400 	return v;
401 }
402 
403 #define DCTV_SIGNATURE_DEBUG 0
404 #if DCTV_SIGNATURE_DEBUG
405 static int signature_test_y = 0x93;
406 #endif
407 
dctv(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines)408 static bool dctv(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
409 {
410 	int y, x, vdbl, hdbl;
411 	int ystart, yend, isntsc;
412 	int xadd;
413 
414 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
415 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
416 		isntsc = currprefs.ntscmode ? 1 : 0;
417 
418 	vdbl = gfxvidinfo.ychange;
419 	hdbl = gfxvidinfo.xchange;
420 
421 	xadd = ((1 << 1) / hdbl) * src->pixbytes;
422 
423 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
424 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
425 
426 	int signature_detected = -1;
427 	int signature_cnt = 0;
428 	bool dctv_enabled = false;
429 	int ycnt = 0;
430 	memset(dctv_luma, 64, sizeof DCTV_BUFFER_SIZE);
431 
432 	for (y = ystart; y < yend; y++) {
433 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
434 		if (yoff < 0)
435 			continue;
436 		if (yoff >= src->inheight)
437 			continue;
438 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
439 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
440 
441 		int firstnz = -1;
442 		bool sign = false;
443 		int oddeven = 0;
444 		uae_u8 prev = 0;
445 		uae_u8 vals[3] = { 0x40, 0x40, 0x40 };
446 		int zigzagoffset = 0;
447 		int prevtval = 0;
448 		uae_s8 *chrbuf_w = NULL, *chrbuf_r1 = NULL, *chrbuf_r2 = NULL;
449 		uae_u8 *lumabuf1 = dctv_luma, *lumabuf2 = dctv_luma;
450 
451 		ycnt++;
452 
453 #if DCTV_SIGNATURE_DEBUG
454 		uae_u8 signx = 0;
455 		uae_u8 signmask = 0xff;
456 		if (y == signature_test_y + 1)
457 			write_log(_T("\n"));
458 #endif
459 
460 		for (x = 0; x < src->inwidth; x++) {
461 			uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
462 			uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes + zigzagoffset;
463 			uae_u8 *s2 = s + src->rowbytes;
464 			uae_u8 *d2 = d + dst->rowbytes;
465 			uae_u8 newval = DCTV_FIRBG(src, s);
466 
467 			int mask = 1 << (7 - (signature_cnt & 7));
468 			int bitval = (newval & 0x40) ? mask : 0;
469 			if ((dctv_signature[signature_cnt / 8] & mask) == bitval) {
470 				signature_cnt++;
471 				if (signature_cnt == sizeof (dctv_signature) * 8) {
472 					dctv_enabled = true;
473 					signature_detected = y;
474 				}
475 			} else {
476 				signature_cnt = 0;
477 			}
478 
479 #if DCTV_SIGNATURE_DEBUG
480 			if (y == signature_test_y) {
481 				if ((newval & 0x40) && signmask == 0xff)
482 					signmask = 0x80;
483 				if (signmask != 0xff) {
484 					if (newval & 0x40)
485 						signx |= signmask;
486 					signmask >>= 1;
487 					if (!signmask) {
488 						signmask = 0x80;
489 						write_log(_T("%02x."), signx);
490 						signx = 0;
491 					}
492 				}
493 			}
494 #endif
495 			if (!dctv_enabled || signature_detected == y) {
496 				PUT_AMIGARGB(d, s, d2, s2, dst, 0, doublelines, false);
497 				continue;
498 			}
499 
500 			uae_u8 val = prev | newval;
501 			if (firstnz < 0 && newval) {
502 				firstnz = 0;
503 				if (ycnt & 1) {
504 					zigzagoffset = 0;
505 					oddeven = -1;
506 					chrbuf_w = dctv_chroma + 8;
507 					chrbuf_r1 = dctv_chroma + 8;
508 					chrbuf_r2 = dctv_chroma + DCTV_BUFFER_SIZE + 8;
509 				} else {
510 					zigzagoffset = dst->pixbytes;
511 					oddeven = -1;
512 					chrbuf_w = dctv_chroma + DCTV_BUFFER_SIZE + 8;
513 					chrbuf_r2 = dctv_chroma + 8;
514 					chrbuf_r1 = dctv_chroma + DCTV_BUFFER_SIZE + 8;
515 				}
516 				sign = false;
517 			}
518 
519 			if (oddeven > 0 && !firstnz) {
520 				sign = !sign;
521 
522 				if (val == 0)
523 					val = 64;
524 
525 				vals[2] = vals[1];
526 				vals[1] = vals[0];
527 				vals[0] = val;
528 
529 				int v0 = 2 * vals[1] - vals[2] - vals[0] + 2;
530 				if (v0 < 0)
531 					v0 += 3;
532 				v0 /= 4;
533 				int v1 = -v0;
534 				if (sign)
535 					v0 = -v0;
536 				*chrbuf_w = minmax(v0, -127, 127);
537 				*lumabuf1 = minmax(vals[2] + v1, 64, 224);
538 
539 				int ch1 = chrbuf_r1[0] + chrbuf_r1[-1];
540 				int ch2 = chrbuf_r2[0] + chrbuf_r2[-1];
541 				ch1 /= 2;
542 				ch2 /= 2;
543 
544 				int luma = lumabuf1[-1] * 2 + lumabuf1[-2] + lumabuf1[0];
545 				luma /= 4;
546 
547 				int l = (uae_s16)dctv_tables[luma];
548 
549 				int rr = (uae_s16)dctv_tables[ch1 + 0x180] + l;
550 				int gg = (uae_s16)dctv_tables[ch1 + 0x380] + (uae_s16)dctv_tables[ch2 + 0x480] + l;
551 				int bb = (uae_s16)dctv_tables[ch2 + 0x280] + l;
552 
553 				uae_u8 r = minmax(rr >> 4, 0, 255);
554 				uae_u8 g = minmax(gg >> 4, 0, 255);
555 				uae_u8 b = minmax(bb >> 4, 0, 255);
556 
557 				PRGB(dst, d - dst->pixbytes, r, g, b);
558 				PRGB(dst, d, r, g, b);
559 				if (doublelines) {
560 					PRGB(dst, d2 - dst->pixbytes, r, g, b);
561 					PRGB(dst, d2, r, g, b);
562 				}
563 
564 				chrbuf_r1++;
565 				chrbuf_r2++;
566 				chrbuf_w++;
567 				lumabuf1++;
568 
569 			} else if (oddeven < 0) {
570 
571 				uae_u8 r = 0, b = 0, g = 0;
572 				PRGB(dst, d - dst->pixbytes, r, g, b);
573 				PRGB(dst, d, r, g, b);
574 				if (doublelines) {
575 					PRGB(dst, d2 - dst->pixbytes, r, g, b);
576 					PRGB(dst, d2, r, g, b);
577 				}
578 
579 			}
580 
581 			if (oddeven >= 0)
582 				oddeven = oddeven ? 0 : 1;
583 			else
584 				oddeven++;
585 			prev = newval << 1;
586 		}
587 	}
588 
589 	if (dctv_enabled) {
590 		dst->nativepositioning = true;
591 		if (monitor != MONITOREMU_DCTV) {
592 			monitor = MONITOREMU_DCTV;
593 			write_log(_T("DCTV mode\n"));
594 		}
595 	}
596 
597 	return dctv_enabled;
598 
599 }
600 
do_dctv(struct vidbuffer * src,struct vidbuffer * dst)601 static bool do_dctv(struct vidbuffer *src, struct vidbuffer *dst)
602 {
603 	bool v;
604 	if (interlace_seen) {
605 		if (currprefs.gfx_iscanlines) {
606 			v = dctv(src, dst, false, lof_store ? 0 : 1);
607 			if (v && currprefs.gfx_iscanlines > 1)
608 				blank_generic(src, dst, lof_store ? 1 : 0);
609 		} else {
610 			v = dctv(src, dst, false, 0);
611 			v |= dctv(src, dst, false, 1);
612 		}
613 	} else {
614 		v = dctv(src, dst, true, 0);
615 	}
616 	return v;
617 }
618 
619 static uae_u8 *sm_frame_buffer;
620 #define SM_VRAM_WIDTH 1024
621 #define SM_VRAM_HEIGHT 800
622 #define SM_VRAM_BYTES 4
623 static int sm_configured;
624 static uae_u8 sm_acmemory[128];
625 
sm_alloc_fb(void)626 static void sm_alloc_fb(void)
627 {
628 	if (!sm_frame_buffer) {
629 		sm_frame_buffer = xcalloc(uae_u8, SM_VRAM_WIDTH * SM_VRAM_HEIGHT * SM_VRAM_BYTES);
630 	}
631 }
sm_free(void)632 static void sm_free(void)
633 {
634 	xfree(sm_frame_buffer);
635 	sm_frame_buffer = NULL;
636 	sm_configured = 0;
637 }
638 
639 #define FC24_MAXHEIGHT 482
640 static uae_u8 fc24_mode, fc24_cr0, fc24_cr1;
641 static uae_u16 fc24_hpos, fc24_vpos, fc24_width;
642 static int fc24_offset;
643 
MAKEFCOVERLAY(uae_u8 v)644 STATIC_INLINE uae_u8 MAKEFCOVERLAY(uae_u8 v)
645 {
646 	v &= 3;
647 	v |= v << 2;
648 	v |= v << 4;
649 	v |= v << 6;
650 	return v;
651 }
652 
firecracker24(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines)653 static bool firecracker24(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
654 {
655 	int y, x, vdbl, hdbl;
656 	int fc24_y, fc24_x, fc24_dx, fc24_xadd, fc24_xmult, fc24_xoffset;
657 	int ystart, yend, isntsc;
658 	int xadd, xaddfc;
659 	int bufferoffset;
660 
661 	// FC disabled and Amiga enabled?
662 	if (!(fc24_cr1 & 1) && !(fc24_cr0 & 1))
663 		return false;
664 
665 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
666 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
667 		isntsc = currprefs.ntscmode ? 1 : 0;
668 
669 	vdbl = gfxvidinfo.ychange;
670 	hdbl = gfxvidinfo.xchange; // 4=lores,2=hires,1=shres
671 
672 	xaddfc = (1 << 1) / hdbl; // 0=lores,1=hires,2=shres
673 	xadd = xaddfc * src->pixbytes;
674 
675 
676 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
677 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
678 
679 	switch (fc24_width)
680 	{
681 		case 384:
682 		fc24_xmult = 0;
683 		break;
684 		case 512:
685 		fc24_xmult = 1;
686 		break;
687 		case 768:
688 		fc24_xmult = 1;
689 		break;
690 		case 1024:
691 		fc24_xmult = 2;
692 		break;
693 		default:
694 		return false;
695 	}
696 
697 	if (fc24_xmult >= xaddfc) {
698 		fc24_xadd = fc24_xmult - xaddfc;
699 		fc24_dx = 0;
700 	} else {
701 		fc24_xadd = 0;
702 		fc24_dx = xaddfc - fc24_xmult;
703 	}
704 
705 	fc24_xoffset = ((src->inwidth - ((fc24_width << fc24_dx) >> fc24_xadd)) / 2);
706 	fc24_xadd = 1 << fc24_xadd;
707 
708 	bufferoffset = (fc24_cr0 & 2) ? 512 * SM_VRAM_BYTES: 0;
709 
710 	fc24_y = 0;
711 	for (y = ystart; y < yend; y++) {
712 		int oddeven = 0;
713 		uae_u8 prev = 0;
714 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
715 		if (yoff < 0)
716 			continue;
717 		if (yoff >= src->inheight)
718 			continue;
719 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
720 		uae_u8 *line_genlock = row_map_genlock[yoff];
721 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
722 		uae_u8 *vramline = sm_frame_buffer + (fc24_y + oddlines) * SM_VRAM_WIDTH * SM_VRAM_BYTES + bufferoffset;
723 		fc24_x = 0;
724 		for (x = 0; x < src->inwidth; x++) {
725 			uae_u8 r = 0, g = 0, b = 0;
726 			uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
727 			uae_u8 *s_genlock = line_genlock + ((x << 1) / hdbl);
728 			uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes;
729 			int fc24_xx = (fc24_x >> fc24_dx) - fc24_xoffset;
730 			uae_u8 *vramptr = NULL;
731 			if (fc24_xx >= 0 && fc24_xx < fc24_width && fc24_y >= 0 && fc24_y < FC24_MAXHEIGHT) {
732 				vramptr = vramline + fc24_xx * SM_VRAM_BYTES;
733 				uae_u8 ax = vramptr[0];
734 				if (ax & 0x40) {
735 					r = MAKEFCOVERLAY(ax >> 4);
736 					g = MAKEFCOVERLAY(ax >> 2);
737 					b = MAKEFCOVERLAY(ax >> 0);
738 				} else {
739 					r = vramptr[1];
740 					g = vramptr[2];
741 					b = vramptr[3];
742 				}
743 			}
744 			if (!(fc24_cr0 & 1) && (!(fc24_cr1 & 1) || (!is_transparent(s_genlock[0])))) {
745 				uae_u8 *s2 = s + src->rowbytes;
746 				uae_u8 *d2 = d + dst->rowbytes;
747 				PUT_AMIGARGB(d, s, d2, s2, dst, xadd, doublelines, false);
748 			} else {
749 				PUT_PRGB(d, NULL, dst, r, g, b, 0, false, false);
750 				if (doublelines) {
751 					if (vramptr) {
752 						vramptr += SM_VRAM_WIDTH * SM_VRAM_BYTES;
753 						uae_u8 ax = vramptr[0];
754 						if (ax & 0x40) {
755 							r = MAKEFCOVERLAY(ax >> 4);
756 							g = MAKEFCOVERLAY(ax >> 2);
757 							b = MAKEFCOVERLAY(ax >> 0);
758 						} else {
759 							r = vramptr[1];
760 							g = vramptr[2];
761 							b = vramptr[3];
762 						}
763 					}
764 					PUT_PRGB(d + dst->rowbytes, NULL, dst, r, g, b, 0, false, false);
765 				}
766 			}
767 			fc24_x += fc24_xadd;
768 		}
769 		fc24_y += 2;
770 	}
771 
772 	dst->nativepositioning = true;
773 	if (monitor != MONITOREMU_FIRECRACKER24) {
774 		monitor = MONITOREMU_FIRECRACKER24;
775 		write_log(_T("FireCracker mode\n"));
776 	}
777 
778 	return true;
779 }
780 
fc24_setoffset(void)781 static void fc24_setoffset(void)
782 {
783 	fc24_vpos &= 511;
784 	fc24_hpos &= 1023;
785 	fc24_offset = fc24_vpos * SM_VRAM_WIDTH * SM_VRAM_BYTES + fc24_hpos * SM_VRAM_BYTES;
786 	sm_alloc_fb();
787 }
788 
fc24_inc(uaecptr addr,bool write)789 static void fc24_inc(uaecptr addr, bool write)
790 {
791 	addr &= 65535;
792 	if (addr >= 6) {
793 		fc24_hpos++;
794 		if (fc24_hpos >= 1024) {
795 			fc24_hpos = 0;
796 			fc24_vpos++;
797 			fc24_vpos &= 511;
798 		}
799 		fc24_setoffset();
800 	}
801 }
802 
fc24_setmode(void)803 static void fc24_setmode(void)
804 {
805 	switch (fc24_cr0 >> 6)
806 	{
807 		case 0:
808 		fc24_width = 384;
809 		break;
810 		case 1:
811 		fc24_width = 512;
812 		break;
813 		case 2:
814 		fc24_width = 768;
815 		break;
816 		case 3:
817 		fc24_width = 1024;
818 		break;
819 	}
820 	sm_alloc_fb();
821 }
822 
fc24_reset(void)823 static void fc24_reset(void)
824 {
825 	if (currprefs.monitoremu != MONITOREMU_FIRECRACKER24)
826 		return;
827 	fc24_cr0 = 0;
828 	fc24_cr1 = 0;
829 	fc24_setmode();
830 	fc24_setoffset();
831 }
832 
firecracker24_write_byte(uaecptr addr,uae_u8 v)833 static void firecracker24_write_byte(uaecptr addr, uae_u8 v)
834 {
835 	addr &= 65535;
836 	switch (addr)
837 	{
838 		default:
839 		if (!sm_frame_buffer)
840 			return;
841 		sm_frame_buffer[fc24_offset + (addr & 3)] = v;
842 		break;
843 		case 10:
844 		fc24_cr0 = v;
845 		fc24_setmode();
846 		write_log(_T("FC24_CR0 = %02x\n"), fc24_cr0);
847 		break;
848 		case 11:
849 		fc24_cr1 = v;
850 		sm_alloc_fb();
851 		write_log(_T("FC24_CR1 = %02x\n"), fc24_cr1);
852 		break;
853 		case 12:
854 		fc24_vpos &= 0x00ff;
855 		fc24_vpos |= v << 8;
856 		fc24_setoffset();
857 		break;
858 		case 13:
859 		fc24_vpos &= 0xff00;
860 		fc24_vpos |= v;
861 		fc24_setoffset();
862 		//write_log(_T("V=%d "), fc24_vpos);
863 		break;
864 		case 14:
865 		fc24_hpos &= 0x00ff;
866 		fc24_hpos |= v << 8;
867 		fc24_setoffset();
868 		break;
869 		case 15:
870 		fc24_hpos &= 0xff00;
871 		fc24_hpos |= v;
872 		fc24_setoffset();
873 		//write_log(_T("H=%d "), fc24_hpos);
874 		break;
875 	}
876 }
877 
firecracker24_read_byte(uaecptr addr)878 static uae_u8 firecracker24_read_byte(uaecptr addr)
879 {
880 	uae_u8 v = 0;
881 	addr &= 65535;
882 	switch (addr)
883 	{
884 		default:
885 		if (!sm_frame_buffer)
886 			return v;
887 		v = sm_frame_buffer[fc24_offset + (addr & 3)];
888 		break;
889 		case 10:
890 		v = fc24_cr0;
891 		break;
892 		case 11:
893 		v = fc24_cr1;
894 		break;
895 		case 12:
896 		v = fc24_vpos >> 8;
897 		break;
898 		case 13:
899 		v = fc24_vpos >> 0;
900 		break;
901 		case 14:
902 		v = fc24_hpos >> 8;
903 		break;
904 		case 15:
905 		v = fc24_hpos >> 0;
906 		break;
907 	}
908 	return v;
909 }
910 
firecracker24_write(uaecptr addr,uae_u32 v,int size)911 static void firecracker24_write(uaecptr addr, uae_u32 v, int size)
912 {
913 	int offset = addr & 3;
914 	uaecptr oaddr = addr;
915 	int shift = 8 * (size - 1);
916 	while (size > 0 && addr < 10) {
917 		int off = fc24_offset + offset;
918 		if ((offset & 3) == 0) {
919 			if (!(fc24_cr1 & 0x80))
920 				sm_frame_buffer[off] = v >> shift;
921 		} else {
922 			sm_frame_buffer[off] = v >> shift;
923 		}
924 		offset++;
925 		size--;
926 		shift -= 8;
927 		addr++;
928 	}
929 	fc24_inc(oaddr, true);
930 }
931 
firecracker24_read(uaecptr addr,int size)932 static uae_u32 firecracker24_read(uaecptr addr, int size)
933 {
934 	uae_u32 v = 0;
935 	uaecptr oaddr = addr;
936 	int offset = addr & 3;
937 	while (size > 0 && addr < 10) {
938 		v <<= 8;
939 		v |= sm_frame_buffer[fc24_offset + offset];
940 		offset++;
941 		size--;
942 		addr++;
943 	}
944 	fc24_inc(oaddr, false);
945 	return v;
946 }
947 
948 extern addrbank specialmonitors_bank;
949 
sm_bput(uaecptr addr,uae_u32 b)950 static void REGPARAM2 sm_bput(uaecptr addr, uae_u32 b)
951 {
952 	b &= 0xff;
953 	addr &= 65535;
954 	if (!sm_configured) {
955 		switch (addr) {
956 			case 0x48:
957 			map_banks_z2(&specialmonitors_bank, expamem_z2_pointer >> 16, 65536 >> 16);
958 			sm_configured = 1;
959 			expamem_next(&specialmonitors_bank, NULL);
960 			break;
961 			case 0x4c:
962 			sm_configured = -1;
963 			expamem_shutup(&specialmonitors_bank);
964 			break;
965 		}
966 		return;
967 	}
968 	if (sm_configured > 0) {
969 		if (addr < 10) {
970 			firecracker24_write(addr, b, 1);
971 		} else {
972 			firecracker24_write_byte(addr, b);
973 		}
974 	}
975 }
sm_wput(uaecptr addr,uae_u32 b)976 static void REGPARAM2 sm_wput(uaecptr addr, uae_u32 b)
977 {
978 	addr &= 65535;
979 	if (addr < 10) {
980 		firecracker24_write(addr, b, 2);
981 	} else {
982 		firecracker24_write_byte(addr + 0, b >> 8);
983 		firecracker24_write_byte(addr + 1, b >> 0);
984 	}
985 }
986 
sm_lput(uaecptr addr,uae_u32 b)987 static void REGPARAM2 sm_lput(uaecptr addr, uae_u32 b)
988 {
989 	addr &= 65535;
990 	if (addr < 10) {
991 		firecracker24_write(addr + 0, b >> 16, 2);
992 		firecracker24_write(addr + 2, b >>  0, 2);
993 	} else {
994 		firecracker24_write_byte(addr + 0, b >> 24);
995 		firecracker24_write_byte(addr + 1, b >> 16);
996 		firecracker24_write_byte(addr + 2, b >> 8);
997 		firecracker24_write_byte(addr + 3, b >> 0);
998 	}
999 }
sm_bget(uaecptr addr)1000 static uae_u32 REGPARAM2 sm_bget(uaecptr addr)
1001 {
1002 	uae_u8 v = 0;
1003 	addr &= 65535;
1004 	if (!sm_configured) {
1005 		if (addr >= sizeof sm_acmemory)
1006 			return 0;
1007 		return sm_acmemory[addr];
1008 	}
1009 	if (sm_configured > 0) {
1010 		if (addr < 10) {
1011 			v = firecracker24_read(addr, 1);
1012 		} else {
1013 			v = firecracker24_read_byte(addr);
1014 		}
1015 	}
1016 	return v;
1017 }
sm_wget(uaecptr addr)1018 static uae_u32 REGPARAM2 sm_wget(uaecptr addr)
1019 {
1020 	uae_u16 v;
1021 	addr &= 65535;
1022 	if (addr < 10) {
1023 		v = firecracker24_read(addr, 2);
1024 	} else {
1025 		v = firecracker24_read_byte(addr) << 8;
1026 		v |= firecracker24_read_byte(addr + 1) << 0;
1027 	}
1028 	return v;
1029 }
sm_lget(uaecptr addr)1030 static uae_u32 REGPARAM2 sm_lget(uaecptr addr)
1031 {
1032 	uae_u32 v;
1033 	addr &= 65535;
1034 	if (addr < 10) {
1035 		v  = firecracker24_read(addr + 0, 2) << 16;
1036 		v |= firecracker24_read(addr + 2, 2) <<  0;
1037 	} else {
1038 		v = firecracker24_read_byte(addr) << 24;
1039 		v |= firecracker24_read_byte(addr + 1) << 16;
1040 		v |= firecracker24_read_byte(addr + 2) << 8;
1041 		v |= firecracker24_read_byte(addr + 3) << 0;
1042 	}
1043 	return v;
1044 }
1045 
1046 addrbank specialmonitors_bank = {
1047 	sm_lget, sm_wget, sm_bget,
1048 	sm_lput, sm_wput, sm_bput,
1049 	default_xlate, default_check, NULL, NULL, _T("DisplayAdapter"),
1050 	dummy_lgeti, dummy_wgeti,
1051 	ABFLAG_IO, S_READ, S_WRITE
1052 };
1053 
ew(int addr,uae_u32 value)1054 static void ew(int addr, uae_u32 value)
1055 {
1056 	addr &= 0xffff;
1057 	if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
1058 		sm_acmemory[addr] = (value & 0xf0);
1059 		sm_acmemory[addr + 2] = (value & 0x0f) << 4;
1060 	} else {
1061 		sm_acmemory[addr] = ~(value & 0xf0);
1062 		sm_acmemory[addr + 2] = ~((value & 0x0f) << 4);
1063 	}
1064 }
1065 
1066 static const uae_u8 firecracker24_autoconfig[16] = { 0xc1, 0, 0, 0, 2104 >> 8, 2104 & 255 };
1067 
specialmonitor_autoconfig_init(int devnum)1068 addrbank *specialmonitor_autoconfig_init(int devnum)
1069 {
1070 	sm_configured = 0;
1071 	memset(sm_acmemory, 0xff, sizeof sm_acmemory);
1072 	for (int i = 0; i < 16; i++) {
1073 		uae_u8 b = firecracker24_autoconfig[i];
1074 		ew(i * 4, b);
1075 	}
1076 	return &specialmonitors_bank;
1077 }
1078 
do_firecracker24(struct vidbuffer * src,struct vidbuffer * dst)1079 static bool do_firecracker24(struct vidbuffer *src, struct vidbuffer *dst)
1080 {
1081 	bool v;
1082 	if (interlace_seen) {
1083 		if (currprefs.gfx_iscanlines) {
1084 			v = firecracker24(src, dst, false, lof_store ? 0 : 1);
1085 			if (v && currprefs.gfx_iscanlines > 1)
1086 				blank_generic(src, dst, lof_store ? 1 : 0);
1087 		} else {
1088 			v = firecracker24(src, dst, false, 0);
1089 			v |= firecracker24(src, dst, false, 1);
1090 		}
1091 	} else {
1092 		v = firecracker24(src, dst, true, 0);
1093 	}
1094 	return v;
1095 }
1096 
1097 static uae_u16 avideo_previous_fmode[2];
1098 static int av24_offset[2];
1099 static int av24_doublebuffer[2];
1100 static int av24_writetovram[2];
1101 static int av24_mode[2];
1102 static int avideo_allowed;
1103 
avideo(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines,int lof)1104 static bool avideo(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines, int lof)
1105 {
1106 	int y, x, vdbl, hdbl;
1107 	int ystart, yend, isntsc;
1108 	int xadd, xaddpix;
1109 	int mode;
1110 	int offset = -1;
1111 	bool writetovram;
1112 	bool av24;
1113 	int doublebuffer = -1;
1114 	uae_u16 fmode;
1115 
1116 	fmode = avideo_previous_fmode[lof];
1117 
1118 	if (currprefs.monitoremu == MONITOREMU_AUTO) {
1119 		if (!avideo_allowed)
1120 			return false;
1121 		av24 = avideo_allowed == 24;
1122 	} else {
1123 		av24 = currprefs.monitoremu == MONITOREMU_AVIDEO24;
1124 	}
1125 
1126 	if (currprefs.chipset_mask & CSMASK_AGA)
1127 		return false;
1128 
1129 	if (av24) {
1130 		writetovram = av24_writetovram[lof] != 0;
1131 		mode = av24_mode[lof];
1132 	} else {
1133 		mode = fmode & 7;
1134 		if (mode == 1)
1135 			offset = 0;
1136 		else if (mode == 3)
1137 			offset = 1;
1138 		else if (mode == 2)
1139 			offset = 2;
1140 		writetovram = offset >= 0;
1141 	}
1142 
1143 	if (!mode)
1144 		return false;
1145 
1146 	sm_alloc_fb();
1147 
1148 	//write_log(_T("%04x %d %d %d\n"), avideo_previous_fmode[oddlines], mode, offset, writetovram);
1149 
1150 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
1151 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
1152 		isntsc = currprefs.ntscmode ? 1 : 0;
1153 
1154 	vdbl = gfxvidinfo.ychange;
1155 	hdbl = gfxvidinfo.xchange;
1156 
1157 	xaddpix = (1 << 1) / hdbl;
1158 	xadd = ((1 << 1) / hdbl) * src->pixbytes;
1159 
1160 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
1161 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
1162 
1163 	for (y = ystart; y < yend; y++) {
1164 		int oddeven = 0;
1165 		uae_u8 prev = 0;
1166 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
1167 		if (yoff < 0)
1168 			continue;
1169 		if (yoff >= src->inheight)
1170 			continue;
1171 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
1172 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
1173 		uae_u8 *vramline = sm_frame_buffer + y * 2 * SM_VRAM_WIDTH * SM_VRAM_BYTES;
1174 
1175 		if (av24) {
1176 			vramline += av24_offset[lof];
1177 		} else {
1178 			if (fmode & 0x10)
1179 				vramline += SM_VRAM_WIDTH * SM_VRAM_BYTES;
1180 		}
1181 
1182 		for (x = 0; x < src->inwidth; x++) {
1183 			uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
1184 			uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes;
1185 			uae_u8 *vramptr = vramline + ((x << 1) / hdbl) * SM_VRAM_BYTES;
1186 			uae_u8 *s2 = s + src->rowbytes;
1187 			uae_u8 *d2 = d + dst->rowbytes;
1188 			if (writetovram) {
1189 				uae_u8 val[3];
1190 				val[0] = FVR(src, s) >> 4;
1191 				val[1] = FVG(src, s) >> 4;
1192 				val[2] = FVB(src, s) >> 4;
1193 				if (av24) {
1194 					uae_u8 v;
1195 
1196 					/*
1197 					R3 = 20 08 08 08
1198 					R2 = 20 01 01 01
1199 					R1 = 10 02 02 02
1200 					R0 = 08 04 04 04
1201 
1202 					G3 = 20 04 04 04
1203 					G2 = 10 08 08 08
1204 					G1 = 10 01 01 01
1205 					G0 = 08 02 02 02
1206 
1207 					B3 = 20 02 02 02
1208 					B2 = 10 04 04 04
1209 					B1 = 08 08 08 08
1210 					B0 = 08 01 01 01
1211 					*/
1212 
1213 					uae_u8 rval = vramptr[0];
1214 					uae_u8 gval = vramptr[1];
1215 					uae_u8 bval = vramptr[2];
1216 
1217 					/* This probably should use lookup tables.. */
1218 
1219 					if (fmode & 0x01) { // Red (low)
1220 
1221 						v = (((val[0] >> 2) & 1) << 0);
1222 						rval &= ~(0x01);
1223 						rval |= v;
1224 
1225 						v = (((val[1] >> 1) & 1) << 0);
1226 						gval &= ~(0x01);
1227 						gval |= v;
1228 
1229 						v = (((val[2] >> 3) & 1) << 1) | (((val[2] >> 0) & 1) << 0);
1230 						bval &= ~(0x02 | 0x01);
1231 						bval |= v;
1232 					}
1233 
1234 					if (fmode & 0x02) { // Green (low)
1235 
1236 						v = (((val[0] >> 1) & 1) << 1);
1237 						rval &= ~(0x02);
1238 						rval |= v;
1239 
1240 						v = (((val[1] >> 0) & 1) << 1) | (((val[1] >> 3) & 1) << 2);
1241 						gval &= ~(0x02 | 0x04);
1242 						gval |= v;
1243 
1244 						v = (((val[2] >> 2) & 1) << 2);
1245 						bval &= ~(0x04);
1246 						bval |= v;
1247 					}
1248 
1249 					if (fmode & 0x04) { // Blue (low)
1250 
1251 						v = (((val[0] >> 0) & 1) << 2) | (((val[0] >> 3) & 1) << 3);
1252 						rval &= ~(0x04 | 0x08);
1253 						rval |= v;
1254 
1255 						v = (((val[1] >> 2) & 1) << 3);
1256 						gval &= ~(0x08);
1257 						gval |= v;
1258 
1259 						v = (((val[2] >> 1) & 1) << 3);
1260 						bval &= ~(0x08);
1261 						bval |= v;
1262 					}
1263 
1264 					if (fmode & 0x08) { // Red (high)
1265 
1266 						v = (((val[0] >> 2) & 1) << 4);
1267 						rval &= ~(0x10);
1268 						rval |= v;
1269 
1270 						v = (((val[1] >> 1) & 1) << 4);
1271 						gval &= ~(0x10);
1272 						gval |= v;
1273 
1274 						v = (((val[2] >> 3) & 1) << 5) | (((val[2] >> 0) & 1) << 4);
1275 						bval &= ~(0x20 | 0x10);
1276 						bval |= v;
1277 					}
1278 
1279 					if (fmode & 0x10) { // Green (high)
1280 
1281 						v = (((val[0] >> 1) & 1) << 5);
1282 						rval &= ~(0x20);
1283 						rval |= v;
1284 
1285 						v = (((val[1] >> 0) & 1) << 5) | (((val[1] >> 3) & 1) << 6);
1286 						gval &= ~(0x20 | 0x40);
1287 						gval |= v;
1288 
1289 						v = (((val[2] >> 2) & 1) << 6);
1290 						bval &= ~(0x40);
1291 						bval |= v;
1292 					}
1293 
1294 					if (fmode & 0x20) { // Blue (high)
1295 
1296 						v = (((val[0] >> 0) & 1) << 6) | (((val[0] >> 3) & 1) << 7);
1297 						rval &= ~(0x40 | 0x80);
1298 						rval |= v;
1299 
1300 						v = (((val[1] >> 2) & 1) << 7);
1301 						gval &= ~(0x80);
1302 						gval |= v;
1303 
1304 						v = (((val[2] >> 1) & 1) << 7);
1305 						bval &= ~(0x80);
1306 						bval |= v;
1307 					}
1308 
1309 					if (av24_doublebuffer[lof] == 0 && (fmode & (0x08 | 0x10 | 0x20))) {
1310 						rval = (rval & 0xf0) | (rval >> 4);
1311 						gval = (gval & 0xf0) | (gval >> 4);
1312 						bval = (bval & 0xf0) | (bval >> 4);
1313 					}
1314 
1315 					vramptr[0] = rval;
1316 					vramptr[1] = gval;
1317 					vramptr[2] = bval;
1318 
1319 				} else {
1320 
1321 					uae_u8 v = val[offset];
1322 					vramptr[offset] = (v << 4) | (v & 15);
1323 
1324 				}
1325 			}
1326 			if (writetovram || mode == 7 || (mode == 6 && FVR(src, s) == 0 && FVG(src, s) == 0 && FVB(src, s) == 0)) {
1327 				uae_u8 r, g, b;
1328 				r = vramptr[0];
1329 				g = vramptr[1];
1330 				b = vramptr[2];
1331 				if (av24_doublebuffer[lof] == 1) {
1332 					r = (r << 4) | (r & 0x0f);
1333 					g = (g << 4) | (g & 0x0f);
1334 					b = (b << 4) | (b & 0x0f);
1335 				} else if (av24_doublebuffer[lof] == 2) {
1336 					r = (r >> 4) | (r & 0xf0);
1337 					g = (g >> 4) | (g & 0xf0);
1338 					b = (b >> 4) | (b & 0xf0);
1339 				}
1340 				PUT_PRGB(d, d2, dst, r, g, b, xaddpix, doublelines, false);
1341 			} else {
1342 				PUT_AMIGARGB(d, s, d2, s2, dst, xaddpix, doublelines, false);
1343 			}
1344 		}
1345 	}
1346 
1347 	dst->nativepositioning = true;
1348 	if (monitor != MONITOREMU_AVIDEO12 && monitor != MONITOREMU_AVIDEO24) {
1349 		monitor = av24 ? MONITOREMU_AVIDEO24 : MONITOREMU_AVIDEO12;
1350 		write_log (_T("AVIDEO%d mode\n"), av24 ? 24 : 12);
1351 	}
1352 
1353 	return true;
1354 }
1355 
specialmonitor_store_fmode(int vpos,int hpos,uae_u16 fmode)1356 void specialmonitor_store_fmode(int vpos, int hpos, uae_u16 fmode)
1357 {
1358 	int lof = lof_store ? 0 : 1;
1359 	if (vpos < 0) {
1360 		for (int i = 0; i < 2; i++) {
1361 			avideo_previous_fmode[i] = 0;
1362 			av24_offset[i] = 0;
1363 			av24_doublebuffer[i] = 0;
1364 			av24_mode[i] = 0;
1365 			av24_writetovram[i] = 0;
1366 		}
1367 		avideo_allowed = 0;
1368 		return;
1369 	}
1370 	if (currprefs.monitoremu == MONITOREMU_AUTO) {
1371 		if ((fmode & 0x0080))
1372 			avideo_allowed = 24;
1373 		if ((fmode & 0x00f0) < 0x40 && !avideo_allowed)
1374 			avideo_allowed = 12;
1375 		if (!avideo_allowed)
1376 			return;
1377 	}
1378 	//write_log(_T("%04x\n"), fmode);
1379 
1380 	if (fmode == 0x91) {
1381 		av24_offset[lof] = SM_VRAM_WIDTH * SM_VRAM_BYTES;
1382 	}
1383 	if (fmode == 0x92) {
1384 		av24_offset[lof] = 0;
1385 	}
1386 
1387 	if (fmode & 0x8000) {
1388 		av24_doublebuffer[lof] = (fmode & 0x4000) ? 1 : 2;
1389 		av24_mode[lof] = 6;
1390 	}
1391 
1392 	if ((fmode & 0xc0) == 0x40) {
1393 		av24_writetovram[lof] = (fmode & 0x3f) != 0;
1394 	}
1395 
1396 	if (fmode == 0x80) {
1397 		av24_mode[lof] = 0;
1398 	}
1399 
1400 	if (fmode == 0x13) {
1401 		av24_mode[lof] = 6;
1402 		av24_doublebuffer[lof] = 0;
1403 	}
1404 
1405 	avideo_previous_fmode[lof] = fmode;
1406 }
1407 
do_avideo(struct vidbuffer * src,struct vidbuffer * dst)1408 static bool do_avideo(struct vidbuffer *src, struct vidbuffer *dst)
1409 {
1410 	bool v;
1411 	int lof = lof_store ? 0 : 1;
1412 	if (interlace_seen) {
1413 		if (currprefs.gfx_iscanlines) {
1414 			v = avideo(src, dst, false, lof, lof);
1415 			if (v && currprefs.gfx_iscanlines > 1)
1416 				blank_generic(src, dst, !lof);
1417 		} else {
1418 			v = avideo(src, dst, false, 0, 0);
1419 			v |= avideo(src, dst, false, 1, 1);
1420 		}
1421 	} else {
1422 		v = avideo(src, dst, true, 0, lof);
1423 	}
1424 	return v;
1425 }
1426 
1427 
videodac18(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines)1428 static bool videodac18(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
1429 {
1430 	int y, x, vdbl, hdbl;
1431 	int ystart, yend, isntsc;
1432 	int xadd, xaddpix;
1433 	uae_u16 hsstrt, hsstop, vsstrt, vsstop;
1434 	int xstart, xstop;
1435 
1436 	if ((beamcon0 & (0x80 | 0x100 | 0x200 | 0x10)) != 0x300)
1437 		return false;
1438 	getsyncregisters(&hsstrt, &hsstop, &vsstrt, &vsstop);
1439 
1440 	if (hsstop >= (maxhpos & ~1))
1441 		hsstrt = 0;
1442 	xstart = ((hsstrt * 2) << RES_MAX) - src->xoffset;
1443 	xstop = ((hsstop * 2) << RES_MAX) - src->xoffset;
1444 
1445 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
1446 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
1447 		isntsc = currprefs.ntscmode ? 1 : 0;
1448 
1449 	vdbl = gfxvidinfo.ychange;
1450 	hdbl = gfxvidinfo.xchange;
1451 
1452 	xaddpix = (1 << 1) / hdbl;
1453 	xadd = ((1 << 1) / hdbl) * src->pixbytes;
1454 
1455 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
1456 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
1457 
1458 	uae_u8 r = 0, g = 0, b = 0;
1459 	for (y = ystart; y < yend; y++) {
1460 		int oddeven = 0;
1461 		uae_u8 prev = 0;
1462 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
1463 		if (yoff < 0)
1464 			continue;
1465 		if (yoff >= src->inheight)
1466 			continue;
1467 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
1468 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
1469 		r = g = b = 0;
1470 		for (x = 0; x < src->inwidth; x++) {
1471 			uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
1472 			uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes;
1473 			uae_u8 *s2 = s + src->rowbytes;
1474 			uae_u8 *d2 = d + dst->rowbytes;
1475 			uae_u8 newval = FIRGB(src, s);
1476 			uae_u8 val = prev | (newval << 4);
1477 			if (oddeven) {
1478 				int mode = val >> 6;
1479 				int data = (val & 63) << 2;
1480 				if (mode == 0) {
1481 					r = data;
1482 					g = data;
1483 					b = data;
1484 				} else if (mode == 1) {
1485 					b = data;
1486 				} else if (mode == 2) {
1487 					r = data;
1488 				} else {
1489 					g = data;
1490 				}
1491 				if (y >= vsstrt && y < vsstop && x >= xstart && y < xstop) {
1492 					PUT_PRGB(d, d2, dst, r, g, b, xaddpix, doublelines, true);
1493 				} else {
1494 					PUT_AMIGARGB(d, s, d2, s2, dst, xaddpix, doublelines, true);
1495 				}
1496 			}
1497 			oddeven = oddeven ? 0 : 1;
1498 			prev = val >> 4;
1499 		}
1500 	}
1501 
1502 	dst->nativepositioning = true;
1503 	if (monitor != MONITOREMU_VIDEODAC18) {
1504 		monitor = MONITOREMU_VIDEODAC18;
1505 		write_log (_T("Video DAC 18 mode\n"));
1506 	}
1507 
1508 	return true;
1509 }
1510 
do_videodac18(struct vidbuffer * src,struct vidbuffer * dst)1511 static bool do_videodac18(struct vidbuffer *src, struct vidbuffer *dst)
1512 {
1513 	bool v;
1514 	if (interlace_seen) {
1515 		if (currprefs.gfx_iscanlines) {
1516 			v = videodac18(src, dst, false, lof_store ? 0 : 1);
1517 			if (v && currprefs.gfx_iscanlines > 1)
1518 				blank_generic(src, dst, lof_store ? 1 : 0);
1519 		} else {
1520 			v = videodac18(src, dst, false, 0);
1521 			v |= videodac18(src, dst, false, 1);
1522 		}
1523 	} else {
1524 		v = videodac18(src, dst, true, 0);
1525 	}
1526 	return v;
1527 }
1528 
1529 static const uae_u8 ham_e_magic_cookie[] = { 0xa2, 0xf5, 0x84, 0xdc, 0x6d, 0xb0, 0x7f  };
1530 static const uae_u8 ham_e_magic_cookie_reg = 0x14;
1531 static const uae_u8 ham_e_magic_cookie_ham = 0x18;
1532 
ham_e(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines)1533 static bool ham_e(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
1534 {
1535 	int y, x, vdbl, hdbl;
1536 	int ystart, yend, isntsc;
1537 	int xadd, xaddpix;
1538 	bool hameplus = currprefs.monitoremu == MONITOREMU_HAM_E_PLUS;
1539 
1540 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
1541 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
1542 		isntsc = currprefs.ntscmode ? 1 : 0;
1543 
1544 	vdbl = gfxvidinfo.ychange;
1545 	hdbl = gfxvidinfo.xchange;
1546 
1547 	xaddpix = (1 << 1) / hdbl;
1548 	xadd = ((1 << 1) / hdbl) * src->pixbytes;
1549 
1550 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
1551 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
1552 
1553 	uae_u8 r, g, b;
1554 	/* or is an alternative operator and cannot be used as an identifier */
1555 	uae_u8 or_, og, ob;
1556 	int pcnt = 0;
1557 	int bank = 0;
1558 	int mode_active = 0;
1559 	bool prevzeroline = false;
1560 	int was_active = 0;
1561 	bool cookie_line = false;
1562 	int cookiestartx = 10000;
1563 	for (y = ystart; y < yend; y++) {
1564 		int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
1565 		if (yoff < 0)
1566 			continue;
1567 		if (yoff >= src->inheight)
1568 			continue;
1569 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
1570 		uae_u8 *line_genlock = row_map_genlock[yoff];
1571 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
1572 
1573 		bool getpalette = false;
1574 		uae_u8 prev = 0;
1575 		bool zeroline = true;
1576 		int oddeven = 0;
1577 		for (x = 0; x < src->inwidth; x++) {
1578 			uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
1579 			uae_u8 *s_genlock = line_genlock + ((x << 1) / hdbl);
1580 			uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes;
1581 			uae_u8 *s2 = s + src->rowbytes;
1582 			uae_u8 *d2 = d + dst->rowbytes;
1583 			uae_u8 newval = FIRGB(src, s);
1584 			uae_u8 val = prev | newval;
1585 
1586 			if (s_genlock[0])
1587 				zeroline = false;
1588 
1589 			if (val == ham_e_magic_cookie[0] && x + sizeof ham_e_magic_cookie + 1 < src->inwidth) {
1590 				int i;
1591 				for (i = 1; i <= sizeof ham_e_magic_cookie; i++) {
1592 					uae_u8 val2 = (FIRGB(src, s + (i * 2 - 1) * xadd) << 4) | FIRGB(src, s + (i * 2 + 0) * xadd);
1593 					if (i < sizeof ham_e_magic_cookie) {
1594 						if (val2 != ham_e_magic_cookie[i])
1595 							break;
1596 					} else if (val2 == ham_e_magic_cookie_reg || val2 == ham_e_magic_cookie_ham) {
1597 						mode_active = val2;
1598 						getpalette = true;
1599 						prevzeroline = false;
1600 						cookiestartx = x - 1;
1601 						x += i * 2;
1602 						oddeven = 0;
1603 						cookie_line = true;
1604 					}
1605 				}
1606 				if (i == sizeof ham_e_magic_cookie + 1)
1607 					continue;
1608 			}
1609 
1610 			if (!cookie_line && x == cookiestartx)
1611 				oddeven = 0;
1612 
1613 			if (oddeven) {
1614 				if (getpalette) {
1615 					graffiti_palette[pcnt] = val;
1616 					pcnt++;
1617 					if ((pcnt & 3) == 3)
1618 						pcnt++;
1619 					// 64 colors/line
1620 					if ((pcnt & ((4 * 64) - 1)) == 0)
1621 						getpalette = false;
1622 					pcnt &= (4 * 256) - 1;
1623 				}
1624 				if (mode_active) {
1625 					if (cookie_line || x < cookiestartx) {
1626 						r = g = b = 0;
1627 						or_ = og = ob = 0;
1628 					} else {
1629 						if (mode_active == ham_e_magic_cookie_reg) {
1630 							uae_u8 *pal = &graffiti_palette[val * 4];
1631 							r = pal[0];
1632 							g = pal[1];
1633 							b = pal[2];
1634 						} else if (mode_active == ham_e_magic_cookie_ham) {
1635 							int mode = val >> 6;
1636 							int color = val & 63;
1637 							if (mode == 0 && color <= 59) {
1638 								uae_u8 *pal = &graffiti_palette[(bank + color) * 4];
1639 								r = pal[0];
1640 								g = pal[1];
1641 								b = pal[2];
1642 							} else if (mode == 0) {
1643 								bank = (color & 3) * 64;
1644 							} else if (mode == 1) {
1645 								b = color << 2;
1646 							} else if (mode == 2) {
1647 								r = color << 2;
1648 							} else if (mode == 3) {
1649 								g = color << 2;
1650 							}
1651 						}
1652 					}
1653 
1654 					if (hameplus) {
1655 						uae_u8 ar, ag, ab;
1656 
1657 						ar = (r + or_) / 2;
1658 						ag = (g + og) / 2;
1659 						ab = (b + ob) / 2;
1660 
1661 						if (xaddpix >= 2) {
1662 							PRGB(dst, d - dst->pixbytes, ar, ag, ab);
1663 							PRGB(dst, d, ar, ag, ab);
1664 							PRGB(dst, d + 1 * dst->pixbytes, r, g, b);
1665 							PRGB(dst, d + 2 * dst->pixbytes, r, g, b);
1666 							if (doublelines) {
1667 								PRGB(dst, d2 - dst->pixbytes, ar, ag, ab);
1668 								PRGB(dst, d2, ar, ag, ab);
1669 								PRGB(dst, d2 + 1 * dst->pixbytes, r, g, b);
1670 								PRGB(dst, d2 + 2 * dst->pixbytes, r, g, b);
1671 							}
1672 						} else {
1673 							PRGB(dst, d - dst->pixbytes, ar, ag, ab);
1674 							PRGB(dst, d, r, g, b);
1675 							if (doublelines) {
1676 								PRGB(dst, d2 - dst->pixbytes, ar, ag, ab);
1677 								PRGB(dst, d2, r, g, b);
1678 							}
1679 						}
1680 						or_ = r;
1681 						og = g;
1682 						ob = b;
1683 					} else {
1684 						PUT_PRGB(d, d2, dst, r, g, b, xaddpix, doublelines, true);
1685 					}
1686 				} else {
1687 					PUT_AMIGARGB(d, s, d2, s2, dst, xaddpix, doublelines, true);
1688 				}
1689 			}
1690 
1691 			oddeven = oddeven ? 0 : 1;
1692 			prev = val << 4;
1693 		}
1694 
1695 		if (cookie_line) {
1696 			// Erase magic cookie. I assume real HAM-E would erase it
1697 			// because not erasing it would look really ugly.
1698 			memset(dstline, 0, dst->outwidth * dst->pixbytes);
1699 			if (doublelines)
1700 				memset(dstline + dst->rowbytes, 0, dst->outwidth * dst->pixbytes);
1701 		}
1702 
1703 		cookie_line = false;
1704 		if (mode_active)
1705 			was_active = mode_active;
1706 		if (zeroline) {
1707 			if (prevzeroline) {
1708 				mode_active = 0;
1709 				pcnt = 0;
1710 				cookiestartx = 10000;
1711 			}
1712 			prevzeroline = true;
1713 		} else {
1714 			prevzeroline = false;
1715 		}
1716 
1717 	}
1718 
1719 	if (was_active) {
1720 		dst->nativepositioning = true;
1721 		if (monitor != MONITOREMU_HAM_E) {
1722 			monitor = MONITOREMU_HAM_E;
1723 			write_log (_T("HAM-E mode, %s\n"), was_active == ham_e_magic_cookie_reg ? _T("REG") : _T("HAM"));
1724 		}
1725 	}
1726 
1727 	return was_active != 0;
1728 }
1729 
do_hame(struct vidbuffer * src,struct vidbuffer * dst)1730 static bool do_hame(struct vidbuffer *src, struct vidbuffer *dst)
1731 {
1732 	bool v;
1733 	if (interlace_seen) {
1734 		if (currprefs.gfx_iscanlines) {
1735 			v = ham_e(src, dst, false, lof_store ? 0 : 1);
1736 			if (v && currprefs.gfx_iscanlines > 1)
1737 				blank_generic(src, dst, lof_store ? 1 : 0);
1738 		} else {
1739 			v = ham_e(src, dst, false, 0);
1740 			v |= ham_e(src, dst, false, 1);
1741 		}
1742 	} else {
1743 		v = ham_e(src, dst, true, 0);
1744 	}
1745 	return v;
1746 }
1747 
graffiti(struct vidbuffer * src,struct vidbuffer * dst)1748 static bool graffiti(struct vidbuffer *src, struct vidbuffer *dst)
1749 {
1750 	int y, x;
1751 	int ystart, yend, isntsc;
1752 	int xstart, xend;
1753 	uae_u8 *srcbuf, *srcend;
1754 	uae_u8 *dstbuf;
1755 	bool command, hires, found;
1756 	int xadd, xpixadd, extrapix;
1757 	int waitline = 0, dbl;
1758 	uae_u8 read_mask = 0xff, color = 0, color2 = 0;
1759 
1760 	if (!(bplcon0 & 0x0100)) // GAUD
1761 		return false;
1762 
1763 	command = true;
1764 	found = false;
1765 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
1766 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
1767 		isntsc = currprefs.ntscmode ? 1 : 0;
1768 
1769 	dbl = gfxvidinfo.ychange == 1 ? 2 : 1;
1770 
1771 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
1772 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
1773 	if (src->yoffset >= (ystart << VRES_MAX))
1774 		ystart = src->yoffset >> VRES_MAX;
1775 
1776 	xadd = gfxvidinfo.xchange == 1 ? src->pixbytes * 2 : src->pixbytes;
1777 	xpixadd = gfxvidinfo.xchange == 1 ? 4 : 2;
1778 
1779 	xstart = 0x1c * 2 + 1;
1780 	xend = 0xf0 * 2 + 1;
1781 	if (!(currprefs.chipset_mask & CSMASK_AGA)) {
1782 		xstart++;
1783 		xend++;
1784 	}
1785 
1786 	srcbuf = src->bufmem + (((ystart << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((xstart << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes;
1787 	srcend = src->bufmem + (((yend << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes;
1788 	extrapix = 0;
1789 
1790 	dstbuf = dst->bufmem + (((ystart << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * dst->rowbytes + (((xstart << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * dst->pixbytes;
1791 
1792 	y = 0;
1793 	while (srcend > srcbuf && dst->bufmemend > dstbuf) {
1794 		uae_u8 *srcp = srcbuf + extrapix;
1795 		uae_u8 *dstp = dstbuf;
1796 
1797 		x = xstart;
1798 		while (x < xend) {
1799 
1800 			uae_u8 mask = 0x80;
1801 			uae_u8 chunky[4] = { 0, 0, 0, 0 };
1802 			while (mask) {
1803 				if (FR(src, srcp)) // R
1804 					chunky[3] |= mask;
1805 				if (FG(src, srcp)) // G
1806 					chunky[2] |= mask;
1807 				if (FB(src, srcp)) // B
1808 					chunky[1] |= mask;
1809 				if (FI(src, srcp)) // I
1810 					chunky[0] |= mask;
1811 				srcp += xadd;
1812 				mask >>= 1;
1813 			}
1814 
1815 			if (command) {
1816 				if (chunky[0] || chunky[1] || chunky[2] || chunky[3] || found) {
1817 					for (int pix = 0; pix < 2; pix++) {
1818 						uae_u8 cmd = chunky[pix * 2 + 0];
1819 						uae_u8 parm = chunky[pix * 2 + 1];
1820 
1821 						if (automatic && cmd >= 0x40)
1822 							return false;
1823 						if (cmd != 0)
1824 							found = true;
1825 						if (cmd & 8) {
1826 							command = false;
1827 							dbl = 1;
1828 							waitline = 2;
1829 							if (0 && (cmd & 16)) {
1830 								hires = true;
1831 								xadd /= 2;
1832 								xpixadd /= 2;
1833 								extrapix = -4 * src->pixbytes;
1834 							} else {
1835 								hires = false;
1836 							}
1837 							if (xpixadd == 0) // shres needed
1838 								return false;
1839 							if (monitor != MONITOREMU_GRAFFITI)
1840 								clearmonitor(dst);
1841 						} else if (cmd & 4) {
1842 							if ((cmd & 3) == 1) {
1843 								read_mask = parm;
1844 							} else if ((cmd & 3) == 2) {
1845 								graffiti_palette[color * 4 + color2] = (parm << 2) | (parm & 3);
1846 								color2++;
1847 								if (color2 == 3) {
1848 									color2 = 0;
1849 									color++;
1850 								}
1851 							} else if ((cmd & 3) == 0) {
1852 								color = parm;
1853 								color2 = 0;
1854 							}
1855 						}
1856 					}
1857 				}
1858 
1859 				memset(dstp, 0, dst->pixbytes * 4 * 2);
1860 				dstp += dst->pixbytes * 4 * 2;
1861 
1862 			} else if (waitline) {
1863 
1864 				memset(dstp, 0, dst->pixbytes * 4 * 2);
1865 				dstp += dst->pixbytes * 4 * 2;
1866 
1867 			} else {
1868 
1869 				for (int pix = 0; pix < 4; pix++) {
1870 					uae_u8 r, g, b, c;
1871 
1872 					c = chunky[pix] & read_mask;
1873 					r = graffiti_palette[c * 4 + 0];
1874 					g = graffiti_palette[c * 4 + 1];
1875 					b = graffiti_palette[c * 4 + 2];
1876 					PRGB(dst, dstp, r, g, b);
1877 					dstp += dst->pixbytes;
1878 					PRGB(dst, dstp, r, g, b);
1879 					dstp += dst->pixbytes;
1880 
1881 					if (gfxvidinfo.xchange == 1 && !hires) {
1882 						PRGB(dst, dstp, r, g, b);
1883 						dstp += dst->pixbytes;
1884 						PRGB(dst, dstp, r, g, b);
1885 						dstp += dst->pixbytes;
1886 					}
1887 				}
1888 
1889 			}
1890 
1891 			x += xpixadd;
1892 		}
1893 
1894 		y++;
1895 		srcbuf += src->rowbytes * dbl;
1896 		dstbuf += dst->rowbytes * dbl;
1897 		if (waitline > 0)
1898 			waitline--;
1899 	}
1900 
1901 	dst->nativepositioning = true;
1902 
1903 	if (monitor != MONITOREMU_GRAFFITI) {
1904 		monitor = MONITOREMU_GRAFFITI;
1905 		write_log (_T("GRAFFITI %s mode\n"), hires ? _T("hires") : _T("lores"));
1906 	}
1907 
1908 	return true;
1909 }
1910 
1911 /* A2024 information comes from US patent 4851826 */
1912 
a2024(struct vidbuffer * src,struct vidbuffer * dst)1913 static bool a2024(struct vidbuffer *src, struct vidbuffer *dst)
1914 {
1915 	int y;
1916 	uae_u8 *srcbuf, *dstbuf;
1917 	uae_u8 *dataline;
1918 	int px, py, doff, pxcnt, dbl;
1919 	int panel_width, panel_width_draw, panel_height, srcxoffset;
1920 	bool f64, interlace, expand, wpb, less16;
1921 	uae_u8 enp, dpl;
1922 	bool hires, ntsc, found;
1923 	int idline;
1924 	int total_width, total_height;
1925 
1926 	dbl = gfxvidinfo.ychange == 1 ? 2 : 1;
1927 	doff = (128 * 2 / gfxvidinfo.xchange) * src->pixbytes;
1928 	found = false;
1929 
1930 	for (idline = 21; idline <= 29; idline += 8) {
1931 		if (src->yoffset > (idline << VRES_MAX))
1932 			continue;
1933 		// min 178 max 234
1934 		dataline = src->bufmem + (((idline << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((200 << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes;
1935 
1936 #if 0
1937 		write_log (_T("%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x\n"),
1938 			dataline[0 * doff + 0], dataline[0 * doff + 1], dataline[0 * doff + 2],
1939 			dataline[1 * doff + 0], dataline[1 * doff + 1], dataline[1 * doff + 2],
1940 			dataline[2 * doff + 0], dataline[2 * doff + 1], dataline[2 * doff + 2],
1941 			dataline[3 * doff + 0], dataline[3 * doff + 1], dataline[3 * doff + 2]);
1942 #endif
1943 
1944 		if (FB(src, &dataline[0 * doff]))			// 0:B = 0
1945 			continue;
1946 		if (!FI(src, &dataline[0 * doff]))			// 0:I = 1
1947 			continue;
1948 		if (FI(src, &dataline[2 * doff]))			// 2:I = 0
1949 			continue;
1950 		if (!FI(src, &dataline[3 * doff]))			// 3:I = 1
1951 			continue;
1952 
1953 		ntsc = idline < 26;
1954 		found = true;
1955 		break;
1956 	}
1957 
1958 	if (!found)
1959 		return false;
1960 
1961 	px = py = 0;
1962 	if (FB(src, &dataline[1 * doff])) // 1:B FN2
1963 		px |= 2;
1964 	if (FG(src, &dataline[1 * doff])) // 1:G FN1
1965 		px |= 1;
1966 	if (FR(src, &dataline[1 * doff])) // 1:R FN0
1967 		py |= 1;
1968 
1969 	f64 = FR(src, &dataline[0 * doff]) != 0;		// 0:R
1970 	interlace = FG(src, &dataline[0 * doff]) != 0;	// 0:G (*Always zero)
1971 	expand = FI(src, &dataline[1 * doff]) != 0;		// 1:I (*Always set)
1972 	enp = FR(src, &dataline[2 * doff]) ? 1 : 0;		// 2:R (*ENP=3)
1973 	enp |= FG(src, &dataline[2 * doff]) ? 2 : 0;	// 2:G
1974 	wpb = FB(src, &dataline[2 * doff]) != 0;		// 2:B (*Always zero)
1975 	dpl = FR(src, &dataline[3 * doff]) ? 1 : 0;		// 3:R (*DPL=3)
1976 	dpl |= FG(src, &dataline[3 * doff]) ? 2 : 0;	// 3:G
1977 	less16 = FB(src, &dataline[3 * doff]) != 0;		// 3:B
1978 
1979 	/* (*) = AOS A2024 driver static bits. Not yet implemented in emulation. */
1980 
1981 	if (f64) {
1982 		panel_width = 336;
1983 		panel_width_draw = px == 2 ? 352 : 336;
1984 		pxcnt = 3;
1985 		hires = false;
1986 		srcxoffset = 113;
1987 		if (px > 2)
1988 			return false;
1989 		total_width = 336 + 336 + 352;
1990 	} else {
1991 		panel_width = 512;
1992 		panel_width_draw = 512;
1993 		pxcnt = 2;
1994 		hires = true;
1995 		srcxoffset = 129;
1996 		if (px > 1)
1997 			return false;
1998 		total_width = 512 + 512;
1999 	}
2000 	panel_height = ntsc ? 400 : 512;
2001 
2002 	if (monitor != MONITOREMU_A2024) {
2003 		clearmonitor(dst);
2004 	}
2005 
2006 #if 0
2007 	write_log (_T("0 = F6-4:%d INTERLACE:%d\n"), f64, interlace);
2008 	write_log (_T("1 = FN:%d EXPAND:%d\n"), py + px *2, expand);
2009 	write_log (_T("2 = ENP:%d WPB=%d\n"), enp, wpb);
2010 	write_log (_T("3 = DPL:%d LESS16=%d\n"), dpl, less16);
2011 #endif
2012 #if 0
2013 	write_log (_T("%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %dx%d\n"),
2014 		dataline[0 * doff + 0], dataline[0 * doff + 1], dataline[0 * doff + 2],
2015 		dataline[1 * doff + 0], dataline[1 * doff + 1], dataline[1 * doff + 2],
2016 		dataline[2 * doff + 0], dataline[2 * doff + 1], dataline[2 * doff + 2],
2017 		dataline[3 * doff + 0], dataline[3 * doff + 1], dataline[3 * doff + 2],
2018 		px, py);
2019 #endif
2020 
2021 	if (less16) {
2022 		total_width -= 16;
2023 		if (px == pxcnt - 1)
2024 			panel_width_draw -= 16;
2025 	}
2026 	total_height = panel_height * dbl;
2027 
2028 	srcbuf = src->bufmem + (((44 << VRES_MAX) - src->yoffset) / gfxvidinfo.ychange) * src->rowbytes + (((srcxoffset << RES_MAX) - src->xoffset) / gfxvidinfo.xchange) * src->pixbytes;
2029 	dstbuf = dst->bufmem + py * (panel_height / gfxvidinfo.ychange) * dst->rowbytes + px * ((panel_width * 2) / gfxvidinfo.xchange) * dst->pixbytes;
2030 
2031 	for (y = 0; y < (panel_height / (dbl == 1 ? 1 : 2)) / gfxvidinfo.ychange; y++) {
2032 #if 0
2033 		memcpy (dstbuf, srcbuf, ((panel_width * 2) / gfxvidinfo.xchange) * dst->pixbytes);
2034 #else
2035 		uae_u8 *srcp = srcbuf;
2036 		uae_u8 *dstp1 = dstbuf;
2037 		uae_u8 *dstp2 = dstbuf + dst->rowbytes;
2038 		int x;
2039 		for (x = 0; x < (panel_width_draw * 2) / gfxvidinfo.xchange; x++) {
2040 			uae_u8 c1 = 0, c2 = 0;
2041 			if (FR(src, srcp)) // R
2042 				c1 |= 2;
2043 			if (FG(src, srcp)) // G
2044 				c2 |= 2;
2045 			if (FB(src, srcp)) // B
2046 				c1 |= 1;
2047 			if (FI(src, srcp)) // I
2048 				c2 |= 1;
2049 			if (dpl == 0) {
2050 				c1 = c2 = 0;
2051 			} else if (dpl == 1) {
2052 				c1 &= 1;
2053 				c1 |= c1 << 1;
2054 				c2 &= 1;
2055 				c2 |= c2 << 1;
2056 			} else if (dpl == 2) {
2057 				c1 &= 2;
2058 				c1 |= c1 >> 1;
2059 				c2 &= 2;
2060 				c2 |= c2 >> 1;
2061 			}
2062 			if (dbl == 1) {
2063 				c1 = (c1 + c2 + 1) / 2;
2064 				c1 = (c1 << 6) | (c1 << 4) | (c1 << 2) | (c1 << 0);
2065 				PRGB(dst, dstp1, c1, c1, c1);
2066 			} else {
2067 				c1 = (c1 << 6) | (c1 << 4) | (c1 << 2) | (c1 << 0);
2068 				c2 = (c2 << 6) | (c2 << 4) | (c2 << 2) | (c2 << 0);
2069 				PRGB(dst, dstp1, c1, c1, c1);
2070 				PRGB(dst, dstp2, c2, c2, c2);
2071 				dstp2 += dst->pixbytes;
2072 			}
2073 			srcp += src->pixbytes;
2074 			if (!hires)
2075 				srcp += src->pixbytes;
2076 			dstp1 += dst->pixbytes;
2077 		}
2078 #endif
2079 		srcbuf += src->rowbytes * dbl;
2080 		dstbuf += dst->rowbytes * dbl;
2081 	}
2082 
2083 	total_width /= 2;
2084 	total_width <<= currprefs.gfx_resolution;
2085 
2086 	dst->outwidth = total_width;
2087 	dst->outheight = total_height;
2088 	dst->inwidth = total_width;
2089 	dst->inheight = total_height;
2090 	dst->inwidth2 = total_width;
2091 	dst->inheight2 = total_height;
2092 	dst->nativepositioning = false;
2093 
2094 	if (monitor != MONITOREMU_A2024) {
2095 		monitor = MONITOREMU_A2024;
2096 		write_log (_T("A2024 %dHz %s mode\n"), hires ? 10 : 15, ntsc ? _T("NTSC") : _T("PAL"));
2097 	}
2098 
2099 	return true;
2100 }
2101 
emulate_specialmonitors2(struct vidbuffer * src,struct vidbuffer * dst)2102 static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *dst)
2103 {
2104 	automatic = false;
2105 	if (currprefs.monitoremu == MONITOREMU_AUTO) {
2106 		automatic = true;
2107 		bool v = a2024(src, dst);
2108 		if (!v)
2109 			v = graffiti(src, dst);
2110 		if (!v)
2111 			v = do_videodac18(src, dst);
2112 		if (!v) {
2113 			if (avideo_allowed)
2114 				v = do_avideo(src, dst);
2115 		}
2116 		return v;
2117 	} else if (currprefs.monitoremu == MONITOREMU_A2024) {
2118 		return a2024(src, dst);
2119 	} else if (currprefs.monitoremu == MONITOREMU_GRAFFITI) {
2120 		return graffiti(src, dst);
2121 	} else if (currprefs.monitoremu == MONITOREMU_DCTV) {
2122 		return do_dctv(src, dst);
2123 	} else if (currprefs.monitoremu == MONITOREMU_HAM_E || currprefs.monitoremu == MONITOREMU_HAM_E_PLUS) {
2124 		return do_hame(src, dst);
2125 	} else if (currprefs.monitoremu == MONITOREMU_VIDEODAC18) {
2126 		return do_videodac18(src, dst);
2127 	} else if (currprefs.monitoremu == MONITOREMU_AVIDEO12 || currprefs.monitoremu == MONITOREMU_AVIDEO24) {
2128 		avideo_allowed = -1;
2129 		return do_avideo(src, dst);
2130 	} else if (currprefs.monitoremu == MONITOREMU_FIRECRACKER24) {
2131 		return do_firecracker24(src, dst);
2132 	}
2133 	return false;
2134 }
2135 
2136 
emulate_specialmonitors(struct vidbuffer * src,struct vidbuffer * dst)2137 bool emulate_specialmonitors(struct vidbuffer *src, struct vidbuffer *dst)
2138 {
2139 	if (!emulate_specialmonitors2(src, dst)) {
2140 		if (monitor) {
2141 			clearmonitor(dst);
2142 			monitor = 0;
2143 			write_log (_T("Native mode\n"));
2144 		}
2145 		return false;
2146 	}
2147 	return true;
2148 }
2149 
specialmonitor_reset(void)2150 void specialmonitor_reset(void)
2151 {
2152 	if (!currprefs.monitoremu)
2153 		return;
2154 	specialmonitor_store_fmode(-1, -1, 0);
2155 	fc24_reset();
2156 }
2157 
specialmonitor_need_genlock(void)2158 bool specialmonitor_need_genlock(void)
2159 {
2160 	switch (currprefs.monitoremu)
2161 	{
2162 		case MONITOREMU_FIRECRACKER24:
2163 		case MONITOREMU_HAM_E:
2164 		case MONITOREMU_HAM_E_PLUS:
2165 		return true;
2166 	}
2167 	if (currprefs.genlock_image && currprefs.genlock)
2168 		return true;
2169 	return false;
2170 }
2171 
2172 static uae_u8 *genlock_image;
2173 static int genlock_image_width, genlock_image_height, genlock_image_pitch;
2174 static uae_u8 noise_buffer[1024];
2175 static uae_u32 noise_seed, noise_add, noise_index;
2176 
quickrand(void)2177 static uae_u32 quickrand(void)
2178 {
2179 	noise_seed = (noise_seed >> 1) ^ (0 - (noise_seed & 1) & 0xd0000001);
2180 	return noise_seed;
2181 }
2182 
init_noise(void)2183 static void init_noise(void)
2184 {
2185 	noise_seed++;
2186 	for (int i = 0; i < sizeof noise_buffer; i++) {
2187 		noise_buffer[i] = quickrand();
2188 	}
2189 }
2190 
get_noise(void)2191 static uae_u8 get_noise(void)
2192 {
2193 	noise_index += noise_add;
2194 	noise_index &= 1023;
2195 	return noise_buffer[noise_index];
2196 }
2197 
2198 #include "png.h"
2199 
2200 struct png_cb
2201 {
2202 	uae_u8 *ptr;
2203 	int size;
2204 };
2205 
2206 #ifdef FSUAE
2207 // FIXME
readcallback(png_structp png_ptr,png_bytep out,png_size_t count)2208 static void readcallback(png_structp png_ptr, png_bytep out, png_size_t count)
2209 #else
2210 static void __cdecl readcallback(png_structp png_ptr, png_bytep out, png_size_t count)
2211 #endif
2212 {
2213 	png_voidp io_ptr = png_get_io_ptr(png_ptr);
2214 
2215 	if (!io_ptr)
2216 		return;
2217 	struct png_cb *cb = (struct png_cb*)io_ptr;
2218 	if (count > cb->size)
2219 		count = cb->size;
2220 	memcpy(out, cb->ptr, count);
2221 	cb->ptr += count;
2222 	cb->size -= count;
2223 }
2224 
load_genlock_image(void)2225 static void load_genlock_image(void)
2226 {
2227 	extern unsigned char test_card_png[];
2228 	extern unsigned int test_card_png_len;
2229 	uae_u8 *b = test_card_png;
2230 	uae_u8 *bfree = NULL;
2231 	int file_size = test_card_png_len;
2232 	png_structp png_ptr;
2233 	png_infop info_ptr;
2234 	png_uint_32 width, height;
2235 	int depth, color_type;
2236 	struct png_cb cb;
2237 	png_bytepp row_pp;
2238 	png_size_t cols;
2239 
2240 	xfree(genlock_image);
2241 	genlock_image = NULL;
2242 
2243 	if (currprefs.genlock_image == 3) {
2244 		int size;
2245 		uae_u8 *bb = zfile_load_file(currprefs.genlock_image_file, &size);
2246 		if (bb) {
2247 			file_size = size;
2248 			b = bb;
2249 			bfree = bb;
2250 		}
2251 	}
2252 
2253 	if (!png_check_sig(b, 8))
2254 		goto end;
2255 
2256 	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
2257 	if (!png_ptr)
2258 		goto end;
2259 	info_ptr = png_create_info_struct(png_ptr);
2260 	if (!info_ptr) {
2261 		png_destroy_read_struct(&png_ptr, 0, 0);
2262 		goto end;
2263 	}
2264 	cb.ptr = b;
2265 	cb.size = file_size;
2266 	png_set_read_fn(png_ptr, &cb, readcallback);
2267 
2268 	png_read_info(png_ptr, info_ptr);
2269 
2270 	png_get_IHDR(png_ptr, info_ptr, &width, &height, &depth, &color_type, 0, 0, 0);
2271 
2272 	if (color_type == PNG_COLOR_TYPE_PALETTE)
2273 		png_set_expand(png_ptr);
2274 	if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
2275 		png_set_expand(png_ptr);
2276 
2277 	if (depth > 8)
2278 		png_set_strip_16(png_ptr);
2279 	if (depth < 8)
2280 		png_set_packing(png_ptr);
2281 	if (!(color_type & PNG_COLOR_MASK_ALPHA))
2282 		png_set_add_alpha(png_ptr, 0, PNG_FILLER_AFTER);
2283 
2284 	cols = png_get_rowbytes(png_ptr, info_ptr);
2285 
2286 	genlock_image_pitch = width * 4;
2287 	genlock_image_width = width;
2288 	genlock_image_height = height;
2289 
2290 	row_pp = new png_bytep[height];
2291 
2292 	genlock_image = xcalloc(uae_u8, width * height * 4);
2293 
2294 	for (int i = 0; i < height; i++) {
2295 		row_pp[i] = (png_bytep) &genlock_image[i * genlock_image_pitch];
2296 	}
2297 
2298 	png_read_image(png_ptr, row_pp);
2299 	png_read_end(png_ptr, info_ptr);
2300 
2301 	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
2302 
2303 	delete[] row_pp;
2304 end:
2305 	xfree(bfree);
2306 }
2307 
do_genlock(struct vidbuffer * src,struct vidbuffer * dst,bool doublelines,int oddlines)2308 static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
2309 {
2310 	int y, x, vdbl, hdbl;
2311 	int ystart, yend, isntsc;
2312 	int gl_vdbl_l, gl_vdbl_r;
2313 	int gl_hdbl_l, gl_hdbl_r, gl_hdbl;
2314 	int gl_hcenter, gl_vcenter;
2315 	int mix1 = 0, mix2 = 0;
2316 
2317 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
2318 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2319 		isntsc = currprefs.ntscmode ? 1 : 0;
2320 
2321 	if (!genlock_image && currprefs.genlock_image == 2) {
2322 		load_genlock_image();
2323 	}
2324 	if (genlock_image && currprefs.genlock_image != 2) {
2325 		xfree(genlock_image);
2326 		genlock_image = NULL;
2327 	}
2328 
2329 	if (gfxvidinfo.xchange == 1)
2330 		hdbl = 0;
2331 	else if (gfxvidinfo.xchange == 2)
2332 		hdbl = 1;
2333 	else
2334 		hdbl = 2;
2335 
2336 	gl_hdbl_l = gl_hdbl_r = 0;
2337 	if (genlock_image_width < 600) {
2338 		gl_hdbl = 0;
2339 	} else if (genlock_image_width < 1000) {
2340 		gl_hdbl = 1;
2341 	} else {
2342 		gl_hdbl = 2;
2343 	}
2344 	if (hdbl >= gl_hdbl) {
2345 		gl_hdbl_l = hdbl - gl_hdbl;
2346 	} else {
2347 		gl_hdbl_r = gl_hdbl - hdbl;
2348 	}
2349 
2350 	if (gfxvidinfo.ychange == 1)
2351 		vdbl = 0;
2352 	else
2353 		vdbl = 1;
2354 
2355 	gl_vdbl_l = gl_vdbl_r = 0;
2356 
2357 	gl_hcenter = (genlock_image_width - ((src->inwidth << hdbl) >> gl_hdbl)) / 2;
2358 
2359 	ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
2360 	yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
2361 
2362 	gl_vcenter = (((genlock_image_height << gl_vdbl_l) >> gl_vdbl_r) - (((yend - ystart) * 2))) / 2;
2363 
2364 	init_noise();
2365 
2366 	if(currprefs.genlock_mix) {
2367 		mix1 = 256 - currprefs.genlock_mix;
2368 		mix2 = currprefs.genlock_mix;
2369 	}
2370 
2371 	uae_u8 r = 0, g = 0, b = 0;
2372 	for (y = ystart; y < yend; y++) {
2373 		int yoff = (((y * 2 + oddlines) - src->yoffset) >> vdbl);
2374 		if (yoff < 0)
2375 			continue;
2376 		if (yoff >= src->inheight)
2377 			continue;
2378 
2379 		uae_u8 *line = src->bufmem + yoff * src->rowbytes;
2380 		uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) >> vdbl) * dst->rowbytes;
2381 		uae_u8 *line_genlock = row_map_genlock[yoff];
2382 		int gy = ((((y * 2 + oddlines) - dst->yoffset) << gl_vdbl_l) >> gl_vdbl_r) + gl_vcenter;
2383 		uae_u8 *image_genlock = genlock_image + gy * genlock_image_pitch;
2384 		r = g = b = 0;
2385 		noise_add = (quickrand() & 15) | 1;
2386 		for (x = 0; x < src->inwidth; x++) {
2387 			uae_u8 *s = line + x * src->pixbytes;
2388 			uae_u8 *d = dstline + x * dst->pixbytes;
2389 			uae_u8 *s_genlock = line_genlock + x;
2390 			uae_u8 *s2 = s + src->rowbytes;
2391 			uae_u8 *d2 = d + dst->rowbytes;
2392 
2393 			if (is_transparent(*s_genlock)) {
2394 				if (genlock_image) {
2395 					int gx = (((x + gl_hcenter) << gl_hdbl_l) >> gl_hdbl_r);
2396 					if (gx >= 0 && gx < genlock_image_width && gy >= 0 && gy < genlock_image_height) {
2397 						uae_u8 *s_genlock_image = image_genlock + gx * 4;
2398 						r = s_genlock_image[0];
2399 						g = s_genlock_image[1];
2400 						b = s_genlock_image[2];
2401 					} else {
2402 						r = g = b = 0;
2403 					}
2404 				} else {
2405 					r = g = b = get_noise();
2406 				}
2407 				if (mix2) {
2408 					r = (mix1 * r + mix2 * FVR(src, s)) / 256;
2409 					g = (mix1 * g + mix2 * FVG(src, s)) / 256;
2410 					b = (mix1 * b + mix2 * FVB(src, s)) / 256;
2411 				}
2412 				PUT_PRGB(d, d2, dst, r, g, b, 0, doublelines, false);
2413 			} else {
2414 				PUT_AMIGARGB(d, s, d2, s2, dst, 0, doublelines, false);
2415 			}
2416 		}
2417 	}
2418 
2419 	dst->nativepositioning = true;
2420 	return true;
2421 }
2422 
emulate_genlock(struct vidbuffer * src,struct vidbuffer * dst)2423 bool emulate_genlock(struct vidbuffer *src, struct vidbuffer *dst)
2424 {
2425 	bool v;
2426 	if (interlace_seen) {
2427 		if (currprefs.gfx_iscanlines) {
2428 			v = do_genlock(src, dst, false, lof_store ? 0 : 1);
2429 			if (v && currprefs.gfx_iscanlines > 1)
2430 				blank_generic(src, dst, lof_store ? 1 : 0);
2431 		} else {
2432 			v = do_genlock(src, dst, false, 0);
2433 			v |= do_genlock(src, dst, false, 1);
2434 		}
2435 	} else {
2436 		if (currprefs.gfx_pscanlines) {
2437 			v = do_genlock(src, dst, false, lof_store ? 0 : 1);
2438 			if (v && currprefs.gfx_pscanlines > 1)
2439 				blank_generic(src, dst, lof_store ? 1 : 0);
2440 		} else {
2441 			v = do_genlock(src, dst, true, 0);
2442 		}
2443 	}
2444 	return v;
2445 }
2446