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