|
|
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).
1.1.1.6 ! root 14:
! 15: Videl can run at 2 frequencies : 25.175 Mhz or 32 MHz
! 16:
! 17: Hardware I/O registers:
! 18:
! 19: $FFFF8006 (byte) : monitor type
! 20:
! 21: $FFFF8201 (byte) : VDL_VBH - Video Base Hi
! 22: $FFFF8203 (byte) : VDL_VBM - Video Base Mi
! 23: $FFFF8205 (byte) : VDL_VCH - Video Count Hi
! 24: $FFFF8207 (byte) : VDL_VCM - Video Count Mi
! 25: $FFFF8209 (byte) : VDL_VCL - Video Count Lo
! 26: $FFFF820A (byte) : VDL_SYM - Sync mode
! 27: $FFFF820D (byte) : VDL_VBL - Video Base Lo
! 28: $FFFF820E (word) : VDL_LOF - Offset to next line
! 29: $FFFF8210 (word) : VDL_LWD - Line Wide in Words
! 30:
! 31: $FFFF8240 (word) : VDL_STC - ST Palette Register 00
! 32: .........
! 33: $FFFF825E (word) : VDL_STC - ST Palette Register 15
! 34:
! 35: $FFFF8260 (byte) : ST shift mode
! 36: $FFFF8265 (byte) : Horizontal scroll register
! 37: $FFFF8266 (word) : Falcon shift mode
! 38:
! 39: $FFFF8280 (word) : HHC - Horizontal Hold Counter
! 40: $FFFF8282 (word) : HHT - Horizontal Hold Timer
! 41: $FFFF8284 (word) : HBB - Horizontal Border Begin
! 42: $FFFF8286 (word) : HBE - Horizontal Border End
! 43: $FFFF8288 (word) : HDB - Horizontal Display Begin
! 44: $FFFF828A (word) : HDE - Horizontal Display End
! 45: $FFFF828C (word) : HSS - Horizontal SS
! 46: $FFFF828E (word) : HFS - Horizontal FS
! 47: $FFFF8290 (word) : HEE - Horizontal EE
! 48:
! 49: $FFFF82A0 (word) : VFC - Vertical Frequency Counter
! 50: $FFFF82A2 (word) : VFT - Vertical Frequency Timer
! 51: $FFFF82A4 (word) : VBB - Vertical Border Begin
! 52: $FFFF82A6 (word) : VBE - Vertical Border End
! 53: $FFFF82A8 (word) : VDB - Vertical Display Begin
! 54: $FFFF82AA (word) : VDE - Vertical Display End
! 55: $FFFF82AC (word) : VSS - Vertical SS
! 56:
! 57: $FFFF82C0 (word) : VCO - Video control
! 58: $FFFF82C2 (word) : VMD - Video mode
! 59:
! 60: $FFFF9800 (long) : VDL_PAL - Videl palette Register 000
! 61: ...........
! 62: $FFFF98FC (long) : VDL_PAL - Videl palette Register 255
1.1 root 63: */
1.1.1.6 ! root 64:
1.1.1.4 root 65: const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__;
1.1 root 66:
1.1.1.6 ! root 67: #include <SDL_endian.h>
! 68: #include <SDL.h>
1.1 root 69: #include "main.h"
70: #include "configuration.h"
1.1.1.6 ! root 71: #include "memorySnapShot.h"
1.1 root 72: #include "ioMem.h"
1.1.1.6 ! root 73: #include "log.h"
1.1 root 74: #include "hostscreen.h"
75: #include "screen.h"
76: #include "stMemory.h"
77: #include "video.h"
78: #include "videl.h"
79:
80:
81: #define handleRead(a) IoMem_ReadByte(a)
82: #define handleReadW(a) IoMem_ReadWord(a)
83: #define Atari2HostAddr(a) (&STRam[a])
84:
85: #define VIDEL_DEBUG 0
86:
87: #if VIDEL_DEBUG
88: #define Dprintf(a) printf a
89: #else
90: #define Dprintf(a)
91: #endif
92:
93: #define HW 0xff8200
94: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
95:
1.1.1.6 ! root 96: struct videl_s {
! 97: bool bUseSTShifter; /* whether to use ST or Falcon palette */
! 98: Uint8 reg_ffff8006_save; /* save reg_ffff8006 as it's a read only register */
! 99: Uint8 monitor_type; /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */
! 100: };
! 101:
! 102: static struct videl_s videl;
! 103:
1.1.1.5 root 104: /* TODO: put these to some struct so that it's easier to see
105: * they're VIDEL global
106: */
1.1.1.6 ! root 107: static int width, height, bpp;
1.1.1.2 root 108: static bool hostColorsSync;
1.1 root 109:
1.1.1.6 ! root 110: Uint16 vfc_counter; /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */
! 111:
1.1 root 112: /* Autozoom */
113: static int zoomwidth, prev_scrwidth;
114: static int zoomheight, prev_scrheight;
115: static int *zoomxtable;
116: static int *zoomytable;
117:
1.1.1.6 ! root 118:
! 119:
1.1 root 120: static void VIDEL_renderScreenNoZoom(void);
121: static void VIDEL_renderScreenZoom(void);
122:
1.1.1.6 ! root 123:
1.1 root 124: // Called upon startup and when CPU encounters a RESET instruction.
125: void VIDEL_reset(void)
126: {
1.1.1.6 ! root 127: videl.bUseSTShifter = false; /* Use Falcon color palette by default */
! 128: videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
! 129: videl.monitor_type = videl.reg_ffff8006_save & 0xc0;
! 130:
! 131: hostColorsSync = false;
1.1 root 132:
1.1.1.6 ! root 133: vfc_counter = 0;
! 134:
1.1 root 135: /* Autozoom */
136: zoomwidth=prev_scrwidth=0;
137: zoomheight=prev_scrheight=0;
138: zoomxtable=NULL;
139: zoomytable=NULL;
140:
1.1.1.4 root 141: /* Default resolution to boot with */
1.1 root 142: width = 640;
143: height = 480;
1.1.1.4 root 144: HostScreen_setWindowSize(width, height, ConfigureParams.Screen.nForceBpp);
145:
146: /* Reset IO register (some are not initialized by TOS) */
147: IoMem_WriteWord(0xff820e, 0); /* Line offset */
148: IoMem_WriteWord(0xff8264, 0); /* Horizontal scroll */
1.1 root 149: }
150:
1.1.1.6 ! root 151: /**
! 152: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
! 153: */
! 154: void VIDEL_MemorySnapShot_Capture(bool bSave)
! 155: {
! 156: /* Save/Restore details */
! 157: MemorySnapShot_Store(&videl, sizeof(videl));
! 158: MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter));
! 159: }
! 160:
! 161: /**
! 162: * Monitor write access to ST/E color palette registers
! 163: */
1.1 root 164: void VIDEL_ColorRegsWrite(void)
165: {
1.1.1.4 root 166: hostColorsSync = false;
1.1 root 167: }
168:
1.1.1.6 ! root 169: /**
! 170: * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration.
! 171: * This register is read only.
! 172: */
! 173: void VIDEL_Monitor_WriteByte(void)
! 174: {
! 175: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8006 Monitor and memory conf write (Read only)\n");
! 176: /* Restore hardware value */
! 177: IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
! 178: }
! 179:
! 180: /**
! 181: * Write to video address base high, med and low register (0xff8201/03/0d).
! 182: * On Falcon, when a program writes to high or med registers, base low register
! 183: * is reset to zero.
! 184: */
! 185: void VIDEL_ScreenBase_WriteByte(void)
! 186: {
! 187: Uint32 screenBase;
! 188:
! 189: if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
! 190: /* Reset screen base low register */
! 191: IoMem[0xff820d] = 0;
! 192: }
! 193:
! 194: screenBase = (IoMem[0xff8201]<<16)+(IoMem[0xff8203]<<8)+IoMem[0xff820d];
! 195:
! 196: LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%01x\t (screen: 0x%04x)\n",
! 197: IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress], screenBase);
! 198: }
! 199:
! 200: /**
! 201: VIDEL_ST_ShiftModeWriteByte :
! 202: $FFFF8260 [R/W] B ______10 ST Shift Mode
! 203: ||
! 204: || others vga
! 205: || $FF8210 $FF82C2 $FF82C2
! 206: 00--4BP/320 Pixels=> $0050 $0000 $0005
! 207: 01--2BP/640 Pixels=> $0050 $0004 $0009
! 208: 10--1BP/640 Pixels=> $0028 $0006 $0008
! 209: 11--???/320 Pixels=> $0050 $0000 $0000
! 210:
! 211: Writing to this register does the following things:
! 212: - activate STE palette
! 213: - sets line width ($ffff8210)
! 214: - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
! 215: */
! 216: void VIDEL_ST_ShiftModeWriteByte(void)
! 217: {
! 218: Uint16 line_width, video_mode;
! 219: Uint8 st_shiftMode;
! 220:
! 221: st_shiftMode = IoMem_ReadByte(0xff8260);
! 222: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8260 ST Shift Mode (STSHIFT) write: 0x%x\n", st_shiftMode);
! 223:
! 224: /* Activate STE palette */
! 225: videl.bUseSTShifter = true;
! 226:
! 227: /* Compute line width and video mode */
! 228: switch (st_shiftMode & 0x3) {
! 229: case 0: /* 4BP/320 Pixels */
! 230: line_width = 0x50;
! 231: /* half pixels + double lines vs. no scaling */
! 232: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
! 233: break;
! 234: case 1: /* 2BP/640 Pixels */
! 235: line_width = 0x50;
! 236: /* quarter pixels + double lines vs. half pixels */
! 237: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
! 238: break;
! 239: case 2: /* 1BP/640 Pixels */
! 240: line_width = 0x28;
! 241: if (videl.monitor_type == FALCON_MONITOR_MONO) {
! 242: video_mode = 0x0;
! 243: break;
! 244: }
! 245: /* quarter pixels vs. half pixels + interlace */
! 246: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
! 247: break;
! 248: case 3: /* ???/320 Pixels */
! 249: line_width = 0x50;
! 250: video_mode = 0x0;
! 251: break;
! 252: }
! 253:
! 254: /* Set line width ($FFFF8210) */
! 255: IoMem_WriteWord(0xff8210, line_width);
! 256:
! 257: /* Set video mode ($FFFF82C2) */
! 258: IoMem_WriteWord(0xff82c2, video_mode);
! 259: }
! 260:
! 261: /**
! 262: VIDEL_FALCON_ShiftModeWriteWord :
! 263: $FFFF8266 [R/W] W _____A98_6543210 Falcon Shift Mode (SPSHIFT)
! 264: ||| |||||||
! 265: ||| |||++++- 0..15: Colourbank setting in 8BP
! 266: ||| ||+----- 0: 8 Bitplanes (256 Colors) off
! 267: ||| ||+----- 1: 8 Bitplanes (256 Colors) on
! 268: ||| |+------ 0: internal Vertical Sync
! 269: ||| | 1: external Vertical Sync
! 270: ||| +------- 0: internal Horizontal Sync
! 271: ||| 1: external Horizontal Sync
! 272: ||+--------- 0: True-Color-Mode off
! 273: || 1: True-Color-Mode on
! 274: |+---------- 0: Overlay-Mode off
! 275: | 1: Overlay-Mode on
! 276: +----------- 0: 2-Color-Mode off
! 277: 1: 2-Color-Mode on
! 278:
! 279: Writing to this register does the following things:
! 280: - activate Falcon palette
! 281: - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
! 282: same as ST LOW since Falcon palette is used!)
! 283: - $8260 register is ignored, you don't need to write here anything
! 284:
! 285: Note: 4-Color-Mode isn't realisable with Falcon palette.
! 286: */
! 287: void VIDEL_FALC_ShiftModeWriteWord(void)
! 288: {
! 289: Uint16 falc_shiftMode = IoMem_ReadWord(0xff8266);
! 290:
! 291: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8266 Falcon Shift Mode (SPSHIFT) write: 0x%02x\n", falc_shiftMode);
! 292:
! 293: videl.bUseSTShifter = false;
! 294: }
! 295:
! 296: /**
! 297: * Write Horizontal Hold Counter (HHC)
! 298: */
! 299: void VIDEL_HHC_WriteWord(void)
! 300: {
! 301: Uint16 hhc = IoMem_ReadWord(0xff8280);
! 302:
! 303: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8280 Horizontal Hold Counter (HHC) write: 0x%02x\n", hhc);
! 304: }
! 305:
! 306: /**
! 307: * Write Horizontal Hold Timer (HHT)
! 308: */
! 309: void VIDEL_HHT_WriteWord(void)
! 310: {
! 311: Uint16 hht = IoMem_ReadWord(0xff8282);
! 312:
! 313: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8282 Horizontal Hold Timer (HHT) write: 0x%02x\n", hht);
! 314: }
! 315:
! 316: /**
! 317: * Write Horizontal Border Begin (HBB)
! 318: */
! 319: void VIDEL_HBB_WriteWord(void)
! 320: {
! 321: Uint16 hbb = IoMem_ReadWord(0xff8284);
! 322:
! 323: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8284 Horizontal Border Begin (HBB) write: 0x%02x\n", hbb);
! 324: }
! 325:
! 326: /**
! 327: * Write Horizontal Border End (HBE)
! 328: */
! 329: void VIDEL_HBE_WriteWord(void)
! 330: {
! 331: Uint16 hbe = IoMem_ReadWord(0xff8286);
! 332:
! 333: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8286 Horizontal Border End (HBE) write: 0x%02x\n", hbe);
! 334: }
! 335:
! 336: /**
! 337: * Write Horizontal Display Begin (HDB)
! 338: */
! 339: void VIDEL_HDB_WriteWord(void)
! 340: {
! 341: Uint16 hdb = IoMem_ReadWord(0xff8288);
! 342:
! 343: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8288 Horizontal Display Begin (HDB) write: 0x%02x\n", hdb);
! 344: }
! 345:
! 346: /**
! 347: * Write Horizontal Display End (HDE)
! 348: */
! 349: void VIDEL_HDE_WriteWord(void)
! 350: {
! 351: Uint16 hde = IoMem_ReadWord(0xff828a);
! 352:
! 353: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828a Horizontal Display End (HDE) write: 0x%02x\n", hde);
! 354: }
! 355:
! 356: /**
! 357: * Write Horizontal SS (HSS)
! 358: */
! 359: void VIDEL_HSS_WriteWord(void)
! 360: {
! 361: Uint16 hss = IoMem_ReadWord(0xff828c);
! 362:
! 363: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828c Horizontal SS (HSS) write: 0x%02x\n", hss);
! 364: }
! 365:
! 366: /**
! 367: * Write Horizontal FS (HFS)
! 368: */
! 369: void VIDEL_HFS_WriteWord(void)
! 370: {
! 371: Uint16 hfs = IoMem_ReadWord(0xff828e);
! 372:
! 373: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828e Horizontal FS (HFS) write: 0x%02x\n", hfs);
! 374: }
! 375:
! 376: /**
! 377: * Write Horizontal EE (HEE)
! 378: */
! 379: void VIDEL_HEE_WriteWord(void)
! 380: {
! 381: Uint16 hee = IoMem_ReadWord(0xff8290);
! 382:
! 383: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8290 Horizontal EE (HEE) write: 0x%02x\n", hee);
! 384: }
! 385:
! 386: /**
! 387: * Write Vertical Frequency Counter (VFC)
! 388: */
! 389: void VIDEL_VFC_ReadWord(void)
! 390: {
! 391: IoMem_WriteWord(0xff82a0, vfc_counter);
! 392: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a0 Vertical Frequency Counter (VFC) read: 0x%02x\n", vfc_counter);
! 393: }
! 394:
! 395: /**
! 396: * Write Vertical Frequency Timer (VFT)
! 397: */
! 398: void VIDEL_VFT_WriteWord(void)
! 399: {
! 400: Uint16 vft = IoMem_ReadWord(0xff82a2);
! 401:
! 402: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a2 Vertical Frequency Timer (VFT) write: 0x%02x\n", vft);
! 403: }
! 404:
! 405: /**
! 406: * Write Vertical Border Begin (VBB)
! 407: */
! 408: void VIDEL_VBB_WriteWord(void)
! 409: {
! 410: Uint16 vbb = IoMem_ReadWord(0xff82a4);
! 411:
! 412: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a4 Vertical Border Begin (VBB) write: 0x%02x\n", vbb);
! 413: }
! 414:
! 415: /**
! 416: * Write Vertical Border End (VBE)
! 417: */
! 418: void VIDEL_VBE_WriteWord(void)
! 419: {
! 420: Uint16 vbe = IoMem_ReadWord(0xff82a6);
! 421:
! 422: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a6 Vertical Border End (VBE) write: 0x%02x\n", vbe);
! 423: }
! 424:
! 425: /**
! 426: * Write Vertical Display Begin (VDB)
! 427: */
! 428: void VIDEL_VDB_WriteWord(void)
1.1 root 429: {
1.1.1.6 ! root 430: Uint16 vdb = IoMem_ReadWord(0xff82a8);
! 431:
! 432: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a8 Vertical Display Begin (VDB) write: 0x%02x\n", vdb);
1.1 root 433: }
434:
1.1.1.6 ! root 435: /**
! 436: * Write Vertical Display End (VDE)
! 437: */
! 438: void VIDEL_VDE_WriteWord(void)
! 439: {
! 440: Uint16 vde = IoMem_ReadWord(0xff82aa);
! 441:
! 442: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82aa Vertical Display End (VDE) write: 0x%02x\n", vde);
! 443: }
! 444:
! 445: /**
! 446: * Write Vertical SS (VSS)
! 447: */
! 448: void VIDEL_VSS_WriteWord(void)
! 449: {
! 450: Uint16 vss = IoMem_ReadWord(0xff82ac);
! 451:
! 452: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82ac Vertical SS (VSS) write: 0x%02x\n", vss);
! 453: }
! 454:
! 455: /**
! 456: * Write Video Control (VCO)
! 457: */
! 458: void VIDEL_VCO_WriteWord(void)
! 459: {
! 460: Uint16 vco = IoMem_ReadWord(0xff82c0);
! 461:
! 462: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c0 Video control (VCO) write: 0x%02x\n", vco);
! 463: }
! 464:
! 465: /**
! 466: * Write Video Mode (VDM)
! 467: */
! 468: void VIDEL_VMD_WriteWord(void)
! 469: {
! 470: Uint16 vdm = IoMem_ReadWord(0xff82c2);
! 471:
! 472: LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c2 Video Mode (VDM) write: 0x%02x\n", vdm);
! 473: }
! 474:
! 475:
1.1 root 476: static long VIDEL_getVideoramAddress(void)
477: {
478: return (handleRead(HW + 1) << 16) | (handleRead(HW + 3) << 8) | handleRead(HW + 0x0d);
479: }
480:
481: static int VIDEL_getScreenBpp(void)
482: {
483: int f_shift = handleReadW(HW + 0x66);
484: int st_shift = handleRead(HW + 0x60);
485: /* to get bpp, we must examine f_shift and st_shift.
486: * f_shift is valid if any of bits no. 10, 8 or 4
487: * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
488: * if bit 10 set then bit 8 and bit 4 don't care...
489: * If all these bits are 0 and ST shifter is written
490: * after Falcon one, get display depth from st_shift
491: * (as for ST and STE)
492: */
493: int bits_per_pixel;
494: if (f_shift & 0x400) /* Falcon: 2 colors */
495: bits_per_pixel = 1;
496: else if (f_shift & 0x100) /* Falcon: hicolor */
497: bits_per_pixel = 16;
498: else if (f_shift & 0x010) /* Falcon: 8 bitplanes */
499: bits_per_pixel = 8;
1.1.1.6 ! root 500: else if (!videl.bUseSTShifter) /* Falcon: 4 bitplanes */
1.1 root 501: bits_per_pixel = 4;
502: else if (st_shift == 0)
503: bits_per_pixel = 4;
504: else if (st_shift == 0x01)
505: bits_per_pixel = 2;
506: else /* if (st_shift == 0x02) */
507: bits_per_pixel = 1;
508:
509: // Dprintf(("Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift));
510:
511: return bits_per_pixel;
512: }
513:
514: static int VIDEL_getScreenWidth(void)
515: {
1.1.1.4 root 516: return (handleReadW(HW + 0x10) & 0x03ff) * 16 / VIDEL_getScreenBpp();
1.1 root 517: }
518:
519: static int VIDEL_getScreenHeight(void)
520: {
1.1.1.4 root 521: int vdb = handleReadW(HW + 0xa8) & 0x07ff;
522: int vde = handleReadW(HW + 0xaa) & 0x07ff;
1.1 root 523: int vmode = handleReadW(HW + 0xc2);
524:
525: /* visible y resolution:
526: * Graphics display starts at line VDB and ends at line
527: * VDE. If interlace mode off unit of VC-registers is
528: * half lines, else lines.
529: */
530: int yres = vde - vdb;
531: if (!(vmode & 0x02)) // interlace
532: yres >>= 1;
1.1.1.4 root 533: if (vmode & 0x01) // double
1.1 root 534: yres >>= 1;
535:
536: return yres;
537: }
538:
1.1.1.5 root 539: #if 0
540: /* this is easier & more robustly done in hostscreen.c just by
541: * comparing requested screen width & height to each other.
542: */
543: static void VIDEL_getMonitorScale(int *sx, int *sy)
544: {
545: /* Videl video mode register bits and resulting desktop resolution:
546: *
547: * quarter, half, interlace, double: pixels: -> zoom:
548: * rgb:
549: * 0 0 0 0 320x200 -> 2 x 2
550: * 0 0 1 0 320x400 -> 2 x 1
551: * 0 1 0 0 640x200 -> 1 x 2 !
552: * 0 1 1 0 640x400 -> 1 x 1
553: * vga:
554: * 0 0 0 1 (just double ?)
555: * 0 0 1 1 (double & interlace ???)
556: * 0 1 0 0 320x480 -> 2 x 1 !
557: * 0 1 0 1 320x240 -> 2 x 2
558: * 0 1 1 1 (double + interlace ???)
559: * 1 0 0 0 640x480 -> 1 x 1
560: * 1 0 0 1 640x240 -> 1 x 2
561: */
562: int vmode = handleReadW(HW + 0xc2);
563:
564: /* half pixel seems to have opposite meaning on
565: * VGA and RGB monitor, so they need to handled separately
566: */
1.1.1.6 ! root 567: if (videl.monitor_type) == FALCON_MONITOR_VGA) {
1.1.1.5 root 568: if (vmode & 0x08) { // quarter pixel
569: *sx = 1;
570: } else {
571: *sx = 2;
572: }
573: if (vmode & 0x01) { // double line
574: *sy = 2;
575: } else {
576: *sy = 1;
577: }
578: } else {
579: if (vmode & 0x04) { // half pixel
580: *sx = 1;
581: } else {
582: *sx = 2;
583: }
584: if (vmode & 0x02) { // interlace used only on RGB?
585: *sy = 1;
586: } else {
587: *sy = 2;
588: }
589: }
590: }
591: #endif
592:
1.1 root 593:
594: /** map the correct colortable into the correct pixel format
595: */
596: static void VIDEL_updateColors(void)
597: {
598: //Dprintf(("ColorUpdate in progress\n"));
599:
600: int i, r, g, b, colors = 1 << bpp;
601:
602: #define F_COLORS(i) handleRead(VIDEL_COLOR_REGS_BEGIN + (i))
603: #define STE_COLORS(i) handleRead(0xff8240 + (i))
604:
1.1.1.6 ! root 605: if (!videl.bUseSTShifter) {
1.1 root 606: for (i = 0; i < colors; i++) {
607: int offset = i << 2;
608: r = F_COLORS(offset) & 0xfc;
609: r |= r>>6;
610: g = F_COLORS(offset + 1) & 0xfc;
611: g |= g>>6;
612: b = F_COLORS(offset + 3) & 0xfc;
613: b |= b>>6;
614: HostScreen_setPaletteColor(i, r,g,b);
615: }
616: HostScreen_updatePalette(colors);
617: } else {
618: for (i = 0; i < colors; i++) {
619: int offset = i << 1;
620: r = STE_COLORS(offset) & 0x0f;
621: r = ((r & 7)<<1)|(r>>3);
622: r |= r<<4;
623: g = (STE_COLORS(offset + 1)>>4) & 0x0f;
624: g = ((g & 7)<<1)|(g>>3);
625: g |= g<<4;
626: b = STE_COLORS(offset + 1) & 0x0f;
627: b = ((b & 7)<<1)|(b>>3);
628: b |= b<<4;
629: HostScreen_setPaletteColor(i, r,g,b);
630: }
631: HostScreen_updatePalette(colors);
632: }
633:
1.1.1.4 root 634: hostColorsSync = true;
1.1 root 635: }
636:
637:
638: void VIDEL_ZoomModeChanged(void)
639: {
640: /* User selected another zoom mode, so set a new screen resolution now */
1.1.1.4 root 641: HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1 root 642: }
643:
644:
1.1.1.2 root 645: bool VIDEL_renderScreen(void)
1.1 root 646: {
647: int vw = VIDEL_getScreenWidth();
648: int vh = VIDEL_getScreenHeight();
649: int vbpp = VIDEL_getScreenBpp();
1.1.1.6 ! root 650: bool change = false;
1.1 root 651:
1.1.1.6 ! root 652: if (vw > 0 && vw != width) {
! 653: Dprintf(("CH width %d\n", width));
! 654: width = vw;
! 655: change = true;
1.1 root 656: }
1.1.1.6 ! root 657: if (vh > 0 && vh != height) {
! 658: Dprintf(("CH height %d\n", width));
! 659: height = vh;
! 660: change = true;
1.1 root 661: }
1.1.1.6 ! root 662: if (vbpp != bpp) {
! 663: Dprintf(("CH bpp %d\n", vbpp));
! 664: bpp = vbpp;
! 665: change = true;
! 666: }
! 667: if (change) {
! 668: LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", width, height, bpp);
! 669: HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1 root 670: }
671:
672: if (!HostScreen_renderBegin())
1.1.1.2 root 673: return false;
1.1 root 674:
1.1.1.5 root 675: if (nScreenZoomX * nScreenZoomY != 1) {
1.1 root 676: VIDEL_renderScreenZoom();
677: } else {
678: VIDEL_renderScreenNoZoom();
679: }
680:
681: HostScreen_renderEnd();
682:
1.1.1.4 root 683: HostScreen_update1(false);
1.1.1.2 root 684:
685: return true;
1.1 root 686: }
687:
688:
1.1.1.4 root 689: /**
690: * Performs conversion from the TOS's bitplane word order (big endian) data
691: * into the native chunky color index.
692: */
693: static void Videl_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp,
694: Uint8 colorValues[16])
695: {
696: Uint32 a, b, c, d, x;
697:
698: /* Obviously the different cases can be broken out in various
699: * ways to lessen the amount of work needed for <8 bit modes.
700: * It's doubtful if the usage of those modes warrants it, though.
701: * The branches below should be ~100% correctly predicted and
702: * thus be more or less for free.
703: * Getting the palette values inline does not seem to help
704: * enough to worry about. The palette lookup is much slower than
705: * this code, though, so it would be nice to do something about it.
706: */
707: if (bpp >= 4) {
708: d = *(Uint32 *)&atariBitplaneData[0];
709: c = *(Uint32 *)&atariBitplaneData[2];
710: if (bpp == 4) {
711: a = b = 0;
712: } else {
713: b = *(Uint32 *)&atariBitplaneData[4];
714: a = *(Uint32 *)&atariBitplaneData[6];
715: }
716: } else {
717: a = b = c = 0;
718: if (bpp == 2) {
719: d = *(Uint32 *)&atariBitplaneData[0];
720: } else {
721: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
722: d = atariBitplaneData[0]<<16;
723: #else
724: d = atariBitplaneData[0];
725: #endif
726: }
727: }
728:
729: x = a;
730: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4);
731: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f);
732: x = b;
733: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4);
734: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f);
735:
736: x = a;
737: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2);
738: b = ((x & 0x33333333) << 2) | (b & 0x33333333);
739: x = c;
740: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2);
741: d = ((x & 0x33333333) << 2) | (d & 0x33333333);
742:
743: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
744: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
745: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
746: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
747: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
748:
749: colorValues[ 8] = a;
750: a >>= 8;
751: colorValues[ 0] = a;
752: a >>= 8;
753: colorValues[ 9] = a;
754: a >>= 8;
755: colorValues[ 1] = a;
756:
757: colorValues[10] = b;
758: b >>= 8;
759: colorValues[ 2] = b;
760: b >>= 8;
761: colorValues[11] = b;
762: b >>= 8;
763: colorValues[ 3] = b;
764:
765: colorValues[12] = c;
766: c >>= 8;
767: colorValues[ 4] = c;
768: c >>= 8;
769: colorValues[13] = c;
770: c >>= 8;
771: colorValues[ 5] = c;
772:
773: colorValues[14] = d;
774: d >>= 8;
775: colorValues[ 6] = d;
776: d >>= 8;
777: colorValues[15] = d;
778: d >>= 8;
779: colorValues[ 7] = d;
780: #else
781: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
782: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
783: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
784: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
785:
786: colorValues[ 1] = a;
787: a >>= 8;
788: colorValues[ 9] = a;
789: a >>= 8;
790: colorValues[ 0] = a;
791: a >>= 8;
792: colorValues[ 8] = a;
793:
794: colorValues[ 3] = b;
795: b >>= 8;
796: colorValues[11] = b;
797: b >>= 8;
798: colorValues[ 2] = b;
799: b >>= 8;
800: colorValues[10] = b;
801:
802: colorValues[ 5] = c;
803: c >>= 8;
804: colorValues[13] = c;
805: c >>= 8;
806: colorValues[ 4] = c;
807: c >>= 8;
808: colorValues[12] = c;
809:
810: colorValues[ 7] = d;
811: d >>= 8;
812: colorValues[15] = d;
813: d >>= 8;
814: colorValues[ 6] = d;
815: d >>= 8;
816: colorValues[14] = d;
817: #endif
818: }
819:
820:
1.1 root 821: static void VIDEL_renderScreenNoZoom(void)
822: {
823: int vw = VIDEL_getScreenWidth();
824: int vh = VIDEL_getScreenHeight();
825:
826: int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
827: int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
828: /*
829: I think this implementation is naive:
830: indeed, I suspect that we should instead skip lineoffset
831: words each time we have read "more" than linewidth words
832: (possibly "more" because of the number of bit planes).
833: Moreover, the 1 bit plane mode is particular;
834: while doing some experiments on my Falcon, it seems to
835: behave like the 4 bit planes mode.
836: At last, we have also to take into account the 4 bits register
837: located at the word $ffff8264 (bit offset). This register makes
838: the semantics of the lineoffset register change a little.
839: int bitoffset = handleReadW(HW + 0x64) & 0x000f;
840: The meaning of this register in True Color mode is not clear
841: for me at the moment (and my experiments on the Falcon don't help
842: me).
843: */
844: int nextline = linewidth + lineoffset;
845:
846: if (bpp < 16 && !hostColorsSync) {
847: VIDEL_updateColors();
848: }
849:
850: VIDEL_ConvertScreenNoZoom(vw, vh, bpp, nextline);
851: }
852:
853:
854: void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline)
855: {
856: int scrpitch = HostScreen_getPitch();
857:
858: long atariVideoRAM = VIDEL_getVideoramAddress();
859:
1.1.1.2 root 860: Uint16 *fvram = (Uint16 *) Atari2HostAddr(atariVideoRAM);
861: Uint8 *hvram = HostScreen_getVideoramAddress();
1.1.1.6 ! root 862: SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1 root 863:
864: int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
865:
866: /* Clip to SDL_Surface dimensions */
867: int scrwidth = HostScreen_getWidth();
868: int scrheight = HostScreen_getHeight();
869: int vw_clip = vw;
870: int vh_clip = vh;
871: if (vw>scrwidth) vw_clip = scrwidth;
872: if (vh>scrheight) vh_clip = scrheight;
873:
874: /* Horizontal scroll register set? */
875: if (hscrolloffset) {
876: /* Yes, so we need to adjust offset to next line: */
877: nextline += vbpp;
878: }
879:
880: /* Center screen */
881: hvram += ((scrheight-vh_clip)>>1)*scrpitch;
882: hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp();
883:
884: /* Render */
885: if (vbpp < 16) {
886: /* Bitplanes modes */
887:
888: // The SDL colors blitting...
1.1.1.2 root 889: Uint8 color[16];
1.1 root 890:
891: // FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels
892: switch ( HostScreen_getBpp() ) {
893: case 1:
894: {
1.1.1.2 root 895: Uint16 *fvram_line = fvram;
896: Uint8 *hvram_line = hvram;
1.1 root 897: int h;
898:
899: for (h = 0; h < vh_clip; h++) {
1.1.1.2 root 900: Uint16 *fvram_column = fvram_line;
901: Uint8 *hvram_column = hvram_line;
1.1 root 902: int w;
903:
904: /* First 16 pixels: */
1.1.1.4 root 905: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1 root 906: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
907: hvram_column += 16-hscrolloffset;
908: fvram_column += vbpp;
909: /* Now the main part of the line: */
910: for (w = 1; w < (vw_clip+15)>>4; w++) {
1.1.1.4 root 911: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 912: memcpy(hvram_column, color, 16);
913: hvram_column += 16;
914: fvram_column += vbpp;
915: }
916: /* Last pixels of the line for fine scrolling: */
917: if (hscrolloffset) {
1.1.1.4 root 918: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1 root 919: memcpy(hvram_column, color, hscrolloffset);
920: }
921:
922: hvram_line += scrpitch;
923: fvram_line += nextline;
924: }
925: }
926: break;
927: case 2:
928: {
1.1.1.2 root 929: Uint16 *fvram_line = fvram;
930: Uint16 *hvram_line = (Uint16 *)hvram;
1.1 root 931: int h;
932:
933: for (h = 0; h < vh_clip; h++) {
1.1.1.2 root 934: Uint16 *fvram_column = fvram_line;
935: Uint16 *hvram_column = hvram_line;
1.1.1.4 root 936: int w, j;
1.1 root 937:
1.1.1.4 root 938: /* First 16 pixels: */
939: Videl_bitplaneToChunky(fvram_column, vbpp, color);
940: for (j = 0; j < 16 - hscrolloffset; j++) {
941: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
942: }
943: fvram_column += vbpp;
944: /* Now the main part of the line: */
945: for (w = 1; w < (vw_clip+15)>>4; w++) {
946: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 947: for (j=0; j<16; j++) {
948: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
949: }
950: fvram_column += vbpp;
951: }
1.1.1.4 root 952: /* Last pixels of the line for fine scrolling: */
953: if (hscrolloffset) {
954: Videl_bitplaneToChunky(fvram_column, vbpp, color);
955: for (j = 0; j < hscrolloffset; j++) {
956: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1 root 957: }
958: }
959:
1.1.1.4 root 960: hvram_line += scrpitch>>1;
1.1 root 961: fvram_line += nextline;
962: }
963: }
964: break;
965: case 4:
966: {
1.1.1.2 root 967: Uint16 *fvram_line = fvram;
968: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 969: int h;
970:
971: for (h = 0; h < vh_clip; h++) {
1.1.1.2 root 972: Uint16 *fvram_column = fvram_line;
973: Uint32 *hvram_column = hvram_line;
1.1.1.4 root 974: int w, j;
1.1 root 975:
1.1.1.4 root 976: /* First 16 pixels: */
977: Videl_bitplaneToChunky(fvram_column, vbpp, color);
978: for (j = 0; j < 16 - hscrolloffset; j++) {
979: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
980: }
981: fvram_column += vbpp;
982: /* Now the main part of the line: */
983: for (w = 1; w < (vw_clip+15)>>4; w++) {
984: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 985: for (j=0; j<16; j++) {
986: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
987: }
988: fvram_column += vbpp;
989: }
1.1.1.4 root 990: /* Last pixels of the line for fine scrolling: */
991: if (hscrolloffset) {
992: Videl_bitplaneToChunky(fvram_column, vbpp, color);
993: for (j = 0; j < hscrolloffset; j++) {
994: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
995: }
996: }
1.1 root 997:
998: hvram_line += scrpitch>>2;
999: fvram_line += nextline;
1000: }
1001: }
1002: break;
1003: }
1004:
1005: } else {
1006:
1007: // Falcon TC (High Color)
1008: switch ( HostScreen_getBpp() ) {
1009: case 1:
1010: {
1011: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
1.1.1.2 root 1012: Uint16 *fvram_line = fvram;
1013: Uint8 *hvram_line = hvram;
1.1 root 1014: int h;
1015:
1016: for (h = 0; h < vh_clip; h++) {
1.1.1.2 root 1017: Uint16 *fvram_column = fvram_line;
1018: Uint8 *hvram_column = hvram_line;
1.1 root 1019: int w, tmp;
1020:
1021: for (w = 0; w < vw_clip; w++) {
1022:
1023: tmp = SDL_SwapBE16(*fvram_column);
1024:
1025: *hvram_column = ((tmp>>13) & 7) << 5;
1026: *hvram_column |= ((tmp>>8) & 7) << 2;
1027: *hvram_column |= ((tmp>>2) & 3);
1028:
1029: hvram_column++;
1030: fvram_column++;
1031: }
1032:
1033: hvram_line += scrpitch;
1034: fvram_line += nextline;
1035: }
1036: }
1037: break;
1038: case 2:
1039: {
1.1.1.2 root 1040: Uint16 *fvram_line = fvram;
1041: Uint16 *hvram_line = (Uint16 *)hvram;
1.1 root 1042: int h;
1043:
1044: for (h = 0; h < vh_clip; h++) {
1045: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1046: //FIXME: here might be a runtime little/big video endian switch like:
1047: // if ( /* videocard memory in Motorola endian format */ false)
1048: memcpy(hvram_line, fvram_line, vw_clip<<1);
1049: #else
1050: int w;
1.1.1.2 root 1051: Uint16 *fvram_column = fvram_line;
1052: Uint16 *hvram_column = hvram_line;
1.1 root 1053:
1054: for (w = 0; w < vw_clip; w++) {
1055: // byteswap with SDL asm macros
1056: *hvram_column++ = SDL_SwapBE16(*fvram_column++);
1057: }
1058: #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
1059:
1060: hvram_line += scrpitch>>1;
1061: fvram_line += nextline;
1062: }
1063: }
1064: break;
1065: case 4:
1066: {
1.1.1.2 root 1067: Uint16 *fvram_line = fvram;
1068: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 1069: int h;
1070:
1071: for (h = 0; h < vh_clip; h++) {
1.1.1.2 root 1072: Uint16 *fvram_column = fvram_line;
1073: Uint32 *hvram_column = hvram_line;
1.1 root 1074: int w;
1075:
1076: for (w = 0; w < vw_clip; w++) {
1.1.1.6 ! root 1077: Uint16 srcword = *fvram_column++;
1.1 root 1078:
1079: *hvram_column++ =
1.1.1.6 ! root 1080: SDL_MapRGB(scrfmt,
! 1081: (srcword & 0xf8),
! 1082: (((srcword & 0x07) << 5) |
! 1083: ((srcword >> 11) & 0x3c)),
! 1084: ((srcword >> 5) & 0xf8));
1.1 root 1085: }
1086:
1087: hvram_line += scrpitch>>2;
1088: fvram_line += nextline;
1089: }
1090: }
1091: break;
1092: }
1093: }
1094: }
1095:
1096:
1097: static void VIDEL_renderScreenZoom(void)
1098: {
1099: /* Atari screen infos */
1100: int vw = VIDEL_getScreenWidth();
1101: int vh = VIDEL_getScreenHeight();
1102:
1103: int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
1104: int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
1105: /* same remark as before: too naive */
1106: int nextline = linewidth + lineoffset;
1107:
1108: if ((vw<32) || (vh<32)) return;
1109:
1110: if (bpp<16 && !hostColorsSync) {
1111: VIDEL_updateColors();
1112: }
1113:
1114: VIDEL_ConvertScreenZoom(vw, vh, bpp, nextline);
1115: }
1116:
1117:
1118: void VIDEL_ConvertScreenZoom(int vw, int vh, int vbpp, int nextline)
1119: {
1120: int i, j, w, h, cursrcline;
1121:
1.1.1.2 root 1122: Uint16 *fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
1.1 root 1123:
1124: /* Host screen infos */
1125: int scrpitch = HostScreen_getPitch();
1126: int scrwidth = HostScreen_getWidth();
1127: int scrheight = HostScreen_getHeight();
1128: int scrbpp = HostScreen_getBpp();
1.1.1.6 ! root 1129: SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1.1.2 root 1130: Uint8 *hvram = (Uint8 *) HostScreen_getVideoramAddress();
1.1 root 1131:
1132: int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
1133:
1134: /* Horizontal scroll register set? */
1135: if (hscrolloffset) {
1136: /* Yes, so we need to adjust offset to next line: */
1137: nextline += vbpp;
1138: }
1139:
1140: /* Integer zoom coef ? */
1141: if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) {
1142: int coefx = scrwidth/vw;
1143: int coefy = scrheight/vh;
1144:
1145: scrwidth = vw * coefx;
1146: scrheight = vh * coefy;
1147:
1148: /* Center screen */
1149: hvram += ((HostScreen_getHeight()-scrheight)>>1)*scrpitch;
1150: hvram += ((HostScreen_getWidth()-scrwidth)>>1)*scrbpp;
1151: }
1152:
1153: /* New zoom ? */
1154: if ((zoomwidth != vw) || (scrwidth != prev_scrwidth)) {
1155: if (zoomxtable) {
1156: free(zoomxtable);
1157: }
1158: zoomxtable = malloc(sizeof(int)*scrwidth);
1159: for (i=0; i<scrwidth; i++) {
1160: zoomxtable[i] = (vw*i)/scrwidth;
1161: }
1162: zoomwidth = vw;
1163: prev_scrwidth = scrwidth;
1164: }
1165: if ((zoomheight != vh) || (scrheight != prev_scrheight)) {
1166: if (zoomytable) {
1167: free(zoomytable);
1168: }
1169: zoomytable = malloc(sizeof(int)*scrheight);
1170: for (i=0; i<scrheight; i++) {
1171: zoomytable[i] = (vh*i)/scrheight;
1172: }
1173: zoomheight = vh;
1174: prev_scrheight = scrheight;
1175: }
1176:
1177: cursrcline = -1;
1178:
1179: if (vbpp<16) {
1.1.1.2 root 1180: Uint8 color[16];
1.1 root 1181:
1182: /* Bitplanes modes */
1183: switch(scrbpp) {
1184: case 1:
1185: {
1186: /* One complete planar 2 chunky line */
1.1.1.2 root 1187: Uint8 *p2cline = malloc(sizeof(Uint8)*vw);
1.1 root 1188:
1.1.1.2 root 1189: Uint16 *fvram_line;
1190: Uint8 *hvram_line = hvram;
1.1 root 1191:
1192: for (h = 0; h < scrheight; h++) {
1193: fvram_line = fvram + (zoomytable[h] * nextline);
1194:
1195: /* Recopy the same line ? */
1196: if (zoomytable[h] == cursrcline) {
1197: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
1198: } else {
1.1.1.2 root 1199: Uint16 *fvram_column = fvram_line;
1200: Uint8 *hvram_column = p2cline;
1.1 root 1201:
1202: /* First 16 pixels of a new line */
1.1.1.4 root 1203: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1 root 1204: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
1205: hvram_column += 16-hscrolloffset;
1206: fvram_column += vbpp;
1207: /* Convert main part of the new line */
1208: for (w=1; w < (vw+15)>>4; w++) {
1.1.1.4 root 1209: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 1210: memcpy(hvram_column, color, 16);
1211: hvram_column += 16;
1212: fvram_column += vbpp;
1213: }
1214: /* Last pixels of the line for fine scrolling: */
1215: if (hscrolloffset) {
1.1.1.4 root 1216: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1 root 1217: memcpy(hvram_column, color, hscrolloffset);
1218: }
1219:
1220: /* Zoom a new line */
1221: for (w=0; w<scrwidth; w++) {
1222: hvram_line[w] = p2cline[zoomxtable[w]];
1223: }
1224: }
1225:
1226: hvram_line += scrpitch;
1227: cursrcline = zoomytable[h];
1228: }
1229:
1230: free(p2cline);
1231: }
1232: break;
1233: case 2:
1234: {
1235: /* One complete planar 2 chunky line */
1.1.1.2 root 1236: Uint16 *p2cline = malloc(sizeof(Uint16)*vw);
1.1 root 1237:
1.1.1.6 ! root 1238: Uint16 *fvram_line;
1.1.1.2 root 1239: Uint16 *hvram_line = (Uint16 *)hvram;
1.1 root 1240:
1241: for (h = 0; h < scrheight; h++) {
1242: fvram_line = fvram + (zoomytable[h] * nextline);
1243:
1244: /* Recopy the same line ? */
1245: if (zoomytable[h] == cursrcline) {
1246: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
1247: } else {
1.1.1.2 root 1248: Uint16 *fvram_column = fvram_line;
1249: Uint16 *hvram_column = p2cline;
1.1 root 1250:
1.1.1.4 root 1251: /* First 16 pixels of a new line: */
1252: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1253: for (j = 0; j < 16 - hscrolloffset; j++) {
1254: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
1255: }
1256: fvram_column += vbpp;
1257: /* Convert the main part of the new line: */
1258: for (w = 1; w < (vw+15)>>4; w++) {
1259: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 1260: for (j=0; j<16; j++) {
1261: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1262: }
1263: fvram_column += vbpp;
1264: }
1.1.1.4 root 1265: /* Last pixels of the new line for fine scrolling: */
1266: if (hscrolloffset) {
1267: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1268: for (j = 0; j < hscrolloffset; j++) {
1269: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1 root 1270: }
1271: }
1.1.1.4 root 1272:
1.1 root 1273: /* Zoom a new line */
1274: for (w=0; w<scrwidth; w++) {
1.1.1.4 root 1275: hvram_line[w] = p2cline[zoomxtable[w]];
1.1 root 1276: }
1277: }
1278:
1.1.1.4 root 1279: hvram_line += scrpitch>>1;
1.1 root 1280: cursrcline = zoomytable[h];
1281: }
1282:
1283: free(p2cline);
1284: }
1285: break;
1286: case 4:
1287: {
1288: /* One complete planar 2 chunky line */
1.1.1.2 root 1289: Uint32 *p2cline = malloc(sizeof(Uint32)*vw);
1.1 root 1290:
1.1.1.2 root 1291: Uint16 *fvram_line;
1292: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 1293:
1294: for (h = 0; h < scrheight; h++) {
1295: fvram_line = fvram + (zoomytable[h] * nextline);
1296:
1297: /* Recopy the same line ? */
1298: if (zoomytable[h] == cursrcline) {
1299: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
1300: } else {
1.1.1.2 root 1301: Uint16 *fvram_column = fvram_line;
1302: Uint32 *hvram_column = p2cline;
1.1 root 1303:
1.1.1.4 root 1304: /* First 16 pixels of a new line: */
1305: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1306: for (j = 0; j < 16 - hscrolloffset; j++) {
1307: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
1308: }
1309: fvram_column += vbpp;
1310: /* Convert the main part of the new line: */
1311: for (w = 1; w < (vw+15)>>4; w++) {
1312: Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1 root 1313: for (j=0; j<16; j++) {
1314: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1315: }
1316: fvram_column += vbpp;
1317: }
1.1.1.4 root 1318: /* Last pixels of the new line for fine scrolling: */
1319: if (hscrolloffset) {
1320: Videl_bitplaneToChunky(fvram_column, vbpp, color);
1321: for (j = 0; j < hscrolloffset; j++) {
1322: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1323: }
1324: }
1325:
1.1 root 1326: /* Zoom a new line */
1327: for (w=0; w<scrwidth; w++) {
1328: hvram_line[w] = p2cline[zoomxtable[w]];
1329: }
1330: }
1331:
1332: hvram_line += scrpitch>>2;
1333: cursrcline = zoomytable[h];
1334: }
1335:
1336: free(p2cline);
1337: }
1338: break;
1339: }
1340: } else {
1.1.1.4 root 1341: /* Falcon high-color (16-bit) mode */
1.1 root 1342:
1343: switch(scrbpp) {
1344: case 1:
1345: {
1346: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
1.1.1.2 root 1347: Uint16 *fvram_line;
1348: Uint8 *hvram_line = hvram;
1.1 root 1349:
1350: for (h = 0; h < scrheight; h++) {
1.1.1.2 root 1351: Uint16 *fvram_column;
1352: Uint8 *hvram_column;
1.1 root 1353:
1354: fvram_line = fvram + (zoomytable[h] * nextline);
1355: fvram_column = fvram_line;
1356: hvram_column = hvram_line;
1357:
1358: /* Recopy the same line ? */
1359: if (zoomytable[h] == cursrcline) {
1360: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
1361: } else {
1362: for (w = 0; w < scrwidth; w++) {
1.1.1.2 root 1363: Uint16 srcword;
1364: Uint8 dstbyte;
1.1 root 1365:
1366: srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
1367:
1368: dstbyte = ((srcword>>13) & 7) << 5;
1369: dstbyte |= ((srcword>>8) & 7) << 2;
1370: dstbyte |= ((srcword>>2) & 3);
1371:
1372: *hvram_column++ = dstbyte;
1373: }
1374: }
1375:
1376: hvram_line += scrpitch;
1377: cursrcline = zoomytable[h];
1378: }
1379: }
1380: break;
1381: case 2:
1382: {
1.1.1.2 root 1383: Uint16 *fvram_line;
1384: Uint16 *hvram_line = (Uint16 *)hvram;
1.1 root 1385:
1386: for (h = 0; h < scrheight; h++) {
1.1.1.2 root 1387: Uint16 *fvram_column;
1388: Uint16 *hvram_column;
1.1 root 1389:
1390: fvram_line = fvram + (zoomytable[h] * nextline);
1391: fvram_column = fvram_line;
1392: hvram_column = hvram_line;
1393:
1394: /* Recopy the same line ? */
1395: if (zoomytable[h] == cursrcline) {
1396: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
1397: } else {
1398: for (w = 0; w < scrwidth; w++) {
1.1.1.2 root 1399: Uint16 srcword;
1.1 root 1400:
1401: srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
1402: *hvram_column++ = srcword;
1403: }
1404: }
1405:
1406: hvram_line += scrpitch>>1;
1407: cursrcline = zoomytable[h];
1408: }
1409: }
1410: break;
1411: case 4:
1412: {
1.1.1.2 root 1413: Uint16 *fvram_line;
1414: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 1415:
1416: for (h = 0; h < scrheight; h++) {
1.1.1.2 root 1417: Uint16 *fvram_column;
1418: Uint32 *hvram_column;
1.1 root 1419:
1420: fvram_line = fvram + (zoomytable[h] * nextline);
1421: fvram_column = fvram_line;
1422: hvram_column = hvram_line;
1423:
1424: /* Recopy the same line ? */
1425: if (zoomytable[h] == cursrcline) {
1426: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
1427: } else {
1428: for (w = 0; w < scrwidth; w++) {
1.1.1.2 root 1429: Uint16 srcword;
1.1 root 1430:
1431: srcword = fvram_column[zoomxtable[w]];
1432:
1433: *hvram_column++ =
1.1.1.6 ! root 1434: SDL_MapRGB(scrfmt,
! 1435: (srcword & 0xf8),
! 1436: (((srcword & 0x07) << 5) |
! 1437: ((srcword >> 11) & 0x3c)),
! 1438: ((srcword >> 5) & 0xf8));
1.1 root 1439: }
1440: }
1441:
1442: hvram_line += scrpitch>>2;
1443: cursrcline = zoomytable[h];
1444: }
1445: }
1446: break;
1447: }
1448: }
1449: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.