|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - screenConvert.c
1.1 root 3:
1.1.1.8 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6: */
7:
1.1.1.5 root 8: #include <SDL_endian.h>
1.1 root 9: #include "main.h"
1.1.1.8 root 10: #include "configuration.h"
11: #include "log.h"
12: #include "ioMem.h"
13: #include "memorySnapShot.h"
1.1 root 14: #include "screen.h"
15: #include "screenConvert.h"
1.1.1.8 root 16: #include "statusbar.h"
17: #include "stMemory.h"
1.1 root 18: #include "video.h"
19:
20:
1.1.1.8 root 21: struct screen_zoom_s {
22: Uint16 zoomwidth;
23: Uint16 prev_scrwidth;
24: Uint16 zoomheight;
25: Uint16 prev_scrheight;
26: int *zoomxtable;
27: int *zoomytable;
28: };
1.1.1.7 root 29:
1.1.1.8 root 30: static struct screen_zoom_s screen_zoom;
31: static bool bTTSampleHold = false; /* TT special video mode */
32: static int nSampleHoldIdx;
1.1 root 33:
1.1.1.3 root 34:
1.1.1.8 root 35: /* TOS palette (bpp < 16) to SDL color mapping */
36: static struct
37: {
38: SDL_Color standard[256];
39: Uint32 native[256];
40: } palette;
1.1.1.3 root 41:
1.1.1.8 root 42: void Screen_SetPaletteColor(Uint8 idx, Uint8 red, Uint8 green, Uint8 blue)
43: {
44: // set the SDL standard RGB palette settings
45: palette.standard[idx].r = red;
46: palette.standard[idx].g = green;
47: palette.standard[idx].b = blue;
48: // convert the color to native
49: palette.native[idx] = SDL_MapRGB(sdlscrn->format, red, green, blue);
50: }
1.1 root 51:
1.1.1.8 root 52: void Screen_RemapPalette(void)
53: {
54: int i;
55: Uint32 *native = palette.native;
56: SDL_Color *standard = palette.standard;
57: SDL_PixelFormat *fmt = sdlscrn->format;
1.1 root 58:
1.1.1.8 root 59: for(i = 0; i < 256; i++, native++, standard++) {
60: *native = SDL_MapRGB(fmt, standard->r, standard->g, standard->b);
61: }
62: }
63:
64: void ScreenConv_MemorySnapShot_Capture(bool bSave)
1.1 root 65: {
1.1.1.8 root 66: MemorySnapShot_Store(palette.standard, sizeof(palette.standard));
67: if (!bSave)
68: Screen_RemapPalette();
69: }
70:
71: static void Screen_memset_uint32(Uint32 *addr, Uint32 color, int count)
72: {
73: while (count-- > 0) {
74: *addr++ = color;
75: }
76: }
77:
78: static void Screen_memset_uint16(Uint16 *addr, Uint16 color, int count)
79: {
80: while (count-- > 0) {
81: *addr++ = color;
82: }
83: }
84:
85: static inline Uint32 idx2pal(Uint8 idx)
86: {
87: if (unlikely(bTTSampleHold))
88: {
89: if (idx == 0)
90: return palette.native[nSampleHoldIdx];
91: nSampleHoldIdx = idx;
92: }
93: return palette.native[idx];
94: }
95:
96: /**
97: * Performs conversion from the TOS's bitplane word order (big endian) data
98: * into the native 16-bit chunky pixels.
99: */
100: static void Screen_BitplaneToChunky16(Uint16 *atariBitplaneData, Uint16 bpp,
101: Uint16 *hvram)
102: {
103: Uint32 a, b, c, d, x;
104:
105: /* Obviously the different cases can be broken out in various
106: * ways to lessen the amount of work needed for <8 bit modes.
107: * It's doubtful if the usage of those modes warrants it, though.
108: * The branches below should be ~100% correctly predicted and
109: * thus be more or less for free.
110: */
111: if (bpp >= 4) {
112: d = *(Uint32 *)&atariBitplaneData[0];
113: c = *(Uint32 *)&atariBitplaneData[2];
114: if (bpp == 4) {
115: a = b = 0;
116: } else {
117: b = *(Uint32 *)&atariBitplaneData[4];
118: a = *(Uint32 *)&atariBitplaneData[6];
119: }
120:
121: x = a;
122: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4);
123: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f);
124: } else {
125: a = b = c = 0;
126: if (bpp == 2) {
127: d = *(Uint32 *)&atariBitplaneData[0];
128: } else {
1.1.1.5 root 129: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.8 root 130: d = atariBitplaneData[0]<<16;
131: #else
132: d = atariBitplaneData[0];
1.1.1.5 root 133: #endif
1.1.1.8 root 134: }
135: }
136:
137: x = b;
138: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4);
139: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f);
140:
141: x = a;
142: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2);
143: b = ((x & 0x33333333) << 2) | (b & 0x33333333);
144: x = c;
145: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2);
146: d = ((x & 0x33333333) << 2) | (d & 0x33333333);
147:
1.1.1.3 root 148: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.8 root 149: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
150: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
151: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
152: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
153:
154: *hvram++ = idx2pal(a >> 8);
155: *hvram++ = idx2pal(a >> 24);
156: *hvram++ = idx2pal(b >> 8);
157: *hvram++ = idx2pal(b >> 24);
158: *hvram++ = idx2pal(c >> 8);
159: *hvram++ = idx2pal(c >> 24);
160: *hvram++ = idx2pal(d >> 8);
161: *hvram++ = idx2pal(d >> 24);
162: *hvram++ = idx2pal(a);
163: *hvram++ = idx2pal(a >> 16);
164: *hvram++ = idx2pal(b);
165: *hvram++ = idx2pal(b >> 16);
166: *hvram++ = idx2pal(c);
167: *hvram++ = idx2pal(c >> 16);
168: *hvram++ = idx2pal(d);
169: *hvram++ = idx2pal(d >> 16);
1.1.1.2 root 170: #else
1.1.1.8 root 171: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
172: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
173: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
174: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
175:
176: *hvram++ = idx2pal(a >> 16);
177: *hvram++ = idx2pal(a);
178: *hvram++ = idx2pal(b >> 16);
179: *hvram++ = idx2pal(b);
180: *hvram++ = idx2pal(c >> 16);
181: *hvram++ = idx2pal(c);
182: *hvram++ = idx2pal(d >> 16);
183: *hvram++ = idx2pal(d);
184: *hvram++ = idx2pal(a >> 24);
185: *hvram++ = idx2pal(a >> 8);
186: *hvram++ = idx2pal(b >> 24);
187: *hvram++ = idx2pal(b >> 8);
188: *hvram++ = idx2pal(c >> 24);
189: *hvram++ = idx2pal(c >> 8);
190: *hvram++ = idx2pal(d >> 24);
191: *hvram++ = idx2pal(d >> 8);
1.1.1.2 root 192: #endif
1.1 root 193: }
194:
1.1.1.8 root 195: /**
196: * Performs conversion from the TOS's bitplane word order (big endian) data
197: * into the native 32-bit chunky pixels.
198: */
199: static void Screen_BitplaneToChunky32(Uint16 *atariBitplaneData, Uint16 bpp,
200: Uint32 *hvram)
201: {
202: Uint32 a, b, c, d, x;
1.1.1.2 root 203:
1.1.1.8 root 204: if (bpp >= 4) {
205: d = *(Uint32 *)&atariBitplaneData[0];
206: c = *(Uint32 *)&atariBitplaneData[2];
207: if (bpp == 4) {
208: a = b = 0;
209: } else {
210: b = *(Uint32 *)&atariBitplaneData[4];
211: a = *(Uint32 *)&atariBitplaneData[6];
212: }
213:
214: x = a;
215: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4);
216: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f);
217: } else {
218: a = b = c = 0;
219: if (bpp == 2) {
220: d = *(Uint32 *)&atariBitplaneData[0];
221: } else {
222: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
223: d = atariBitplaneData[0]<<16;
224: #else
225: d = atariBitplaneData[0];
226: #endif
227: }
228: }
229:
230: x = b;
231: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4);
232: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f);
233:
234: x = a;
235: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2);
236: b = ((x & 0x33333333) << 2) | (b & 0x33333333);
237: x = c;
238: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2);
239: d = ((x & 0x33333333) << 2) | (d & 0x33333333);
240:
241: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
242: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
243: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
244: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
245: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
246:
247: *hvram++ = idx2pal(a >> 8);
248: *hvram++ = idx2pal(a >> 24);
249: *hvram++ = idx2pal(b >> 8);
250: *hvram++ = idx2pal(b >> 24);
251: *hvram++ = idx2pal(c >> 8);
252: *hvram++ = idx2pal(c >> 24);
253: *hvram++ = idx2pal(d >> 8);
254: *hvram++ = idx2pal(d >> 24);
255: *hvram++ = idx2pal(a);
256: *hvram++ = idx2pal(a >> 16);
257: *hvram++ = idx2pal(b);
258: *hvram++ = idx2pal(b >> 16);
259: *hvram++ = idx2pal(c);
260: *hvram++ = idx2pal(c >> 16);
261: *hvram++ = idx2pal(d);
262: *hvram++ = idx2pal(d >> 16);
263: #else
264: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
265: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
266: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
267: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
268:
269: *hvram++ = idx2pal(a >> 16);
270: *hvram++ = idx2pal(a);
271: *hvram++ = idx2pal(b >> 16);
272: *hvram++ = idx2pal(b);
273: *hvram++ = idx2pal(c >> 16);
274: *hvram++ = idx2pal(c);
275: *hvram++ = idx2pal(d >> 16);
276: *hvram++ = idx2pal(d);
277: *hvram++ = idx2pal(a >> 24);
278: *hvram++ = idx2pal(a >> 8);
279: *hvram++ = idx2pal(b >> 24);
280: *hvram++ = idx2pal(b >> 8);
281: *hvram++ = idx2pal(c >> 24);
282: *hvram++ = idx2pal(c >> 8);
283: *hvram++ = idx2pal(d >> 24);
284: *hvram++ = idx2pal(d >> 8);
285: #endif
286: }
287:
288: static inline Uint16 *ScreenConv_BitplaneLineTo16bpp(Uint16 *fvram_column,
289: Uint16 *hvram_column, int vw,
290: int vbpp, int hscrolloffset)
1.1 root 291: {
1.1.1.8 root 292: Uint16 hvram_buf[16];
293: int i;
294:
295: /* First 16 pixels */
296: Screen_BitplaneToChunky16(fvram_column, vbpp, hvram_buf);
297: for (i = hscrolloffset; i < 16; i++)
298: {
299: *hvram_column++ = hvram_buf[i];
300: }
301: fvram_column += vbpp;
302:
303: /* Now the main part of the line */
304: for (i = 1; i < (vw + 15) >> 4; i++)
305: {
306: Screen_BitplaneToChunky16(fvram_column, vbpp, hvram_column);
307: hvram_column += 16;
308: fvram_column += vbpp;
309: }
310:
311: /* Last pixels of the line for fine scrolling */
312: if (hscrolloffset)
313: {
314: Screen_BitplaneToChunky16(fvram_column, vbpp, hvram_buf);
315: for (i = 0; i < hscrolloffset; i++)
316: {
317: *hvram_column++ = hvram_buf[i];
318: }
319: }
320:
321: return hvram_column;
322: }
323:
324: static inline Uint32 *ScreenConv_BitplaneLineTo32bpp(Uint16 *fvram_column,
325: Uint32 *hvram_column, int vw,
326: int vbpp, int hscrolloffset)
327: {
328: Uint32 hvram_buf[16];
329: int i;
330:
331: /* First 16 pixels */
332: Screen_BitplaneToChunky32(fvram_column, vbpp, hvram_buf);
333: for (i = hscrolloffset; i < 16; i++)
334: {
335: *hvram_column++ = hvram_buf[i];
336: }
337: fvram_column += vbpp;
338:
339: /* Now the main part of the line */
340: for (i = 1; i < (vw + 15) >> 4; i++)
341: {
342: Screen_BitplaneToChunky32(fvram_column, vbpp, hvram_column);
343: hvram_column += 16;
344: fvram_column += vbpp;
345: }
346:
347: /* Last pixels of the line for fine scrolling */
348: if (hscrolloffset)
349: {
350: Screen_BitplaneToChunky32(fvram_column, vbpp, hvram_buf);
351: for (i = 0; i < hscrolloffset; i++)
352: {
353: *hvram_column++ = hvram_buf[i];
354: }
355: }
356:
357: return hvram_column;
358: }
359:
360: static void ScreenConv_BitplaneTo16bppNoZoom(Uint16 *fvram_line, Uint8 *hvram,
361: int scrwidth, int scrheight,
362: int vw, int vh, int vbpp,
363: int nextline, int hscrolloffset,
364: int leftBorder, int rightBorder,
365: int upperBorder, int lowBorder)
366: {
367: Uint16 *hvram_line = (Uint16 *)hvram;
368: int pitch = sdlscrn->pitch >> 1;
369: int h;
370:
371: /* Render the upper border */
372: for (h = 0; h < upperBorder; h++)
373: {
374: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
375: hvram_line += pitch;
376: }
377:
378: /* Render the graphical area */
379: for (h = 0; h < vh; h++)
380: {
381: Uint16 *hvram_column = hvram_line;
382:
383: nSampleHoldIdx = 0;
384:
385: /* Left border first */
386: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder);
387: hvram_column += leftBorder;
388:
389: hvram_column = ScreenConv_BitplaneLineTo16bpp(fvram_line, hvram_column,
390: vw, vbpp, hscrolloffset);
391:
392: /* Right border */
393: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder);
394:
395: fvram_line += nextline;
396: hvram_line += pitch;
397: }
398:
399: /* Render the lower border */
400: for (h = 0; h < lowBorder; h++)
401: {
402: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
403: hvram_line += pitch;
404: }
405: }
406:
407: static void ScreenConv_BitplaneTo32bppNoZoom(Uint16 *fvram_line, Uint8 *hvram,
408: int scrwidth, int scrheight,
409: int vw, int vh, int vbpp,
410: int nextline, int hscrolloffset,
411: int leftBorder, int rightBorder,
412: int upperBorder, int lowBorder)
413: {
414: Uint32 *hvram_line = (Uint32 *)hvram;
415: int pitch = sdlscrn->pitch >> 2;
416: int h;
417:
418: /* Render the upper border */
419: for (h = 0; h < upperBorder; h++)
420: {
421: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
422: hvram_line += pitch;
423: }
424:
425: /* Render the graphical area */
426: for (h = 0; h < vh; h++)
427: {
428: Uint32 *hvram_column = hvram_line;
429:
430: nSampleHoldIdx = 0;
431:
432: /* Left border first */
433: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder);
434: hvram_column += leftBorder;
435:
436: hvram_column = ScreenConv_BitplaneLineTo32bpp(fvram_line, hvram_column,
437: vw, vbpp, hscrolloffset);
438:
439: /* Right border */
440: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder);
441:
442: fvram_line += nextline;
443: hvram_line += pitch;
444: }
445:
446: /* Render the lower border */
447: for (h = 0; h < lowBorder; h++)
448: {
449: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
450: hvram_line += pitch;
451: }
452: }
453:
454: static void ScreenConv_HiColorTo16bppNoZoom(Uint16 *fvram_line, Uint8 *hvram,
455: int scrwidth, int scrheight,
456: int vw, int vh, int vbpp,
457: int nextline, int hscrolloffset,
458: int leftBorder, int rightBorder,
459: int upperBorder, int lowBorder)
460: {
461: Uint16 *hvram_line = (Uint16 *)hvram;
462: int pitch = sdlscrn->pitch >> 1;
463: int h;
464:
465: /* Render the upper border */
466: for (h = 0; h < upperBorder; h++)
467: {
468: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
469: hvram_line += pitch;
470: }
471:
472: /* Render the graphical area */
473: for (h = 0; h < vh; h++)
474: {
475: Uint16 *hvram_column = hvram_line;
476: #if SDL_BYTEORDER != SDL_BIG_ENDIAN
477: Uint16 *fvram_column;
478: int w;
479: #endif
480: /* Left border first */
481: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder);
482: hvram_column += leftBorder;
483:
484: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
485: /* FIXME: here might be a runtime little/big video endian switch like:
486: * if ( " videocard memory in Motorola endian format " false)
487: */
488: memcpy(hvram_column, fvram_line, vw<<1);
489: hvram_column += vw;
490: #else
491: fvram_column = fvram_line;
492: /* Graphical area */
493: for (w = 0; w < vw; w++)
494: *hvram_column ++ = SDL_SwapBE16(*fvram_column++);
495: #endif /* SDL_BYTEORDER == SDL_BIG_ENDIAN */
496:
497: /* Right border */
498: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder);
499:
500: fvram_line += nextline;
501: hvram_line += pitch;
502: }
503:
504: /* Render the bottom border */
505: for (h = 0; h < lowBorder; h++)
506: {
507: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
508: hvram_line += pitch;
509: }
510: }
511:
512: static void ScreenConv_HiColorTo32bppNoZoom(Uint16 *fvram_line, Uint8 *hvram,
513: int scrwidth, int scrheight,
514: int vw, int vh, int vbpp,
515: int nextline, int hscrolloffset,
516: int leftBorder, int rightBorder,
517: int upperBorder, int lowBorder)
518: {
519: Uint32 *hvram_line = (Uint32 *)hvram;
520: int pitch = sdlscrn->pitch >> 2;
521: int h, w;
522:
523: /* Render the upper border */
524: for (h = 0; h < upperBorder; h++)
525: {
526: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
527: hvram_line += pitch;
528: }
529:
530: /* Render the graphical area */
531: for (h = 0; h < vh; h++)
532: {
533: Uint16 *fvram_column = fvram_line;
534: Uint32 *hvram_column = hvram_line;
535:
536: /* Left border first */
537: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder);
538: hvram_column += leftBorder;
539:
540: /* Graphical area */
541: for (w = 0; w < vw; w++)
542: {
543: Uint16 srcword = SDL_SwapBE16(*fvram_column++);
544: Uint8 r = ((srcword >> 8) & 0xf8) | (srcword >> 13);
545: Uint8 g = ((srcword >> 3) & 0xfc) | ((srcword >> 9) & 0x3);
546: Uint8 b = (srcword << 3) | ((srcword >> 2) & 0x07);
547: *hvram_column ++ = SDL_MapRGB(sdlscrn->format, r, g, b);
548: }
549:
550: /* Right border */
551: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder);
552:
553: fvram_line += nextline;
554: hvram_line += pitch;
555: }
556:
557: /* Render the bottom border */
558: for (h = 0; h < lowBorder; h++)
559: {
560: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
561: hvram_line += pitch;
562: }
563: }
564:
565: static void Screen_ConvertWithoutZoom(Uint16 *fvram, int vw, int vh, int vbpp, int nextline,
566: int hscrolloffset, int leftBorder, int rightBorder,
567: int upperBorder, int lowerBorder)
568: {
569: Uint16 *fvram_line;
570: Uint8 *hvram = sdlscrn->pixels;
571:
572: Uint16 lowBorderSize, rightBorderSize;
573: int scrwidth, scrheight;
1.1.1.10! root 574: unsigned int nBytesPerPixel = sdlscrn->format->BytesPerPixel;
1.1.1.8 root 575: int vw_clip, vh_clip;
576:
577: /* Horizontal scroll register set? */
578: if (hscrolloffset) {
579: /* Yes, so we need to adjust offset to next line: */
580: nextline += vbpp;
581: }
582:
583: /* The sample-hold feature exists only on the TT */
584: bTTSampleHold = (TTSpecialVideoMode & 0x80) != 0;
585:
586: /* Clip to SDL_Surface dimensions */
587: scrwidth = Screen_GetGenConvWidth();
588: scrheight = Screen_GetGenConvHeight();
589: vw_clip = vw + rightBorder + leftBorder;
590: vh_clip = vh + upperBorder + lowerBorder;
591: if (vw_clip > scrwidth)
592: vw_clip = scrwidth;
593: if (vh_clip > scrheight)
594: vh_clip = scrheight;
595:
596: /* If there's not enough space to display the left border, just return */
597: if (vw_clip < leftBorder)
598: return;
599: /* If there's not enough space for the left border + the graphic area, we clip */
600: if (vw_clip < vw + leftBorder) {
601: vw = vw_clip - leftBorder;
602: rightBorderSize = 0;
603: }
604: /* if there's not enough space for the left border + the graphic area + the right border, we clip the border */
605: else if (vw_clip < vw + leftBorder + rightBorder)
606: rightBorderSize = vw_clip - leftBorder - vw;
607: else
608: rightBorderSize = rightBorder;
609:
610: /* If there's not enough space to display the upper border, just return */
611: if (vh_clip < upperBorder)
612: return;
613:
614: /* If there's not enough space for the upper border + the graphic area, we clip */
615: if (vh_clip < vh + upperBorder) {
616: vh = vh_clip - upperBorder;
617: lowBorderSize = 0;
618: }
619: /* if there's not enough space for the upper border + the graphic area + the lower border, we clip the border */
620: else if (vh_clip < vh + upperBorder + lowerBorder)
621: lowBorderSize = vh_clip - upperBorder - vh;
622: else
623: lowBorderSize = lowerBorder;
624:
625: /* Center screen */
626: hvram += ((scrheight-vh_clip)>>1) * sdlscrn->pitch;
1.1.1.10! root 627: hvram += ((scrwidth-vw_clip)>>1) * nBytesPerPixel;
1.1.1.8 root 628:
629: fvram_line = fvram;
630: scrwidth = leftBorder + vw + rightBorder;
631:
632: /* render the graphic area */
633: if (vbpp < 16) {
634: /* Bitplanes modes */
1.1.1.10! root 635: switch (nBytesPerPixel)
1.1.1.8 root 636: {
637: case 2:
638: ScreenConv_BitplaneTo16bppNoZoom(fvram_line, hvram,
639: scrwidth, scrheight, vw, vh,
640: vbpp, nextline, hscrolloffset,
641: leftBorder, rightBorderSize,
642: upperBorder, lowBorderSize);
643: break;
644: case 4:
645: ScreenConv_BitplaneTo32bppNoZoom(fvram_line, hvram,
646: scrwidth, scrheight, vw, vh,
647: vbpp, nextline, hscrolloffset,
648: leftBorder, rightBorderSize,
649: upperBorder, lowBorderSize);
650: break;
651: }
652: } else {
653: /* Falcon TC (High Color) */
1.1.1.10! root 654: switch (nBytesPerPixel)
1.1.1.8 root 655: {
656: case 2:
657: ScreenConv_HiColorTo16bppNoZoom(fvram_line, hvram,
658: scrwidth, scrheight, vw, vh,
659: vbpp, nextline, hscrolloffset,
660: leftBorder, rightBorderSize,
661: upperBorder, lowBorderSize);
662: break;
663: case 4:
664: ScreenConv_HiColorTo32bppNoZoom(fvram_line, hvram,
665: scrwidth, scrheight, vw, vh,
666: vbpp, nextline, hscrolloffset,
667: leftBorder, rightBorderSize,
668: upperBorder, lowBorderSize);
669: break;
670: }
671: }
672: }
673:
674:
675: static void ScreenConv_BitplaneTo16bppZoomed(Uint16 *fvram, Uint8 *hvram,
676: int scrwidth, int scrheight,
677: int vw, int vh, int vbpp,
678: int nextline, int hscrolloffset,
679: int leftBorder, int rightBorder,
680: int upperBorder, int lowerBorder,
681: int coefx, int coefy)
682: {
683: /* One complete 16-pixel aligned planar 2 chunky line */
684: Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15));
685: Uint16 *hvram_line = (Uint16 *)hvram;
686: Uint16 *hvram_column = p2cline;
687: Uint16 *fvram_line;
1.1.1.10! root 688: unsigned int nBytesPerPixel = sdlscrn->format->BytesPerPixel;
1.1.1.8 root 689: int pitch = sdlscrn->pitch >> 1;
690: int cursrcline = -1;
691: int scrIdx = 0;
692: int w, h;
693:
694: /* Render the upper border */
695: for (h = 0; h < upperBorder * coefy; h++)
696: {
697: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
698: hvram_line += pitch;
699: }
700:
701: /* Render the graphical area */
702: for (h = 0; h < scrheight; h++)
703: {
704: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
705: scrIdx ++;
706: nSampleHoldIdx = 0;
707:
708: /* Recopy the same line ? */
709: if (screen_zoom.zoomytable[h] == cursrcline)
710: {
1.1.1.10! root 711: memcpy(hvram_line, hvram_line - pitch, scrwidth * nBytesPerPixel);
1.1.1.8 root 712: }
713: else
714: {
715: ScreenConv_BitplaneLineTo16bpp(fvram_line, p2cline,
716: vw, vbpp, hscrolloffset);
717:
718: hvram_column = hvram_line;
719:
720: /* Display the Left border */
721: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder * coefx);
722: hvram_column += leftBorder * coefx;
723:
724: /* Display the Graphical area */
725: for (w = 0; w < vw * coefx; w++)
726: hvram_column[w] = p2cline[screen_zoom.zoomxtable[w]];
727: hvram_column += vw * coefx;
728:
729: /* Display the Right border */
730: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder * coefx);
731: }
732:
733: hvram_line += pitch;
734: cursrcline = screen_zoom.zoomytable[h];
735: }
736:
737: /* Render the lower border */
738: for (h = 0; h < lowerBorder * coefy; h++)
739: {
740: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
741: hvram_line += pitch;
742: }
743:
744: free(p2cline);
745: }
746:
747: static void ScreenConv_BitplaneTo32bppZoomed(Uint16 *fvram, Uint8 *hvram,
748: int scrwidth, int scrheight,
749: int vw, int vh, int vbpp,
750: int nextline, int hscrolloffset,
751: int leftBorder, int rightBorder,
752: int upperBorder, int lowerBorder,
753: int coefx, int coefy)
754: {
755: /* One complete 16-pixel aligned planar 2 chunky line */
756: Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15));
757: Uint32 *hvram_line = (Uint32 *)hvram;
758: Uint32 *hvram_column = p2cline;
759: Uint16 *fvram_line;
1.1.1.10! root 760: unsigned int nBytesPerPixel = sdlscrn->format->BytesPerPixel;
1.1.1.8 root 761: int pitch = sdlscrn->pitch >> 2;
762: int cursrcline = -1;
763: int scrIdx = 0;
764: int w, h;
765:
766: /* Render the upper border */
767: for (h = 0; h < upperBorder * coefy; h++)
768: {
769: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
770: hvram_line += pitch;
771: }
772:
773: /* Render the graphical area */
774: for (h = 0; h < scrheight; h++)
775: {
776: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
777: scrIdx ++;
778: nSampleHoldIdx = 0;
779:
780: /* Recopy the same line ? */
781: if (screen_zoom.zoomytable[h] == cursrcline)
782: {
1.1.1.10! root 783: memcpy(hvram_line, hvram_line - pitch, scrwidth * nBytesPerPixel);
1.1.1.8 root 784: }
785: else
786: {
787: ScreenConv_BitplaneLineTo32bpp(fvram_line, p2cline,
788: vw, vbpp, hscrolloffset);
789:
790: hvram_column = hvram_line;
791: /* Display the Left border */
792: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder * coefx);
793: hvram_column += leftBorder * coefx;
794:
795: /* Display the Graphical area */
796: for (w = 0; w < vw * coefx; w++)
797: {
798: hvram_column[w] = p2cline[screen_zoom.zoomxtable[w]];
799: }
800: hvram_column += vw * coefx;
801:
802: /* Display the Right border */
803: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder * coefx);
804: }
805:
806: hvram_line += pitch;
807: cursrcline = screen_zoom.zoomytable[h];
808: }
809:
810: /* Render the lower border */
811: for (h = 0; h < lowerBorder * coefy; h++)
812: {
813: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
814: hvram_line += pitch;
815: }
816:
817: free(p2cline);
818: }
819:
820: static void ScreenConv_HiColorTo16bppZoomed(Uint16 *fvram, Uint8 *hvram,
821: int scrwidth, int scrheight,
822: int vw, int vh, int vbpp,
823: int nextline, int hscrolloffset,
824: int leftBorder, int rightBorder,
825: int upperBorder, int lowerBorder,
826: int coefx, int coefy)
827: {
828: Uint16 *hvram_line = (Uint16 *)hvram;
829: Uint16 *hvram_column = hvram_line;
830: Uint16 *fvram_line;
1.1.1.10! root 831: unsigned int nBytesPerPixel = sdlscrn->format->BytesPerPixel;
1.1.1.8 root 832: int pitch = sdlscrn->pitch >> 1;
833: int cursrcline = -1;
834: int scrIdx = 0;
835: int w, h;
836:
837: /* Render the upper border */
838: for (h = 0; h < upperBorder * coefy; h++)
839: {
840: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
841: hvram_line += pitch;
842: }
843:
844: /* Render the graphical area */
845: for (h = 0; h < scrheight; h++)
846: {
847: Uint16 *fvram_column;
848:
849: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
850: scrIdx ++;
851:
852: fvram_column = fvram_line;
853:
854: /* Recopy the same line ? */
855: if (screen_zoom.zoomytable[h] == cursrcline)
856: {
1.1.1.10! root 857: memcpy(hvram_line, hvram_line - pitch, scrwidth * nBytesPerPixel);
1.1.1.8 root 858: }
859: else
860: {
861: hvram_column = hvram_line;
862:
863: /* Display the Left border */
864: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder * coefx);
865: hvram_column += leftBorder * coefx;
866:
867: /* Display the Graphical area */
868: for (w = 0; w < vw * coefx; w++)
869: *hvram_column++ = SDL_SwapBE16(fvram_column[screen_zoom.zoomxtable[w]]);
870:
871: /* Display the Right border */
872: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder * coefx);
873: }
874:
875: hvram_line += pitch;
876: cursrcline = screen_zoom.zoomytable[h];
877: }
878:
879: /* Render the lower border */
880: for (h = 0; h < lowerBorder * coefy; h++)
881: {
882: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
883: hvram_line += pitch;
884: }
885: }
886:
887: static void ScreenConv_HiColorTo32bppZoomed(Uint16 *fvram, Uint8 *hvram,
888: int scrwidth, int scrheight,
889: int vw, int vh, int vbpp,
890: int nextline, int hscrolloffset,
891: int leftBorder, int rightBorder,
892: int upperBorder, int lowerBorder,
893: int coefx, int coefy)
894: {
895: Uint32 *hvram_line = (Uint32 *)hvram;
896: Uint32 *hvram_column = hvram_line;
897: Uint16 *fvram_line;
1.1.1.10! root 898: unsigned int nBytesPerPixel = sdlscrn->format->BytesPerPixel;
1.1.1.8 root 899: int pitch = sdlscrn->pitch >> 2;
900: int cursrcline = -1;
901: int scrIdx = 0;
902: int w, h;
903:
904: /* Render the upper border */
905: for (h = 0; h < upperBorder * coefy; h++)
906: {
907: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
908: hvram_line += pitch;
909: }
910:
911: /* Render the graphical area */
912: for (h = 0; h < scrheight; h++)
913: {
914: Uint16 *fvram_column;
915:
916: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
917: scrIdx ++;
918: fvram_column = fvram_line;
919:
920: /* Recopy the same line ? */
921: if (screen_zoom.zoomytable[h] == cursrcline)
922: {
1.1.1.10! root 923: memcpy(hvram_line, hvram_line - pitch, scrwidth * nBytesPerPixel);
1.1.1.8 root 924: }
925: else
926: {
927: hvram_column = hvram_line;
928:
929: /* Display the Left border */
930: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder * coefx);
931: hvram_column += leftBorder * coefx;
932:
933: /* Display the Graphical area */
934: for (w = 0; w < vw * coefx; w++)
935: {
936: Uint16 srcword;
937: Uint8 r, g, b;
938: srcword = SDL_SwapBE16(fvram_column[screen_zoom.zoomxtable[w]]);
939: r = ((srcword >> 8) & 0xf8) | (srcword >> 13);
940: g = ((srcword >> 3) & 0xfc) | ((srcword >> 9) & 0x3);
941: b = (srcword << 3) | ((srcword >> 2) & 0x07);
942: *hvram_column ++ = SDL_MapRGB(sdlscrn->format, r, g, b);
943: }
944:
945: /* Display the Right border */
946: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder * coefx);
947: }
948:
949: hvram_line += pitch;
950: cursrcline = screen_zoom.zoomytable[h];
951: }
952:
953: /* Render the lower border */
954: for (h = 0; h < lowerBorder * coefy; h++)
955: {
956: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
957: hvram_line += pitch;
958: }
959: }
960:
961: static void Screen_ConvertWithZoom(Uint16 *fvram, int vw, int vh, int vbpp, int nextline,
962: int hscrolloffset, int leftBorder, int rightBorder,
963: int upperBorder, int lowerBorder)
964: {
965: int coefx = 1;
966: int coefy = 1;
967: int scrpitch, scrwidth, scrheight, scrbpp;
968: Uint8 *hvram;
969: int vw_b, vh_b;
970: int i;
971:
972: /* The sample-hold feature exists only on the TT */
973: bTTSampleHold = (TTSpecialVideoMode & 0x80) != 0;
974:
975: vw_b = vw + leftBorder + rightBorder;
976: vh_b = vh + upperBorder + lowerBorder;
977:
978: /* Host screen infos */
979: scrpitch = sdlscrn->pitch;
980: scrwidth = Screen_GetGenConvWidth();
981: scrheight = Screen_GetGenConvHeight();
982: scrbpp = sdlscrn->format->BytesPerPixel;
983: hvram = sdlscrn->pixels;
984:
985: /* Horizontal scroll register set? */
986: if (hscrolloffset) {
987: /* Yes, so we need to adjust offset to next line: */
988: nextline += vbpp;
989: }
990:
991: /* Integer zoom coef ? */
992: if (scrwidth >= vw_b && scrheight >= vh_b) {
993: coefx = scrwidth / vw_b;
994: coefy = scrheight / vh_b;
995:
996: scrwidth = vw_b * coefx;
997: scrheight = vh_b * coefy;
998:
999: /* Center screen */
1000: hvram += ((Screen_GetGenConvHeight()-scrheight)>>1)*scrpitch;
1001: hvram += ((Screen_GetGenConvWidth()-scrwidth)>>1)*scrbpp;
1002: }
1003:
1004: /* New zoom ? */
1005: if (screen_zoom.zoomwidth != vw_b || scrwidth != screen_zoom.prev_scrwidth) {
1006: if (screen_zoom.zoomxtable) {
1007: free(screen_zoom.zoomxtable);
1008: }
1009: screen_zoom.zoomxtable = malloc(sizeof(int)*scrwidth);
1010: for (i=0; i<scrwidth; i++) {
1011: screen_zoom.zoomxtable[i] = (vw_b * i) / scrwidth;
1012: }
1013: screen_zoom.zoomwidth = vw_b;
1014: screen_zoom.prev_scrwidth = scrwidth;
1015: }
1016: if (screen_zoom.zoomheight != vh_b || scrheight != screen_zoom.prev_scrheight) {
1017: if (screen_zoom.zoomytable) {
1018: free(screen_zoom.zoomytable);
1019: }
1020: screen_zoom.zoomytable = malloc(sizeof(int)*scrheight);
1021: for (i=0; i<scrheight; i++) {
1022: screen_zoom.zoomytable[i] = (vh_b * i) / scrheight;
1023: }
1024: screen_zoom.zoomheight = vh_b;
1025: screen_zoom.prev_scrheight = scrheight;
1026: }
1027:
1028: /* scrwidth must not change */
1029: scrheight = vh * coefy;
1030:
1031: if (vw < 16) {
1.1.1.10! root 1032: Log_Printf(LOG_WARN, "Videl <16 screen width (%dx%d without borders)\n"
! 1033: "If this happens at TOS boot, remove hatari.nvram,\n"
! 1034: "NVRAM video settings in it are corrupted.\n", vw, vh);
1.1.1.8 root 1035: /* prevent memory corruption */
1036: return;
1037: }
1038:
1039: if (vbpp<16) {
1040: /* Bitplanes modes */
1041: switch(scrbpp) {
1042: case 2:
1043: ScreenConv_BitplaneTo16bppZoomed(fvram, hvram, scrwidth, scrheight,
1044: vw, vh, vbpp, nextline, hscrolloffset,
1045: leftBorder, rightBorder, upperBorder,
1046: lowerBorder, coefx, coefy);
1047: break;
1048: case 4:
1049: ScreenConv_BitplaneTo32bppZoomed(fvram, hvram, scrwidth, scrheight,
1050: vw, vh, vbpp, nextline, hscrolloffset,
1051: leftBorder, rightBorder, upperBorder,
1052: lowerBorder, coefx, coefy);
1053: break;
1054: }
1055: } else {
1056: /* Falcon high-color (16-bit) mode */
1057: switch(scrbpp) {
1058: case 2:
1059: ScreenConv_HiColorTo16bppZoomed(fvram, hvram, scrwidth, scrheight,
1060: vw, vh, vbpp, nextline, hscrolloffset,
1061: leftBorder, rightBorder, upperBorder,
1062: lowerBorder, coefx, coefy);
1063: break;
1064: case 4:
1065: ScreenConv_HiColorTo32bppZoomed(fvram, hvram, scrwidth, scrheight,
1066: vw, vh, vbpp, nextline, hscrolloffset,
1067: leftBorder, rightBorder, upperBorder,
1068: lowerBorder, coefx, coefy);
1069: break;
1070: }
1071: }
1072: }
1073:
1074: void Screen_GenConvert(void *fvram, int vw, int vh, int vbpp, int nextline,
1075: int hscroll, int leftBorderSize, int rightBorderSize,
1076: int upperBorderSize, int lowerBorderSize)
1077: {
1078: if (nScreenZoomX * nScreenZoomY != 1) {
1079: Screen_ConvertWithZoom(fvram, vw, vh, vbpp, nextline, hscroll,
1080: leftBorderSize, rightBorderSize,
1081: upperBorderSize, lowerBorderSize);
1082: } else {
1083: Screen_ConvertWithoutZoom(fvram, vw, vh, vbpp, nextline, hscroll,
1084: leftBorderSize, rightBorderSize,
1085: upperBorderSize, lowerBorderSize);
1086: }
1087: }
1088:
1089: bool Screen_GenDraw(uint32_t vaddr, int vw, int vh, int vbpp, int nextline,
1090: int leftBorder, int rightBorder,
1091: int upperBorder, int lowerBorder)
1092: {
1093: int hscrolloffset;
1094:
1.1.1.10! root 1095: if (ConfigureParams.Screen.DisableVideo || !Screen_Lock())
1.1.1.8 root 1096: return false;
1097:
1098: if (Config_IsMachineST())
1099: hscrolloffset = 0;
1100: else
1101: hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1102:
1103: Screen_GenConvert(&STRam[vaddr], vw, vh, vbpp, nextline, hscrolloffset,
1104: leftBorder, rightBorder, upperBorder, lowerBorder);
1105:
1106: Screen_UnLock();
1107: Screen_GenConvUpdate(Statusbar_Update(sdlscrn, false), false);
1108: return true;
1109: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.