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