|
|
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.