|
|
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
1.1.1.8 ! root 36: $FFFF8264 (byte) : Horizontal scroll register shadow register
1.1.1.6 root 37: $FFFF8265 (byte) : Horizontal scroll register
38: $FFFF8266 (word) : Falcon shift mode
39:
40: $FFFF8280 (word) : HHC - Horizontal Hold Counter
41: $FFFF8282 (word) : HHT - Horizontal Hold Timer
42: $FFFF8284 (word) : HBB - Horizontal Border Begin
43: $FFFF8286 (word) : HBE - Horizontal Border End
44: $FFFF8288 (word) : HDB - Horizontal Display Begin
45: $FFFF828A (word) : HDE - Horizontal Display End
46: $FFFF828C (word) : HSS - Horizontal SS
47: $FFFF828E (word) : HFS - Horizontal FS
48: $FFFF8290 (word) : HEE - Horizontal EE
49:
50: $FFFF82A0 (word) : VFC - Vertical Frequency Counter
51: $FFFF82A2 (word) : VFT - Vertical Frequency Timer
52: $FFFF82A4 (word) : VBB - Vertical Border Begin
53: $FFFF82A6 (word) : VBE - Vertical Border End
54: $FFFF82A8 (word) : VDB - Vertical Display Begin
55: $FFFF82AA (word) : VDE - Vertical Display End
56: $FFFF82AC (word) : VSS - Vertical SS
57:
58: $FFFF82C0 (word) : VCO - Video control
59: $FFFF82C2 (word) : VMD - Video mode
60:
61: $FFFF9800 (long) : VDL_PAL - Videl palette Register 000
62: ...........
63: $FFFF98FC (long) : VDL_PAL - Videl palette Register 255
1.1 root 64: */
1.1.1.6 root 65:
1.1.1.4 root 66: const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__;
1.1 root 67:
1.1.1.6 root 68: #include <SDL_endian.h>
69: #include <SDL.h>
1.1 root 70: #include "main.h"
71: #include "configuration.h"
1.1.1.6 root 72: #include "memorySnapShot.h"
1.1 root 73: #include "ioMem.h"
1.1.1.6 root 74: #include "log.h"
1.1 root 75: #include "hostscreen.h"
76: #include "screen.h"
77: #include "stMemory.h"
78: #include "videl.h"
79:
80:
81: #define Atari2HostAddr(a) (&STRam[a])
82: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
83:
1.1.1.8 ! root 84:
1.1.1.6 root 85: struct videl_s {
86: bool bUseSTShifter; /* whether to use ST or Falcon palette */
87: Uint8 reg_ffff8006_save; /* save reg_ffff8006 as it's a read only register */
88: Uint8 monitor_type; /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */
1.1.1.8 ! root 89: Uint32 videoBaseAddr; /* Video base address, refreshed after each VBL */
1.1.1.6 root 90:
1.1.1.8 ! root 91: Sint16 leftBorderSize; /* Size of the left border */
! 92: Sint16 rightBorderSize; /* Size of the right border */
! 93: Sint16 upperBorderSize; /* Size of the upper border */
! 94: Sint16 lowerBorderSize; /* Size of the lower border */
! 95: Uint16 XSize; /* X size of the graphical area */
! 96: Uint16 YSize; /* Y size of the graphical area */
! 97:
! 98: Uint16 save_scrWidth; /* save screen width to detect a change of X resolution */
! 99: Uint16 save_scrHeight; /* save screen height to detect a change of Y resolution */
! 100: Uint16 save_scrBpp; /* save screen Bpp to detect a change of bitplan mode */
1.1 root 101:
1.1.1.8 ! root 102: bool hostColorsSync; /* Sync palette with host's */
! 103: };
1.1.1.6 root 104:
1.1.1.8 ! root 105: struct videl_zoom_s {
! 106: Uint16 zoomwidth;
! 107: Uint16 prev_scrwidth;
! 108: Uint16 zoomheight;
! 109: Uint16 prev_scrheight;
! 110: int *zoomxtable;
! 111: int *zoomytable;
! 112: };
1.1 root 113:
1.1.1.8 ! root 114: static struct videl_s videl;
! 115: static struct videl_zoom_s videl_zoom;
1.1.1.6 root 116:
1.1.1.8 ! root 117: Uint16 vfc_counter; /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */
1.1.1.6 root 118:
1.1.1.8 ! root 119: static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count);
! 120: static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count);
! 121: static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count);
1.1 root 122:
1.1.1.8 ! root 123: /**
! 124: * Called upon startup and when CPU encounters a RESET instruction.
! 125: */
1.1 root 126: void VIDEL_reset(void)
127: {
1.1.1.6 root 128: videl.bUseSTShifter = false; /* Use Falcon color palette by default */
129: videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
1.1.1.8 ! root 130: videl.monitor_type = videl.reg_ffff8006_save & 0xc0;
1.1.1.6 root 131:
1.1.1.8 ! root 132: videl.hostColorsSync = false;
1.1 root 133:
1.1.1.6 root 134: vfc_counter = 0;
135:
1.1 root 136: /* Autozoom */
1.1.1.8 ! root 137: videl_zoom.zoomwidth = 0;
! 138: videl_zoom.prev_scrwidth = 0;
! 139: videl_zoom.zoomheight = 0;
! 140: videl_zoom.prev_scrheight = 0;
! 141: videl_zoom.zoomxtable = NULL;
! 142: videl_zoom.zoomytable = NULL;
1.1 root 143:
1.1.1.4 root 144: /* Default resolution to boot with */
1.1.1.8 ! root 145: videl.save_scrWidth = 640;
! 146: videl.save_scrHeight = 480;
! 147: videl.save_scrBpp = ConfigureParams.Screen.nForceBpp;
! 148: HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp);
1.1.1.4 root 149:
150: /* Reset IO register (some are not initialized by TOS) */
151: IoMem_WriteWord(0xff820e, 0); /* Line offset */
152: IoMem_WriteWord(0xff8264, 0); /* Horizontal scroll */
1.1.1.8 ! root 153:
! 154: /* Init synch mode register */
! 155: VIDEL_SyncMode_WriteByte();
1.1 root 156: }
157:
1.1.1.6 root 158: /**
159: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
160: */
161: void VIDEL_MemorySnapShot_Capture(bool bSave)
162: {
163: /* Save/Restore details */
164: MemorySnapShot_Store(&videl, sizeof(videl));
1.1.1.8 ! root 165: MemorySnapShot_Store(&videl_zoom, sizeof(videl_zoom));
1.1.1.6 root 166: MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter));
167: }
168:
169: /**
170: * Monitor write access to ST/E color palette registers
171: */
1.1 root 172: void VIDEL_ColorRegsWrite(void)
173: {
1.1.1.8 ! root 174: videl.hostColorsSync = false;
1.1 root 175: }
176:
1.1.1.6 root 177: /**
178: * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration.
1.1.1.8 ! root 179: * This register is read only.
1.1.1.6 root 180: */
181: void VIDEL_Monitor_WriteByte(void)
182: {
1.1.1.8 ! root 183: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8006 Monitor and memory conf write (Read only)\n");
1.1.1.6 root 184: /* Restore hardware value */
1.1.1.8 ! root 185:
1.1.1.6 root 186: IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
187: }
188:
189: /**
1.1.1.8 ! root 190: * VIDEL_SyncMode_WriteByte : Videl synchronization mode.
! 191: * $FFFF820A [R/W] _______0 .................................. SYNC-MODE
! 192: ||
! 193: |+--Synchronisation [ 0:internal / 1:external ]
! 194: +---Vertical frequency [ Read-only bit ]
! 195: [ Monochrome monitor:0 / Colour monitor:1 ]
! 196: */
! 197: void VIDEL_SyncMode_WriteByte(void)
! 198: {
! 199: Uint8 syncMode = IoMem_ReadByte(0xff820a);
! 200: LOG_TRACE(TRACE_VIDEL, "Videl : $ff820a Sync Mode write: 0x%02x\n", syncMode);
! 201:
! 202: if (videl.monitor_type == FALCON_MONITOR_MONO)
! 203: syncMode &= 0xfd;
! 204: else
! 205: syncMode |= 0x2;
! 206:
! 207: IoMem_WriteByte(0xff820a, syncMode);
! 208: }
! 209:
! 210: /**
! 211: * Read video address counter and update ff8205/07/09
! 212: */
! 213: void VIDEL_ScreenCounter_ReadByte(void)
! 214: {
! 215: // Uint32 addr; // To be used
! 216: Uint32 addr = 0; // To be removed
! 217:
! 218: // addr = Videl_CalculateAddress(); /* TODO: get current video address */
! 219: IoMem[0xff8205] = ( addr >> 16 ) & 0xff;
! 220: IoMem[0xff8207] = ( addr >> 8 ) & 0xff;
! 221: IoMem[0xff8209] = addr & 0xff;
! 222:
! 223: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode read: 0x%08x\n", addr);
! 224: }
! 225:
! 226: /**
! 227: * Write video address counter
! 228: */
! 229: void VIDEL_ScreenCounter_WriteByte(void)
! 230: {
! 231: Uint32 addr_new = 0;
! 232: Uint8 AddrByte;
! 233:
! 234: AddrByte = IoMem[ IoAccessCurrentAddress ];
! 235:
! 236: /* Compute the new video address with one modified byte */
! 237: if ( IoAccessCurrentAddress == 0xff8205 )
! 238: addr_new = ( addr_new & 0x00ffff ) | ( AddrByte << 16 );
! 239: else if ( IoAccessCurrentAddress == 0xff8207 )
! 240: addr_new = ( addr_new & 0xff00ff ) | ( AddrByte << 8 );
! 241: else if ( IoAccessCurrentAddress == 0xff8209 )
! 242: addr_new = ( addr_new & 0xffff00 ) | ( AddrByte );
! 243:
! 244: // TODO: save the value in a table for the final rendering
! 245: }
! 246:
! 247: /**
! 248: * VIDEL_LineOffset_WriteWord: $FFFF820E [R/W] W _______876543210 Line Offset
! 249: * How many words are added to the end of display line, i.e. how many words are
! 250: * 'behind' the display.
! 251: */
! 252: void VIDEL_LineOffset_WriteWord(void)
! 253: {
! 254: Uint16 lineOffset = IoMem_ReadWord(0xff820e);
! 255:
! 256: LOG_TRACE(TRACE_VIDEL, "Videl : $ff820e Line Offset write: 0x%04x\n", lineOffset);
! 257: }
! 258:
! 259: /**
! 260: * VIDEL_Line_Width_WriteWord: $FFFF8210 [R/W] W ______9876543210 Line Width (VWRAP)
! 261: * Length of display line in words.Or, how many words should be added to
! 262: * vram counter after every display line.
! 263: */
! 264: void VIDEL_Line_Width_WriteWord(void)
! 265: {
! 266: Uint16 lineWidth = IoMem_ReadWord(0xff8210);
! 267:
! 268: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8210 Line Width write: 0x%04x\n", lineWidth);
! 269: }
! 270:
! 271: /**
1.1.1.6 root 272: * Write to video address base high, med and low register (0xff8201/03/0d).
273: * On Falcon, when a program writes to high or med registers, base low register
274: * is reset to zero.
275: */
276: void VIDEL_ScreenBase_WriteByte(void)
277: {
278: Uint32 screenBase;
279:
280: if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
281: /* Reset screen base low register */
282: IoMem[0xff820d] = 0;
283: }
284:
285: screenBase = (IoMem[0xff8201]<<16)+(IoMem[0xff8203]<<8)+IoMem[0xff820d];
286:
1.1.1.8 ! root 287: LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%02x\t (screen: 0x%04x)\n",
1.1.1.6 root 288: IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress], screenBase);
289: }
290:
291: /**
292: VIDEL_ST_ShiftModeWriteByte :
293: $FFFF8260 [R/W] B ______10 ST Shift Mode
294: ||
295: || others vga
296: || $FF8210 $FF82C2 $FF82C2
297: 00--4BP/320 Pixels=> $0050 $0000 $0005
298: 01--2BP/640 Pixels=> $0050 $0004 $0009
299: 10--1BP/640 Pixels=> $0028 $0006 $0008
300: 11--???/320 Pixels=> $0050 $0000 $0000
301:
302: Writing to this register does the following things:
303: - activate STE palette
304: - sets line width ($ffff8210)
305: - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
306: */
307: void VIDEL_ST_ShiftModeWriteByte(void)
308: {
309: Uint16 line_width, video_mode;
310: Uint8 st_shiftMode;
311:
312: st_shiftMode = IoMem_ReadByte(0xff8260);
1.1.1.8 ! root 313: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8260 ST Shift Mode (STSHIFT) write: 0x%02x\n", st_shiftMode);
! 314:
! 315: /* Bits 2-7 are set to 0 */
! 316: IoMem_WriteByte(0xff8260, st_shiftMode & 3);
1.1.1.6 root 317:
318: /* Activate STE palette */
319: videl.bUseSTShifter = true;
320:
321: /* Compute line width and video mode */
322: switch (st_shiftMode & 0x3) {
323: case 0: /* 4BP/320 Pixels */
324: line_width = 0x50;
325: /* half pixels + double lines vs. no scaling */
326: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
327: break;
328: case 1: /* 2BP/640 Pixels */
329: line_width = 0x50;
330: /* quarter pixels + double lines vs. half pixels */
331: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
332: break;
333: case 2: /* 1BP/640 Pixels */
334: line_width = 0x28;
335: if (videl.monitor_type == FALCON_MONITOR_MONO) {
336: video_mode = 0x0;
337: break;
338: }
339: /* quarter pixels vs. half pixels + interlace */
340: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
341: break;
342: case 3: /* ???/320 Pixels */
1.1.1.8 ! root 343: default:
1.1.1.6 root 344: line_width = 0x50;
345: video_mode = 0x0;
346: break;
347: }
348:
349: /* Set line width ($FFFF8210) */
350: IoMem_WriteWord(0xff8210, line_width);
351:
352: /* Set video mode ($FFFF82C2) */
353: IoMem_WriteWord(0xff82c2, video_mode);
354: }
355:
356: /**
1.1.1.8 ! root 357: VIDEL_HorScroll64_WriteByte : Horizontal scroll register (0-15)
! 358: $FFFF8264 [R/W] ________ ................................ H-SCROLL HI
! 359: |||| [ Shadow register for $FFFF8265 ]
! 360: ++++--Pixel shift [ 0:normal / 1..15:Left shift ]
! 361: [ Change in line-width NOT required ]
! 362: */
! 363: void VIDEL_HorScroll64_WriteByte(void)
! 364: {
! 365: Uint8 horScroll64 = IoMem_ReadWord(0xff8264);
! 366: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8264 Horizontal scroll 64 write: 0x%02x\n", horScroll64);
! 367: }
! 368:
! 369: /**
! 370: VIDEL_HorScroll65_WriteByte : Horizontal scroll register (0-15)
! 371: $FFFF8265 [R/W] ____3210 .................................H-SCROLL LO
! 372: ||||
! 373: ++++--Pixel [ 0:normal / 1..15:Left shift ]
! 374: [ Change in line-width NOT required ]
! 375: */
! 376: void VIDEL_HorScroll65_WriteByte(void)
! 377: {
! 378: Uint8 horScroll65 = IoMem_ReadWord(0xff8265);
! 379: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8265 Horizontal scroll 65 write: 0x%02x\n", horScroll65);
! 380: }
! 381:
! 382: /**
! 383: VIDEL_Falcon_ShiftMode_WriteWord :
1.1.1.6 root 384: $FFFF8266 [R/W] W _____A98_6543210 Falcon Shift Mode (SPSHIFT)
385: ||| |||||||
1.1.1.8 ! root 386: ||| |||++++- 0..15: Colourbank choice from 256-colour table in 16 colour multiples
! 387: ||| ||+----- 8 Bitplanes mode (256 Colors) [0:off / 1:on]
! 388: ||| |+------ Vertical Sync [0: internal / 1: external]
! 389: ||| +------- Horizontal Sync [0: internal / 1: external]
! 390: ||+--------- True-Color-Mode [0:off / 1:on]
! 391: |+---------- Overlay-Mode [0:off / 1:on]
! 392: +----------- 0: 2-Color-Mode [0:off / 1:on]
1.1.1.6 root 393:
394: Writing to this register does the following things:
395: - activate Falcon palette
396: - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
397: same as ST LOW since Falcon palette is used!)
398: - $8260 register is ignored, you don't need to write here anything
399:
400: Note: 4-Color-Mode isn't realisable with Falcon palette.
401: */
1.1.1.8 ! root 402: void VIDEL_Falcon_ShiftMode_WriteWord(void)
1.1.1.6 root 403: {
404: Uint16 falc_shiftMode = IoMem_ReadWord(0xff8266);
405:
1.1.1.8 ! root 406: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8266 Falcon Shift Mode (SPSHIFT) write: 0x%04x\n", falc_shiftMode);
1.1.1.6 root 407:
408: videl.bUseSTShifter = false;
409: }
410:
411: /**
412: * Write Horizontal Hold Counter (HHC)
413: */
414: void VIDEL_HHC_WriteWord(void)
415: {
416: Uint16 hhc = IoMem_ReadWord(0xff8280);
417:
1.1.1.8 ! root 418: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8280 Horizontal Hold Counter (HHC) write: 0x%04x\n", hhc);
1.1.1.6 root 419: }
420:
421: /**
422: * Write Horizontal Hold Timer (HHT)
423: */
424: void VIDEL_HHT_WriteWord(void)
425: {
426: Uint16 hht = IoMem_ReadWord(0xff8282);
427:
1.1.1.8 ! root 428: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8282 Horizontal Hold Timer (HHT) write: 0x%04x\n", hht);
1.1.1.6 root 429: }
430:
431: /**
432: * Write Horizontal Border Begin (HBB)
433: */
434: void VIDEL_HBB_WriteWord(void)
435: {
436: Uint16 hbb = IoMem_ReadWord(0xff8284);
437:
1.1.1.8 ! root 438: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8284 Horizontal Border Begin (HBB) write: 0x%04x\n", hbb);
1.1.1.6 root 439: }
440:
441: /**
442: * Write Horizontal Border End (HBE)
443: */
444: void VIDEL_HBE_WriteWord(void)
445: {
446: Uint16 hbe = IoMem_ReadWord(0xff8286);
447:
1.1.1.8 ! root 448: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8286 Horizontal Border End (HBE) write: 0x%04x\n", hbe);
1.1.1.6 root 449: }
450:
451: /**
452: * Write Horizontal Display Begin (HDB)
1.1.1.8 ! root 453: $FFFF8288 [R/W] W ______9876543210 Horizontal Display Begin (HDB)
! 454: |
! 455: +---------- Display will start in [0: 1st halfline / 1: 2nd halfline]
1.1.1.6 root 456: */
457: void VIDEL_HDB_WriteWord(void)
458: {
459: Uint16 hdb = IoMem_ReadWord(0xff8288);
460:
1.1.1.8 ! root 461: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8288 Horizontal Display Begin (HDB) write: 0x%04x\n", hdb);
1.1.1.6 root 462: }
463:
464: /**
465: * Write Horizontal Display End (HDE)
466: */
467: void VIDEL_HDE_WriteWord(void)
468: {
469: Uint16 hde = IoMem_ReadWord(0xff828a);
470:
1.1.1.8 ! root 471: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828a Horizontal Display End (HDE) write: 0x%04x\n", hde);
1.1.1.6 root 472: }
473:
474: /**
475: * Write Horizontal SS (HSS)
476: */
477: void VIDEL_HSS_WriteWord(void)
478: {
479: Uint16 hss = IoMem_ReadWord(0xff828c);
480:
1.1.1.8 ! root 481: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828c Horizontal SS (HSS) write: 0x%04x\n", hss);
1.1.1.6 root 482: }
483:
484: /**
485: * Write Horizontal FS (HFS)
486: */
487: void VIDEL_HFS_WriteWord(void)
488: {
489: Uint16 hfs = IoMem_ReadWord(0xff828e);
490:
1.1.1.8 ! root 491: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828e Horizontal FS (HFS) write: 0x%04x\n", hfs);
1.1.1.6 root 492: }
493:
494: /**
495: * Write Horizontal EE (HEE)
496: */
497: void VIDEL_HEE_WriteWord(void)
498: {
499: Uint16 hee = IoMem_ReadWord(0xff8290);
500:
1.1.1.8 ! root 501: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8290 Horizontal EE (HEE) write: 0x%04x\n", hee);
1.1.1.6 root 502: }
503:
504: /**
505: * Write Vertical Frequency Counter (VFC)
506: */
507: void VIDEL_VFC_ReadWord(void)
508: {
509: IoMem_WriteWord(0xff82a0, vfc_counter);
1.1.1.8 ! root 510: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", vfc_counter);
1.1.1.6 root 511: }
512:
513: /**
514: * Write Vertical Frequency Timer (VFT)
515: */
516: void VIDEL_VFT_WriteWord(void)
517: {
518: Uint16 vft = IoMem_ReadWord(0xff82a2);
519:
1.1.1.8 ! root 520: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a2 Vertical Frequency Timer (VFT) write: 0x%04x\n", vft);
1.1.1.6 root 521: }
522:
523: /**
524: * Write Vertical Border Begin (VBB)
525: */
526: void VIDEL_VBB_WriteWord(void)
527: {
528: Uint16 vbb = IoMem_ReadWord(0xff82a4);
529:
1.1.1.8 ! root 530: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a4 Vertical Border Begin (VBB) write: 0x%04x\n", vbb);
1.1.1.6 root 531: }
532:
533: /**
534: * Write Vertical Border End (VBE)
535: */
536: void VIDEL_VBE_WriteWord(void)
537: {
538: Uint16 vbe = IoMem_ReadWord(0xff82a6);
539:
1.1.1.8 ! root 540: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a6 Vertical Border End (VBE) write: 0x%04x\n", vbe);
1.1.1.6 root 541: }
542:
543: /**
544: * Write Vertical Display Begin (VDB)
545: */
546: void VIDEL_VDB_WriteWord(void)
1.1 root 547: {
1.1.1.6 root 548: Uint16 vdb = IoMem_ReadWord(0xff82a8);
549:
1.1.1.8 ! root 550: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a8 Vertical Display Begin (VDB) write: 0x%04x\n", vdb);
1.1 root 551: }
552:
1.1.1.6 root 553: /**
554: * Write Vertical Display End (VDE)
555: */
556: void VIDEL_VDE_WriteWord(void)
557: {
558: Uint16 vde = IoMem_ReadWord(0xff82aa);
559:
1.1.1.8 ! root 560: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82aa Vertical Display End (VDE) write: 0x%04x\n", vde);
1.1.1.6 root 561: }
562:
563: /**
564: * Write Vertical SS (VSS)
565: */
566: void VIDEL_VSS_WriteWord(void)
567: {
568: Uint16 vss = IoMem_ReadWord(0xff82ac);
569:
1.1.1.8 ! root 570: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82ac Vertical SS (VSS) write: 0x%04x\n", vss);
1.1.1.6 root 571: }
572:
573: /**
574: * Write Video Control (VCO)
575: */
576: void VIDEL_VCO_WriteWord(void)
577: {
578: Uint16 vco = IoMem_ReadWord(0xff82c0);
579:
1.1.1.8 ! root 580: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c0 Video control (VCO) write: 0x%04x\n", vco);
1.1.1.6 root 581: }
582:
583: /**
584: * Write Video Mode (VDM)
585: */
586: void VIDEL_VMD_WriteWord(void)
587: {
588: Uint16 vdm = IoMem_ReadWord(0xff82c2);
589:
1.1.1.8 ! root 590: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c2 Video Mode (VDM) write: 0x%04x\n", vdm);
1.1.1.6 root 591: }
592:
593:
1.1.1.8 ! root 594: /**
! 595: * VIDEL_getVideoramAddress: returns the video RAM address.
! 596: * On Falcon, video address must be a multiple of four in bitplane modes.
! 597: */
! 598: static Uint32 VIDEL_getVideoramAddress(void)
1.1 root 599: {
1.1.1.8 ! root 600: Uint32 videoBase;
! 601:
! 602: videoBase = (Uint32) IoMem_ReadByte(0xff8201) << 16;
! 603: videoBase |= (Uint32) IoMem_ReadByte(0xff8203) << 8;
! 604: videoBase |= IoMem_ReadByte(0xff820d) & ~3;
! 605:
! 606: return videoBase;
1.1 root 607: }
608:
1.1.1.8 ! root 609: static Uint16 VIDEL_getScreenBpp(void)
1.1 root 610: {
1.1.1.8 ! root 611: Uint16 f_shift = IoMem_ReadWord(0xff8266);
! 612: Uint16 bits_per_pixel;
! 613: Uint8 st_shift = IoMem_ReadByte(0xff8260);
! 614:
1.1 root 615: /* to get bpp, we must examine f_shift and st_shift.
1.1.1.8 ! root 616: * f_shift is valid if any of bits no. 10, 8 or 4 is set.
! 617: * Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1.1 root 618: * if bit 10 set then bit 8 and bit 4 don't care...
619: * If all these bits are 0 and ST shifter is written
620: * after Falcon one, get display depth from st_shift
621: * (as for ST and STE)
622: */
623: if (f_shift & 0x400) /* Falcon: 2 colors */
624: bits_per_pixel = 1;
625: else if (f_shift & 0x100) /* Falcon: hicolor */
626: bits_per_pixel = 16;
627: else if (f_shift & 0x010) /* Falcon: 8 bitplanes */
628: bits_per_pixel = 8;
1.1.1.6 root 629: else if (!videl.bUseSTShifter) /* Falcon: 4 bitplanes */
1.1 root 630: bits_per_pixel = 4;
631: else if (st_shift == 0)
632: bits_per_pixel = 4;
633: else if (st_shift == 0x01)
634: bits_per_pixel = 2;
635: else /* if (st_shift == 0x02) */
636: bits_per_pixel = 1;
637:
1.1.1.8 ! root 638: /* LOG_TRACE(TRACE_VIDEL, "Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift); */
1.1 root 639:
640: return bits_per_pixel;
641: }
642:
1.1.1.8 ! root 643: /**
! 644: * VIDEL_getScreenWidth : returns the visible X resolution
! 645: * left border + graphic area + right border
! 646: * left border : hdb - hbe-offset
! 647: * right border : hbb - hde-offset
! 648: * Graphics display : starts at cycle HDB and ends at cycle HDE.
! 649: */
1.1 root 650: static int VIDEL_getScreenWidth(void)
651: {
1.1.1.8 ! root 652: Uint16 bpp = VIDEL_getScreenBpp();
! 653:
! 654: /* X Size of the Display area */
! 655: videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp;
! 656:
! 657: /* If the user disabled the borders display from the gui, we suppress them */
! 658: if (ConfigureParams.Screen.bAllowOverscan == 0) {
! 659: videl.leftBorderSize = 0;
! 660: videl.rightBorderSize = 0;
! 661: return videl.XSize;
! 662: }
! 663:
! 664: /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
! 665: * HDB and HDE have no significance and no border is displayed.
! 666: */
! 667: if (videl.monitor_type == FALCON_MONITOR_MONO) {
! 668: videl.leftBorderSize = 0;
! 669: videl.rightBorderSize = 0;
! 670: return videl.XSize;
! 671: }
! 672:
! 673: Uint16 hbb = IoMem_ReadWord(0xff8284) & 0x01ff;
! 674: Uint16 hbe = IoMem_ReadWord(0xff8286) & 0x01ff;
! 675: Uint16 hdb = IoMem_ReadWord(0xff8288) & 0x01ff;
! 676: Uint16 hde = IoMem_ReadWord(0xff828a) & 0x01ff;
! 677: Uint16 vdm = IoMem_ReadWord(0xff82c2) & 0xc;
! 678: Uint16 hht = IoMem_ReadWord(0xff8282) & 0x1ff;
! 679:
! 680: Uint16 cycPerPixel, divider;
! 681: Sint16 hdb_offset, hde_offset;
! 682: Sint16 leftBorder, rightBorder;
! 683:
! 684: /* Compute cycles per pixel */
! 685: if (vdm == 0)
! 686: cycPerPixel = 4;
! 687: else if (vdm == 4)
! 688: cycPerPixel = 2;
! 689: else
! 690: cycPerPixel = 1;
! 691:
! 692: /* Compute the divider */
! 693: if (videl.monitor_type == FALCON_MONITOR_VGA) {
! 694: if (cycPerPixel == 4)
! 695: divider = 4;
! 696: else
! 697: divider = 2;
! 698: }
! 699: else if (videl.bUseSTShifter == true) {
! 700: divider = 16;
! 701: }
! 702: else {
! 703: divider = cycPerPixel;
! 704: }
! 705:
! 706: /* Compute hdb_offset and hde_offset */
! 707: if (videl.bUseSTShifter == false) {
! 708: if (bpp < 16) {
! 709: /* falcon mode bpp */
! 710: hdb_offset = ((64+(128/bpp + 16 + 2) * cycPerPixel) / divider ) + 1;
! 711: hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
! 712: }
! 713: else {
! 714: /* falcon mode true color */
! 715: hdb_offset = ((64 + 16 * cycPerPixel) / divider ) + 1;
! 716: hde_offset = 0;
! 717: }
! 718: }
! 719: else {
! 720: /* ST bitplan mode */
! 721: hdb_offset = ((128+(128/bpp + 2) * cycPerPixel) / divider ) + 1;
! 722: hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
! 723: }
! 724:
! 725: LOG_TRACE(TRACE_VIDEL, "hdb_offset=%04x, hde_offset=%04x\n", hdb_offset, hde_offset);
! 726:
! 727: /* Compute left border size in cycles */
! 728: if (IoMem_ReadWord(0xff8288) & 0x0200)
! 729: leftBorder = hdb - hbe + hdb_offset - hht - 2;
! 730: else
! 731: leftBorder = hdb - hbe + hdb_offset;
! 732:
! 733: /* Compute right border size in cycles */
! 734: rightBorder = hbb - hde_offset - hde;
! 735:
! 736: videl.leftBorderSize = leftBorder / cycPerPixel;
! 737: videl.rightBorderSize = rightBorder / cycPerPixel;
! 738: LOG_TRACE(TRACE_VIDEL, "left border size=%04x, right border size=%04x\n", videl.leftBorderSize, videl.rightBorderSize);
! 739:
! 740: if (videl.leftBorderSize < 0) {
! 741: // fprintf(stderr, "BORDER LEFT < 0 %d\n", videl.leftBorderSize);
! 742: videl.leftBorderSize = 0;
! 743: }
! 744: if (videl.rightBorderSize < 0) {
! 745: // fprintf(stderr, "BORDER RIGHT < 0 %d\n", videl.rightBorderSize);
! 746: videl.rightBorderSize = 0;
! 747: }
! 748:
! 749: return videl.leftBorderSize + videl.XSize + videl.rightBorderSize;
1.1 root 750: }
751:
1.1.1.8 ! root 752: /**
! 753: * VIDEL_getScreenHeight : returns the visible Y resolution
! 754: * upper border + graphic area + lower border
! 755: * upper border : vdb - vbe
! 756: * lower border : vbb - vde
! 757: * Graphics display : starts at line VDB and ends at line VDE.
! 758: * If interlace mode off unit of VC-registers is half lines, else lines.
! 759: */
1.1 root 760: static int VIDEL_getScreenHeight(void)
761: {
1.1.1.8 ! root 762: Uint16 vbb = IoMem_ReadWord(0xff82a4) & 0x07ff;
! 763: Uint16 vbe = IoMem_ReadWord(0xff82a6) & 0x07ff;
! 764: Uint16 vdb = IoMem_ReadWord(0xff82a8) & 0x07ff;
! 765: Uint16 vde = IoMem_ReadWord(0xff82aa) & 0x07ff;
! 766: Uint16 vmode = IoMem_ReadWord(0xff82c2);
! 767:
! 768: /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
! 769: * VDB and VDE have no significance and no border is displayed.
1.1 root 770: */
1.1.1.8 ! root 771: if (videl.monitor_type == FALCON_MONITOR_MONO) {
! 772: videl.upperBorderSize = 0;
! 773: videl.lowerBorderSize = 0;
! 774: }
! 775: else {
! 776: /* We must take the positive value only, as a program like AceTracker starts the */
! 777: /* graphical area 1 line before the end of the upper border */
! 778: videl.upperBorderSize = vdb - vbe > 0 ? vdb - vbe : 0;
! 779: videl.lowerBorderSize = vbb - vde > 0 ? vbb - vde : 0;
! 780: }
1.1 root 781:
1.1.1.8 ! root 782: /* Y Size of the Display area */
! 783: videl.YSize = vde - vdb;
! 784:
! 785: /* If the user disabled the borders display from the gui, we suppress them */
! 786: if (ConfigureParams.Screen.bAllowOverscan == 0) {
! 787: videl.upperBorderSize = 0;
! 788: videl.lowerBorderSize = 0;
! 789: }
! 790:
! 791: if (!(vmode & 0x02)){ /* interlace */
! 792: videl.YSize >>= 1;
! 793: videl.upperBorderSize >>= 1;
! 794: videl.lowerBorderSize >>= 1;
! 795: }
! 796:
! 797: if (vmode & 0x01) { /* double */
! 798: videl.YSize >>= 1;
! 799: videl.upperBorderSize >>= 1;
! 800: videl.lowerBorderSize >>= 1;
! 801: }
! 802:
! 803: return videl.upperBorderSize + videl.YSize + videl.lowerBorderSize;
1.1 root 804: }
805:
1.1.1.5 root 806: #if 0
807: /* this is easier & more robustly done in hostscreen.c just by
808: * comparing requested screen width & height to each other.
809: */
810: static void VIDEL_getMonitorScale(int *sx, int *sy)
811: {
812: /* Videl video mode register bits and resulting desktop resolution:
813: *
814: * quarter, half, interlace, double: pixels: -> zoom:
815: * rgb:
816: * 0 0 0 0 320x200 -> 2 x 2
817: * 0 0 1 0 320x400 -> 2 x 1
818: * 0 1 0 0 640x200 -> 1 x 2 !
819: * 0 1 1 0 640x400 -> 1 x 1
820: * vga:
821: * 0 0 0 1 (just double ?)
822: * 0 0 1 1 (double & interlace ???)
823: * 0 1 0 0 320x480 -> 2 x 1 !
824: * 0 1 0 1 320x240 -> 2 x 2
825: * 0 1 1 1 (double + interlace ???)
826: * 1 0 0 0 640x480 -> 1 x 1
827: * 1 0 0 1 640x240 -> 1 x 2
828: */
1.1.1.8 ! root 829: int vmode = IoMem_ReadWord(0xff82c2);
1.1.1.5 root 830:
831: /* half pixel seems to have opposite meaning on
832: * VGA and RGB monitor, so they need to handled separately
833: */
1.1.1.6 root 834: if (videl.monitor_type) == FALCON_MONITOR_VGA) {
1.1.1.8 ! root 835: if (vmode & 0x08) { /* quarter pixel */
1.1.1.5 root 836: *sx = 1;
837: } else {
838: *sx = 2;
839: }
1.1.1.8 ! root 840: if (vmode & 0x01) { /* double line */
1.1.1.5 root 841: *sy = 2;
842: } else {
843: *sy = 1;
844: }
845: } else {
1.1.1.8 ! root 846: if (vmode & 0x04) { /* half pixel */
1.1.1.5 root 847: *sx = 1;
848: } else {
849: *sx = 2;
850: }
1.1.1.8 ! root 851: if (vmode & 0x02) { /* interlace used only on RGB ? */
1.1.1.5 root 852: *sy = 1;
853: } else {
854: *sy = 2;
855: }
856: }
857: }
858: #endif
859:
1.1 root 860:
861: /** map the correct colortable into the correct pixel format
862: */
863: static void VIDEL_updateColors(void)
864: {
1.1.1.8 ! root 865: int i, r, g, b, colors = 1 << videl.save_scrBpp;
1.1 root 866:
1.1.1.8 ! root 867: #define F_COLORS(i) IoMem_ReadByte(VIDEL_COLOR_REGS_BEGIN + (i))
! 868: #define STE_COLORS(i) IoMem_ReadByte(0xff8240 + (i))
1.1 root 869:
1.1.1.6 root 870: if (!videl.bUseSTShifter) {
1.1 root 871: for (i = 0; i < colors; i++) {
872: int offset = i << 2;
873: r = F_COLORS(offset) & 0xfc;
874: r |= r>>6;
875: g = F_COLORS(offset + 1) & 0xfc;
876: g |= g>>6;
877: b = F_COLORS(offset + 3) & 0xfc;
878: b |= b>>6;
879: HostScreen_setPaletteColor(i, r,g,b);
880: }
881: HostScreen_updatePalette(colors);
882: } else {
883: for (i = 0; i < colors; i++) {
884: int offset = i << 1;
885: r = STE_COLORS(offset) & 0x0f;
886: r = ((r & 7)<<1)|(r>>3);
887: r |= r<<4;
888: g = (STE_COLORS(offset + 1)>>4) & 0x0f;
889: g = ((g & 7)<<1)|(g>>3);
890: g |= g<<4;
891: b = STE_COLORS(offset + 1) & 0x0f;
892: b = ((b & 7)<<1)|(b>>3);
893: b |= b<<4;
894: HostScreen_setPaletteColor(i, r,g,b);
895: }
896: HostScreen_updatePalette(colors);
897: }
898:
1.1.1.8 ! root 899: videl.hostColorsSync = true;
1.1 root 900: }
901:
902:
903: void VIDEL_ZoomModeChanged(void)
904: {
905: /* User selected another zoom mode, so set a new screen resolution now */
1.1.1.8 ! root 906: HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1 root 907: }
908:
909:
1.1.1.2 root 910: bool VIDEL_renderScreen(void)
1.1 root 911: {
1.1.1.8 ! root 912: videl.videoBaseAddr = VIDEL_getVideoramAddress(); // Todo: to be removed when all code is in Videl
! 913:
! 914: /* Atari screen infos */
1.1 root 915: int vw = VIDEL_getScreenWidth();
916: int vh = VIDEL_getScreenHeight();
917: int vbpp = VIDEL_getScreenBpp();
1.1.1.8 ! root 918:
! 919: int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
! 920: int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; /* 10 bits */
! 921:
1.1.1.6 root 922: bool change = false;
1.1 root 923:
1.1.1.8 ! root 924: if (vw > 0 && vw != videl.save_scrWidth) {
! 925: LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw);
! 926: videl.save_scrWidth = vw;
1.1.1.6 root 927: change = true;
1.1 root 928: }
1.1.1.8 ! root 929: if (vh > 0 && vh != videl.save_scrHeight) {
! 930: LOG_TRACE(TRACE_VIDEL, "Videl : height change from %d to %d\n", videl.save_scrHeight, vh);
! 931: videl.save_scrHeight = vh;
1.1.1.6 root 932: change = true;
1.1 root 933: }
1.1.1.8 ! root 934: if (vbpp != videl.save_scrBpp) {
! 935: LOG_TRACE(TRACE_VIDEL, "Videl : bpp change from %d to %d\n", videl.save_scrBpp, vbpp);
! 936: videl.save_scrBpp = vbpp;
1.1.1.6 root 937: change = true;
938: }
939: if (change) {
1.1.1.8 ! root 940: LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp);
! 941: HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1 root 942: }
943:
944: if (!HostScreen_renderBegin())
1.1.1.2 root 945: return false;
1.1 root 946:
1.1.1.8 ! root 947: /*
! 948: I think this implementation is naive:
! 949: indeed, I suspect that we should instead skip lineoffset
! 950: words each time we have read "more" than linewidth words
! 951: (possibly "more" because of the number of bit planes).
! 952: Moreover, the 1 bit plane mode is particular;
! 953: while doing some experiments on my Falcon, it seems to
! 954: behave like the 4 bit planes mode.
! 955: At last, we have also to take into account the 4 bits register
! 956: located at the word $ffff8264 (bit offset). This register makes
! 957: the semantics of the lineoffset register change a little.
! 958: int bitoffset = IoMem_ReadWord(0xff8264) & 0x000f;
! 959: The meaning of this register in True Color mode is not clear
! 960: for me at the moment (and my experiments on the Falcon don't help
! 961: me).
! 962: */
! 963: int nextline = linewidth + lineoffset;
! 964:
! 965: if ((vw<32) || (vh<32))
! 966: return false;
! 967:
! 968: if (videl.save_scrBpp < 16 && videl.hostColorsSync == 0)
! 969: VIDEL_updateColors();
! 970:
1.1.1.5 root 971: if (nScreenZoomX * nScreenZoomY != 1) {
1.1.1.8 ! root 972: VIDEL_ConvertScreenZoom(vw, vh, videl.save_scrBpp, nextline);
1.1 root 973: } else {
1.1.1.8 ! root 974: VIDEL_ConvertScreenNoZoom(vw, vh, videl.save_scrBpp, nextline);
1.1 root 975: }
976:
977:
1.1.1.8 ! root 978: HostScreen_renderEnd();
1.1.1.4 root 979: HostScreen_update1(false);
1.1.1.2 root 980:
981: return true;
1.1 root 982: }
983:
984:
1.1.1.4 root 985: /**
986: * Performs conversion from the TOS's bitplane word order (big endian) data
987: * into the native chunky color index.
988: */
1.1.1.8 ! root 989: static void VIDEL_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp,
1.1.1.4 root 990: Uint8 colorValues[16])
991: {
992: Uint32 a, b, c, d, x;
993:
994: /* Obviously the different cases can be broken out in various
995: * ways to lessen the amount of work needed for <8 bit modes.
996: * It's doubtful if the usage of those modes warrants it, though.
997: * The branches below should be ~100% correctly predicted and
998: * thus be more or less for free.
999: * Getting the palette values inline does not seem to help
1000: * enough to worry about. The palette lookup is much slower than
1001: * this code, though, so it would be nice to do something about it.
1002: */
1003: if (bpp >= 4) {
1004: d = *(Uint32 *)&atariBitplaneData[0];
1005: c = *(Uint32 *)&atariBitplaneData[2];
1006: if (bpp == 4) {
1007: a = b = 0;
1008: } else {
1009: b = *(Uint32 *)&atariBitplaneData[4];
1010: a = *(Uint32 *)&atariBitplaneData[6];
1011: }
1012: } else {
1013: a = b = c = 0;
1014: if (bpp == 2) {
1015: d = *(Uint32 *)&atariBitplaneData[0];
1016: } else {
1017: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1018: d = atariBitplaneData[0]<<16;
1019: #else
1020: d = atariBitplaneData[0];
1021: #endif
1022: }
1023: }
1024:
1025: x = a;
1026: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4);
1027: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f);
1028: x = b;
1029: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4);
1030: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f);
1031:
1032: x = a;
1033: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2);
1034: b = ((x & 0x33333333) << 2) | (b & 0x33333333);
1035: x = c;
1036: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2);
1037: d = ((x & 0x33333333) << 2) | (d & 0x33333333);
1038:
1039: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1040: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
1041: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
1042: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
1043: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
1044:
1045: colorValues[ 8] = a;
1046: a >>= 8;
1047: colorValues[ 0] = a;
1048: a >>= 8;
1049: colorValues[ 9] = a;
1050: a >>= 8;
1051: colorValues[ 1] = a;
1052:
1053: colorValues[10] = b;
1054: b >>= 8;
1055: colorValues[ 2] = b;
1056: b >>= 8;
1057: colorValues[11] = b;
1058: b >>= 8;
1059: colorValues[ 3] = b;
1060:
1061: colorValues[12] = c;
1062: c >>= 8;
1063: colorValues[ 4] = c;
1064: c >>= 8;
1065: colorValues[13] = c;
1066: c >>= 8;
1067: colorValues[ 5] = c;
1068:
1069: colorValues[14] = d;
1070: d >>= 8;
1071: colorValues[ 6] = d;
1072: d >>= 8;
1073: colorValues[15] = d;
1074: d >>= 8;
1075: colorValues[ 7] = d;
1076: #else
1077: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
1078: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
1079: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
1080: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
1081:
1082: colorValues[ 1] = a;
1083: a >>= 8;
1084: colorValues[ 9] = a;
1085: a >>= 8;
1086: colorValues[ 0] = a;
1087: a >>= 8;
1088: colorValues[ 8] = a;
1089:
1090: colorValues[ 3] = b;
1091: b >>= 8;
1092: colorValues[11] = b;
1093: b >>= 8;
1094: colorValues[ 2] = b;
1095: b >>= 8;
1096: colorValues[10] = b;
1097:
1098: colorValues[ 5] = c;
1099: c >>= 8;
1100: colorValues[13] = c;
1101: c >>= 8;
1102: colorValues[ 4] = c;
1103: c >>= 8;
1104: colorValues[12] = c;
1105:
1106: colorValues[ 7] = d;
1107: d >>= 8;
1108: colorValues[15] = d;
1109: d >>= 8;
1110: colorValues[ 6] = d;
1111: d >>= 8;
1112: colorValues[14] = d;
1113: #endif
1114: }
1115:
1.1 root 1116: void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline)
1117: {
1118: int scrpitch = HostScreen_getPitch();
1.1.1.8 ! root 1119: int h, w, j;
1.1 root 1120:
1.1.1.8 ! root 1121: Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr);
1.1.1.2 root 1122: Uint8 *hvram = HostScreen_getVideoramAddress();
1.1.1.6 root 1123: SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1 root 1124:
1.1.1.8 ! root 1125: Uint16 lowBorderSize, rightBorderSize;
! 1126:
! 1127: int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
! 1128:
! 1129: /* Horizontal scroll register set? */
! 1130: if (hscrolloffset) {
! 1131: /* Yes, so we need to adjust offset to next line: */
! 1132: nextline += vbpp;
! 1133: }
! 1134:
! 1135: /* If emulated computer is the TT, we use the same rendering for display, but without the borders */
! 1136: if (ConfigureParams.System.nMachineType == MACHINE_TT) {
! 1137: videl.leftBorderSize = 0;
! 1138: videl.rightBorderSize = 0;
! 1139: videl.upperBorderSize = 0;
! 1140: videl.lowerBorderSize = 0;
! 1141: fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
! 1142: }
1.1 root 1143:
1144: /* Clip to SDL_Surface dimensions */
1145: int scrwidth = HostScreen_getWidth();
1146: int scrheight = HostScreen_getHeight();
1147: int vw_clip = vw;
1148: int vh_clip = vh;
1149: if (vw>scrwidth) vw_clip = scrwidth;
1150: if (vh>scrheight) vh_clip = scrheight;
1151:
1.1.1.8 ! root 1152: /* If emulated computer is the FALCON, we must take :
! 1153: * vw = X area display size and not all the X screen with the borders into account
! 1154: * vh = Y area display size and not all the Y screen with the borders into account
! 1155: */
! 1156: if (ConfigureParams.System.nMachineType == MACHINE_FALCON) {
! 1157: vw = videl.XSize;
! 1158: vh = videl.YSize;
1.1 root 1159: }
1160:
1.1.1.8 ! root 1161: /* If there's not enough space to display the left border, just return */
! 1162: if (vw_clip < videl.leftBorderSize)
! 1163: return;
! 1164: /* If there's not enough space for the left border + the graphic area, we clip */
! 1165: if (vw_clip < vw + videl.leftBorderSize) {
! 1166: vw = vw_clip - videl.leftBorderSize;
! 1167: rightBorderSize = 0;
! 1168: }
! 1169: /* if there's not enough space for the left border + the graphic area + the right border, we clip the border */
! 1170: else if (vw_clip < vw + videl.leftBorderSize + videl.rightBorderSize)
! 1171: rightBorderSize = vw_clip - videl.leftBorderSize - vw;
! 1172: else
! 1173: rightBorderSize = videl.rightBorderSize;
! 1174:
! 1175: /* If there's not enough space to display the upper border, just return */
! 1176: if (vh_clip < videl.upperBorderSize)
! 1177: return;
! 1178:
! 1179: /* If there's not enough space for the upper border + the graphic area, we clip */
! 1180: if (vh_clip < vh + videl.upperBorderSize) {
! 1181: vh = vh_clip - videl.upperBorderSize;
! 1182: lowBorderSize = 0;
! 1183: }
! 1184: /* if there's not enough space for the upper border + the graphic area + the lower border, we clip the border */
! 1185: else if (vh_clip < vh + videl.upperBorderSize + videl.lowerBorderSize)
! 1186: lowBorderSize = vh_clip - videl.upperBorderSize - vh;
! 1187: else
! 1188: lowBorderSize = videl.lowerBorderSize;
! 1189:
1.1 root 1190: /* Center screen */
1191: hvram += ((scrheight-vh_clip)>>1)*scrpitch;
1192: hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp();
1193:
1.1.1.8 ! root 1194: Uint16 *fvram_line = fvram;
! 1195: scrwidth = videl.leftBorderSize + vw + videl.rightBorderSize;
! 1196:
! 1197: /* render the graphic area */
1.1 root 1198: if (vbpp < 16) {
1199: /* Bitplanes modes */
1200:
1.1.1.8 ! root 1201: /* The SDL colors blitting... */
1.1.1.2 root 1202: Uint8 color[16];
1.1 root 1203:
1.1.1.8 ! root 1204: /* FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels */
1.1 root 1205: switch ( HostScreen_getBpp() ) {
1206: case 1:
1.1.1.8 ! root 1207: {
! 1208: Uint8 *hvram_line = hvram;
1.1 root 1209:
1.1.1.8 ! root 1210: /* Render the upper border */
! 1211: for (h = 0; h < videl.upperBorderSize; h++) {
! 1212: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1213: hvram_line += scrpitch;
! 1214: }
1.1 root 1215:
1.1.1.8 ! root 1216: /* Render the graphical area */
! 1217: for (h = 0; h < vh; h++) {
! 1218: Uint16 *fvram_column = fvram_line;
! 1219: Uint8 *hvram_column = hvram_line;
! 1220:
! 1221: /* Left border first */
! 1222: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1223: hvram_column += videl.leftBorderSize;
! 1224:
! 1225: /* First 16 pixels */
! 1226: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1227: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
! 1228: hvram_column += 16-hscrolloffset;
! 1229: fvram_column += vbpp;
! 1230: /* Now the main part of the line */
! 1231: for (w = 1; w < (vw+15)>>4; w++) {
! 1232: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1233: memcpy(hvram_column, color, 16);
! 1234: hvram_column += 16;
1.1 root 1235: fvram_column += vbpp;
1236: }
1.1.1.8 ! root 1237: /* Last pixels of the line for fine scrolling */
! 1238: if (hscrolloffset) {
! 1239: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1240: memcpy(hvram_column, color, hscrolloffset);
! 1241: }
! 1242: /* Right border */
! 1243: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
! 1244:
! 1245: fvram_line += nextline;
! 1246: hvram_line += scrpitch;
1.1 root 1247: }
1.1.1.8 ! root 1248:
! 1249: /* Render the lower border */
! 1250: for (h = 0; h < lowBorderSize; h++) {
! 1251: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1252: hvram_line += scrpitch;
! 1253: }
! 1254: }
! 1255: break;
1.1 root 1256: case 2:
1.1.1.8 ! root 1257: {
! 1258: Uint16 *hvram_line = (Uint16 *)hvram;
1.1 root 1259:
1.1.1.8 ! root 1260: /* Render the upper border */
! 1261: for (h = 0; h < videl.upperBorderSize; h++) {
! 1262: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1263: hvram_line += scrpitch>>1;
! 1264: }
1.1 root 1265:
1.1.1.8 ! root 1266: /* Render the graphical area */
! 1267: for (h = 0; h < vh; h++) {
! 1268: Uint16 *fvram_column = fvram_line;
! 1269: Uint16 *hvram_column = hvram_line;
! 1270:
! 1271: /* Left border first */
! 1272: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1273: hvram_column += videl.leftBorderSize;
! 1274:
! 1275: /* First 16 pixels */
! 1276: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1277: for (j = 0; j < 16 - hscrolloffset; j++) {
! 1278: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
! 1279: }
! 1280: fvram_column += vbpp;
! 1281: /* Now the main part of the line */
! 1282: for (w = 1; w < (vw+15)>>4; w++) {
! 1283: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1284: for (j=0; j<16; j++) {
! 1285: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4 root 1286: }
1287: fvram_column += vbpp;
1.1.1.8 ! root 1288: }
! 1289: /* Last pixels of the line for fine scrolling */
! 1290: if (hscrolloffset) {
! 1291: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1292: for (j = 0; j < hscrolloffset; j++) {
! 1293: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1 root 1294: }
1295: }
1.1.1.8 ! root 1296: /* Right border */
! 1297: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
! 1298:
! 1299: fvram_line += nextline;
! 1300: hvram_line += scrpitch>>1;
1.1 root 1301: }
1.1.1.8 ! root 1302:
! 1303: /* Render the lower border */
! 1304: for (h = 0; h < lowBorderSize; h++) {
! 1305: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1306: hvram_line += scrpitch>>1;
! 1307: }
! 1308: }
! 1309: break;
1.1 root 1310: case 4:
1.1.1.8 ! root 1311: {
! 1312: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 1313:
1.1.1.8 ! root 1314: /* Render the upper border */
! 1315: for (h = 0; h < videl.upperBorderSize; h++) {
! 1316: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1317: hvram_line += scrpitch>>2;
! 1318: }
1.1 root 1319:
1.1.1.8 ! root 1320: /* Render the graphical area */
! 1321: for (h = 0; h < vh; h++) {
! 1322: Uint16 *fvram_column = fvram_line;
! 1323: Uint32 *hvram_column = hvram_line;
! 1324:
! 1325: /* Left border first */
! 1326: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1327: hvram_column += videl.leftBorderSize;
! 1328:
! 1329: /* First 16 pixels */
! 1330: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1331: for (j = 0; j < 16 - hscrolloffset; j++) {
! 1332: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
! 1333: }
! 1334: fvram_column += vbpp;
! 1335: /* Now the main part of the line */
! 1336: for (w = 1; w < (vw+15)>>4; w++) {
! 1337: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1338: for (j=0; j<16; j++) {
! 1339: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4 root 1340: }
1341: fvram_column += vbpp;
1.1.1.8 ! root 1342: }
! 1343: /* Last pixels of the line for fine scrolling */
! 1344: if (hscrolloffset) {
! 1345: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1346: for (j = 0; j < hscrolloffset; j++) {
! 1347: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1.1.4 root 1348: }
1.1 root 1349: }
1.1.1.8 ! root 1350: /* Right border */
! 1351: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
! 1352:
! 1353: fvram_line += nextline;
! 1354: hvram_line += scrpitch>>2;
1.1 root 1355: }
1.1.1.8 ! root 1356:
! 1357: /* Render the lower border */
! 1358: for (h = 0; h < lowBorderSize; h++) {
! 1359: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1360: hvram_line += scrpitch>>2;
! 1361: }
! 1362: }
! 1363: break;
1.1 root 1364: }
1365:
1366: } else {
1367:
1.1.1.8 ! root 1368: /* Falcon TC (High Color) */
1.1 root 1369: switch ( HostScreen_getBpp() ) {
1370: case 1:
1.1.1.8 ! root 1371: {
! 1372: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
! 1373: Uint8 *hvram_line = hvram;
! 1374:
! 1375: /* Render the upper border */
! 1376: for (h = 0; h < videl.upperBorderSize; h++) {
! 1377: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1378: hvram_line += scrpitch;
! 1379: }
1.1 root 1380:
1.1.1.8 ! root 1381: /* Render the graphical area */
! 1382: for (h = 0; h < vh; h++) {
! 1383: Uint16 *fvram_column = fvram_line;
! 1384: Uint8 *hvram_column = hvram_line;
! 1385: int tmp;
! 1386:
! 1387: /* Left border first */
! 1388: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1389: hvram_column += videl.leftBorderSize;
! 1390:
! 1391: /* Graphical area */
! 1392: for (w = 0; w < vw; w++) {
! 1393: tmp = SDL_SwapBE16(*fvram_column++);
! 1394: *hvram_column++ = (((tmp>>13) & 7) << 5) + (((tmp>>8) & 7) << 2) + (((tmp>>2) & 3));
! 1395: }
1.1 root 1396:
1.1.1.8 ! root 1397: /* Right border */
! 1398: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
1.1 root 1399:
1.1.1.8 ! root 1400: fvram_line += nextline;
! 1401: hvram_line += scrpitch;
1.1 root 1402: }
1.1.1.8 ! root 1403: /* Render the bottom border */
! 1404: for (h = 0; h < lowBorderSize; h++) {
! 1405: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1406: hvram_line += scrpitch;
! 1407: }
! 1408: }
! 1409: break;
1.1 root 1410: case 2:
1.1.1.8 ! root 1411: {
! 1412: Uint16 *hvram_line = (Uint16 *)hvram;
! 1413:
! 1414: /* Render the upper border */
! 1415: for (h = 0; h < videl.upperBorderSize; h++) {
! 1416: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1417: hvram_line += scrpitch>>1;
! 1418: }
! 1419:
! 1420: /* Render the graphical area */
! 1421: for (h = 0; h < vh; h++) {
! 1422: Uint16 *hvram_column = hvram_line;
! 1423:
! 1424: /* Left border first */
! 1425: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1426: hvram_column += videl.leftBorderSize;
1.1 root 1427:
1428: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.8 ! root 1429: /* FIXME: here might be a runtime little/big video endian switch like:
! 1430: if ( " videocard memory in Motorola endian format " false)
! 1431: */
! 1432: memcpy(hvram_column, fvram_line, vw<<1);
! 1433: hvram_column += vw<<1;
1.1 root 1434: #else
1.1.1.8 ! root 1435: Uint16 *fvram_column = fvram_line;
! 1436: /* Graphical area */
! 1437: for (w = 0; w < vw; w++)
! 1438: *hvram_column ++ = SDL_SwapBE16(*fvram_column++);
! 1439: #endif /* SDL_BYTEORDER == SDL_BIG_ENDIAN */
1.1 root 1440:
1.1.1.8 ! root 1441: /* Right border */
! 1442: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
1.1 root 1443:
1.1.1.8 ! root 1444: fvram_line += nextline;
! 1445: hvram_line += scrpitch>>1;
1.1 root 1446: }
1447:
1.1.1.8 ! root 1448: /* Render the bottom border */
! 1449: for (h = 0; h < lowBorderSize; h++) {
! 1450: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1451: hvram_line += scrpitch>>1;
1.1 root 1452: }
1.1.1.8 ! root 1453: }
! 1454: break;
! 1455: case 4:
! 1456: {
! 1457: Uint32 *hvram_line = (Uint32 *)hvram;
1.1 root 1458:
1.1.1.8 ! root 1459: /* Render the upper border */
! 1460: for (h = 0; h < videl.upperBorderSize; h++) {
! 1461: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1462: hvram_line += scrpitch>>2;
! 1463: }
1.1 root 1464:
1.1.1.8 ! root 1465: /* Render the graphical area */
! 1466: for (h = 0; h < vh; h++) {
! 1467: Uint16 *fvram_column = fvram_line;
! 1468: Uint32 *hvram_column = hvram_line;
! 1469:
! 1470: /* Left border first */
! 1471: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
! 1472: hvram_column += videl.leftBorderSize;
! 1473:
! 1474: /* Graphical area */
! 1475: for (w = 0; w < vw; w++) {
! 1476: Uint16 srcword = *fvram_column++;
! 1477: *hvram_column ++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8));
! 1478: }
1.1 root 1479:
1.1.1.8 ! root 1480: /* Right border */
! 1481: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
! 1482: }
1.1 root 1483:
1.1.1.8 ! root 1484: fvram_line += nextline;
! 1485: hvram_line += scrpitch>>2;
1.1 root 1486:
1.1.1.8 ! root 1487: /* Render the bottom border */
! 1488: for (h = 0; h < lowBorderSize; h++) {
! 1489: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1490: hvram_line += scrpitch>>2;
! 1491: }
! 1492: }
! 1493: break;
! 1494: }
1.1 root 1495: }
1496: }
1497:
1498:
1499: void VIDEL_ConvertScreenZoom(int vw, int vh, int vbpp, int nextline)
1500: {
1501: int i, j, w, h, cursrcline;
1502:
1.1.1.8 ! root 1503: Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr);
! 1504: Uint16 *fvram_line;
! 1505: Uint16 scrIdx = 0;
! 1506:
! 1507: int coefx = 1;
! 1508: int coefy = 1;
! 1509:
! 1510: /* If emulated computer is the TT, we use the same rendering for display, but without the borders */
! 1511: if (ConfigureParams.System.nMachineType == MACHINE_TT) {
! 1512: videl.leftBorderSize = 0;
! 1513: videl.rightBorderSize = 0;
! 1514: videl.upperBorderSize = 0;
! 1515: videl.lowerBorderSize = 0;
! 1516: videl.XSize = vw;
! 1517: videl.YSize = vh;
! 1518: fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
! 1519: }
1.1 root 1520:
1521: /* Host screen infos */
1522: int scrpitch = HostScreen_getPitch();
1523: int scrwidth = HostScreen_getWidth();
1524: int scrheight = HostScreen_getHeight();
1525: int scrbpp = HostScreen_getBpp();
1.1.1.6 root 1526: SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1.1.2 root 1527: Uint8 *hvram = (Uint8 *) HostScreen_getVideoramAddress();
1.1 root 1528:
1.1.1.8 ! root 1529: int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1.1 root 1530:
1531: /* Horizontal scroll register set? */
1532: if (hscrolloffset) {
1533: /* Yes, so we need to adjust offset to next line: */
1534: nextline += vbpp;
1535: }
1536:
1537: /* Integer zoom coef ? */
1538: if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) {
1.1.1.8 ! root 1539: coefx = scrwidth/vw;
! 1540: coefy = scrheight/vh;
1.1 root 1541:
1542: scrwidth = vw * coefx;
1543: scrheight = vh * coefy;
1544:
1545: /* Center screen */
1546: hvram += ((HostScreen_getHeight()-scrheight)>>1)*scrpitch;
1547: hvram += ((HostScreen_getWidth()-scrwidth)>>1)*scrbpp;
1548: }
1549:
1550: /* New zoom ? */
1.1.1.8 ! root 1551: if ((videl_zoom.zoomwidth != vw) || (scrwidth != videl_zoom.prev_scrwidth)) {
! 1552: if (videl_zoom.zoomxtable) {
! 1553: free(videl_zoom.zoomxtable);
1.1 root 1554: }
1.1.1.8 ! root 1555: videl_zoom.zoomxtable = malloc(sizeof(int)*scrwidth);
1.1 root 1556: for (i=0; i<scrwidth; i++) {
1.1.1.8 ! root 1557: videl_zoom.zoomxtable[i] = (vw*i)/scrwidth;
1.1 root 1558: }
1.1.1.8 ! root 1559: videl_zoom.zoomwidth = vw;
! 1560: videl_zoom.prev_scrwidth = scrwidth;
1.1 root 1561: }
1.1.1.8 ! root 1562: if ((videl_zoom.zoomheight != vh) || (scrheight != videl_zoom.prev_scrheight)) {
! 1563: if (videl_zoom.zoomytable) {
! 1564: free(videl_zoom.zoomytable);
1.1 root 1565: }
1.1.1.8 ! root 1566: videl_zoom.zoomytable = malloc(sizeof(int)*scrheight);
1.1 root 1567: for (i=0; i<scrheight; i++) {
1.1.1.8 ! root 1568: videl_zoom.zoomytable[i] = (vh*i)/scrheight;
1.1 root 1569: }
1.1.1.8 ! root 1570: videl_zoom.zoomheight = vh;
! 1571: videl_zoom.prev_scrheight = scrheight;
1.1 root 1572: }
1573:
1574: cursrcline = -1;
1575:
1.1.1.8 ! root 1576: /* We reuse the following values to compute the display area size in zoom mode */
! 1577: /* scrwidth must not change */
! 1578: if (ConfigureParams.System.nMachineType == MACHINE_FALCON) {
! 1579: vw = videl.XSize;
! 1580: vh = videl.YSize;
! 1581: scrheight = vh * coefy;
! 1582: }
! 1583:
1.1 root 1584: if (vbpp<16) {
1.1.1.2 root 1585: Uint8 color[16];
1.1 root 1586:
1587: /* Bitplanes modes */
1588: switch(scrbpp) {
1589: case 1:
1.1.1.8 ! root 1590: {
! 1591: /* One complete 16-pixel aligned planar 2 chunky line */
! 1592: Uint8 *p2cline = malloc(sizeof(Uint8) * ((vw+15) & ~15));
! 1593: Uint8 *hvram_line = hvram;
! 1594: Uint8 *hvram_column = p2cline;
! 1595:
! 1596: /* Render the upper border */
! 1597: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1598: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1599: hvram_line += scrpitch;
! 1600: }
1.1 root 1601:
1.1.1.8 ! root 1602: /* Render the graphical area */
! 1603: for (h = 0; h < scrheight; h++) {
! 1604:
! 1605: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1606: scrIdx ++;
! 1607:
! 1608: /* Recopy the same line ? */
! 1609: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1610: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
! 1611: } else {
! 1612: Uint16 *fvram_column = fvram_line;
! 1613: hvram_column = p2cline;
! 1614:
! 1615: /* First 16 pixels of a new line */
! 1616: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1617: memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
! 1618: hvram_column += 16-hscrolloffset;
! 1619: fvram_column += vbpp;
! 1620: /* Convert main part of the new line */
! 1621: for (w=1; w < (vw+15)>>4; w++) {
! 1622: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1623: memcpy(hvram_column, color, 16);
! 1624: hvram_column += 16;
! 1625: fvram_column += vbpp;
! 1626: }
! 1627: /* Last pixels of the line for fine scrolling */
! 1628: if (hscrolloffset) {
! 1629: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1630: memcpy(hvram_column, color, hscrolloffset);
1.1 root 1631: }
1632:
1.1.1.8 ! root 1633: hvram_column = hvram_line;
! 1634:
! 1635: /* Display the Left border */
! 1636: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1637: hvram_column += videl.leftBorderSize * coefx;
! 1638:
! 1639: /* Display the Graphical area */
! 1640: for (w=0; w<(vw*coefx); w++)
! 1641: hvram_column[w] = p2cline[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]];
! 1642: hvram_column += vw * coefx;
! 1643:
! 1644: /* Display the Right border */
! 1645: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1646: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1647: }
1648:
1.1.1.8 ! root 1649: hvram_line += scrpitch;
! 1650: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1651: }
1.1.1.8 ! root 1652:
! 1653: /* Render the lower border */
! 1654: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1655: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1656: hvram_line += scrpitch;
! 1657: }
! 1658:
! 1659: free(p2cline);
! 1660: }
! 1661: break;
1.1 root 1662: case 2:
1.1.1.8 ! root 1663: {
! 1664: /* One complete 16-pixel aligned planar 2 chunky line */
! 1665: Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15));
! 1666: Uint16 *hvram_line = (Uint16 *)hvram;
! 1667: Uint16 *hvram_column = p2cline;
! 1668:
! 1669: /* Render the upper border */
! 1670: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1671: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1672: hvram_line += scrpitch>>1;
! 1673: }
! 1674:
! 1675: /* Render the graphical area */
! 1676: for (h = 0; h < scrheight; h++) {
! 1677: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1678: scrIdx ++;
! 1679:
! 1680: /* Recopy the same line ? */
! 1681: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1682: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
! 1683: } else {
! 1684: Uint16 *fvram_column = fvram_line;
! 1685: hvram_column = p2cline;
! 1686:
! 1687: /* First 16 pixels of a new line */
! 1688: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1689: for (j = 0; j < 16 - hscrolloffset; j++) {
! 1690: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
! 1691: }
! 1692: fvram_column += vbpp;
! 1693: /* Convert the main part of the new line */
! 1694: for (w = 1; w < (vw+15)>>4; w++) {
! 1695: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1696: for (j=0; j<16; j++) {
! 1697: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4 root 1698: }
1699: fvram_column += vbpp;
1.1.1.8 ! root 1700: }
! 1701: /* Last pixels of the new line for fine scrolling */
! 1702: if (hscrolloffset) {
! 1703: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1704: for (j = 0; j < hscrolloffset; j++) {
! 1705: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1 root 1706: }
1707: }
1708:
1.1.1.8 ! root 1709: hvram_column = hvram_line;
! 1710:
! 1711: /* Display the Left border */
! 1712: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1713: hvram_column += videl.leftBorderSize * coefx;
! 1714:
! 1715: /* Display the Graphical area */
! 1716: for (w=0; w<(vw*coefx); w++)
! 1717: hvram_column[w] = p2cline[videl_zoom.zoomxtable[w]];
! 1718: hvram_column += vw * coefx;
! 1719:
! 1720: /* Display the Right border */
! 1721: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1722: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1723: }
1724:
1.1.1.8 ! root 1725: hvram_line += scrpitch>>1;
! 1726: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1727: }
1.1.1.8 ! root 1728:
! 1729: /* Render the lower border */
! 1730: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1731: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1732: hvram_line += scrpitch>>1;
! 1733: }
! 1734:
! 1735: free(p2cline);
! 1736: }
! 1737: break;
1.1 root 1738: case 4:
1.1.1.8 ! root 1739: {
! 1740: /* One complete 16-pixel aligned planar 2 chunky line */
! 1741: Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15));
! 1742: Uint32 *hvram_line = (Uint32 *)hvram;
! 1743: Uint32 *hvram_column = p2cline;
! 1744:
! 1745: /* Render the upper border */
! 1746: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1747: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1748: hvram_line += scrpitch>>2;
! 1749: }
! 1750:
! 1751: /* Render the graphical area */
! 1752: for (h = 0; h < scrheight; h++) {
! 1753: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1754: scrIdx ++;
! 1755: /* Recopy the same line ? */
! 1756: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1757: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
! 1758: } else {
! 1759: Uint16 *fvram_column = fvram_line;
! 1760: hvram_column = p2cline;
! 1761:
! 1762: /* First 16 pixels of a new line */
! 1763: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1764: for (j = 0; j < 16 - hscrolloffset; j++) {
! 1765: *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
! 1766: }
! 1767: fvram_column += vbpp;
! 1768: /* Convert the main part of the new line */
! 1769: for (w = 1; w < (vw+15)>>4; w++) {
! 1770: VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
! 1771: for (j=0; j<16; j++) {
! 1772: *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4 root 1773: }
1774: fvram_column += vbpp;
1.1.1.8 ! root 1775: }
! 1776: /* Last pixels of the new line for fine scrolling */
! 1777: if (hscrolloffset) {
! 1778: VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
! 1779: for (j = 0; j < hscrolloffset; j++) {
! 1780: *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1.1.4 root 1781: }
1.1.1.8 ! root 1782: }
1.1.1.4 root 1783:
1.1.1.8 ! root 1784: hvram_column = hvram_line;
! 1785: /* Display the Left border */
! 1786: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1787: hvram_column += videl.leftBorderSize * coefx;
! 1788:
! 1789: /* Display the Graphical area */
! 1790: for (w=0; w<(vw*coefx); w++) {
! 1791: hvram_column[w] = p2cline[videl_zoom.zoomxtable[w]];
1.1 root 1792: }
1.1.1.8 ! root 1793: hvram_column += vw * coefx;
1.1 root 1794:
1.1.1.8 ! root 1795: /* Display the Right border */
! 1796: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1797: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1798: }
1799:
1.1.1.8 ! root 1800: hvram_line += scrpitch>>2;
! 1801: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1802: }
1.1.1.8 ! root 1803:
! 1804: /* Render the lower border */
! 1805: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1806: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1807: hvram_line += scrpitch>>2;
! 1808: }
! 1809:
! 1810: free(p2cline);
! 1811: }
! 1812: break;
1.1 root 1813: }
1814: } else {
1.1.1.4 root 1815: /* Falcon high-color (16-bit) mode */
1.1 root 1816:
1817: switch(scrbpp) {
1818: case 1:
1.1.1.8 ! root 1819: {
! 1820: /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
! 1821: Uint8 *hvram_line = hvram;
! 1822: Uint8 *hvram_column = hvram_line;
! 1823:
! 1824: /* Render the upper border */
! 1825: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1826: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1827: hvram_line += scrpitch;
! 1828: }
1.1 root 1829:
1.1.1.8 ! root 1830: /* Render the graphical area */
! 1831: for (h = 0; h < scrheight; h++) {
! 1832: Uint16 *fvram_column;
! 1833:
! 1834: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1835: scrIdx ++;
! 1836:
! 1837: fvram_column = fvram_line;
! 1838:
! 1839: /* Recopy the same line ? */
! 1840: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1841: memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
! 1842: } else {
1.1 root 1843:
1.1.1.8 ! root 1844: hvram_column = hvram_line;
! 1845: /* Display the Left border */
! 1846: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1847: hvram_column += videl.leftBorderSize * coefx;
! 1848:
! 1849: /* Display the Graphical area */
! 1850: for (w = 0; w<(vw*coefx); w++) {
! 1851: Uint16 srcword;
! 1852: Uint8 dstbyte;
1.1 root 1853:
1.1.1.8 ! root 1854: srcword = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]]);
1.1 root 1855:
1.1.1.8 ! root 1856: dstbyte = ((srcword>>13) & 7) << 5;
! 1857: dstbyte |= ((srcword>>8) & 7) << 2;
! 1858: dstbyte |= ((srcword>>2) & 3);
! 1859: *hvram_column++ = dstbyte;
1.1 root 1860: }
1861:
1.1.1.8 ! root 1862: /* Display the Right border */
! 1863: VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1864: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1865: }
1.1.1.8 ! root 1866:
! 1867: hvram_line += scrpitch;
! 1868: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1869: }
1.1.1.8 ! root 1870:
! 1871: /* Render the lower border */
! 1872: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1873: VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1874: hvram_line += scrpitch;
! 1875: }
! 1876: }
! 1877: break;
1.1 root 1878: case 2:
1.1.1.8 ! root 1879: {
! 1880: Uint16 *hvram_line = (Uint16 *)hvram;
! 1881: Uint16 *hvram_column = hvram_line;
! 1882:
! 1883: /* Render the upper border */
! 1884: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1885: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1886: hvram_line += scrpitch>>1;
! 1887: }
! 1888:
! 1889: /* Render the graphical area */
! 1890: for (h = 0; h < scrheight; h++) {
! 1891: Uint16 *fvram_column;
! 1892:
! 1893: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1894: scrIdx ++;
! 1895:
! 1896: fvram_column = fvram_line;
! 1897:
! 1898: /* Recopy the same line ? */
! 1899: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1900: memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
! 1901: } else {
1.1 root 1902:
1903: hvram_column = hvram_line;
1904:
1.1.1.8 ! root 1905: /* Display the Left border */
! 1906: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1907: hvram_column += videl.leftBorderSize * coefx;
! 1908:
! 1909: /* Display the Graphical area */
! 1910: for (w=0; w<(vw*coefx); w++)
! 1911: *hvram_column++ = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w]]);
! 1912:
1.1 root 1913:
1.1.1.8 ! root 1914: /* Display the Right border */
! 1915: VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1916: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1917: }
1.1.1.8 ! root 1918:
! 1919: hvram_line += scrpitch>>1;
! 1920: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1921: }
1.1.1.8 ! root 1922:
! 1923: /* Render the lower border */
! 1924: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1925: VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1926: hvram_line += scrpitch>>1;
! 1927: }
! 1928: }
! 1929: break;
1.1 root 1930: case 4:
1.1.1.8 ! root 1931: {
! 1932: Uint32 *hvram_line = (Uint32 *)hvram;
! 1933: Uint32 *hvram_column = hvram_line;
! 1934:
! 1935: /* Render the upper border */
! 1936: for (h = 0; h < videl.upperBorderSize * coefy; h++) {
! 1937: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1938: }
! 1939:
! 1940: /* Render the graphical area */
! 1941: for (h = 0; h < scrheight; h++) {
! 1942: Uint16 *fvram_column;
! 1943:
! 1944: fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
! 1945: scrIdx ++;
! 1946: fvram_column = fvram_line;
! 1947:
! 1948: /* Recopy the same line ? */
! 1949: if (videl_zoom.zoomytable[h] == cursrcline) {
! 1950: memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
! 1951: hvram_line += scrpitch>>2;
! 1952: } else {
1.1 root 1953:
1954: hvram_column = hvram_line;
1955:
1.1.1.8 ! root 1956: /* Display the Left border */
! 1957: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
! 1958: hvram_column += videl.leftBorderSize * coefx;
! 1959:
! 1960: /* Display the Graphical area */
! 1961: for (w = 0; w<(vw*coefx); w++) {
! 1962: Uint16 srcword;
1.1 root 1963:
1.1.1.8 ! root 1964: srcword = fvram_column[videl_zoom.zoomxtable[w]];
! 1965: *hvram_column++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8));
1.1 root 1966: }
1967:
1.1.1.8 ! root 1968: /* Display the Right border */
! 1969: VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
! 1970: hvram_column += videl.rightBorderSize * coefx;
1.1 root 1971: }
1.1.1.8 ! root 1972:
! 1973: hvram_line += scrpitch>>2;
! 1974: cursrcline = videl_zoom.zoomytable[h];
1.1 root 1975: }
1.1.1.8 ! root 1976:
! 1977: /* Render the lower border */
! 1978: for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
! 1979: VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
! 1980: hvram_line += scrpitch>>2;
! 1981: }
! 1982: }
! 1983: break;
1.1 root 1984: }
1985: }
1986: }
1.1.1.8 ! root 1987:
! 1988: static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count)
! 1989: {
! 1990: while (count-- > 0) {
! 1991: *addr++ = color;
! 1992: }
! 1993: }
! 1994:
! 1995: static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count)
! 1996: {
! 1997: while (count-- > 0) {
! 1998: *addr++ = color;
! 1999: }
! 2000: }
! 2001:
! 2002: static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count)
! 2003: {
! 2004: memset(addr, color, count);
! 2005: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.