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