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