DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/vga_misc.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include "dosbox.h"
00021 #include "inout.h"
00022 #include "pic.h"
00023 #include "vga.h"
00024 #include <math.h>
00025 
00026 void vsync_poll_debug_notify();
00027 
00028 void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen);
00029 Bitu vga_read_p3d4(Bitu port,Bitu iolen);
00030 void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen);
00031 Bitu vga_read_p3d5(Bitu port,Bitu iolen);
00032 
00033 /* allow the user to specify that undefined bits in 3DA/3BA be set to some nonzero value.
00034  * this is needed for "JOOP #2" by Europe demo, which has some weird retrace tracking code
00035  * like this:
00036  *
00037  *        in    al,dx       ; <- dx = 3DAh
00038  * l1:    shr   al,1        ; AL >>= 1, CF = bit shifted out
00039  *        jnc   l1
00040  *
00041  * of course, if AL == 0, it becomes an infinite loop. this is why this option exists. */
00042 unsigned char vga_p3da_undefined_bits = 0;
00043 
00044 Bitu vga_read_p3da(Bitu port,Bitu iolen) {
00045     (void)port;//UNUSED
00046     (void)iolen;//UNUSED
00047         Bit8u retval = vga_p3da_undefined_bits;
00048         double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
00049 
00050         vga.internal.attrindex=false;
00051         vga.tandy.pcjr_flipflop=false;
00052 
00053         // 3DAh (R):  Status Register
00054         // bit   0  Horizontal or Vertical blanking
00055         //       3  Vertical sync
00056 
00057         if (timeInFrame >= vga.draw.delay.vdend) {
00058                 retval |= 1; // vertical blanking
00059         } else {
00060                 double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal);
00061                 if (timeInLine >= vga.draw.delay.hblkstart && 
00062                         timeInLine <= vga.draw.delay.hblkend) {
00063                         retval |= 1; // horizontal blanking
00064                 }
00065         }
00066 
00067     if (timeInFrame >= vga.draw.delay.vrstart &&
00068         timeInFrame <= vga.draw.delay.vrend) {
00069         retval |= 8; // vertical retrace
00070     }
00071 
00072         vsync_poll_debug_notify();
00073         return retval;
00074 }
00075 
00076 static void write_p3c2(Bitu port,Bitu val,Bitu iolen) {
00077     (void)port;//UNUSED
00078     (void)iolen;//UNUSED
00079         if((machine==MCH_EGA) && ((vga.misc_output^val)&0xc)) VGA_StartResize();
00080         vga.misc_output=(Bit8u)val;
00081         Bitu base=(val & 0x1) ? 0x3d0 : 0x3b0;
00082         Bitu free=(val & 0x1) ? 0x3b0 : 0x3d0;
00083         Bitu first=2, last=2;
00084         if (machine==MCH_EGA) {first=0; last=3;}
00085 
00086         for (Bitu i=first; i<=last; i++) {
00087                 IO_RegisterWriteHandler(base+i*2,vga_write_p3d4,IO_MB);
00088                 IO_RegisterReadHandler(base+i*2,vga_read_p3d4,IO_MB);
00089                 IO_RegisterWriteHandler(base+i*2+1,vga_write_p3d5,IO_MB);
00090                 IO_RegisterReadHandler(base+i*2+1,vga_read_p3d5,IO_MB);
00091                 IO_FreeWriteHandler(free+i*2,IO_MB);
00092                 IO_FreeReadHandler(free+i*2,IO_MB);
00093                 IO_FreeWriteHandler(free+i*2+1,IO_MB);
00094                 IO_FreeReadHandler(free+i*2+1,IO_MB);
00095         }
00096 
00097         IO_RegisterReadHandler(base+0xa,vga_read_p3da,IO_MB);
00098         IO_FreeReadHandler(free+0xa,IO_MB);
00099         
00100         /*
00101                 0       If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh.
00102                 2-3     Clock Select. 0: 25MHz, 1: 28MHz
00103                 5       When in Odd/Even modes Select High 64k bank if set
00104                 6       Horizontal Sync Polarity. Negative if set
00105                 7       Vertical Sync Polarity. Negative if set
00106                         Bit 6-7 indicates the number of lines on the display:
00107                         1:  400, 2: 350, 3: 480
00108                         Note: Set to all zero on a hardware reset.
00109                         Note: This register can be read from port 3CCh.
00110         */
00111 }
00112 
00113 
00114 static Bitu read_p3cc(Bitu port,Bitu iolen) {
00115     (void)port;//UNUSED
00116     (void)iolen;//UNUSED
00117         return vga.misc_output;
00118 }
00119 
00120 // VGA feature control register
00121 static Bitu read_p3ca(Bitu port,Bitu iolen) {
00122     (void)port;//UNUSED
00123     (void)iolen;//UNUSED
00124         return 0;
00125 }
00126 
00127 static Bitu read_p3c8(Bitu port,Bitu iolen) {
00128     (void)port;//UNUSED
00129     (void)iolen;//UNUSED
00130         return 0x10;
00131 }
00132 
00133 static Bitu read_p3c2(Bitu port,Bitu iolen) {
00134     (void)port;//UNUSED
00135     (void)iolen;//UNUSED
00136         Bit8u retval=0;
00137 
00138         if (machine==MCH_EGA) retval = 0x0F;
00139         else if (IS_VGA_ARCH) retval = 0x60;
00140 
00141         if(IS_EGAVGA_ARCH) {
00142                 switch((vga.misc_output>>2)&3) {
00143                         case 0:
00144                         case 3:
00145                                 retval |= 0x10; // 0110 switch positions
00146                                 break;
00147                         default:
00148                                 break;
00149                 }
00150         }
00151 
00152         if (vga.draw.vret_triggered) retval |= 0x80;
00153         return retval;
00154         /*
00155                 0-3 0xF on EGA, 0x0 on VGA 
00156                 4       Status of the switch selected by the Miscellaneous Output
00157                         Register 3C2h bit 2-3. Switch high if set.
00158                         (apparently always 1 on VGA)
00159                 5       (EGA) Pin 19 of the Feature Connector (FEAT0) is high if set
00160                 6       (EGA) Pin 17 of the Feature Connector (FEAT1) is high if set
00161                         (default differs by card, ET4000 sets them both)
00162                 7       If set IRQ 2 has happened due to Vertical Retrace.
00163                         Should be cleared by IRQ 2 interrupt routine by clearing port 3d4h
00164                         index 11h bit 4.
00165         */
00166 }
00167 
00168 void VGA_SetupMisc(void) {
00169         if (IS_EGAVGA_ARCH) {
00170                 vga.draw.vret_triggered=false;
00171                 IO_RegisterReadHandler(0x3c2,read_p3c2,IO_MB);
00172                 IO_RegisterWriteHandler(0x3c2,write_p3c2,IO_MB);
00173                 if (IS_VGA_ARCH) {
00174                         IO_RegisterReadHandler(0x3ca,read_p3ca,IO_MB);
00175                         IO_RegisterReadHandler(0x3cc,read_p3cc,IO_MB);
00176                 } else {
00177                         IO_RegisterReadHandler(0x3c8,read_p3c8,IO_MB);
00178                 }
00179         } else if (machine==MCH_CGA || machine==MCH_MCGA || machine==MCH_AMSTRAD || IS_TANDY_ARCH) {
00180                 IO_RegisterReadHandler(0x3da,vga_read_p3da,IO_MB);
00181         }
00182 }
00183 
00184 void VGA_UnsetupMisc(void) {
00185     IO_FreeWriteHandler(0x3b4,IO_MB);
00186     IO_FreeReadHandler(0x3b4,IO_MB);
00187     IO_FreeWriteHandler(0x3b5,IO_MB);
00188     IO_FreeReadHandler(0x3b5,IO_MB);
00189     IO_FreeWriteHandler(0x3c2,IO_MB);
00190     IO_FreeReadHandler(0x3c2,IO_MB);
00191     IO_FreeWriteHandler(0x3c8,IO_MB);
00192     IO_FreeReadHandler(0x3c8,IO_MB);
00193     IO_FreeWriteHandler(0x3ca,IO_MB);
00194     IO_FreeReadHandler(0x3ca,IO_MB);
00195     IO_FreeWriteHandler(0x3cc,IO_MB);
00196     IO_FreeReadHandler(0x3cc,IO_MB);
00197     IO_FreeWriteHandler(0x3d4,IO_MB);
00198     IO_FreeReadHandler(0x3d4,IO_MB);
00199     IO_FreeWriteHandler(0x3d5,IO_MB);
00200     IO_FreeReadHandler(0x3d5,IO_MB);
00201     IO_FreeWriteHandler(0x3da,IO_MB);
00202     IO_FreeReadHandler(0x3da,IO_MB);
00203 }
00204 
00205 void pc98_clear_text(void) {
00206         for (unsigned int i = 0; i < 0x2000; i += 2) {
00207                 *((uint16_t*)(vga.mem.linear + i)) = 0;
00208                 *((uint16_t*)(vga.mem.linear + i + 0x2000)) = 0xE1;
00209         }
00210 }
00211 
00212 void pc98_clear_graphics(void) {
00213         for (unsigned int i = 0; i < 0x8000; i += 2) {
00214                 *((uint16_t*)(vga.mem.linear + i + 0x08000)) = 0;
00215                 *((uint16_t*)(vga.mem.linear + i + 0x10000)) = 0;
00216                 *((uint16_t*)(vga.mem.linear + i + 0x18000)) = 0;
00217                 *((uint16_t*)(vga.mem.linear + i + 0x20000)) = 0;
00218                 *((uint16_t*)(vga.mem.linear + i + 0x28000)) = 0;
00219                 *((uint16_t*)(vga.mem.linear + i + 0x30000)) = 0;
00220                 *((uint16_t*)(vga.mem.linear + i + 0x38000)) = 0;
00221                 *((uint16_t*)(vga.mem.linear + i + 0x40000)) = 0;
00222         }
00223 }