|
|
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;
574: int vw_clip, vh_clip;
575:
576: /* Horizontal scroll register set? */
577: if (hscrolloffset) {
578: /* Yes, so we need to adjust offset to next line: */
579: nextline += vbpp;
580: }
581:
582: /* The sample-hold feature exists only on the TT */
583: bTTSampleHold = (TTSpecialVideoMode & 0x80) != 0;
584:
585: /* Clip to SDL_Surface dimensions */
586: scrwidth = Screen_GetGenConvWidth();
587: scrheight = Screen_GetGenConvHeight();
588: vw_clip = vw + rightBorder + leftBorder;
589: vh_clip = vh + upperBorder + lowerBorder;
590: if (vw_clip > scrwidth)
591: vw_clip = scrwidth;
592: if (vh_clip > scrheight)
593: vh_clip = scrheight;
594:
595: /* If there's not enough space to display the left border, just return */
596: if (vw_clip < leftBorder)
597: return;
598: /* If there's not enough space for the left border + the graphic area, we clip */
599: if (vw_clip < vw + leftBorder) {
600: vw = vw_clip - leftBorder;
601: rightBorderSize = 0;
602: }
603: /* if there's not enough space for the left border + the graphic area + the right border, we clip the border */
604: else if (vw_clip < vw + leftBorder + rightBorder)
605: rightBorderSize = vw_clip - leftBorder - vw;
606: else
607: rightBorderSize = rightBorder;
608:
609: /* If there's not enough space to display the upper border, just return */
610: if (vh_clip < upperBorder)
611: return;
612:
613: /* If there's not enough space for the upper border + the graphic area, we clip */
614: if (vh_clip < vh + upperBorder) {
615: vh = vh_clip - upperBorder;
616: lowBorderSize = 0;
617: }
618: /* if there's not enough space for the upper border + the graphic area + the lower border, we clip the border */
619: else if (vh_clip < vh + upperBorder + lowerBorder)
620: lowBorderSize = vh_clip - upperBorder - vh;
621: else
622: lowBorderSize = lowerBorder;
623:
624: /* Center screen */
625: hvram += ((scrheight-vh_clip)>>1) * sdlscrn->pitch;
626: hvram += ((scrwidth-vw_clip)>>1) * sdlscrn->format->BytesPerPixel;
627:
628: fvram_line = fvram;
629: scrwidth = leftBorder + vw + rightBorder;
630:
631: /* render the graphic area */
632: if (vbpp < 16) {
633: /* Bitplanes modes */
634: switch (sdlscrn->format->BytesPerPixel)
635: {
636: case 2:
637: ScreenConv_BitplaneTo16bppNoZoom(fvram_line, hvram,
638: scrwidth, scrheight, vw, vh,
639: vbpp, nextline, hscrolloffset,
640: leftBorder, rightBorderSize,
641: upperBorder, lowBorderSize);
642: break;
643: case 4:
644: ScreenConv_BitplaneTo32bppNoZoom(fvram_line, hvram,
645: scrwidth, scrheight, vw, vh,
646: vbpp, nextline, hscrolloffset,
647: leftBorder, rightBorderSize,
648: upperBorder, lowBorderSize);
649: break;
650: }
651: } else {
652: /* Falcon TC (High Color) */
653: switch (sdlscrn->format->BytesPerPixel)
654: {
655: case 2:
656: ScreenConv_HiColorTo16bppNoZoom(fvram_line, hvram,
657: scrwidth, scrheight, vw, vh,
658: vbpp, nextline, hscrolloffset,
659: leftBorder, rightBorderSize,
660: upperBorder, lowBorderSize);
661: break;
662: case 4:
663: ScreenConv_HiColorTo32bppNoZoom(fvram_line, hvram,
664: scrwidth, scrheight, vw, vh,
665: vbpp, nextline, hscrolloffset,
666: leftBorder, rightBorderSize,
667: upperBorder, lowBorderSize);
668: break;
669: }
670: }
671: }
672:
673:
674: static void ScreenConv_BitplaneTo16bppZoomed(Uint16 *fvram, Uint8 *hvram,
675: int scrwidth, int scrheight,
676: int vw, int vh, int vbpp,
677: int nextline, int hscrolloffset,
678: int leftBorder, int rightBorder,
679: int upperBorder, int lowerBorder,
680: int coefx, int coefy)
681: {
682: /* One complete 16-pixel aligned planar 2 chunky line */
683: Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15));
684: Uint16 *hvram_line = (Uint16 *)hvram;
685: Uint16 *hvram_column = p2cline;
686: Uint16 *fvram_line;
687: int pitch = sdlscrn->pitch >> 1;
688: int cursrcline = -1;
689: int scrIdx = 0;
690: int w, h;
691:
692: /* Render the upper border */
693: for (h = 0; h < upperBorder * coefy; h++)
694: {
695: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
696: hvram_line += pitch;
697: }
698:
699: /* Render the graphical area */
700: for (h = 0; h < scrheight; h++)
701: {
702: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
703: scrIdx ++;
704: nSampleHoldIdx = 0;
705:
706: /* Recopy the same line ? */
707: if (screen_zoom.zoomytable[h] == cursrcline)
708: {
709: memcpy(hvram_line, hvram_line - pitch, scrwidth * sdlscrn->format->BytesPerPixel);
710: }
711: else
712: {
713: ScreenConv_BitplaneLineTo16bpp(fvram_line, p2cline,
714: vw, vbpp, hscrolloffset);
715:
716: hvram_column = hvram_line;
717:
718: /* Display the Left border */
719: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder * coefx);
720: hvram_column += leftBorder * coefx;
721:
722: /* Display the Graphical area */
723: for (w = 0; w < vw * coefx; w++)
724: hvram_column[w] = p2cline[screen_zoom.zoomxtable[w]];
725: hvram_column += vw * coefx;
726:
727: /* Display the Right border */
728: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder * coefx);
729: }
730:
731: hvram_line += pitch;
732: cursrcline = screen_zoom.zoomytable[h];
733: }
734:
735: /* Render the lower border */
736: for (h = 0; h < lowerBorder * coefy; h++)
737: {
738: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
739: hvram_line += pitch;
740: }
741:
742: free(p2cline);
743: }
744:
745: static void ScreenConv_BitplaneTo32bppZoomed(Uint16 *fvram, Uint8 *hvram,
746: int scrwidth, int scrheight,
747: int vw, int vh, int vbpp,
748: int nextline, int hscrolloffset,
749: int leftBorder, int rightBorder,
750: int upperBorder, int lowerBorder,
751: int coefx, int coefy)
752: {
753: /* One complete 16-pixel aligned planar 2 chunky line */
754: Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15));
755: Uint32 *hvram_line = (Uint32 *)hvram;
756: Uint32 *hvram_column = p2cline;
757: Uint16 *fvram_line;
758: int pitch = sdlscrn->pitch >> 2;
759: int cursrcline = -1;
760: int scrIdx = 0;
761: int w, h;
762:
763: /* Render the upper border */
764: for (h = 0; h < upperBorder * coefy; h++)
765: {
766: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
767: hvram_line += pitch;
768: }
769:
770: /* Render the graphical area */
771: for (h = 0; h < scrheight; h++)
772: {
773: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
774: scrIdx ++;
775: nSampleHoldIdx = 0;
776:
777: /* Recopy the same line ? */
778: if (screen_zoom.zoomytable[h] == cursrcline)
779: {
780: memcpy(hvram_line, hvram_line - pitch, scrwidth * sdlscrn->format->BytesPerPixel);
781: }
782: else
783: {
784: ScreenConv_BitplaneLineTo32bpp(fvram_line, p2cline,
785: vw, vbpp, hscrolloffset);
786:
787: hvram_column = hvram_line;
788: /* Display the Left border */
789: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder * coefx);
790: hvram_column += leftBorder * coefx;
791:
792: /* Display the Graphical area */
793: for (w = 0; w < vw * coefx; w++)
794: {
795: hvram_column[w] = p2cline[screen_zoom.zoomxtable[w]];
796: }
797: hvram_column += vw * coefx;
798:
799: /* Display the Right border */
800: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder * coefx);
801: }
802:
803: hvram_line += pitch;
804: cursrcline = screen_zoom.zoomytable[h];
805: }
806:
807: /* Render the lower border */
808: for (h = 0; h < lowerBorder * coefy; h++)
809: {
810: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
811: hvram_line += pitch;
812: }
813:
814: free(p2cline);
815: }
816:
817: static void ScreenConv_HiColorTo16bppZoomed(Uint16 *fvram, Uint8 *hvram,
818: int scrwidth, int scrheight,
819: int vw, int vh, int vbpp,
820: int nextline, int hscrolloffset,
821: int leftBorder, int rightBorder,
822: int upperBorder, int lowerBorder,
823: int coefx, int coefy)
824: {
825: Uint16 *hvram_line = (Uint16 *)hvram;
826: Uint16 *hvram_column = hvram_line;
827: Uint16 *fvram_line;
828: int pitch = sdlscrn->pitch >> 1;
829: int cursrcline = -1;
830: int scrIdx = 0;
831: int w, h;
832:
833: /* Render the upper border */
834: for (h = 0; h < upperBorder * coefy; h++)
835: {
836: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
837: hvram_line += pitch;
838: }
839:
840: /* Render the graphical area */
841: for (h = 0; h < scrheight; h++)
842: {
843: Uint16 *fvram_column;
844:
845: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
846: scrIdx ++;
847:
848: fvram_column = fvram_line;
849:
850: /* Recopy the same line ? */
851: if (screen_zoom.zoomytable[h] == cursrcline)
852: {
853: memcpy(hvram_line, hvram_line - pitch, scrwidth * sdlscrn->format->BytesPerPixel);
854: }
855: else
856: {
857: hvram_column = hvram_line;
858:
859: /* Display the Left border */
860: Screen_memset_uint16(hvram_column, palette.native[0], leftBorder * coefx);
861: hvram_column += leftBorder * coefx;
862:
863: /* Display the Graphical area */
864: for (w = 0; w < vw * coefx; w++)
865: *hvram_column++ = SDL_SwapBE16(fvram_column[screen_zoom.zoomxtable[w]]);
866:
867: /* Display the Right border */
868: Screen_memset_uint16(hvram_column, palette.native[0], rightBorder * coefx);
869: }
870:
871: hvram_line += pitch;
872: cursrcline = screen_zoom.zoomytable[h];
873: }
874:
875: /* Render the lower border */
876: for (h = 0; h < lowerBorder * coefy; h++)
877: {
878: Screen_memset_uint16(hvram_line, palette.native[0], scrwidth);
879: hvram_line += pitch;
880: }
881: }
882:
883: static void ScreenConv_HiColorTo32bppZoomed(Uint16 *fvram, Uint8 *hvram,
884: int scrwidth, int scrheight,
885: int vw, int vh, int vbpp,
886: int nextline, int hscrolloffset,
887: int leftBorder, int rightBorder,
888: int upperBorder, int lowerBorder,
889: int coefx, int coefy)
890: {
891: Uint32 *hvram_line = (Uint32 *)hvram;
892: Uint32 *hvram_column = hvram_line;
893: Uint16 *fvram_line;
894: int pitch = sdlscrn->pitch >> 2;
895: int cursrcline = -1;
896: int scrIdx = 0;
897: int w, h;
898:
899: /* Render the upper border */
900: for (h = 0; h < upperBorder * coefy; h++)
901: {
902: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
903: hvram_line += pitch;
904: }
905:
906: /* Render the graphical area */
907: for (h = 0; h < scrheight; h++)
908: {
909: Uint16 *fvram_column;
910:
911: fvram_line = fvram + (screen_zoom.zoomytable[scrIdx] * nextline);
912: scrIdx ++;
913: fvram_column = fvram_line;
914:
915: /* Recopy the same line ? */
916: if (screen_zoom.zoomytable[h] == cursrcline)
917: {
918: memcpy(hvram_line, hvram_line - pitch, scrwidth * sdlscrn->format->BytesPerPixel);
919: }
920: else
921: {
922: hvram_column = hvram_line;
923:
924: /* Display the Left border */
925: Screen_memset_uint32(hvram_column, palette.native[0], leftBorder * coefx);
926: hvram_column += leftBorder * coefx;
927:
928: /* Display the Graphical area */
929: for (w = 0; w < vw * coefx; w++)
930: {
931: Uint16 srcword;
932: Uint8 r, g, b;
933: srcword = SDL_SwapBE16(fvram_column[screen_zoom.zoomxtable[w]]);
934: r = ((srcword >> 8) & 0xf8) | (srcword >> 13);
935: g = ((srcword >> 3) & 0xfc) | ((srcword >> 9) & 0x3);
936: b = (srcword << 3) | ((srcword >> 2) & 0x07);
937: *hvram_column ++ = SDL_MapRGB(sdlscrn->format, r, g, b);
938: }
939:
940: /* Display the Right border */
941: Screen_memset_uint32(hvram_column, palette.native[0], rightBorder * coefx);
942: }
943:
944: hvram_line += pitch;
945: cursrcline = screen_zoom.zoomytable[h];
946: }
947:
948: /* Render the lower border */
949: for (h = 0; h < lowerBorder * coefy; h++)
950: {
951: Screen_memset_uint32(hvram_line, palette.native[0], scrwidth);
952: hvram_line += pitch;
953: }
954: }
955:
956: static void Screen_ConvertWithZoom(Uint16 *fvram, int vw, int vh, int vbpp, int nextline,
957: int hscrolloffset, int leftBorder, int rightBorder,
958: int upperBorder, int lowerBorder)
959: {
960: int coefx = 1;
961: int coefy = 1;
962: int scrpitch, scrwidth, scrheight, scrbpp;
963: Uint8 *hvram;
964: int vw_b, vh_b;
965: int i;
966:
967: /* The sample-hold feature exists only on the TT */
968: bTTSampleHold = (TTSpecialVideoMode & 0x80) != 0;
969:
970: vw_b = vw + leftBorder + rightBorder;
971: vh_b = vh + upperBorder + lowerBorder;
972:
973: /* Host screen infos */
974: scrpitch = sdlscrn->pitch;
975: scrwidth = Screen_GetGenConvWidth();
976: scrheight = Screen_GetGenConvHeight();
977: scrbpp = sdlscrn->format->BytesPerPixel;
978: hvram = sdlscrn->pixels;
979:
980: /* Horizontal scroll register set? */
981: if (hscrolloffset) {
982: /* Yes, so we need to adjust offset to next line: */
983: nextline += vbpp;
984: }
985:
986: /* Integer zoom coef ? */
987: if (scrwidth >= vw_b && scrheight >= vh_b) {
988: coefx = scrwidth / vw_b;
989: coefy = scrheight / vh_b;
990:
991: scrwidth = vw_b * coefx;
992: scrheight = vh_b * coefy;
993:
994: /* Center screen */
995: hvram += ((Screen_GetGenConvHeight()-scrheight)>>1)*scrpitch;
996: hvram += ((Screen_GetGenConvWidth()-scrwidth)>>1)*scrbpp;
997: }
998:
999: /* New zoom ? */
1000: if (screen_zoom.zoomwidth != vw_b || scrwidth != screen_zoom.prev_scrwidth) {
1001: if (screen_zoom.zoomxtable) {
1002: free(screen_zoom.zoomxtable);
1003: }
1004: screen_zoom.zoomxtable = malloc(sizeof(int)*scrwidth);
1005: for (i=0; i<scrwidth; i++) {
1006: screen_zoom.zoomxtable[i] = (vw_b * i) / scrwidth;
1007: }
1008: screen_zoom.zoomwidth = vw_b;
1009: screen_zoom.prev_scrwidth = scrwidth;
1010: }
1011: if (screen_zoom.zoomheight != vh_b || scrheight != screen_zoom.prev_scrheight) {
1012: if (screen_zoom.zoomytable) {
1013: free(screen_zoom.zoomytable);
1014: }
1015: screen_zoom.zoomytable = malloc(sizeof(int)*scrheight);
1016: for (i=0; i<scrheight; i++) {
1017: screen_zoom.zoomytable[i] = (vh_b * i) / scrheight;
1018: }
1019: screen_zoom.zoomheight = vh_b;
1020: screen_zoom.prev_scrheight = scrheight;
1021: }
1022:
1023: /* scrwidth must not change */
1024: scrheight = vh * coefy;
1025:
1026: if (vw < 16) {
1027: Log_Printf(LOG_WARN, "ERROR: Videl <16 screen width (%dx%d without borders)\nIf this happens at TOS boot, remove hatari.nvram,\nNVRAM video settings in it are corrupted.\n", vw, vh);
1028: /* prevent memory corruption */
1029: return;
1030: }
1031:
1032: if (vbpp<16) {
1033: /* Bitplanes modes */
1034: switch(scrbpp) {
1035: case 2:
1036: ScreenConv_BitplaneTo16bppZoomed(fvram, hvram, scrwidth, scrheight,
1037: vw, vh, vbpp, nextline, hscrolloffset,
1038: leftBorder, rightBorder, upperBorder,
1039: lowerBorder, coefx, coefy);
1040: break;
1041: case 4:
1042: ScreenConv_BitplaneTo32bppZoomed(fvram, hvram, scrwidth, scrheight,
1043: vw, vh, vbpp, nextline, hscrolloffset,
1044: leftBorder, rightBorder, upperBorder,
1045: lowerBorder, coefx, coefy);
1046: break;
1047: }
1048: } else {
1049: /* Falcon high-color (16-bit) mode */
1050: switch(scrbpp) {
1051: case 2:
1052: ScreenConv_HiColorTo16bppZoomed(fvram, hvram, scrwidth, scrheight,
1053: vw, vh, vbpp, nextline, hscrolloffset,
1054: leftBorder, rightBorder, upperBorder,
1055: lowerBorder, coefx, coefy);
1056: break;
1057: case 4:
1058: ScreenConv_HiColorTo32bppZoomed(fvram, hvram, scrwidth, scrheight,
1059: vw, vh, vbpp, nextline, hscrolloffset,
1060: leftBorder, rightBorder, upperBorder,
1061: lowerBorder, coefx, coefy);
1062: break;
1063: }
1064: }
1065: }
1066:
1067: void Screen_GenConvert(void *fvram, int vw, int vh, int vbpp, int nextline,
1068: int hscroll, int leftBorderSize, int rightBorderSize,
1069: int upperBorderSize, int lowerBorderSize)
1070: {
1071: if (nScreenZoomX * nScreenZoomY != 1) {
1072: Screen_ConvertWithZoom(fvram, vw, vh, vbpp, nextline, hscroll,
1073: leftBorderSize, rightBorderSize,
1074: upperBorderSize, lowerBorderSize);
1075: } else {
1076: Screen_ConvertWithoutZoom(fvram, vw, vh, vbpp, nextline, hscroll,
1077: leftBorderSize, rightBorderSize,
1078: upperBorderSize, lowerBorderSize);
1079: }
1080: }
1081:
1082: bool Screen_GenDraw(uint32_t vaddr, int vw, int vh, int vbpp, int nextline,
1083: int leftBorder, int rightBorder,
1084: int upperBorder, int lowerBorder)
1085: {
1086: int hscrolloffset;
1087:
1088: if (!Screen_Lock())
1089: return false;
1090:
1091: if (Config_IsMachineST())
1092: hscrolloffset = 0;
1093: else
1094: hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1095:
1096: Screen_GenConvert(&STRam[vaddr], vw, vh, vbpp, nextline, hscrolloffset,
1097: leftBorder, rightBorder, upperBorder, lowerBorder);
1098:
1099: Screen_UnLock();
1100: Screen_GenConvUpdate(Statusbar_Update(sdlscrn, false), false);
1101: return true;
1102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.