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