1 /*
2 * Copyright (C) 2002-2015 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include "dosbox.h"
21 #include "mem.h"
22 #include "inout.h"
23 #include "int10.h"
24
25 static Bit8u cga_masks[4]={0x3f,0xcf,0xf3,0xfc};
26 static Bit8u cga_masks2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
27
INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color)28 void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
29 static bool putpixelwarned = false;
30
31 switch (CurMode->type) {
32 case M_CGA4:
33 {
34 if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)<=5) {
35 // this is a 16k mode
36 Bit16u off=(y>>1)*80+(x>>2);
37 if (y&1) off+=8*1024;
38
39 Bit8u old=real_readb(0xb800,off);
40 if (color & 0x80) {
41 color&=3;
42 old^=color << (2*(3-(x&3)));
43 } else {
44 old=(old&cga_masks[x&3])|((color&3) << (2*(3-(x&3))));
45 }
46 real_writeb(0xb800,off,old);
47 } else {
48 // a 32k mode: PCJr special case (see M_TANDY16)
49 Bit16u seg;
50 if (machine==MCH_PCJR) {
51 Bitu cpupage =
52 (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
53 seg = cpupage << 10; // A14-16 to addr bits 14-16
54 } else
55 seg = 0xb800;
56
57 Bit16u off=(y>>2)*160+((x>>2)&(~1));
58 off+=(8*1024) * (y & 3);
59
60 Bit16u old=real_readw(seg,off);
61 if (color & 0x80) {
62 old^=(color&1) << (7-(x&7));
63 old^=((color&2)>>1) << ((7-(x&7))+8);
64 } else {
65 old=(old&(~(0x101<<(7-(x&7))))) | ((color&1) << (7-(x&7))) | (((color&2)>>1) << ((7-(x&7))+8));
66 }
67 real_writew(seg,off,old);
68 }
69 }
70 break;
71 case M_CGA2:
72 {
73 Bit16u off=(y>>1)*80+(x>>3);
74 if (y&1) off+=8*1024;
75 Bit8u old=real_readb(0xb800,off);
76 if (color & 0x80) {
77 color&=1;
78 old^=color << ((7-(x&7)));
79 } else {
80 old=(old&cga_masks2[x&7])|((color&1) << ((7-(x&7))));
81 }
82 real_writeb(0xb800,off,old);
83 }
84 break;
85 case M_TANDY16:
86 {
87 // find out if we are in a 32k mode (0x9 or 0xa)
88 // This requires special handling on the PCJR
89 // because only 16k are mapped at 0xB800
90 bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?
91 true:false;
92
93 Bit16u segment, offset;
94 if (is_32k) {
95 if (machine==MCH_PCJR) {
96 Bitu cpupage =
97 (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
98 segment = cpupage << 10; // A14-16 to addr bits 14-16
99 } else
100 segment = 0xb800;
101 // bits 1 and 0 of y select the bank
102 // two pixels per byte (thus x>>1)
103 offset = (y >> 2) * (CurMode->swidth >> 1) + (x>>1);
104 // select the scanline bank
105 offset += (8*1024) * (y & 3);
106 } else {
107 segment = 0xb800;
108 // bit 0 of y selects the bank
109 offset = (y >> 1) * (CurMode->swidth >> 1) + (x>>1);
110 offset += (8*1024) * (y & 1);
111 }
112
113 // update the pixel
114 Bit8u old=real_readb(segment, offset);
115 Bit8u p[2];
116 p[1] = (old >> 4) & 0xf;
117 p[0] = old & 0xf;
118 Bitu ind = 1-(x & 0x1);
119
120 if (color & 0x80) {
121 // color is to be XORed
122 p[ind]^=(color & 0x7f);
123 } else {
124 p[ind]=color;
125 }
126 old = (p[1] << 4) | p[0];
127 real_writeb(segment,offset, old);
128 }
129 break;
130 case M_LIN4:
131 if ((machine!=MCH_VGA) || (svgaCard!=SVGA_TsengET4K) ||
132 (CurMode->swidth>800)) {
133 // the ET4000 BIOS supports text output in 800x600 SVGA (Gateway 2)
134 // putpixel warining?
135 break;
136 }
137 case M_EGA:
138 {
139 /* Set the correct bitmask for the pixel position */
140 IO_Write(0x3ce,0x8);Bit8u mask=128>>(x&7);IO_Write(0x3cf,mask);
141 /* Set the color to set/reset register */
142 IO_Write(0x3ce,0x0);IO_Write(0x3cf,color);
143 /* Enable all the set/resets */
144 IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
145 /* test for xorring */
146 if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); }
147 //Perhaps also set mode 1
148 /* Calculate where the pixel is in video memory */
149 if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
150 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_p: %x!=%x",CurMode->plength,real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
151 if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
152 LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
153 PhysPt off=0xa0000+real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
154 ((y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x)>>3);
155 /* Bitmask and set/reset should do the rest */
156 mem_readb(off);
157 mem_writeb(off,0xff);
158 /* Restore bitmask */
159 IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
160 IO_Write(0x3ce,0x1);IO_Write(0x3cf,0);
161 /* Restore write operating if changed */
162 if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); }
163 break;
164 }
165
166 case M_VGA:
167 mem_writeb(PhysMake(0xa000,y*320+x),color);
168 break;
169 case M_LIN8: {
170 if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
171 LOG(LOG_INT10,LOG_ERROR)("PutPixel_VGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
172 PhysPt off=S3_LFB_BASE+y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x;
173 mem_writeb(off,color);
174 break;
175 }
176 default:
177 if(GCC_UNLIKELY(!putpixelwarned)) {
178 putpixelwarned = true;
179 LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",CurMode->type);
180 }
181 break;
182 }
183 }
184
INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color)185 void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
186 switch (CurMode->type) {
187 case M_CGA4:
188 {
189 Bit16u off=(y>>1)*80+(x>>2);
190 if (y&1) off+=8*1024;
191 Bit8u val=real_readb(0xb800,off);
192 *color=(val>>(((3-(x&3)))*2)) & 3 ;
193 }
194 break;
195 case M_CGA2:
196 {
197 Bit16u off=(y>>1)*80+(x>>3);
198 if (y&1) off+=8*1024;
199 Bit8u val=real_readb(0xb800,off);
200 *color=(val>>(((7-(x&7))))) & 1 ;
201 }
202 break;
203 case M_TANDY16:
204 {
205 bool is_32k = (real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE) >= 9)?true:false;
206 Bit16u segment, offset;
207 if (is_32k) {
208 if (machine==MCH_PCJR) {
209 Bitu cpupage = (real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE) >> 3) & 0x7;
210 segment = cpupage << 10;
211 } else segment = 0xb800;
212 offset = (y >> 2) * (CurMode->swidth >> 1) + (x>>1);
213 offset += (8*1024) * (y & 3);
214 } else {
215 segment = 0xb800;
216 offset = (y >> 1) * (CurMode->swidth >> 1) + (x>>1);
217 offset += (8*1024) * (y & 1);
218 }
219 Bit8u val=real_readb(segment,offset);
220 *color=(val>>((x&1)?0:4)) & 0xf;
221 }
222 break;
223 case M_EGA:
224 {
225 /* Calculate where the pixel is in video memory */
226 if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE))
227 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_p: %x!=%x",CurMode->plength,real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE));
228 if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
229 LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
230 PhysPt off=0xa0000+real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+
231 ((y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x)>>3);
232 Bitu shift=7-(x & 7);
233 /* Set the read map */
234 *color=0;
235 IO_Write(0x3ce,0x4);IO_Write(0x3cf,0);
236 *color|=((mem_readb(off)>>shift) & 1) << 0;
237 IO_Write(0x3ce,0x4);IO_Write(0x3cf,1);
238 *color|=((mem_readb(off)>>shift) & 1) << 1;
239 IO_Write(0x3ce,0x4);IO_Write(0x3cf,2);
240 *color|=((mem_readb(off)>>shift) & 1) << 2;
241 IO_Write(0x3ce,0x4);IO_Write(0x3cf,3);
242 *color|=((mem_readb(off)>>shift) & 1) << 3;
243 break;
244 }
245 case M_VGA:
246 *color=mem_readb(PhysMake(0xa000,320*y+x));
247 break;
248 case M_LIN8: {
249 if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)
250 LOG(LOG_INT10,LOG_ERROR)("GetPixel_VGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
251 PhysPt off=S3_LFB_BASE+y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x;
252 *color = mem_readb(off);
253 break;
254 }
255 default:
256 LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",CurMode->type);
257 break;
258 }
259 }
260