DOSBox-X
|
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