|
|
1.1 root 1: /*
2: Hatari - videl.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Falcon Videl emulation. The Videl is the graphics shifter chip of the Falcon.
8: It supports free programmable resolutions with 1, 2, 4, 8 or 16 bits per
9: pixel.
10:
11: This file originally came from the Aranym project and has been heavily
12: modified to work for Hatari (but the kudos for the great Videl emulation
13: code goes to the people from the Aranym project of course).
14: */
15: const char VIDEL_rcsid[] = "Hatari $Id: videl.c,v 1.17 2007/12/18 20:35:55 thothy Exp $";
16:
17: #include "main.h"
18: #include "configuration.h"
19: #include "ioMem.h"
20: #include "hostscreen.h"
21: #include "screen.h"
22: #include "stMemory.h"
23: #include "video.h"
24: #include "videl.h"
25: #include <SDL_endian.h>
26:
27:
28: #define handleRead(a) IoMem_ReadByte(a)
29: #define handleReadW(a) IoMem_ReadWord(a)
30: #define Atari2HostAddr(a) (&STRam[a])
31:
32: #define VIDEL_DEBUG 0
33:
34: #if VIDEL_DEBUG
35: #define Dprintf(a) printf a
36: #else
37: #define Dprintf(a)
38: #endif
39:
40: #define HW 0xff8200
41: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
42: #define VIDEL_COLOR_REGS_END 0xffa200
43:
44:
45: static int width, height, bpp, since_last_change;
46: static BOOL hostColorsSync;
47:
48: /* Autozoom */
49: static int zoomwidth, prev_scrwidth;
50: static int zoomheight, prev_scrheight;
51: static int *zoomxtable;
52: static int *zoomytable;
53:
54: static void VIDEL_renderScreenNoZoom(void);
55: static void VIDEL_renderScreenZoom(void);
56:
57:
58: // Called upon startup and when CPU encounters a RESET instruction.
59: void VIDEL_reset(void)
60: {
61: since_last_change = 0;
62:
63: hostColorsSync = FALSE;
64:
65: /* Autozoom */
66: zoomwidth=prev_scrwidth=0;
67: zoomheight=prev_scrheight=0;
68: zoomxtable=NULL;
69: zoomytable=NULL;
70:
71: // default resolution to boot with
72: width = 640;
73: height = 480;
74: HostScreen_setWindowSize( width, height, 8 );
75: }
76:
77: // monitor write access to Falcon and ST/E color palette registers
78: void VIDEL_ColorRegsWrite(void)
79: {
80: hostColorsSync = FALSE;
81: }
82:
83: void VIDEL_ShiftModeWriteWord(void)
84: {
85: Dprintf(("VIDEL f_shift: %06x = 0x%x\n", IoAccessBaseAddress, handleReadW(HW+0x66)));
86: bUseSTShifter = FALSE;
87: }
88:
89: static long VIDEL_getVideoramAddress(void)
90: {
91: return (handleRead(HW + 1) << 16) | (handleRead(HW + 3) << 8) | handleRead(HW + 0x0d);
92: }
93:
94: static int VIDEL_getScreenBpp(void)
95: {
96: int f_shift = handleReadW(HW + 0x66);
97: int st_shift = handleRead(HW + 0x60);
98: /* to get bpp, we must examine f_shift and st_shift.
99: * f_shift is valid if any of bits no. 10, 8 or 4
100: * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
101: * if bit 10 set then bit 8 and bit 4 don't care...
102: * If all these bits are 0 and ST shifter is written
103: * after Falcon one, get display depth from st_shift
104: * (as for ST and STE)
105: */
106: int bits_per_pixel;
107: if (f_shift & 0x400) /* Falcon: 2 colors */
108: bits_per_pixel = 1;
109: else if (f_shift & 0x100) /* Falcon: hicolor */
110: bits_per_pixel = 16;
111: else if (f_shift & 0x010) /* Falcon: 8 bitplanes */
112: bits_per_pixel = 8;
113: else if (!bUseSTShifter) /* Falcon: 4 bitplanes */
114: bits_per_pixel = 4;
115: else if (st_shift == 0)
116: bits_per_pixel = 4;
117: else if (st_shift == 0x01)
118: bits_per_pixel = 2;
119: else /* if (st_shift == 0x02) */
120: bits_per_pixel = 1;
121:
122: // Dprintf(("Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift));
123:
124: return bits_per_pixel;
125: }
126:
127: static int VIDEL_getScreenWidth(void)
128: {
129: return handleReadW(HW + 0x10) * 16 / VIDEL_getScreenBpp();
130: }
131:
132: static int VIDEL_getScreenHeight(void)
133: {
134: int vdb = handleReadW(HW + 0xa8);
135: int vde = handleReadW(HW + 0xaa);
136: int vmode = handleReadW(HW + 0xc2);
137:
138: /* visible y resolution:
139: * Graphics display starts at line VDB and ends at line
140: * VDE. If interlace mode off unit of VC-registers is
141: * half lines, else lines.
142: */
143: int yres = vde - vdb;
144: if (!(vmode & 0x02)) // interlace
145: yres >>= 1;
146: if (vmode & 0x01) // double
147: yres >>= 1;
148:
149: return yres;
150: }
151:
152:
153: /** map the correct colortable into the correct pixel format
154: */
155: static void VIDEL_updateColors(void)
156: {
157: //Dprintf(("ColorUpdate in progress\n"));
158:
159: int i, r, g, b, colors = 1 << bpp;
160:
161: #define F_COLORS(i) handleRead(VIDEL_COLOR_REGS_BEGIN + (i))
162: #define STE_COLORS(i) handleRead(0xff8240 + (i))
163:
164: if (!bUseSTShifter) {
165: for (i = 0; i < colors; i++) {
166: int offset = i << 2;
167: r = F_COLORS(offset) & 0xfc;
168: r |= r>>6;
169: g = F_COLORS(offset + 1) & 0xfc;
170: g |= g>>6;
171: b = F_COLORS(offset + 3) & 0xfc;
172: b |= b>>6;
173: HostScreen_setPaletteColor(i, r,g,b);
174: }
175: HostScreen_updatePalette(colors);
176: } else {
177: for (i = 0; i < colors; i++) {
178: int offset = i << 1;
179: r = STE_COLORS(offset) & 0x0f;
180: r = ((r & 7)<<1)|(r>>3);
181: r |= r<<4;
182: g = (STE_COLORS(offset + 1)>>4) & 0x0f;
183: g = ((g & 7)<<1)|(g>>3);
184: g |= g<<4;
185: b = STE_COLORS(offset + 1) & 0x0f;
186: b = ((b & 7)<<1)|(b>>3);
187: b |= b<<4;
188: HostScreen_setPaletteColor(i, r,g,b);
189: }
190: HostScreen_updatePalette(colors);
191: }
192:
193: hostColorsSync = TRUE;
194: }
195:
196:
197: void VIDEL_ZoomModeChanged(void)
198: {
199: /* User selected another zoom mode, so set a new screen resolution now */
200: HostScreen_setWindowSize(width, height, bpp >= 8 ? bpp : 8);
201: }
202:
203:
204: void VIDEL_renderScreen(void)
205: {
206: int vw = VIDEL_getScreenWidth();
207: int vh = VIDEL_getScreenHeight();
208: int vbpp = VIDEL_getScreenBpp();
209:
210: if (since_last_change > 2) {
211: if (vw > 0 && vw != width) {
212: Dprintf(("CH width %d\n", width));
213: width = vw;
214: since_last_change = 0;
215: }
216: if (vh > 0 && vh != height) {
217: Dprintf(("CH height %d\n", width));
218: height = vh;
219: since_last_change = 0;
220: }
221: if (vbpp != bpp) {
222: Dprintf(("CH bpp %d\n", vbpp));
223: bpp = vbpp;
224: since_last_change = 0;
225: }
226: }
227: if (since_last_change == 3) {
228: HostScreen_setWindowSize( width, height, bpp >= 8 ? bpp : 8 );
229: }
230: if (since_last_change < 4) {
231: since_last_change++;
232: return;
233: }
234:
235: if (!HostScreen_renderBegin())
236: return;
237:
238: if (ConfigureParams.Screen.bZoomLowRes) {
239: VIDEL_renderScreenZoom();
240: } else {
241: VIDEL_renderScreenNoZoom();
242: }
243:
244: HostScreen_renderEnd();
245:
246: HostScreen_update1( FALSE );
247: }
248:
249:
250: static void VIDEL_renderScreenNoZoom(void)
251: {
252: int vw = VIDEL_getScreenWidth();
253: int vh = VIDEL_getScreenHeight();
254:
255: int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
256: int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
257: /*
258: I think this implementation is naive:
259: indeed, I suspect that we should instead skip lineoffset
260: words each time we have read "more" than linewidth words
261: (possibly "more" because of the number of bit planes).
262: Moreover, the 1 bit plane mode is particular;
263: while doing some experiments on my Falcon, it seems to
264: behave like the 4 bit planes mode.
265: At last, we have also to take into account the 4 bits register
266: located at the word $ffff8264 (bit offset). This register makes
267: the semantics of the lineoffset register change a little.
268: int bitoffset = handleReadW(HW + 0x64) & 0x000f;
269: The meaning of this register in True Color mode is not clear
270: for me at the moment (and my experiments on the Falcon don't help
271: me).
272: */
273: int nextline = linewidth + lineoffset;
274:
275: if (bpp < 16 && !hostColorsSync) {
276: VIDEL_updateColors();
277: }
278:
279: VIDEL_ConvertScreenNoZoom(vw, vh, bpp, nextline);
280: }
281:
282:
283: void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline)
284: {
285: int scrpitch = HostScreen_getPitch();
286:
287: long atariVideoRAM = VIDEL_getVideoramAddress();
288:
289: uint16 *fvram = (uint16 *) Atari2HostAddr(atariVideoRAM);
290: uint8 *hvram = HostScreen_getVideoramAddress();
291:
292: int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
293:
294: /* Clip to SDL_Surface dimensions */
295: int scrwidth = HostScreen_getWidth();
296: int scrheight = HostScreen_getHeight();
297: int vw_clip = vw;
298: int vh_clip = vh;
299: if (vw>scrwidth) vw_clip = scrwidth;
300: if (vh>scrheight) vh_clip = scrheight;
301:
302: /* Horizontal scroll register set? */
303: if (hscrolloffset) {
304: /* Yes, so we need to adjust offset to next line: */
305: nextline += vbpp;
306: }
307:
308: /* Center screen */
309: hvram += ((scrheight-vh_clip)>>1)*scrpitch;
310: hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp();
311:
312: /* Render */
313: if (vbpp < 16) {
314: /* Bitplanes modes */
315:
316: // The SDL colors blitting...
317: uint8 color[16];
318:
319: // FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels
320: switch ( HostScreen_getBpp() ) {
321: case 1:
322: {
323: uint16 *fvram_line = fvram;
324: uint8 *hvram_line = hvram;
325: int h;
326:
327: for (h = 0; h < vh_clip; h++) {
328: uint16 *fvram_column = fvram_line;
329: uint8 *hvram_column = hvram_line;
330: int w;
331:
332: /* First 16 pixels: */
333: HostScreen_bitplaneToChunky(fvram_column, vbpp, color);
334: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
335: hvram_column += 16-hscrolloffset;
336: fvram_column += vbpp;
337: /* Now the main part of the line: */
338: for (w = 1; w < (vw_clip+15)>>4; w++) {
339: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
340: memcpy(hvram_column, color, 16);
341: hvram_column += 16;
342: fvram_column += vbpp;
343: }
344: /* Last pixels of the line for fine scrolling: */
345: if (hscrolloffset) {
346: HostScreen_bitplaneToChunky(fvram_column, vbpp, color);
347: memcpy(hvram_column, color, hscrolloffset);
348: }
349:
350: hvram_line += scrpitch;
351: fvram_line += nextline;
352: }
353: }
354: break;
355: case 2:
356: {
357: uint16 *fvram_line = fvram;
358: uint16 *hvram_line = (uint16 *)hvram;
359: int h;
360:
361: for (h = 0; h < vh_clip; h++) {
362: uint16 *fvram_column = fvram_line;
363: uint16 *hvram_column = hvram_line;
364: int w;
365:
366: for (w = 0; w < (vw_clip+15)>>4; w++) {
367: int j;
368: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
369:
370: for (j=0; j<16; j++) {
371: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
372: }
373:
374: fvram_column += vbpp;
375: }
376:
377: hvram_line += scrpitch>>1;
378: fvram_line += nextline;
379: }
380: }
381: break;
382: case 3:
383: {
384: uint16 *fvram_line = fvram;
385: uint8 *hvram_line = hvram;
386: int h;
387:
388: for (h = 0; h < vh_clip; h++) {
389: uint16 *fvram_column = fvram_line;
390: uint8 *hvram_column = hvram_line;
391: int w;
392:
393: for (w = 0; w < (vw_clip+15)>>4; w++) {
394: int j;
395: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
396:
397: for (j=0; j<16; j++) {
398: uint32 tmpColor = HostScreen_getPaletteColor( color[j] );
399: putBpp24Pixel( hvram_column, tmpColor );
400: hvram_column += 3;
401: }
402:
403: fvram_column += vbpp;
404: }
405:
406: hvram_line += scrpitch;
407: fvram_line += nextline;
408: }
409: }
410: break;
411: case 4:
412: {
413: uint16 *fvram_line = fvram;
414: uint32 *hvram_line = (uint32 *)hvram;
415: int h;
416:
417: for (h = 0; h < vh_clip; h++) {
418: uint16 *fvram_column = fvram_line;
419: uint32 *hvram_column = hvram_line;
420: int w;
421:
422: for (w = 0; w < (vw_clip+15)>>4; w++) {
423: int j;
424: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
425:
426: for (j=0; j<16; j++) {
427: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
428: }
429:
430: fvram_column += vbpp;
431: }
432:
433: hvram_line += scrpitch>>2;
434: fvram_line += nextline;
435: }
436: }
437: break;
438: }
439:
440: } else {
441:
442: // Falcon TC (High Color)
443: switch ( HostScreen_getBpp() ) {
444: case 1:
445: {
446: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
447: uint16 *fvram_line = fvram;
448: uint8 *hvram_line = hvram;
449: int h;
450:
451: for (h = 0; h < vh_clip; h++) {
452: uint16 *fvram_column = fvram_line;
453: uint8 *hvram_column = hvram_line;
454: int w, tmp;
455:
456: for (w = 0; w < vw_clip; w++) {
457:
458: tmp = SDL_SwapBE16(*fvram_column);
459:
460: *hvram_column = ((tmp>>13) & 7) << 5;
461: *hvram_column |= ((tmp>>8) & 7) << 2;
462: *hvram_column |= ((tmp>>2) & 3);
463:
464: hvram_column++;
465: fvram_column++;
466: }
467:
468: hvram_line += scrpitch;
469: fvram_line += nextline;
470: }
471: }
472: break;
473: case 2:
474: {
475: uint16 *fvram_line = fvram;
476: uint16 *hvram_line = (uint16 *)hvram;
477: int h;
478:
479: for (h = 0; h < vh_clip; h++) {
480: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
481: //FIXME: here might be a runtime little/big video endian switch like:
482: // if ( /* videocard memory in Motorola endian format */ false)
483: memcpy(hvram_line, fvram_line, vw_clip<<1);
484: #else
485: int w;
486: uint16 *fvram_column = fvram_line;
487: uint16 *hvram_column = hvram_line;
488:
489: for (w = 0; w < vw_clip; w++) {
490: // byteswap with SDL asm macros
491: *hvram_column++ = SDL_SwapBE16(*fvram_column++);
492: }
493: #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
494:
495: hvram_line += scrpitch>>1;
496: fvram_line += nextline;
497: }
498: }
499: break;
500: case 3:
501: {
502: uint16 *fvram_line = fvram;
503: uint8 *hvram_line = hvram;
504: int h;
505:
506: for (h = 0; h < vh_clip; h++) {
507: uint16 *fvram_column = fvram_line;
508: uint8 *hvram_column = hvram_line;
509: int w;
510:
511: for (w = 0; w < vw_clip; w++) {
512: int data = *fvram_column++;
513:
514: uint32 tmpColor =
515: HostScreen_getColor(
516: (uint8) (data & 0xf8),
517: (uint8) ( ((data & 0x07) << 5) |
518: ((data >> 11) & 0x3c)),
519: (uint8) ((data >> 5) & 0xf8));
520:
521: putBpp24Pixel( hvram_column, tmpColor );
522:
523: hvram_column += 3;
524: }
525:
526: hvram_line += scrpitch;
527: fvram_line += nextline;
528: }
529: }
530: break;
531: case 4:
532: {
533: uint16 *fvram_line = fvram;
534: uint32 *hvram_line = (uint32 *)hvram;
535: int h;
536:
537: for (h = 0; h < vh_clip; h++) {
538: uint16 *fvram_column = fvram_line;
539: uint32 *hvram_column = hvram_line;
540: int w;
541:
542: for (w = 0; w < vw_clip; w++) {
543: int data = *fvram_column++;
544:
545: *hvram_column++ =
546: HostScreen_getColor(
547: (uint8) (data & 0xf8),
548: (uint8) ( ((data & 0x07) << 5) |
549: ((data >> 11) & 0x3c)),
550: (uint8) ((data >> 5) & 0xf8));
551: }
552:
553: hvram_line += scrpitch>>2;
554: fvram_line += nextline;
555: }
556: }
557: break;
558: }
559: }
560: }
561:
562:
563: static void VIDEL_renderScreenZoom(void)
564: {
565: /* Atari screen infos */
566: int vw = VIDEL_getScreenWidth();
567: int vh = VIDEL_getScreenHeight();
568:
569: int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
570: int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
571: /* same remark as before: too naive */
572: int nextline = linewidth + lineoffset;
573:
574: if ((vw<32) || (vh<32)) return;
575:
576: if (bpp<16 && !hostColorsSync) {
577: VIDEL_updateColors();
578: }
579:
580: VIDEL_ConvertScreenZoom(vw, vh, bpp, nextline);
581: }
582:
583:
584: void VIDEL_ConvertScreenZoom(int vw, int vh, int vbpp, int nextline)
585: {
586: int i, j, w, h, cursrcline;
587:
588: uint16 *fvram = (uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
589:
590: /* Host screen infos */
591: int scrpitch = HostScreen_getPitch();
592: int scrwidth = HostScreen_getWidth();
593: int scrheight = HostScreen_getHeight();
594: int scrbpp = HostScreen_getBpp();
595: uint8 *hvram = (uint8 *) HostScreen_getVideoramAddress();
596:
597: int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
598:
599: /* Horizontal scroll register set? */
600: if (hscrolloffset) {
601: /* Yes, so we need to adjust offset to next line: */
602: nextline += vbpp;
603: }
604:
605: /* Integer zoom coef ? */
606: if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) {
607: int coefx = scrwidth/vw;
608: int coefy = scrheight/vh;
609:
610: scrwidth = vw * coefx;
611: scrheight = vh * coefy;
612:
613: /* Center screen */
614: hvram += ((HostScreen_getHeight()-scrheight)>>1)*scrpitch;
615: hvram += ((HostScreen_getWidth()-scrwidth)>>1)*scrbpp;
616: }
617:
618: /* New zoom ? */
619: if ((zoomwidth != vw) || (scrwidth != prev_scrwidth)) {
620: if (zoomxtable) {
621: free(zoomxtable);
622: }
623: zoomxtable = malloc(sizeof(int)*scrwidth);
624: for (i=0; i<scrwidth; i++) {
625: zoomxtable[i] = (vw*i)/scrwidth;
626: }
627: zoomwidth = vw;
628: prev_scrwidth = scrwidth;
629: }
630: if ((zoomheight != vh) || (scrheight != prev_scrheight)) {
631: if (zoomytable) {
632: free(zoomytable);
633: }
634: zoomytable = malloc(sizeof(int)*scrheight);
635: for (i=0; i<scrheight; i++) {
636: zoomytable[i] = (vh*i)/scrheight;
637: }
638: zoomheight = vh;
639: prev_scrheight = scrheight;
640: }
641:
642: cursrcline = -1;
643:
644: if (vbpp<16) {
645: uint8 color[16];
646:
647: /* Bitplanes modes */
648: switch(scrbpp) {
649: case 1:
650: {
651: /* One complete planar 2 chunky line */
652: uint8 *p2cline = malloc(sizeof(uint8)*vw);
653:
654: uint16 *fvram_line;
655: uint8 *hvram_line = hvram;
656:
657: for (h = 0; h < scrheight; h++) {
658: fvram_line = fvram + (zoomytable[h] * nextline);
659:
660: /* Recopy the same line ? */
661: if (zoomytable[h] == cursrcline) {
662: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
663: } else {
664: uint16 *fvram_column = fvram_line;
665: uint8 *hvram_column = p2cline;
666:
667: /* First 16 pixels of a new line */
668: HostScreen_bitplaneToChunky(fvram_column, vbpp, color);
669: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
670: hvram_column += 16-hscrolloffset;
671: fvram_column += vbpp;
672: /* Convert main part of the new line */
673: for (w=1; w < (vw+15)>>4; w++) {
674: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
675: memcpy(hvram_column, color, 16);
676: hvram_column += 16;
677: fvram_column += vbpp;
678: }
679: /* Last pixels of the line for fine scrolling: */
680: if (hscrolloffset) {
681: HostScreen_bitplaneToChunky(fvram_column, vbpp, color);
682: memcpy(hvram_column, color, hscrolloffset);
683: }
684:
685: /* Zoom a new line */
686: for (w=0; w<scrwidth; w++) {
687: hvram_line[w] = p2cline[zoomxtable[w]];
688: }
689: }
690:
691: hvram_line += scrpitch;
692: cursrcline = zoomytable[h];
693: }
694:
695: free(p2cline);
696: }
697: break;
698: case 2:
699: {
700: /* One complete planar 2 chunky line */
701: uint16 *p2cline = malloc(sizeof(uint16)*vw);
702:
703: uint16 *fvram_line = fvram;
704: uint16 *hvram_line = (uint16 *)hvram;
705:
706: for (h = 0; h < scrheight; h++) {
707: fvram_line = fvram + (zoomytable[h] * nextline);
708:
709: /* Recopy the same line ? */
710: if (zoomytable[h] == cursrcline) {
711: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
712: } else {
713: uint16 *fvram_column = fvram_line;
714: uint16 *hvram_column = p2cline;
715:
716: /* Convert a new line */
717: for (w=0; w < (vw+15)>>4; w++) {
718: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
719:
720: for (j=0; j<16; j++) {
721: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
722: }
723:
724: fvram_column += vbpp;
725: }
726:
727: /* Zoom a new line */
728: for (w=0; w<scrwidth; w++) {
729: hvram_line[w] = p2cline[zoomxtable[w]];
730: }
731: }
732:
733: hvram_line += scrpitch>>1;
734: cursrcline = zoomytable[h];
735: }
736:
737: free(p2cline);
738: }
739: break;
740: case 3:
741: {
742: /* One complete planar 2 chunky line */
743: uint8 *p2cline = malloc(sizeof(uint8)*vw*3);
744:
745: uint16 *fvram_line;
746: uint8 *hvram_line = hvram;
747:
748: for (h = 0; h < scrheight; h++) {
749: fvram_line = fvram + (zoomytable[h] * nextline);
750:
751: /* Recopy the same line ? */
752: if (zoomytable[h] == cursrcline) {
753: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
754: } else {
755: uint16 *fvram_column = fvram_line;
756: uint8 *hvram_column = p2cline;
757:
758: /* Convert a new line */
759: for (w=0; w < (vw+15)>>4; w++) {
760: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
761:
762: for (j=0; j<16; j++) {
763: uint32 tmpColor = HostScreen_getPaletteColor( color[j] );
764: putBpp24Pixel( hvram_column, tmpColor );
765: hvram_column += 3;
766: }
767:
768: fvram_column += vbpp;
769: }
770:
771: /* Zoom a new line */
772: for (w=0; w<scrwidth; w++) {
773: hvram_line[w*3] = p2cline[zoomxtable[w]*3];
774: hvram_line[w*3+1] = p2cline[zoomxtable[w]*3+1];
775: hvram_line[w*3+2] = p2cline[zoomxtable[w]*3+2];
776: }
777: }
778:
779: hvram_line += scrpitch;
780: cursrcline = zoomytable[h];
781: }
782:
783: free(p2cline);
784: }
785: break;
786: case 4:
787: {
788: /* One complete planar 2 chunky line */
789: uint32 *p2cline = malloc(sizeof(uint32)*vw);
790:
791: uint16 *fvram_line;
792: uint32 *hvram_line = (uint32 *)hvram;
793:
794: for (h = 0; h < scrheight; h++) {
795: fvram_line = fvram + (zoomytable[h] * nextline);
796:
797: /* Recopy the same line ? */
798: if (zoomytable[h] == cursrcline) {
799: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
800: } else {
801: uint16 *fvram_column = fvram_line;
802: uint32 *hvram_column = p2cline;
803:
804: /* Convert a new line */
805: for (w=0; w < (vw+15)>>4; w++) {
806: HostScreen_bitplaneToChunky( fvram_column, vbpp, color );
807:
808: for (j=0; j<16; j++) {
809: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
810: }
811:
812: fvram_column += vbpp;
813: }
814:
815: /* Zoom a new line */
816: for (w=0; w<scrwidth; w++) {
817: hvram_line[w] = p2cline[zoomxtable[w]];
818: }
819: }
820:
821: hvram_line += scrpitch>>2;
822: cursrcline = zoomytable[h];
823: }
824:
825: free(p2cline);
826: }
827: break;
828: }
829: } else {
830: /* Falcon TrueColour mode */
831:
832: switch(scrbpp) {
833: case 1:
834: {
835: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
836: uint16 *fvram_line;
837: uint8 *hvram_line = hvram;
838:
839: for (h = 0; h < scrheight; h++) {
840: uint16 *fvram_column;
841: uint8 *hvram_column;
842:
843: fvram_line = fvram + (zoomytable[h] * nextline);
844: fvram_column = fvram_line;
845: hvram_column = hvram_line;
846:
847: /* Recopy the same line ? */
848: if (zoomytable[h] == cursrcline) {
849: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
850: } else {
851: for (w = 0; w < scrwidth; w++) {
852: uint16 srcword;
853: uint8 dstbyte;
854:
855: srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
856:
857: dstbyte = ((srcword>>13) & 7) << 5;
858: dstbyte |= ((srcword>>8) & 7) << 2;
859: dstbyte |= ((srcword>>2) & 3);
860:
861: *hvram_column++ = dstbyte;
862: }
863: }
864:
865: hvram_line += scrpitch;
866: cursrcline = zoomytable[h];
867: }
868: }
869: break;
870: case 2:
871: {
872: uint16 *fvram_line;
873: uint16 *hvram_line = (uint16 *)hvram;
874:
875: for (h = 0; h < scrheight; h++) {
876: uint16 *fvram_column;
877: uint16 *hvram_column;
878:
879: fvram_line = fvram + (zoomytable[h] * nextline);
880: fvram_column = fvram_line;
881: hvram_column = hvram_line;
882:
883: /* Recopy the same line ? */
884: if (zoomytable[h] == cursrcline) {
885: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
886: } else {
887: for (w = 0; w < scrwidth; w++) {
888: uint16 srcword;
889:
890: srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
891: *hvram_column++ = srcword;
892: }
893: }
894:
895: hvram_line += scrpitch>>1;
896: cursrcline = zoomytable[h];
897: }
898: }
899: break;
900: case 3:
901: {
902: uint16 *fvram_line;
903: uint8 *hvram_line = hvram;
904:
905: for (h = 0; h < scrheight; h++) {
906: uint16 *fvram_column;
907: uint8 *hvram_column;
908:
909: fvram_line = fvram + (zoomytable[h] * nextline);
910: fvram_column = fvram_line;
911: hvram_column = hvram_line;
912:
913: /* Recopy the same line ? */
914: if (zoomytable[h] == cursrcline) {
915: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
916: } else {
917: for (w = 0; w < scrwidth; w++) {
918: uint16 srcword;
919: uint32 dstlong;
920:
921: srcword = fvram_column[zoomxtable[w]];
922:
923: dstlong = HostScreen_getColor(
924: (uint8) (srcword & 0xf8),
925: (uint8) ( ((srcword & 0x07) << 5) |
926: ((srcword >> 11) & 0x3c)),
927: (uint8) ((srcword >> 5) & 0xf8));
928:
929: putBpp24Pixel( hvram_column, dstlong );
930: hvram_column += 3;
931: }
932: }
933:
934: hvram_line += scrpitch;
935: cursrcline = zoomytable[h];
936: }
937: }
938: break;
939: case 4:
940: {
941: uint16 *fvram_line;
942: uint32 *hvram_line = (uint32 *)hvram;
943:
944: for (h = 0; h < scrheight; h++) {
945: uint16 *fvram_column;
946: uint32 *hvram_column;
947:
948: fvram_line = fvram + (zoomytable[h] * nextline);
949: fvram_column = fvram_line;
950: hvram_column = hvram_line;
951:
952: /* Recopy the same line ? */
953: if (zoomytable[h] == cursrcline) {
954: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
955: } else {
956: for (w = 0; w < scrwidth; w++) {
957: uint16 srcword;
958:
959: srcword = fvram_column[zoomxtable[w]];
960:
961: *hvram_column++ =
962: HostScreen_getColor(
963: (uint8) (srcword & 0xf8),
964: (uint8) ( ((srcword & 0x07) << 5) |
965: ((srcword >> 11) & 0x3c)),
966: (uint8) ((srcword >> 5) & 0xf8));
967: }
968: }
969:
970: hvram_line += scrpitch>>2;
971: cursrcline = zoomytable[h];
972: }
973: }
974: break;
975: }
976: }
977: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.