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