DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/ints/int10_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 "mem.h"
00022 #include "inout.h"
00023 #include "int10.h"
00024 
00025 
00026 
00027 #pragma pack(1)
00028 struct Dynamic_Functionality {
00029         RealPt static_table;            /* 00h   DWORD  address of static functionality table */
00030         Bit8u cur_mode;                         /* 04h   BYTE   video mode in effect */
00031         Bit16u num_cols;                        /* 05h   WORD   number of columns */
00032         Bit16u regen_size;                      /* 07h   WORD   length of regen buffer in bytes */
00033         Bit16u regen_start;                     /* 09h   WORD   starting address of regen buffer*/
00034         Bit16u cursor_pos[8];           /* 0Bh   WORD   cursor position for page 0-7 */
00035         Bit16u cursor_type;                     /* 1Bh   WORD   cursor type */
00036         Bit8u active_page;                      /* 1Dh   BYTE   active display page */
00037         Bit16u crtc_address;            /* 1Eh   WORD   CRTC port address */
00038         Bit8u reg_3x8;                          /* 20h   BYTE   current setting of register (3?8) */
00039         Bit8u reg_3x9;                          /* 21h   BYTE   current setting of register (3?9) */
00040         Bit8u num_rows;                         /* 22h   BYTE   number of rows */
00041         Bit16u bytes_per_char;          /* 23h   WORD   bytes/character */
00042         Bit8u dcc;                                      /* 25h   BYTE   display combination code of active display */
00043         Bit8u dcc_alternate;            /* 26h   BYTE   DCC of alternate display */
00044         Bit16u num_colors;                      /* 27h   WORD   number of colors supported in current mode */
00045         Bit8u num_pages;                        /* 29h   BYTE   number of pages supported in current mode */
00046         Bit8u num_scanlines;            /* 2Ah   BYTE   number of scan lines active mode (0,1,2,3) = (200,350,400,480) */
00047         Bit8u pri_char_block;           /* 2Bh   BYTE   primary character block */
00048         Bit8u sec_char_block;           /* 2Ch   BYTE   secondary character block */
00049         Bit8u misc_flags;                       /* 2Dh   BYTE   miscellaneous flags
00050                                                                         bit 0 all modes on all displays on
00051                                                                         1 grey summing on
00052                                                                         2 monochrome display attached
00053                                                                         3 default palette loading disabled
00054                                                                         4 cursor emulation enabled
00055                                                                         5 0 = intensity; 1 = blinking
00056                                                                         6 PS/2 P70 plasma display (without 9-dot wide font) active
00057                                                                         7 reserved
00058                                                                 */
00059         Bit8u reserved1[3];                     /* 2Eh  3 BYTEs reserved (00h) */
00060         Bit8u vid_mem;                          /* 31h   BYTE   video memory available 00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K */
00061         Bit8u savep_state_flag;         /* 32h   BYTE   save pointer state flags 
00062                                                                         bit 0 512 character set active
00063                                                                         1 dynamic save area present
00064                                                                         2 alpha font override active
00065                                                                         3 graphics font override active
00066                                                                         4 palette override active
00067                                                                         5 DCC override active
00068                                                                         6 reserved
00069                                                                         7 reserved
00070                                                                 */
00071         Bit8u reserved2[13];            /*  33h 13 BYTEs reserved (00h) */
00072 } GCC_ATTRIBUTE(packed);
00073 #pragma pack()
00074 
00075 void INT10_DisplayCombinationCode(Bit16u * dcc,bool set) {
00076         Bit8u index=0xff;
00077         Bit16u dccentry=0xffff;
00078         // walk the tables...
00079         RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER);
00080         RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10);
00081         if (svstable) {
00082                 RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02);
00083                 Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00);
00084                 if (set) {
00085                         if (entries) {
00086                                 Bit16u swap=(*dcc<<8)|(*dcc>>8);
00087                                 // search for the index in the dcc table
00088                                 for (Bit8u entry=0; entry<entries; entry++) {
00089                                         dccentry=real_readw(RealSeg(dcctable),RealOff(dcctable)+0x04+entry*2);
00090                                         if ((dccentry==*dcc) || (dccentry==swap)) {
00091                                                 index=entry;
00092                                                 break;
00093                                         }
00094                                 }
00095                         }
00096                 } else {
00097                         index=real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX);
00098                         // check if index within range
00099                         if (index<entries) {
00100                                 dccentry=real_readw(RealSeg(dcctable),RealOff(dcctable)+0x04+index*2);
00101                                 if ((dccentry&0xff)==0) dccentry>>=8;
00102                                 else if (dccentry>>8) {
00103                                         Bit16u cfg_mono=((real_readw(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0x30)==0x30)?1:0;
00104                                         if (cfg_mono^(dccentry&1)) dccentry=(dccentry<<8)|(dccentry>>8);
00105                                 }
00106                         }
00107                 }
00108         }
00109         if (set) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,index);
00110         else *dcc=dccentry;
00111 }
00112 
00113 void INT10_GetFuncStateInformation(PhysPt save) {
00114         /* set static state pointer */
00115         mem_writed(save,int10.rom.static_state);
00116         /* Copy BIOS Segment areas */
00117         Bit16u i;
00118 
00119         /* First area in Bios Seg */
00120         for (i=0;i<0x1e;i++) {
00121                 mem_writeb(save+0x4+i,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE+i));
00122         }
00123         /* Second area */
00124         mem_writeb(save+0x22,real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1);
00125         for (i=1;i<3;i++) {
00126                 mem_writeb(save+0x22+i,real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS+i));
00127         }
00128         /* Zero out rest of block */
00129         for (i=0x25;i<0x40;i++) mem_writeb(save+i,0);
00130         /* DCC */
00131         Bit16u dcc=0;
00132         INT10_DisplayCombinationCode(&dcc,false);
00133         mem_writew(save+0x25,dcc);
00134 
00135         Bit16u col_count=0;
00136         switch (CurMode->type) {
00137         case M_TEXT:
00138                 if (CurMode->mode==0x7) col_count=1; else col_count=16;break; 
00139         case M_CGA2:
00140                 col_count=2;break;
00141         case M_CGA4:
00142                 col_count=4;break;
00143         case M_EGA:
00144                 if (CurMode->mode==0x11 || CurMode->mode==0x0f) 
00145                         col_count=2; 
00146                 else 
00147                         col_count=16;
00148                 break; 
00149         case M_VGA:
00150                 col_count=256;break;
00151         default:
00152                 LOG(LOG_INT10,LOG_ERROR)("Get Func State illegal mode type %d",CurMode->type);
00153         }
00154         /* Colour count */
00155         mem_writew(save+0x27,col_count);
00156         /* Page count */
00157         mem_writeb(save+0x29,CurMode->ptotal);
00158         /* scan lines */
00159         switch (CurMode->sheight) {
00160         case 200:
00161                 mem_writeb(save+0x2a,0);break;
00162         case 350:
00163                 mem_writeb(save+0x2a,1);break;
00164         case 400:
00165                 mem_writeb(save+0x2a,2);break;
00166         case 480:
00167                 mem_writeb(save+0x2a,3);break;
00168         };
00169         /* misc flags */
00170         if (CurMode->type==M_TEXT) mem_writeb(save+0x2d,0x21);
00171         else mem_writeb(save+0x2d,0x01);
00172         /* Video Memory available */
00173         mem_writeb(save+0x31,3);
00174 }
00175 
00176 RealPt INT10_EGA_RIL_GetVersionPt(void) {
00177         /* points to a graphics ROM location at the moment
00178            as checks test for bx!=0 only */
00179         return RealMake(0xc000,0x30);
00180 }
00181 
00182 static void EGA_RIL(Bit16u dx, Bitu& port, Bitu& regs) {
00183         port = 0;
00184         regs = 0; //if nul is returned it's a single register port
00185         switch(dx) {
00186         case 0x00: /* CRT Controller (25 reg) 3B4h mono modes, 3D4h color modes */
00187                 port = real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
00188                 regs = 25;
00189                 break;
00190         case 0x08: /* Sequencer (5 registers) 3C4h */
00191                 port = 0x3C4;
00192                 regs = 5;
00193                 break;
00194         case 0x10: /* Graphics Controller (9 registers) 3CEh */
00195                 port = 0x3CE;
00196                 regs = 9;
00197                 break;
00198         case 0x18: /* Attribute Controller (20 registers) 3C0h */
00199                 port = 0x3c0;
00200                 regs = 20;
00201                 break;
00202         case 0x20: /* Miscellaneous Output register 3C2h */
00203                 port = 0x3C2;
00204                 break;
00205         case 0x28: /* Feature Control register (3BAh mono modes, 3DAh color modes) */
00206                 port = real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u;
00207                 break;
00208         case 0x30: /* Graphics 1 Position register 3CCh */
00209                 port = 0x3CC;
00210                 break;
00211         case 0x38: /* Graphics 2 Position register 3CAh */
00212                 port = 0x3CA;
00213                 break;
00214         default:
00215                 LOG(LOG_INT10,LOG_ERROR)("unknown RIL port selection %X",dx);
00216                 break;
00217         }
00218 }
00219 
00220 void INT10_EGA_RIL_ReadRegister(Bit8u & bl, Bit16u dx) {
00221         Bitu port = 0;
00222         Bitu regs = 0;
00223         EGA_RIL(dx,port,regs);
00224         if(regs == 0) {
00225                 if(port) bl = IO_Read(port);
00226         } else {
00227                 if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00228                 IO_Write(port,bl);
00229                 bl = IO_Read(port+1u);
00230                 if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00231                 LOG(LOG_INT10,LOG_NORMAL)("EGA RIL read used with multi-reg");
00232         }
00233 }
00234 
00235 void INT10_EGA_RIL_WriteRegister(Bit8u & bl, Bit8u bh, Bit16u dx) {
00236         Bitu port = 0;
00237         Bitu regs = 0;
00238         EGA_RIL(dx,port,regs);
00239         if(regs == 0) {
00240                 if(port) IO_Write(port,bl);
00241         } else {
00242                 if(port == 0x3c0) {
00243                         IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00244                         IO_Write(port,bl);
00245                         IO_Write(port,bh);
00246                 } else {
00247                         IO_Write(port,bl);
00248                         IO_Write(port+1u,bh);
00249                 }
00250                 bl = bh;//Not sure
00251                 LOG(LOG_INT10,LOG_NORMAL)("EGA RIL write used with multi-reg");
00252         }
00253 }
00254 
00255 void INT10_EGA_RIL_ReadRegisterRange(Bit8u ch, Bit8u cl, Bit16u dx, PhysPt dst) {
00256         Bitu port = 0;
00257         Bitu regs = 0;
00258         EGA_RIL(dx,port,regs);
00259         if(regs == 0) {
00260                 LOG(LOG_INT10,LOG_ERROR)("EGA RIL range read with port %x called",(int)port);
00261         } else {
00262                 if(ch<regs) {
00263                         if ((Bitu)ch+cl>regs) cl=(Bit8u)(regs-ch);
00264                         for (Bitu i=0; i<cl; i++) {
00265                                 if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00266                                 IO_Write(port,ch+i);
00267                                 mem_writeb(dst++,IO_Read(port+1u));
00268                         }
00269                         if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00270                 } else LOG(LOG_INT10,LOG_ERROR)("EGA RIL range read from %x for invalid register %x",(int)port,(int)ch);
00271         }
00272 }
00273 
00274 void INT10_EGA_RIL_WriteRegisterRange(Bit8u ch, Bit8u cl, Bit16u dx, PhysPt src) {
00275         Bitu port = 0;
00276         Bitu regs = 0;
00277         EGA_RIL(dx,port,regs);
00278         if(regs == 0) {
00279                 LOG(LOG_INT10,LOG_ERROR)("EGA RIL range write called with port %x",(int)port);
00280         } else {
00281                 if(ch<regs) {
00282                         if ((Bitu)ch+cl>regs) cl=(Bit8u)(regs-ch);
00283                         if(port == 0x3c0) {
00284                                 IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00285                                 for (Bitu i=0; i<cl; i++) {
00286                                         IO_Write(port,ch+i);
00287                                         IO_Write(port,mem_readb(src++));
00288                                 }
00289                         } else {
00290                                 for (Bitu i=0; i<cl; i++) {
00291                                         IO_Write(port,ch+i);
00292                                         IO_Write(port+1u,mem_readb(src++));
00293                                 }
00294                         }
00295                 } else LOG(LOG_INT10,LOG_ERROR)("EGA RIL range write to %x with invalid register %x",(int)port,(int)ch);
00296         }
00297 }
00298 
00299 /* register sets are of the form
00300    offset 0 (word): group index
00301    offset 2 (byte): register number (0 for single registers, ignored)
00302    offset 3 (byte): register value (return value when reading)
00303 */
00304 void INT10_EGA_RIL_ReadRegisterSet(Bit16u cx, PhysPt tbl) {
00305         /* read cx register sets */
00306         for (Bitu i=0; i<cx; i++) {
00307                 Bit8u vl=mem_readb(tbl+2);
00308                 INT10_EGA_RIL_ReadRegister(vl, mem_readw(tbl));
00309                 mem_writeb(tbl+3, vl);
00310                 tbl+=4;
00311         }
00312 }
00313 
00314 void INT10_EGA_RIL_WriteRegisterSet(Bit16u cx, PhysPt tbl) {
00315         /* write cx register sets */
00316         Bitu port = 0;
00317         Bitu regs = 0;
00318         for (Bitu i=0; i<cx; i++) {
00319                 EGA_RIL(mem_readw(tbl),port,regs);
00320                 Bit8u vl=mem_readb(tbl+3);
00321                 if(regs == 0) {
00322                         if(port) IO_Write(port,vl);
00323                 } else {
00324                         Bit8u idx=mem_readb(tbl+2);
00325                         if(port == 0x3c0) {
00326                                 IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6u);
00327                                 IO_Write(port,idx);
00328                                 IO_Write(port,vl);
00329                         } else {
00330                                 IO_Write(port,idx);
00331                                 IO_Write(port+1u,vl);
00332                         }
00333                 }
00334                 tbl+=4;
00335         }
00336 }