|
|
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
1.1.1.12 root 16:
1.1.1.6 root 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
1.1.1.12 root 30:
1.1.1.6 root 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
1.1.1.12 root 39:
1.1.1.6 root 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
1.1.1.12 root 49:
1.1.1.6 root 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
1.1.1.12 root 57:
1.1.1.6 root 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:
68: #include "main.h"
69: #include "configuration.h"
1.1.1.6 root 70: #include "memorySnapShot.h"
1.1 root 71: #include "ioMem.h"
1.1.1.6 root 72: #include "log.h"
1.1 root 73: #include "screen.h"
1.1.1.12 root 74: #include "screenConvert.h"
1.1.1.13 root 75: #include "avi_record.h"
1.1.1.12 root 76: #include "statusbar.h"
1.1 root 77: #include "stMemory.h"
1.1.1.14! root 78: #include "tos.h"
1.1 root 79: #include "videl.h"
1.1.1.13 root 80: #include "video.h" /* for bUseHighRes variable */
81: #include "vdi.h" /* for bUseVDIRes variable */
1.1 root 82:
83: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
84:
1.1.1.8 root 85:
1.1.1.6 root 86: struct videl_s {
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.13 root 89:
90: Uint16 vertFreqCounter; /* Counter for VFC register $ff82a0, restarted on each VBL */
91: Uint32 videoRaster; /* Video raster offset, restarted on each VBL */
1.1.1.6 root 92:
1.1.1.8 root 93: Sint16 leftBorderSize; /* Size of the left border */
94: Sint16 rightBorderSize; /* Size of the right border */
95: Sint16 upperBorderSize; /* Size of the upper border */
96: Sint16 lowerBorderSize; /* Size of the lower border */
97: Uint16 XSize; /* X size of the graphical area */
98: Uint16 YSize; /* Y size of the graphical area */
99:
100: Uint16 save_scrWidth; /* save screen width to detect a change of X resolution */
101: Uint16 save_scrHeight; /* save screen height to detect a change of Y resolution */
102: Uint16 save_scrBpp; /* save screen Bpp to detect a change of bitplan mode */
1.1 root 103:
1.1.1.8 root 104: bool hostColorsSync; /* Sync palette with host's */
1.1.1.13 root 105: bool bUseSTShifter; /* whether to use ST or Falcon palette */
1.1.1.8 root 106: };
1.1.1.6 root 107:
1.1.1.8 root 108: static struct videl_s videl;
1.1.1.6 root 109:
110:
1.1.1.12 root 111: /**
112: * Called upon startup (and via VIDEL_reset())
113: */
114: void Videl_Init(void)
115: {
116: videl.hostColorsSync = false;
1.1.1.10 root 117:
1.1.1.12 root 118: /* Default resolution to boot with */
119: videl.save_scrWidth = 640;
120: videl.save_scrHeight = 480;
121: videl.save_scrBpp = 4;
122: }
1.1 root 123:
1.1.1.8 root 124: /**
1.1.1.12 root 125: * Called when CPU encounters a RESET instruction.
1.1.1.8 root 126: */
1.1 root 127: void VIDEL_reset(void)
128: {
1.1.1.12 root 129: Videl_Init();
130: Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight,
131: ConfigureParams.Screen.nForceBpp, false);
132:
1.1.1.6 root 133: videl.bUseSTShifter = false; /* Use Falcon color palette by default */
134: videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
1.1.1.8 root 135: videl.monitor_type = videl.reg_ffff8006_save & 0xc0;
1.1 root 136:
1.1.1.13 root 137: VIDEL_RestartVideoCounter();
1.1.1.4 root 138:
139: /* Reset IO register (some are not initialized by TOS) */
140: IoMem_WriteWord(0xff820e, 0); /* Line offset */
141: IoMem_WriteWord(0xff8264, 0); /* Horizontal scroll */
1.1.1.8 root 142:
1.1.1.12 root 143: /* Init sync mode register */
144: VIDEL_SyncMode_WriteByte();
1.1 root 145: }
146:
1.1.1.6 root 147: /**
148: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
149: */
150: void VIDEL_MemorySnapShot_Capture(bool bSave)
151: {
152: /* Save/Restore details */
153: MemorySnapShot_Store(&videl, sizeof(videl));
154: }
155:
156: /**
1.1.1.10 root 157: * Monitor write access to Falcon color palette registers
1.1.1.6 root 158: */
1.1.1.10 root 159: void VIDEL_FalconColorRegsWrite(void)
1.1 root 160: {
1.1.1.10 root 161: uint32_t color = IoMem_ReadLong(IoAccessBaseAddress & ~3);
162: color &= 0xfcfc00fc; /* Unused bits have to be set to 0 */
163: IoMem_WriteLong(IoAccessBaseAddress & ~3, color);
1.1.1.8 root 164: videl.hostColorsSync = false;
1.1 root 165: }
166:
1.1.1.6 root 167: /**
1.1.1.12 root 168: * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration.
1.1.1.8 root 169: * This register is read only.
1.1.1.6 root 170: */
171: void VIDEL_Monitor_WriteByte(void)
172: {
1.1.1.8 root 173: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8006 Monitor and memory conf write (Read only)\n");
1.1.1.6 root 174: /* Restore hardware value */
1.1.1.8 root 175:
1.1.1.6 root 176: IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
177: }
178:
179: /**
1.1.1.12 root 180: * VIDEL_SyncMode_WriteByte : Videl synchronization mode.
1.1.1.8 root 181: * $FFFF820A [R/W] _______0 .................................. SYNC-MODE
182: ||
183: |+--Synchronisation [ 0:internal / 1:external ]
184: +---Vertical frequency [ Read-only bit ]
185: [ Monochrome monitor:0 / Colour monitor:1 ]
186: */
187: void VIDEL_SyncMode_WriteByte(void)
188: {
189: Uint8 syncMode = IoMem_ReadByte(0xff820a);
190: LOG_TRACE(TRACE_VIDEL, "Videl : $ff820a Sync Mode write: 0x%02x\n", syncMode);
191:
192: if (videl.monitor_type == FALCON_MONITOR_MONO)
193: syncMode &= 0xfd;
194: else
195: syncMode |= 0x2;
1.1.1.12 root 196:
1.1.1.8 root 197: IoMem_WriteByte(0xff820a, syncMode);
198: }
199:
200: /**
201: * Read video address counter and update ff8205/07/09
202: */
203: void VIDEL_ScreenCounter_ReadByte(void)
204: {
1.1.1.13 root 205: Uint32 addr = videl.videoRaster;
1.1.1.8 root 206: IoMem[0xff8205] = ( addr >> 16 ) & 0xff;
207: IoMem[0xff8207] = ( addr >> 8 ) & 0xff;
208: IoMem[0xff8209] = addr & 0xff;
209:
210: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode read: 0x%08x\n", addr);
211: }
212:
213: /**
214: * Write video address counter
215: */
216: void VIDEL_ScreenCounter_WriteByte(void)
217: {
1.1.1.13 root 218: Uint32 addr_new = videl.videoRaster;
219: Uint8 AddrByte = IoMem[ IoAccessCurrentAddress ];
1.1.1.8 root 220:
221: /* Compute the new video address with one modified byte */
222: if ( IoAccessCurrentAddress == 0xff8205 )
223: addr_new = ( addr_new & 0x00ffff ) | ( AddrByte << 16 );
224: else if ( IoAccessCurrentAddress == 0xff8207 )
225: addr_new = ( addr_new & 0xff00ff ) | ( AddrByte << 8 );
226: else if ( IoAccessCurrentAddress == 0xff8209 )
227: addr_new = ( addr_new & 0xffff00 ) | ( AddrByte );
228:
1.1.1.13 root 229: videl.videoRaster = addr_new;
230: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode write: 0x%08x\n", addr_new);
231: }
232:
233: /**
234: * VIDEL_LineOffset_ReadWord: $FFFF820E [R/W] W _______876543210 Line Offset
235: * How many words are added to the end of display line, i.e. how many words are
236: * 'behind' the display.
237: */
238: void VIDEL_LineOffset_ReadWord(void)
239: {
240: /* Unused bits in the first byte are read as zero, so mask them */
241: IoMem[0xff820e] &= 0x01;
1.1.1.8 root 242: }
243:
244: /**
245: * VIDEL_LineOffset_WriteWord: $FFFF820E [R/W] W _______876543210 Line Offset
246: * How many words are added to the end of display line, i.e. how many words are
247: * 'behind' the display.
248: */
249: void VIDEL_LineOffset_WriteWord(void)
250: {
1.1.1.9 root 251: LOG_TRACE(TRACE_VIDEL, "Videl : $ff820e Line Offset write: 0x%04x\n",
252: IoMem_ReadWord(0xff820e));
1.1.1.8 root 253: }
254:
255: /**
256: * VIDEL_Line_Width_WriteWord: $FFFF8210 [R/W] W ______9876543210 Line Width (VWRAP)
257: * Length of display line in words.Or, how many words should be added to
258: * vram counter after every display line.
259: */
260: void VIDEL_Line_Width_WriteWord(void)
261: {
1.1.1.9 root 262: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8210 Line Width write: 0x%04x\n",
263: IoMem_ReadWord(0xff8210));
1.1.1.8 root 264: }
265:
266: /**
1.1.1.6 root 267: * Write to video address base high, med and low register (0xff8201/03/0d).
268: * On Falcon, when a program writes to high or med registers, base low register
269: * is reset to zero.
270: */
271: void VIDEL_ScreenBase_WriteByte(void)
272: {
273: if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
274: /* Reset screen base low register */
275: IoMem[0xff820d] = 0;
276: }
277:
1.1.1.9 root 278: LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%02x\t (screen: 0x%04x)\n",
279: IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
280: (IoMem[0xff8201]<<16) + (IoMem[0xff8203]<<8) + IoMem[0xff820d]);
1.1.1.6 root 281: }
282:
283: /**
1.1.1.12 root 284: VIDEL_ST_ShiftModeWriteByte :
1.1.1.6 root 285: $FFFF8260 [R/W] B ______10 ST Shift Mode
286: ||
287: || others vga
288: || $FF8210 $FF82C2 $FF82C2
289: 00--4BP/320 Pixels=> $0050 $0000 $0005
290: 01--2BP/640 Pixels=> $0050 $0004 $0009
291: 10--1BP/640 Pixels=> $0028 $0006 $0008
292: 11--???/320 Pixels=> $0050 $0000 $0000
293:
294: Writing to this register does the following things:
295: - activate STE palette
296: - sets line width ($ffff8210)
297: - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
298: */
299: void VIDEL_ST_ShiftModeWriteByte(void)
300: {
301: Uint16 line_width, video_mode;
302: Uint8 st_shiftMode;
303:
304: st_shiftMode = IoMem_ReadByte(0xff8260);
1.1.1.8 root 305: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8260 ST Shift Mode (STSHIFT) write: 0x%02x\n", st_shiftMode);
306:
307: /* Bits 2-7 are set to 0 */
1.1.1.12 root 308: IoMem_WriteByte(0xff8260, st_shiftMode & 3);
1.1.1.6 root 309:
310: /* Activate STE palette */
311: videl.bUseSTShifter = true;
312:
313: /* Compute line width and video mode */
314: switch (st_shiftMode & 0x3) {
315: case 0: /* 4BP/320 Pixels */
316: line_width = 0x50;
317: /* half pixels + double lines vs. no scaling */
318: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
319: break;
320: case 1: /* 2BP/640 Pixels */
321: line_width = 0x50;
322: /* quarter pixels + double lines vs. half pixels */
323: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
324: break;
325: case 2: /* 1BP/640 Pixels */
326: line_width = 0x28;
327: if (videl.monitor_type == FALCON_MONITOR_MONO) {
328: video_mode = 0x0;
329: break;
330: }
331: /* quarter pixels vs. half pixels + interlace */
332: video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
333: break;
334: case 3: /* ???/320 Pixels */
1.1.1.8 root 335: default:
1.1.1.6 root 336: line_width = 0x50;
337: video_mode = 0x0;
338: break;
339: }
340:
341: /* Set line width ($FFFF8210) */
1.1.1.12 root 342: IoMem_WriteWord(0xff8210, line_width);
343:
1.1.1.6 root 344: /* Set video mode ($FFFF82C2) */
1.1.1.12 root 345: IoMem_WriteWord(0xff82c2, video_mode);
1.1.1.14! root 346:
! 347: /* Hack for Sparrow-TOS (which does not know about Videl registers): */
! 348: if (TosVersion == 0x207)
! 349: {
! 350: if (st_shiftMode == 2) /* Mono? */
! 351: {
! 352: IoMem_WriteWord(0xff82a4, 0);
! 353: IoMem_WriteWord(0xff82a6, 0);
! 354: IoMem_WriteWord(0xff82a8, 0x43);
! 355: IoMem_WriteWord(0xff82aa, 0x363);
! 356: }
! 357: else if (ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_VGA)
! 358: {
! 359: IoMem_WriteWord(0xff82a4, 0x3af);
! 360: IoMem_WriteWord(0xff82a6, 0x8f);
! 361: IoMem_WriteWord(0xff82a8, 0x8f);
! 362: IoMem_WriteWord(0xff82aa, 0x3af);
! 363: }
! 364: else
! 365: {
! 366: IoMem_WriteWord(0xff82a4, 0x20e);
! 367: IoMem_WriteWord(0xff82a6, 0x7e);
! 368: IoMem_WriteWord(0xff82a8, 0x7e);
! 369: IoMem_WriteWord(0xff82aa, 0x20e);
! 370: }
! 371: }
1.1.1.6 root 372: }
373:
374: /**
1.1.1.8 root 375: VIDEL_HorScroll64_WriteByte : Horizontal scroll register (0-15)
376: $FFFF8264 [R/W] ________ ................................ H-SCROLL HI
377: |||| [ Shadow register for $FFFF8265 ]
378: ++++--Pixel shift [ 0:normal / 1..15:Left shift ]
379: [ Change in line-width NOT required ]
380: */
381: void VIDEL_HorScroll64_WriteByte(void)
382: {
1.1.1.9 root 383: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8264 Horizontal scroll 64 write: 0x%02x\n",
384: IoMem_ReadByte(0xff8264));
1.1.1.8 root 385: }
386:
387: /**
388: VIDEL_HorScroll65_WriteByte : Horizontal scroll register (0-15)
389: $FFFF8265 [R/W] ____3210 .................................H-SCROLL LO
390: ||||
391: ++++--Pixel [ 0:normal / 1..15:Left shift ]
392: [ Change in line-width NOT required ]
393: */
394: void VIDEL_HorScroll65_WriteByte(void)
395: {
1.1.1.9 root 396: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8265 Horizontal scroll 65 write: 0x%02x\n",
397: IoMem_ReadByte(0xff8265));
1.1.1.8 root 398: }
399:
400: /**
401: VIDEL_Falcon_ShiftMode_WriteWord :
1.1.1.6 root 402: $FFFF8266 [R/W] W _____A98_6543210 Falcon Shift Mode (SPSHIFT)
403: ||| |||||||
1.1.1.8 root 404: ||| |||++++- 0..15: Colourbank choice from 256-colour table in 16 colour multiples
405: ||| ||+----- 8 Bitplanes mode (256 Colors) [0:off / 1:on]
406: ||| |+------ Vertical Sync [0: internal / 1: external]
407: ||| +------- Horizontal Sync [0: internal / 1: external]
408: ||+--------- True-Color-Mode [0:off / 1:on]
409: |+---------- Overlay-Mode [0:off / 1:on]
410: +----------- 0: 2-Color-Mode [0:off / 1:on]
1.1.1.6 root 411:
412: Writing to this register does the following things:
413: - activate Falcon palette
414: - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
415: same as ST LOW since Falcon palette is used!)
416: - $8260 register is ignored, you don't need to write here anything
417:
418: Note: 4-Color-Mode isn't realisable with Falcon palette.
419: */
1.1.1.8 root 420: void VIDEL_Falcon_ShiftMode_WriteWord(void)
1.1.1.6 root 421: {
1.1.1.9 root 422: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8266 Falcon Shift Mode (SPSHIFT) write: 0x%04x\n",
423: IoMem_ReadWord(0xff8266));
1.1.1.6 root 424:
425: videl.bUseSTShifter = false;
426: }
427:
428: /**
429: * Write Horizontal Hold Counter (HHC)
430: */
431: void VIDEL_HHC_WriteWord(void)
432: {
1.1.1.9 root 433: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8280 Horizontal Hold Counter (HHC) write: 0x%04x\n",
434: IoMem_ReadWord(0xff8280));
1.1.1.6 root 435: }
436:
437: /**
438: * Write Horizontal Hold Timer (HHT)
439: */
440: void VIDEL_HHT_WriteWord(void)
441: {
1.1.1.9 root 442: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8282 Horizontal Hold Timer (HHT) write: 0x%04x\n",
443: IoMem_ReadWord(0xff8282));
1.1.1.6 root 444: }
445:
446: /**
447: * Write Horizontal Border Begin (HBB)
448: */
449: void VIDEL_HBB_WriteWord(void)
450: {
1.1.1.9 root 451: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8284 Horizontal Border Begin (HBB) write: 0x%04x\n",
452: IoMem_ReadWord(0xff8284));
1.1.1.6 root 453: }
454:
455: /**
456: * Write Horizontal Border End (HBE)
457: */
458: void VIDEL_HBE_WriteWord(void)
459: {
1.1.1.9 root 460: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8286 Horizontal Border End (HBE) write: 0x%04x\n",
461: IoMem_ReadWord(0xff8286));
1.1.1.6 root 462: }
463:
464: /**
465: * Write Horizontal Display Begin (HDB)
1.1.1.8 root 466: $FFFF8288 [R/W] W ______9876543210 Horizontal Display Begin (HDB)
467: |
468: +---------- Display will start in [0: 1st halfline / 1: 2nd halfline]
1.1.1.6 root 469: */
470: void VIDEL_HDB_WriteWord(void)
471: {
1.1.1.9 root 472: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8288 Horizontal Display Begin (HDB) write: 0x%04x\n",
473: IoMem_ReadWord(0xff8288));
1.1.1.6 root 474: }
475:
476: /**
477: * Write Horizontal Display End (HDE)
478: */
479: void VIDEL_HDE_WriteWord(void)
480: {
1.1.1.9 root 481: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828a Horizontal Display End (HDE) write: 0x%04x\n",
482: IoMem_ReadWord(0xff828a));
1.1.1.6 root 483: }
484:
485: /**
486: * Write Horizontal SS (HSS)
487: */
488: void VIDEL_HSS_WriteWord(void)
489: {
1.1.1.9 root 490: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828c Horizontal SS (HSS) write: 0x%04x\n",
491: IoMem_ReadWord(0xff828c));
1.1.1.6 root 492: }
493:
494: /**
495: * Write Horizontal FS (HFS)
496: */
497: void VIDEL_HFS_WriteWord(void)
498: {
1.1.1.9 root 499: LOG_TRACE(TRACE_VIDEL, "Videl : $ff828e Horizontal FS (HFS) write: 0x%04x\n",
500: IoMem_ReadWord(0xff828e));
1.1.1.6 root 501: }
502:
503: /**
504: * Write Horizontal EE (HEE)
505: */
506: void VIDEL_HEE_WriteWord(void)
507: {
1.1.1.9 root 508: LOG_TRACE(TRACE_VIDEL, "Videl : $ff8290 Horizontal EE (HEE) write: 0x%04x\n",
509: IoMem_ReadWord(0xff8290));
1.1.1.6 root 510: }
511:
512: /**
513: * Write Vertical Frequency Counter (VFC)
514: */
515: void VIDEL_VFC_ReadWord(void)
516: {
1.1.1.13 root 517: IoMem_WriteWord(0xff82a0, videl.vertFreqCounter);
518: videl.vertFreqCounter++;
519: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", videl.vertFreqCounter);
1.1.1.6 root 520: }
521:
522: /**
523: * Write Vertical Frequency Timer (VFT)
524: */
525: void VIDEL_VFT_WriteWord(void)
526: {
1.1.1.9 root 527: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a2 Vertical Frequency Timer (VFT) write: 0x%04x\n",
528: IoMem_ReadWord(0xff82a2));
1.1.1.6 root 529: }
530:
531: /**
532: * Write Vertical Border Begin (VBB)
533: */
534: void VIDEL_VBB_WriteWord(void)
535: {
1.1.1.9 root 536: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a4 Vertical Border Begin (VBB) write: 0x%04x\n",
537: IoMem_ReadWord(0xff82a4));
1.1.1.6 root 538: }
539:
540: /**
541: * Write Vertical Border End (VBE)
542: */
543: void VIDEL_VBE_WriteWord(void)
544: {
1.1.1.9 root 545: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a6 Vertical Border End (VBE) write: 0x%04x\n",
546: IoMem_ReadWord(0xff82a6));
1.1.1.6 root 547: }
548:
549: /**
550: * Write Vertical Display Begin (VDB)
551: */
552: void VIDEL_VDB_WriteWord(void)
1.1 root 553: {
1.1.1.9 root 554: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a8 Vertical Display Begin (VDB) write: 0x%04x\n",
555: IoMem_ReadWord(0xff82a8));
1.1 root 556: }
557:
1.1.1.6 root 558: /**
559: * Write Vertical Display End (VDE)
560: */
561: void VIDEL_VDE_WriteWord(void)
562: {
1.1.1.9 root 563: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82aa Vertical Display End (VDE) write: 0x%04x\n",
564: IoMem_ReadWord(0xff82aa));
1.1.1.6 root 565: }
566:
567: /**
568: * Write Vertical SS (VSS)
569: */
570: void VIDEL_VSS_WriteWord(void)
571: {
1.1.1.9 root 572: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82ac Vertical SS (VSS) write: 0x%04x\n",
573: IoMem_ReadWord(0xff82ac));
1.1.1.6 root 574: }
575:
576: /**
577: * Write Video Control (VCO)
578: */
579: void VIDEL_VCO_WriteWord(void)
580: {
1.1.1.9 root 581: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c0 Video control (VCO) write: 0x%04x\n",
582: IoMem_ReadWord(0xff82c0));
1.1.1.6 root 583: }
584:
585: /**
586: * Write Video Mode (VDM)
587: */
588: void VIDEL_VMD_WriteWord(void)
589: {
1.1.1.9 root 590: LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c2 Video Mode (VDM) write: 0x%04x\n",
591: IoMem_ReadWord(0xff82c2));
1.1.1.6 root 592: }
593:
594:
1.1.1.8 root 595: /**
596: * VIDEL_getVideoramAddress: returns the video RAM address.
597: * On Falcon, video address must be a multiple of four in bitplane modes.
598: */
599: static Uint32 VIDEL_getVideoramAddress(void)
1.1 root 600: {
1.1.1.8 root 601: Uint32 videoBase;
1.1.1.12 root 602:
1.1.1.8 root 603: videoBase = (Uint32) IoMem_ReadByte(0xff8201) << 16;
604: videoBase |= (Uint32) IoMem_ReadByte(0xff8203) << 8;
605: videoBase |= IoMem_ReadByte(0xff820d) & ~3;
1.1.1.12 root 606:
1.1.1.8 root 607: return videoBase;
1.1 root 608: }
609:
1.1.1.13 root 610: /**
611: * Reset appropriate registers on VBL etc
612: */
613: void VIDEL_RestartVideoCounter(void)
614: {
615: videl.videoRaster = VIDEL_getVideoramAddress();
616: /* counter for VFC register $ff82a0 */
617: videl.vertFreqCounter = 0;
618: }
619:
620: /**
621: * Increment appropriate registers on HBL
622: */
623: void VIDEL_VideoRasterHBL(void)
624: {
625: int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
626: int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; /* 10 bits */
627:
628: videl.videoRaster += linewidth + lineoffset;
629:
630: /* TODO: VFC is incremented every half line, here, we increment it every line */
631: videl.vertFreqCounter++;
632: }
633:
634:
1.1.1.8 root 635: static Uint16 VIDEL_getScreenBpp(void)
1.1 root 636: {
1.1.1.8 root 637: Uint16 f_shift = IoMem_ReadWord(0xff8266);
638: Uint16 bits_per_pixel;
639: Uint8 st_shift = IoMem_ReadByte(0xff8260);
640:
1.1 root 641: /* to get bpp, we must examine f_shift and st_shift.
1.1.1.12 root 642: * f_shift is valid if any of bits no. 10, 8 or 4 is set.
1.1.1.8 root 643: * Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1.1 root 644: * if bit 10 set then bit 8 and bit 4 don't care...
645: * If all these bits are 0 and ST shifter is written
646: * after Falcon one, get display depth from st_shift
647: * (as for ST and STE)
648: */
649: if (f_shift & 0x400) /* Falcon: 2 colors */
650: bits_per_pixel = 1;
651: else if (f_shift & 0x100) /* Falcon: hicolor */
652: bits_per_pixel = 16;
653: else if (f_shift & 0x010) /* Falcon: 8 bitplanes */
654: bits_per_pixel = 8;
1.1.1.6 root 655: else if (!videl.bUseSTShifter) /* Falcon: 4 bitplanes */
1.1 root 656: bits_per_pixel = 4;
657: else if (st_shift == 0)
658: bits_per_pixel = 4;
659: else if (st_shift == 0x01)
660: bits_per_pixel = 2;
661: else /* if (st_shift == 0x02) */
662: bits_per_pixel = 1;
663:
1.1.1.8 root 664: /* 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 665:
666: return bits_per_pixel;
667: }
668:
1.1.1.8 root 669: /**
670: * VIDEL_getScreenWidth : returns the visible X resolution
671: * left border + graphic area + right border
672: * left border : hdb - hbe-offset
673: * right border : hbb - hde-offset
1.1.1.12 root 674: * Graphics display : starts at cycle HDB and ends at cycle HDE.
1.1.1.8 root 675: */
1.1 root 676: static int VIDEL_getScreenWidth(void)
677: {
1.1.1.9 root 678: Uint16 hbb, hbe, hdb, hde, vdm, hht;
679: Uint16 cycPerPixel, divider;
680: Sint16 hdb_offset, hde_offset;
681: Sint16 leftBorder, rightBorder;
1.1.1.8 root 682: Uint16 bpp = VIDEL_getScreenBpp();
683:
684: /* X Size of the Display area */
685: videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp;
686:
1.1.1.13 root 687: /* Sanity check - don't use unsupported texture sizes for SDL2:
688: * http://answers.unity3d.com/questions/563094/mobile-max-texture-size.html
689: * (largest currently known real Videl width is ~1600)
690: */
691: while (videl.XSize > 2048)
692: videl.XSize /= 2;
693:
1.1.1.8 root 694: /* If the user disabled the borders display from the gui, we suppress them */
695: if (ConfigureParams.Screen.bAllowOverscan == 0) {
696: videl.leftBorderSize = 0;
697: videl.rightBorderSize = 0;
698: return videl.XSize;
699: }
700:
701: /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
702: * HDB and HDE have no significance and no border is displayed.
703: */
704: if (videl.monitor_type == FALCON_MONITOR_MONO) {
705: videl.leftBorderSize = 0;
706: videl.rightBorderSize = 0;
707: return videl.XSize;
708: }
709:
1.1.1.9 root 710: hbb = IoMem_ReadWord(0xff8284) & 0x01ff;
711: hbe = IoMem_ReadWord(0xff8286) & 0x01ff;
712: hdb = IoMem_ReadWord(0xff8288) & 0x01ff;
713: hde = IoMem_ReadWord(0xff828a) & 0x01ff;
714: vdm = IoMem_ReadWord(0xff82c2) & 0xc;
715: hht = IoMem_ReadWord(0xff8282) & 0x1ff;
1.1.1.8 root 716:
717: /* Compute cycles per pixel */
718: if (vdm == 0)
719: cycPerPixel = 4;
720: else if (vdm == 4)
721: cycPerPixel = 2;
722: else
723: cycPerPixel = 1;
724:
725: /* Compute the divider */
726: if (videl.monitor_type == FALCON_MONITOR_VGA) {
727: if (cycPerPixel == 4)
728: divider = 4;
729: else
730: divider = 2;
731: }
732: else if (videl.bUseSTShifter == true) {
733: divider = 16;
734: }
735: else {
736: divider = cycPerPixel;
737: }
738:
739: /* Compute hdb_offset and hde_offset */
740: if (videl.bUseSTShifter == false) {
741: if (bpp < 16) {
742: /* falcon mode bpp */
743: hdb_offset = ((64+(128/bpp + 16 + 2) * cycPerPixel) / divider ) + 1;
744: hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
745: }
746: else {
747: /* falcon mode true color */
748: hdb_offset = ((64 + 16 * cycPerPixel) / divider ) + 1;
749: hde_offset = 0;
750: }
751: }
752: else {
753: /* ST bitplan mode */
754: hdb_offset = ((128+(128/bpp + 2) * cycPerPixel) / divider ) + 1;
755: hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
756: }
757:
758: LOG_TRACE(TRACE_VIDEL, "hdb_offset=%04x, hde_offset=%04x\n", hdb_offset, hde_offset);
759:
760: /* Compute left border size in cycles */
761: if (IoMem_ReadWord(0xff8288) & 0x0200)
762: leftBorder = hdb - hbe + hdb_offset - hht - 2;
763: else
764: leftBorder = hdb - hbe + hdb_offset;
765:
766: /* Compute right border size in cycles */
767: rightBorder = hbb - hde_offset - hde;
768:
769: videl.leftBorderSize = leftBorder / cycPerPixel;
770: videl.rightBorderSize = rightBorder / cycPerPixel;
771: LOG_TRACE(TRACE_VIDEL, "left border size=%04x, right border size=%04x\n", videl.leftBorderSize, videl.rightBorderSize);
772:
773: if (videl.leftBorderSize < 0) {
774: // fprintf(stderr, "BORDER LEFT < 0 %d\n", videl.leftBorderSize);
775: videl.leftBorderSize = 0;
776: }
777: if (videl.rightBorderSize < 0) {
778: // fprintf(stderr, "BORDER RIGHT < 0 %d\n", videl.rightBorderSize);
779: videl.rightBorderSize = 0;
780: }
781:
782: return videl.leftBorderSize + videl.XSize + videl.rightBorderSize;
1.1 root 783: }
784:
1.1.1.8 root 785: /**
786: * VIDEL_getScreenHeight : returns the visible Y resolution
787: * upper border + graphic area + lower border
788: * upper border : vdb - vbe
789: * lower border : vbb - vde
1.1.1.12 root 790: * Graphics display : starts at line VDB and ends at line VDE.
1.1.1.8 root 791: * If interlace mode off unit of VC-registers is half lines, else lines.
792: */
1.1 root 793: static int VIDEL_getScreenHeight(void)
794: {
1.1.1.8 root 795: Uint16 vbb = IoMem_ReadWord(0xff82a4) & 0x07ff;
1.1.1.12 root 796: Uint16 vbe = IoMem_ReadWord(0xff82a6) & 0x07ff;
1.1.1.8 root 797: Uint16 vdb = IoMem_ReadWord(0xff82a8) & 0x07ff;
798: Uint16 vde = IoMem_ReadWord(0xff82aa) & 0x07ff;
799: Uint16 vmode = IoMem_ReadWord(0xff82c2);
800:
801: /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
802: * VDB and VDE have no significance and no border is displayed.
1.1 root 803: */
1.1.1.8 root 804: if (videl.monitor_type == FALCON_MONITOR_MONO) {
805: videl.upperBorderSize = 0;
806: videl.lowerBorderSize = 0;
807: }
808: else {
809: /* We must take the positive value only, as a program like AceTracker starts the */
810: /* graphical area 1 line before the end of the upper border */
811: videl.upperBorderSize = vdb - vbe > 0 ? vdb - vbe : 0;
812: videl.lowerBorderSize = vbb - vde > 0 ? vbb - vde : 0;
813: }
1.1 root 814:
1.1.1.8 root 815: /* Y Size of the Display area */
1.1.1.9 root 816: if (vde >= vdb) {
817: videl.YSize = vde - vdb;
818: }
819: else {
820: LOG_TRACE(TRACE_VIDEL, "WARNING: vde=0x%x is less than vdb=0x%x\n",
821: vde, vdb);
822: }
1.1.1.8 root 823:
824: /* If the user disabled the borders display from the gui, we suppress them */
825: if (ConfigureParams.Screen.bAllowOverscan == 0) {
826: videl.upperBorderSize = 0;
827: videl.lowerBorderSize = 0;
828: }
829:
830: if (!(vmode & 0x02)){ /* interlace */
831: videl.YSize >>= 1;
832: videl.upperBorderSize >>= 1;
833: videl.lowerBorderSize >>= 1;
834: }
1.1.1.12 root 835:
1.1.1.8 root 836: if (vmode & 0x01) { /* double */
837: videl.YSize >>= 1;
838: videl.upperBorderSize >>= 1;
839: videl.lowerBorderSize >>= 1;
840: }
1.1.1.9 root 841:
1.1.1.8 root 842: return videl.upperBorderSize + videl.YSize + videl.lowerBorderSize;
1.1 root 843: }
844:
845:
1.1.1.12 root 846: /**
847: * Map the correct colortable into the correct pixel format
1.1 root 848: */
1.1.1.12 root 849: void VIDEL_UpdateColors(void)
1.1 root 850: {
1.1.1.8 root 851: int i, r, g, b, colors = 1 << videl.save_scrBpp;
1.1 root 852:
1.1.1.12 root 853: if (videl.hostColorsSync)
854: return;
855:
1.1.1.8 root 856: #define F_COLORS(i) IoMem_ReadByte(VIDEL_COLOR_REGS_BEGIN + (i))
857: #define STE_COLORS(i) IoMem_ReadByte(0xff8240 + (i))
1.1 root 858:
1.1.1.12 root 859: /* True color mode ? */
860: if (videl.save_scrBpp > 8) {
861: /* Videl color 0 ($ffff9800) must be taken into account as it is the border color in true color mode */
862: r = F_COLORS(0) & 0xfc;
863: r |= r>>6;
864: g = F_COLORS(0 + 1) & 0xfc;
865: g |= g>>6;
866: b = F_COLORS(0 + 3) & 0xfc;
867: b |= b>>6;
868: Screen_SetPaletteColor(0, r,g,b);
869: return;
870: }
871:
1.1.1.6 root 872: if (!videl.bUseSTShifter) {
1.1 root 873: for (i = 0; i < colors; i++) {
874: int offset = i << 2;
875: r = F_COLORS(offset) & 0xfc;
876: r |= r>>6;
877: g = F_COLORS(offset + 1) & 0xfc;
878: g |= g>>6;
879: b = F_COLORS(offset + 3) & 0xfc;
880: b |= b>>6;
1.1.1.12 root 881: Screen_SetPaletteColor(i, r,g,b);
1.1 root 882: }
883: } else {
884: for (i = 0; i < colors; i++) {
885: int offset = i << 1;
886: r = STE_COLORS(offset) & 0x0f;
887: r = ((r & 7)<<1)|(r>>3);
888: r |= r<<4;
889: g = (STE_COLORS(offset + 1)>>4) & 0x0f;
890: g = ((g & 7)<<1)|(g>>3);
891: g |= g<<4;
892: b = STE_COLORS(offset + 1) & 0x0f;
893: b = ((b & 7)<<1)|(b>>3);
894: b |= b<<4;
1.1.1.12 root 895: Screen_SetPaletteColor(i, r,g,b);
1.1 root 896: }
897: }
898:
1.1.1.8 root 899: videl.hostColorsSync = true;
1.1 root 900: }
901:
902:
1.1.1.13 root 903: void Videl_ScreenModeChanged(bool bForceChange)
1.1 root 904: {
1.1.1.13 root 905: int bpp;
906:
907: if (ConfigureParams.Screen.nForceBpp)
908: {
909: bpp = ConfigureParams.Screen.nForceBpp;
910: }
911: else if (Avi_AreWeRecording())
912: {
913: /* Avoid changing the bpp if we are recording */
914: bpp = sdlscrn->format->BitsPerPixel;
915: }
916: else
917: {
918: /* Using SDL's 16 bpp conversion function is a bit faster */
919: bpp = (videl.save_scrBpp == 16) ? 16 : 0;
920: }
921:
922: LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n",
923: videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp);
1.1.1.12 root 924:
925: Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight,
926: bpp, bForceChange);
1.1 root 927: }
928:
929:
1.1.1.2 root 930: bool VIDEL_renderScreen(void)
1.1 root 931: {
1.1.1.8 root 932: /* Atari screen infos */
1.1 root 933: int vw = VIDEL_getScreenWidth();
934: int vh = VIDEL_getScreenHeight();
935: int vbpp = VIDEL_getScreenBpp();
1.1.1.8 root 936:
937: int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
938: int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; /* 10 bits */
1.1.1.12 root 939: int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1.1.1.9 root 940: int nextline;
1.1.1.8 root 941:
1.1.1.6 root 942: bool change = false;
1.1 root 943:
1.1.1.13 root 944: Uint32 videoBase = VIDEL_getVideoramAddress();
1.1.1.9 root 945:
1.1.1.8 root 946: if (vw > 0 && vw != videl.save_scrWidth) {
947: LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw);
948: videl.save_scrWidth = vw;
1.1.1.6 root 949: change = true;
1.1 root 950: }
1.1.1.8 root 951: if (vh > 0 && vh != videl.save_scrHeight) {
952: LOG_TRACE(TRACE_VIDEL, "Videl : height change from %d to %d\n", videl.save_scrHeight, vh);
953: videl.save_scrHeight = vh;
1.1.1.6 root 954: change = true;
1.1 root 955: }
1.1.1.8 root 956: if (vbpp != videl.save_scrBpp) {
957: LOG_TRACE(TRACE_VIDEL, "Videl : bpp change from %d to %d\n", videl.save_scrBpp, vbpp);
958: videl.save_scrBpp = vbpp;
1.1.1.6 root 959: change = true;
960: }
961: if (change) {
1.1.1.13 root 962: Videl_ScreenModeChanged(false);
1.1 root 963: }
964:
1.1.1.12 root 965: if (vw < 32 || vh < 32) {
966: LOG_TRACE(TRACE_VIDEL, "Videl : %dx%d screen size, not drawing\n", vw, vh);
967: return false;
968: }
969:
970: if (!Screen_Lock())
1.1.1.2 root 971: return false;
1.1 root 972:
1.1.1.12 root 973: /*
974: I think this implementation is naive:
1.1.1.8 root 975: indeed, I suspect that we should instead skip lineoffset
976: words each time we have read "more" than linewidth words
977: (possibly "more" because of the number of bit planes).
978: Moreover, the 1 bit plane mode is particular;
979: while doing some experiments on my Falcon, it seems to
980: behave like the 4 bit planes mode.
981: At last, we have also to take into account the 4 bits register
982: located at the word $ffff8264 (bit offset). This register makes
983: the semantics of the lineoffset register change a little.
984: int bitoffset = IoMem_ReadWord(0xff8264) & 0x000f;
985: The meaning of this register in True Color mode is not clear
986: for me at the moment (and my experiments on the Falcon don't help
987: me).
988: */
1.1.1.9 root 989: nextline = linewidth + lineoffset;
1.1.1.8 root 990:
1.1.1.12 root 991: VIDEL_UpdateColors();
1.1.1.8 root 992:
1.1.1.13 root 993: Screen_GenConvert(&STRam[videoBase], videl.XSize, videl.YSize,
1.1.1.12 root 994: videl.save_scrBpp, nextline, hscrolloffset,
995: videl.leftBorderSize, videl.rightBorderSize,
996: videl.upperBorderSize, videl.lowerBorderSize);
1.1 root 997:
1.1.1.12 root 998: Screen_UnLock();
999: Screen_GenConvUpdate(Statusbar_Update(sdlscrn, false), false);
1.1.1.2 root 1000:
1001: return true;
1.1 root 1002: }
1003:
1004:
1.1.1.4 root 1005: /**
1.1.1.10 root 1006: * Write to videl ST palette registers (0xff8240-0xff825e)
1007: *
1008: * Note that there's a special "strange" case when writing only to the upper byte
1009: * of the color reg (instead of writing 16 bits at once with .W/.L).
1010: * In that case, the byte written to address x is automatically written
1011: * to address x+1 too (but we shouldn't copy x in x+1 after masking x ; we apply the mask at the end)
1012: * Similarly, when writing a byte to address x+1, it's also written to address x
1013: * So : move.w #0,$ff8240 -> color 0 is now $000
1014: * move.b #7,$ff8240 -> color 0 is now $707 !
1015: * move.b #$55,$ff8241 -> color 0 is now $555 !
1016: * move.b #$71,$ff8240 -> color 0 is now $171 (bytes are first copied, then masked)
1017: */
1.1.1.11 root 1018: static void Videl_ColorReg_WriteWord(void)
1.1.1.10 root 1019: {
1020: Uint16 col;
1021: Uint32 addr = IoAccessCurrentAddress;
1022:
1023: videl.hostColorsSync = false;
1024:
1025: if (bUseHighRes || bUseVDIRes) /* Don't store if hi-res or VDI resolution */
1026: return;
1027:
1.1.1.12 root 1028: /* Handle special case when writing only to the lower or
1029: * upper byte of the color reg: copy written byte also
1030: * to the other byte before masking the color value.
1031: */
1032: if (nIoMemAccessSize == SIZE_BYTE)
1033: col = (IoMem_ReadByte(addr) << 8) + IoMem_ReadByte(addr);
1.1.1.10 root 1034: /* Usual case, writing a word or a long (2 words) */
1.1.1.12 root 1035: else
1.1.1.10 root 1036: col = IoMem_ReadWord(addr);
1037:
1038: col &= 0xfff; /* Mask off to 4096 palette */
1039:
1040: addr &= 0xfffffffe; /* Ensure addr is even to store the 16 bit color */
1041:
1042: IoMem_WriteWord(addr, col);
1043: }
1044:
1045: /*
1046: * [NP] TODO : due to how .L accesses are handled in ioMem.c, we can't call directly
1047: * Video_ColorReg_WriteWord from ioMemTabFalcon.c, we must use an intermediate
1048: * function, else .L accesses will not change 2 .W color regs, but only one.
1049: * This should be changed in ioMem.c to do 2 separate .W accesses, as would do a real 68000
1050: */
1051:
1052: void Videl_Color0_WriteWord(void)
1053: {
1054: Videl_ColorReg_WriteWord();
1055: }
1056:
1057: void Videl_Color1_WriteWord(void)
1058: {
1059: Videl_ColorReg_WriteWord();
1060: }
1061:
1062: void Videl_Color2_WriteWord(void)
1063: {
1064: Videl_ColorReg_WriteWord();
1065: }
1066:
1067: void Videl_Color3_WriteWord(void)
1068: {
1069: Videl_ColorReg_WriteWord();
1070: }
1071:
1072: void Videl_Color4_WriteWord(void)
1073: {
1074: Videl_ColorReg_WriteWord();
1075: }
1076:
1077: void Videl_Color5_WriteWord(void)
1078: {
1079: Videl_ColorReg_WriteWord();
1080: }
1081:
1082: void Videl_Color6_WriteWord(void)
1083: {
1084: Videl_ColorReg_WriteWord();
1085: }
1086:
1087: void Videl_Color7_WriteWord(void)
1088: {
1089: Videl_ColorReg_WriteWord();
1090: }
1091:
1092: void Videl_Color8_WriteWord(void)
1093: {
1094: Videl_ColorReg_WriteWord();
1095: }
1096:
1097: void Videl_Color9_WriteWord(void)
1098: {
1099: Videl_ColorReg_WriteWord();
1100: }
1101:
1102: void Videl_Color10_WriteWord(void)
1103: {
1104: Videl_ColorReg_WriteWord();
1105: }
1106:
1107: void Videl_Color11_WriteWord(void)
1108: {
1109: Videl_ColorReg_WriteWord();
1110: }
1111:
1112: void Videl_Color12_WriteWord(void)
1113: {
1114: Videl_ColorReg_WriteWord();
1115: }
1116:
1117: void Videl_Color13_WriteWord(void)
1118: {
1119: Videl_ColorReg_WriteWord();
1120: }
1121:
1122: void Videl_Color14_WriteWord(void)
1123: {
1124: Videl_ColorReg_WriteWord();
1125: }
1126:
1127: void Videl_Color15_WriteWord(void)
1128: {
1129: Videl_ColorReg_WriteWord();
1130: }
1131:
1132: /**
1133: * display Videl registers values (for debugger info command)
1134: */
1.1.1.11 root 1135: void Videl_Info(FILE *fp, Uint32 dummy)
1.1.1.10 root 1136: {
1137: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
1.1.1.11 root 1138: fprintf(fp, "Not Falcon - no Videl!\n");
1.1.1.10 root 1139: return;
1140: }
1141:
1.1.1.11 root 1142: fprintf(fp, "$FF8006.b : monitor type : %02x\n", IoMem_ReadByte(0xff8006));
1143: fprintf(fp, "$FF8201.b : Video Base Hi : %02x\n", IoMem_ReadByte(0xff8201));
1144: fprintf(fp, "$FF8203.b : Video Base Mi : %02x\n", IoMem_ReadByte(0xff8203));
1145: fprintf(fp, "$FF8205.b : Video Count Hi : %02x\n", IoMem_ReadByte(0xff8205));
1146: fprintf(fp, "$FF8207.b : Video Count Mi : %02x\n", IoMem_ReadByte(0xff8207));
1147: fprintf(fp, "$FF8209.b : Video Count Lo : %02x\n", IoMem_ReadByte(0xff8209));
1148: fprintf(fp, "$FF820A.b : Sync mode : %02x\n", IoMem_ReadByte(0xff820a));
1149: fprintf(fp, "$FF820D.b : Video Base Lo : %02x\n", IoMem_ReadByte(0xff820d));
1150: fprintf(fp, "$FF820E.w : offset to next line : %04x\n", IoMem_ReadWord(0xff820e));
1151: fprintf(fp, "$FF8210.w : VWRAP - line width : %04x\n", IoMem_ReadWord(0xff8210));
1152: fprintf(fp, "$FF8260.b : ST shift mode : %02x\n", IoMem_ReadByte(0xff8260));
1153: fprintf(fp, "$FF8264.w : Horizontal scroll register : %04x\n", IoMem_ReadWord(0xff8264));
1154: fprintf(fp, "$FF8266.w : Falcon shift mode : %04x\n", IoMem_ReadWord(0xff8266));
1155: fprintf(fp, "\n");
1156: fprintf(fp, "$FF8280.w : HHC - Horizontal Hold Counter : %04x\n", IoMem_ReadWord(0xff8280));
1157: fprintf(fp, "$FF8282.w : HHT - Horizontal Hold Timer : %04x\n", IoMem_ReadWord(0xff8282));
1158: fprintf(fp, "$FF8284.w : HBB - Horizontal Border Begin : %04x\n", IoMem_ReadWord(0xff8284));
1159: fprintf(fp, "$FF8286.w : HBE - Horizontal Border End : %04x\n", IoMem_ReadWord(0xff8286));
1160: fprintf(fp, "$FF8288.w : HDB - Horizontal Display Begin : %04x\n", IoMem_ReadWord(0xff8288));
1161: fprintf(fp, "$FF828A.w : HDE - Horizontal Display End : %04x\n", IoMem_ReadWord(0xff828a));
1162: fprintf(fp, "$FF828C.w : HSS - Horizontal SS : %04x\n", IoMem_ReadWord(0xff828c));
1163: fprintf(fp, "$FF828E.w : HFS - Horizontal FS : %04x\n", IoMem_ReadWord(0xff828e));
1164: fprintf(fp, "$FF8290.w : HEE - Horizontal EE : %04x\n", IoMem_ReadWord(0xff8290));
1165: fprintf(fp, "\n");
1166: fprintf(fp, "$FF82A0.w : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0));
1167: fprintf(fp, "$FF82A2.w : VFT - Vertical Frequency Timer : %04x\n", IoMem_ReadWord(0xff82a2));
1168: fprintf(fp, "$FF82A4.w : VBB - Vertical Border Begin : %04x\n", IoMem_ReadWord(0xff82a4));
1169: fprintf(fp, "$FF82A6.w : VBE - Vertical Border End : %04x\n", IoMem_ReadWord(0xff82a6));
1170: fprintf(fp, "$FF82A8.w : VDB - Vertical Display Begin : %04x\n", IoMem_ReadWord(0xff82a8));
1171: fprintf(fp, "$FF82AA.w : VDE - Vertical Display End : %04x\n", IoMem_ReadWord(0xff82aa));
1172: fprintf(fp, "$FF82AC.w : VSS - Vertical SS : %04x\n", IoMem_ReadWord(0xff82ac));
1173: fprintf(fp, "\n");
1174: fprintf(fp, "$FF82C0.w : VCO - Video control : %04x\n", IoMem_ReadWord(0xff82c0));
1175: fprintf(fp, "$FF82C2.w : VMD - Video mode : %04x\n", IoMem_ReadWord(0xff82c2));
1176: fprintf(fp, "\n-------------------------\n");
1.1.1.10 root 1177:
1.1.1.11 root 1178: fprintf(fp, "Video base : %08x\n",
1.1.1.12 root 1179: (IoMem_ReadByte(0xff8201)<<16) +
1180: (IoMem_ReadByte(0xff8203)<<8) +
1.1.1.10 root 1181: IoMem_ReadByte(0xff820d));
1.1.1.11 root 1182: fprintf(fp, "Video count : %08x\n",
1.1.1.12 root 1183: (IoMem_ReadByte(0xff8205)<<16) +
1184: (IoMem_ReadByte(0xff8207)<<8) +
1.1.1.10 root 1185: IoMem_ReadByte(0xff8209));
1186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.