DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/vga_misc.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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=val;
00081         if (val & 0x1) {
00082                 IO_RegisterWriteHandler(0x3d4,vga_write_p3d4,IO_MB);
00083                 IO_RegisterReadHandler(0x3d4,vga_read_p3d4,IO_MB);
00084                 IO_RegisterReadHandler(0x3da,vga_read_p3da,IO_MB);
00085 
00086                 IO_RegisterWriteHandler(0x3d5,vga_write_p3d5,IO_MB);
00087                 IO_RegisterReadHandler(0x3d5,vga_read_p3d5,IO_MB);
00088 
00089                 IO_FreeWriteHandler(0x3b4,IO_MB);
00090                 IO_FreeReadHandler(0x3b4,IO_MB);
00091                 IO_FreeWriteHandler(0x3b5,IO_MB);
00092                 IO_FreeReadHandler(0x3b5,IO_MB);
00093                 IO_FreeReadHandler(0x3ba,IO_MB);
00094         } else {
00095                 IO_RegisterWriteHandler(0x3b4,vga_write_p3d4,IO_MB);
00096                 IO_RegisterReadHandler(0x3b4,vga_read_p3d4,IO_MB);
00097                 IO_RegisterReadHandler(0x3ba,vga_read_p3da,IO_MB);
00098 
00099                 IO_RegisterWriteHandler(0x3b5,vga_write_p3d5,IO_MB);
00100                 IO_RegisterReadHandler(0x3b5,vga_read_p3d5,IO_MB);
00101 
00102                 IO_FreeWriteHandler(0x3d4,IO_MB);
00103                 IO_FreeReadHandler(0x3d4,IO_MB);
00104                 IO_FreeWriteHandler(0x3d5,IO_MB);
00105                 IO_FreeReadHandler(0x3d5,IO_MB);
00106                 IO_FreeReadHandler(0x3da,IO_MB);
00107         }
00108         /*
00109                 0       If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh.
00110                 2-3     Clock Select. 0: 25MHz, 1: 28MHz
00111                 5       When in Odd/Even modes Select High 64k bank if set
00112                 6       Horizontal Sync Polarity. Negative if set
00113                 7       Vertical Sync Polarity. Negative if set
00114                         Bit 6-7 indicates the number of lines on the display:
00115                         1:  400, 2: 350, 3: 480
00116                         Note: Set to all zero on a hardware reset.
00117                         Note: This register can be read from port 3CCh.
00118         */
00119 }
00120 
00121 
00122 static Bitu read_p3cc(Bitu port,Bitu iolen) {
00123     (void)port;//UNUSED
00124     (void)iolen;//UNUSED
00125         return vga.misc_output;
00126 }
00127 
00128 // VGA feature control register
00129 static Bitu read_p3ca(Bitu port,Bitu iolen) {
00130     (void)port;//UNUSED
00131     (void)iolen;//UNUSED
00132         return 0;
00133 }
00134 
00135 static Bitu read_p3c8(Bitu port,Bitu iolen) {
00136     (void)port;//UNUSED
00137     (void)iolen;//UNUSED
00138         return 0x10;
00139 }
00140 
00141 static Bitu read_p3c2(Bitu port,Bitu iolen) {
00142     (void)port;//UNUSED
00143     (void)iolen;//UNUSED
00144         Bit8u retval=0;
00145 
00146         if (machine==MCH_EGA) retval = 0x0F;
00147         else if (IS_VGA_ARCH) retval = 0x60;
00148 
00149         if(IS_EGAVGA_ARCH) {
00150                 switch((vga.misc_output>>2)&3) {
00151                         case 0:
00152                         case 3:
00153                                 retval |= 0x10; // 0110 switch positions
00154                                 break;
00155                         default:
00156                                 break;
00157                 }
00158         }
00159 
00160         if (vga.draw.vret_triggered) retval |= 0x80;
00161         return retval;
00162         /*
00163                 0-3 0xF on EGA, 0x0 on VGA 
00164                 4       Status of the switch selected by the Miscellaneous Output
00165                         Register 3C2h bit 2-3. Switch high if set.
00166                         (apparently always 1 on VGA)
00167                 5       (EGA) Pin 19 of the Feature Connector (FEAT0) is high if set
00168                 6       (EGA) Pin 17 of the Feature Connector (FEAT1) is high if set
00169                         (default differs by card, ET4000 sets them both)
00170                 7       If set IRQ 2 has happened due to Vertical Retrace.
00171                         Should be cleared by IRQ 2 interrupt routine by clearing port 3d4h
00172                         index 11h bit 4.
00173         */
00174 }
00175 
00176 void VGA_SetupMisc(void) {
00177         if (IS_EGAVGA_ARCH) {
00178                 vga.draw.vret_triggered=false;
00179                 IO_RegisterReadHandler(0x3c2,read_p3c2,IO_MB);
00180                 IO_RegisterWriteHandler(0x3c2,write_p3c2,IO_MB);
00181                 if (IS_VGA_ARCH) {
00182                         IO_RegisterReadHandler(0x3ca,read_p3ca,IO_MB);
00183                         IO_RegisterReadHandler(0x3cc,read_p3cc,IO_MB);
00184                 } else {
00185                         IO_RegisterReadHandler(0x3c8,read_p3c8,IO_MB);
00186                 }
00187         } else if (machine==MCH_CGA || machine==MCH_AMSTRAD || IS_TANDY_ARCH) {
00188                 IO_RegisterReadHandler(0x3da,vga_read_p3da,IO_MB);
00189         }
00190 }
00191 
00192 void VGA_UnsetupMisc(void) {
00193     IO_FreeWriteHandler(0x3b4,IO_MB);
00194     IO_FreeReadHandler(0x3b4,IO_MB);
00195     IO_FreeWriteHandler(0x3b5,IO_MB);
00196     IO_FreeReadHandler(0x3b5,IO_MB);
00197     IO_FreeWriteHandler(0x3c2,IO_MB);
00198     IO_FreeReadHandler(0x3c2,IO_MB);
00199     IO_FreeWriteHandler(0x3c8,IO_MB);
00200     IO_FreeReadHandler(0x3c8,IO_MB);
00201     IO_FreeWriteHandler(0x3ca,IO_MB);
00202     IO_FreeReadHandler(0x3ca,IO_MB);
00203     IO_FreeWriteHandler(0x3cc,IO_MB);
00204     IO_FreeReadHandler(0x3cc,IO_MB);
00205     IO_FreeWriteHandler(0x3d4,IO_MB);
00206     IO_FreeReadHandler(0x3d4,IO_MB);
00207     IO_FreeWriteHandler(0x3d5,IO_MB);
00208     IO_FreeReadHandler(0x3d5,IO_MB);
00209     IO_FreeWriteHandler(0x3da,IO_MB);
00210     IO_FreeReadHandler(0x3da,IO_MB);
00211 }
00212 
00213 void pc98_clear_text(void) {
00214         for (unsigned int i = 0; i < 0x2000; i += 2) {
00215                 *((uint16_t*)(vga.mem.linear + i)) = 0;
00216                 *((uint16_t*)(vga.mem.linear + i + 0x2000)) = 0xE1;
00217         }
00218 }
00219 
00220 void pc98_clear_graphics(void) {
00221         for (unsigned int i = 0; i < 0x8000; i += 2) {
00222                 *((uint16_t*)(vga.mem.linear + i + 0x08000)) = 0;
00223                 *((uint16_t*)(vga.mem.linear + i + 0x10000)) = 0;
00224                 *((uint16_t*)(vga.mem.linear + i + 0x18000)) = 0;
00225                 *((uint16_t*)(vga.mem.linear + i + 0x20000)) = 0;
00226                 *((uint16_t*)(vga.mem.linear + i + 0x28000)) = 0;
00227                 *((uint16_t*)(vga.mem.linear + i + 0x30000)) = 0;
00228                 *((uint16_t*)(vga.mem.linear + i + 0x38000)) = 0;
00229                 *((uint16_t*)(vga.mem.linear + i + 0x40000)) = 0;
00230         }
00231 }