DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/ints/int10_put_pixel.cpp
00001 /*
00002  *  Copyright (C) 2002-2013  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 static Bit8u cga_masks[4]={0x3f,0xcf,0xf3,0xfc};
00026 static Bit8u cga_masks2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
00027 
00028 void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
00029         static bool putpixelwarned = false;
00030 
00031         switch (CurMode->type) {
00032         case M_CGA4:
00033         {
00034                 if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)<=5) {
00035                         // this is a 16k mode
00036                         Bit16u off=(y>>1)*80+(x>>2);
00037                         if (y&1) off+=8*1024;
00038 
00039                         Bit8u old=real_readb(0xb800,off);
00040                         if (color & 0x80) {
00041                                 color&=3;
00042                                 old^=color << (2*(3-(x&3)));
00043                         } else {
00044                                 old=(old&cga_masks[x&3])|((color&3) << (2*(3-(x&3))));
00045                         }
00046                         real_writeb(0xb800,off,old);
00047                 } else {
00048                         // a 32k mode: PCJr special case (see M_TANDY16)
00049                         Bit16u seg;
00050                         if (machine==MCH_PCJR) {
00051                                 Bitu cpupage =
00052                                         (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
00053                                 seg = cpupage << 10; // A14-16 to addr bits 14-16
00054                         } else
00055                                 seg = 0xb800;
00056 
00057                         Bit16u off=(y>>2)*160+((x>>2)&(~1));
00058                         off+=(8*1024) * (y & 3);
00059 
00060                         Bit16u old=real_readw(seg,off);
00061                         if (color & 0x80) {
00062                                 old^=(color&1) << (7-(x&7));
00063                                 old^=((color&2)>>1) << ((7-(x&7))+8);
00064                         } else {
00065                                 old=(old&(~(0x101<<(7-(x&7))))) | ((color&1) << (7-(x&7))) | (((color&2)>>1) << ((7-(x&7))+8));
00066                         }
00067                         real_writew(seg,off,old);
00068                 }
00069         }
00070         break;
00071         case M_CGA2:
00072         if (machine == MCH_MCGA && real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) == 0x11) {
00073             Bit16u off=y*80+(x>>3);
00074             Bit8u old=real_readb(0xa000,off);
00075 
00076             if (color & 0x80) {
00077                 color&=1;
00078                 old^=color << ((7-(x&7)));
00079             } else {
00080                 old=(old&cga_masks2[x&7])|((color&1) << ((7-(x&7))));
00081             }
00082             real_writeb(0xa000,off,old);
00083         }
00084         else {
00085                                 Bit16u off=(y>>1)*80+(x>>3);
00086                                 if (y&1) off+=8*1024;
00087                                 Bit8u old=real_readb(0xb800,off);
00088                                 if (color & 0x80) {
00089                                         color&=1;
00090                                         old^=color << ((7-(x&7)));
00091                                 } else {
00092                                         old=(old&cga_masks2[x&7])|((color&1) << ((7-(x&7))));
00093                                 }
00094                                 real_writeb(0xb800,off,old);
00095                 }
00096                 break;
00097         case M_TANDY16:
00098         {
00099                 // find out if we are in a 32k mode (0x9 or 0xa)
00100                 // This requires special handling on the PCJR
00101                 // because only 16k are mapped at 0xB800
00102                 bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?
00103                         true:false;
00104 
00105                 Bit16u segment, offset;
00106                 if (is_32k) {
00107                         if (machine==MCH_PCJR) {
00108                                 Bitu cpupage =
00109                                         (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
00110                                 segment = cpupage << 10; // A14-16 to addr bits 14-16
00111                         } else
00112                                 segment = 0xb800;
00113                         // bits 1 and 0 of y select the bank
00114                         // two pixels per byte (thus x>>1)
00115                         offset = ((unsigned int)y >> 2u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00116                         // select the scanline bank
00117                         offset += (8u*1024u) * ((unsigned int)y & 3u);
00118                 } else {
00119                         segment = 0xb800;
00120                         // bit 0 of y selects the bank
00121                         offset = ((unsigned int)y >> 1u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00122                         offset += (8u*1024u) * ((unsigned int)y & 1u);
00123                 }
00124 
00125                 // update the pixel
00126                 Bit8u old=real_readb(segment, offset);
00127                 Bit8u p[2];
00128                 p[1] = (old >> 4u) & 0xf;
00129                 p[0] = old & 0xf;
00130                 Bitu ind = 1-(x & 0x1);
00131 
00132                 if (color & 0x80) {
00133                         // color is to be XORed
00134                         p[ind]^=(color & 0x7f);
00135                 } else {
00136                         p[ind]=color;
00137                 }
00138                 old = (p[1] << 4u) | p[0];
00139                 real_writeb(segment,offset, old);
00140         }
00141         break;
00142         case M_LIN4:
00143                 if ((machine!=MCH_VGA) || (svgaCard!=SVGA_TsengET4K) ||
00144                                 (CurMode->swidth>800)) {
00145                         // the ET4000 BIOS supports text output in 800x600 SVGA (Gateway 2)
00146                         // putpixel warining?
00147                         break;
00148                 }
00149         case M_EGA:
00150                 {
00151                         /* Set the correct bitmask for the pixel position */
00152                         IO_Write(0x3ce,0x8);Bit8u mask=128u>>(x&7u);IO_Write(0x3cf,mask);
00153                         /* Set the color to set/reset register */
00154                         IO_Write(0x3ce,0x0);IO_Write(0x3cf,color);
00155                         /* Enable all the set/resets */
00156                         IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
00157                         /* test for xorring */
00158                         if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); }
00159                         //Perhaps also set mode 1 
00160                         /* Calculate where the pixel is in video memory */
00161                         if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
00162                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_p: %x!=%x",(int)CurMode->plength,(int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
00163                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00164                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00165                         PhysPt off=0xa0000u+(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
00166                                 (((unsigned int)y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x)>>3u);
00167                         /* Bitmask and set/reset should do the rest */
00168                         mem_readb(off);
00169                         mem_writeb(off,0xff);
00170                         /* Restore bitmask */   
00171                         IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
00172                         IO_Write(0x3ce,0x1);IO_Write(0x3cf,0);
00173                         /* Restore write operating if changed */
00174                         if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); }
00175                         break;
00176                 }
00177 
00178         case M_VGA:
00179                 mem_writeb(PhysMake(0xa000,y*320u+x),color);
00180                 break;
00181         case M_LIN8: {
00182                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u)
00183                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_VGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u);
00184                         PhysPt off=S3_LFB_BASE+y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+x;
00185                         mem_writeb(off,color);
00186                         break;
00187                 }
00188         default:
00189                 if(GCC_UNLIKELY(!putpixelwarned)) {
00190                         putpixelwarned = true;          
00191                         LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",(int)CurMode->type);
00192                 }
00193                 break;
00194         }       
00195 }
00196 
00197 void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
00198         switch (CurMode->type) {
00199         case M_CGA4:
00200                 {
00201                         Bit16u off=(y>>1)*80+(x>>2);
00202                         if (y&1) off+=8*1024;
00203                         Bit8u val=real_readb(0xb800,off);
00204                         *color=(val>>(((3-(x&3)))*2)) & 3 ;
00205                 }
00206                 break;
00207         case M_CGA2:
00208                 {
00209                         Bit16u off=(y>>1)*80+(x>>3);
00210                         if (y&1) off+=8*1024;
00211                         Bit8u val=real_readb(0xb800,off);
00212                         *color=(val>>(((7-(x&7))))) & 1 ;
00213                 }
00214                 break;
00215         case M_TANDY16:
00216                 {
00217                         bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?true:false;
00218                         Bit16u segment, offset;
00219                         if (is_32k) {
00220                                 if (machine==MCH_PCJR) {
00221                                         Bitu cpupage = (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
00222                                         segment = cpupage << 10;
00223                                 } else segment = 0xb800;
00224                                 offset = ((unsigned int)y >> 2u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00225                                 offset += (8u*1024u) * (y & 3u);
00226                         } else {
00227                                 segment = 0xb800;
00228                                 offset = ((unsigned int)y >> 1u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00229                                 offset += (8u*1024u) * (y & 1u);
00230                         }
00231                         Bit8u val=real_readb(segment,offset);
00232                         *color=(val>>((x&1)?0:4)) & 0xf;
00233                 }
00234                 break;
00235         case M_EGA:
00236                 {
00237                         /* Calculate where the pixel is in video memory */
00238                         if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
00239                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_p: %x!=%x",(int)CurMode->plength,(int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
00240                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00241                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00242                         PhysPt off=0xa0000u+(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
00243                                 (((unsigned int)y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x)>>3u);
00244                         Bitu shift=7u-(x & 7u);
00245                         /* Set the read map */
00246                         *color=0;
00247                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,0);
00248                         *color|=((mem_readb(off)>>shift) & 1) << 0;
00249                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,1);
00250                         *color|=((mem_readb(off)>>shift) & 1) << 1;
00251                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,2);
00252                         *color|=((mem_readb(off)>>shift) & 1) << 2;
00253                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,3);
00254                         *color|=((mem_readb(off)>>shift) & 1) << 3;
00255                         break;
00256                 }
00257         case M_VGA:
00258                 *color=mem_readb(PhysMake(0xa000,320*y+x));
00259                 break;
00260         case M_LIN8: {
00261                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00262                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_VGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00263                         PhysPt off=S3_LFB_BASE+(unsigned int)y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x;
00264                         *color = mem_readb(off);
00265                         break;
00266                 }
00267         default:
00268                 LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",(int)CurMode->type);
00269                 break;
00270         }       
00271 }
00272