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                 {
00073                                 Bit16u off=(y>>1)*80+(x>>3);
00074                                 if (y&1) off+=8*1024;
00075                                 Bit8u old=real_readb(0xb800,off);
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(0xb800,off,old);
00083                 }
00084                 break;
00085         case M_TANDY16:
00086         {
00087                 // find out if we are in a 32k mode (0x9 or 0xa)
00088                 // This requires special handling on the PCJR
00089                 // because only 16k are mapped at 0xB800
00090                 bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?
00091                         true:false;
00092 
00093                 Bit16u segment, offset;
00094                 if (is_32k) {
00095                         if (machine==MCH_PCJR) {
00096                                 Bitu cpupage =
00097                                         (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
00098                                 segment = cpupage << 10; // A14-16 to addr bits 14-16
00099                         } else
00100                                 segment = 0xb800;
00101                         // bits 1 and 0 of y select the bank
00102                         // two pixels per byte (thus x>>1)
00103                         offset = ((unsigned int)y >> 2u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00104                         // select the scanline bank
00105                         offset += (8u*1024u) * ((unsigned int)y & 3u);
00106                 } else {
00107                         segment = 0xb800;
00108                         // bit 0 of y selects the bank
00109                         offset = ((unsigned int)y >> 1u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00110                         offset += (8u*1024u) * ((unsigned int)y & 1u);
00111                 }
00112 
00113                 // update the pixel
00114                 Bit8u old=real_readb(segment, offset);
00115                 Bit8u p[2];
00116                 p[1] = (old >> 4u) & 0xf;
00117                 p[0] = old & 0xf;
00118                 Bitu ind = 1-(x & 0x1);
00119 
00120                 if (color & 0x80) {
00121                         // color is to be XORed
00122                         p[ind]^=(color & 0x7f);
00123                 } else {
00124                         p[ind]=color;
00125                 }
00126                 old = (p[1] << 4u) | p[0];
00127                 real_writeb(segment,offset, old);
00128         }
00129         break;
00130         case M_LIN4:
00131                 if ((machine!=MCH_VGA) || (svgaCard!=SVGA_TsengET4K) ||
00132                                 (CurMode->swidth>800)) {
00133                         // the ET4000 BIOS supports text output in 800x600 SVGA (Gateway 2)
00134                         // putpixel warining?
00135                         break;
00136                 }
00137         case M_EGA:
00138                 {
00139                         /* Set the correct bitmask for the pixel position */
00140                         IO_Write(0x3ce,0x8);Bit8u mask=128u>>(x&7u);IO_Write(0x3cf,mask);
00141                         /* Set the color to set/reset register */
00142                         IO_Write(0x3ce,0x0);IO_Write(0x3cf,color);
00143                         /* Enable all the set/resets */
00144                         IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
00145                         /* test for xorring */
00146                         if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); }
00147                         //Perhaps also set mode 1 
00148                         /* Calculate where the pixel is in video memory */
00149                         if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
00150                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_p: %x!=%x",(int)CurMode->plength,(int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
00151                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00152                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00153                         PhysPt off=0xa0000u+(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
00154                                 (((unsigned int)y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x)>>3u);
00155                         /* Bitmask and set/reset should do the rest */
00156                         mem_readb(off);
00157                         mem_writeb(off,0xff);
00158                         /* Restore bitmask */   
00159                         IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
00160                         IO_Write(0x3ce,0x1);IO_Write(0x3cf,0);
00161                         /* Restore write operating if changed */
00162                         if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); }
00163                         break;
00164                 }
00165 
00166         case M_VGA:
00167                 mem_writeb(PhysMake(0xa000,y*320u+x),color);
00168                 break;
00169         case M_LIN8: {
00170                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u)
00171                                 LOG(LOG_INT10,LOG_ERROR)("PutPixel_VGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u);
00172                         PhysPt off=S3_LFB_BASE+y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+x;
00173                         mem_writeb(off,color);
00174                         break;
00175                 }
00176         default:
00177                 if(GCC_UNLIKELY(!putpixelwarned)) {
00178                         putpixelwarned = true;          
00179                         LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",(int)CurMode->type);
00180                 }
00181                 break;
00182         }       
00183 }
00184 
00185 void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
00186         switch (CurMode->type) {
00187         case M_CGA4:
00188                 {
00189                         Bit16u off=(y>>1)*80+(x>>2);
00190                         if (y&1) off+=8*1024;
00191                         Bit8u val=real_readb(0xb800,off);
00192                         *color=(val>>(((3-(x&3)))*2)) & 3 ;
00193                 }
00194                 break;
00195         case M_CGA2:
00196                 {
00197                         Bit16u off=(y>>1)*80+(x>>3);
00198                         if (y&1) off+=8*1024;
00199                         Bit8u val=real_readb(0xb800,off);
00200                         *color=(val>>(((7-(x&7))))) & 1 ;
00201                 }
00202                 break;
00203         case M_TANDY16:
00204                 {
00205                         bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?true:false;
00206                         Bit16u segment, offset;
00207                         if (is_32k) {
00208                                 if (machine==MCH_PCJR) {
00209                                         Bitu cpupage = (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
00210                                         segment = cpupage << 10;
00211                                 } else segment = 0xb800;
00212                                 offset = ((unsigned int)y >> 2u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00213                                 offset += (8u*1024u) * (y & 3u);
00214                         } else {
00215                                 segment = 0xb800;
00216                                 offset = ((unsigned int)y >> 1u) * ((unsigned int)CurMode->swidth >> 1u) + ((unsigned int)x>>1u);
00217                                 offset += (8u*1024u) * (y & 1u);
00218                         }
00219                         Bit8u val=real_readb(segment,offset);
00220                         *color=(val>>((x&1)?0:4)) & 0xf;
00221                 }
00222                 break;
00223         case M_EGA:
00224                 {
00225                         /* Calculate where the pixel is in video memory */
00226                         if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
00227                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_p: %x!=%x",(int)CurMode->plength,(int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
00228                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00229                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00230                         PhysPt off=0xa0000u+(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
00231                                 (((unsigned int)y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x)>>3u);
00232                         Bitu shift=7u-(x & 7u);
00233                         /* Set the read map */
00234                         *color=0;
00235                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,0);
00236                         *color|=((mem_readb(off)>>shift) & 1) << 0;
00237                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,1);
00238                         *color|=((mem_readb(off)>>shift) & 1) << 1;
00239                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,2);
00240                         *color|=((mem_readb(off)>>shift) & 1) << 2;
00241                         IO_Write(0x3ce,0x4);IO_Write(0x3cf,3);
00242                         *color|=((mem_readb(off)>>shift) & 1) << 3;
00243                         break;
00244                 }
00245         case M_VGA:
00246                 *color=mem_readb(PhysMake(0xa000,320*y+x));
00247                 break;
00248         case M_LIN8: {
00249                         if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
00250                                 LOG(LOG_INT10,LOG_ERROR)("GetPixel_VGA_w: %x!=%x",(int)CurMode->swidth,(int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
00251                         PhysPt off=S3_LFB_BASE+(unsigned int)y*(unsigned int)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8u+(unsigned int)x;
00252                         *color = mem_readb(off);
00253                         break;
00254                 }
00255         default:
00256                 LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",(int)CurMode->type);
00257                 break;
00258         }       
00259 }
00260