1 /*EGA emulation*/
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5 #include "io.h"
6 #include "mem.h"
7 #include "rom.h"
8 #include "timer.h"
9 #include "video.h"
10 #include "vid_ega.h"
11
12 extern uint8_t edatlookup[4][4];
13
14 static uint8_t ega_rotate[8][256];
15
16 static uint32_t pallook16[256], pallook64[256];
17
18 /*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/
19 int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/
20
ega_out(uint16_t addr,uint8_t val,void * p)21 void ega_out(uint16_t addr, uint8_t val, void *p)
22 {
23 ega_t *ega = (ega_t *)p;
24 int c;
25 uint8_t o, old;
26
27 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
28 addr ^= 0x60;
29
30 switch (addr)
31 {
32 case 0x3c0:
33 if (!ega->attrff)
34 ega->attraddr = val & 31;
35 else
36 {
37 ega->attrregs[ega->attraddr & 31] = val;
38 if (ega->attraddr < 16)
39 fullchange = changeframecount;
40 if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10)
41 {
42 for (c = 0; c < 16; c++)
43 {
44 if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4);
45 else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4);
46 }
47 }
48 }
49 ega->attrff ^= 1;
50 break;
51 case 0x3c2:
52 egaswitchread = val & 0xc;
53 ega->vres = !(val & 0x80);
54 ega->pallook = ega->vres ? pallook16 : pallook64;
55 ega->vidclock = val & 4; /*printf("3C2 write %02X\n",val);*/
56 ega->miscout=val;
57 break;
58 case 0x3c4:
59 ega->seqaddr = val;
60 break;
61 case 0x3c5:
62 o = ega->seqregs[ega->seqaddr & 0xf];
63 ega->seqregs[ega->seqaddr & 0xf] = val;
64 if (o != val && (ega->seqaddr & 0xf) == 1)
65 ega_recalctimings(ega);
66 switch (ega->seqaddr & 0xf)
67 {
68 case 1:
69 if (ega->scrblank && !(val & 0x20))
70 fullchange = 3;
71 ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20);
72 break;
73 case 2:
74 ega->writemask = val & 0xf;
75 break;
76 case 3:
77 ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2;
78 ega->charseta = ((val & 3) * 0x10000) + 2;
79 break;
80 case 4:
81 ega->chain2_write = !(val & 4);
82 break;
83 }
84 break;
85 case 0x3ce:
86 ega->gdcaddr = val;
87 break;
88 case 0x3cf:
89 ega->gdcreg[ega->gdcaddr & 15] = val;
90 switch (ega->gdcaddr & 15)
91 {
92 case 2:
93 ega->colourcompare = val;
94 break;
95 case 4:
96 ega->readplane = val & 3;
97 break;
98 case 5:
99 ega->writemode = val & 3;
100 ega->readmode = val & 8;
101 ega->chain2_read = val & 0x10;
102 break;
103 case 6:
104 // pclog("Write mapping %02X\n", val);
105 switch (val & 0xc)
106 {
107 case 0x0: /*128k at A0000*/
108 mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000);
109 break;
110 case 0x4: /*64k at A0000*/
111 mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000);
112 break;
113 case 0x8: /*32k at B0000*/
114 mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000);
115 break;
116 case 0xC: /*32k at B8000*/
117 mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000);
118 break;
119 }
120 break;
121 case 7:
122 ega->colournocare = val;
123 break;
124 }
125 break;
126 case 0x3d4:
127 pclog("Write 3d4 %02X %04X:%04X\n", val, CS, cpu_state.pc);
128 ega->crtcreg = val & 31;
129 return;
130 case 0x3d5:
131 pclog("Write 3d5 %02X %02X %02X\n", ega->crtcreg, val, ega->crtc[0x11]);
132 // if (ega->crtcreg == 1 && val == 0x14)
133 // fatal("Here\n");
134 if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return;
135 old = ega->crtc[ega->crtcreg];
136 ega->crtc[ega->crtcreg] = val;
137 if (old != val)
138 {
139 if (ega->crtcreg < 0xe || ega->crtcreg > 0x10)
140 {
141 fullchange = changeframecount;
142 ega_recalctimings(ega);
143 }
144 }
145 break;
146 }
147 }
148
ega_in(uint16_t addr,void * p)149 uint8_t ega_in(uint16_t addr, void *p)
150 {
151 ega_t *ega = (ega_t *)p;
152
153 if (addr != 0x3da && addr != 0x3ba)
154 pclog("ega_in %04X\n", addr);
155 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
156 addr ^= 0x60;
157
158 switch (addr)
159 {
160 case 0x3c0:
161 return ega->attraddr;
162 case 0x3c1:
163 return ega->attrregs[ega->attraddr];
164 case 0x3c2:
165 // printf("Read egaswitch %02X %02X %i\n",egaswitchread,egaswitches,VGA);
166 switch (egaswitchread)
167 {
168 case 0xc: return (egaswitches & 1) ? 0x10 : 0;
169 case 0x8: return (egaswitches & 2) ? 0x10 : 0;
170 case 0x4: return (egaswitches & 4) ? 0x10 : 0;
171 case 0x0: return (egaswitches & 8) ? 0x10 : 0;
172 }
173 break;
174 case 0x3c4:
175 return ega->seqaddr;
176 case 0x3c5:
177 return ega->seqregs[ega->seqaddr & 0xf];
178 case 0x3ce:
179 return ega->gdcaddr;
180 case 0x3cf:
181 return ega->gdcreg[ega->gdcaddr & 0xf];
182 case 0x3d4:
183 return ega->crtcreg;
184 case 0x3d5:
185 return ega->crtc[ega->crtcreg];
186 case 0x3da:
187 ega->attrff = 0;
188 ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/
189 return ega->stat;
190 }
191 // printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
192 return 0xff;
193 }
194
ega_recalctimings(ega_t * ega)195 void ega_recalctimings(ega_t *ega)
196 {
197 double _dispontime, _dispofftime, disptime;
198 double crtcconst;
199
200 ega->vtotal = ega->crtc[6];
201 ega->dispend = ega->crtc[0x12];
202 ega->vsyncstart = ega->crtc[0x10];
203 ega->split = ega->crtc[0x18];
204
205 if (ega->crtc[7] & 1) ega->vtotal |= 0x100;
206 if (ega->crtc[7] & 32) ega->vtotal |= 0x200;
207 ega->vtotal++;
208
209 if (ega->crtc[7] & 2) ega->dispend |= 0x100;
210 if (ega->crtc[7] & 64) ega->dispend |= 0x200;
211 ega->dispend++;
212
213 if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100;
214 if (ega->crtc[7] & 128) ega->vsyncstart |= 0x200;
215 ega->vsyncstart++;
216
217 if (ega->crtc[7] & 0x10) ega->split |= 0x100;
218 if (ega->crtc[9] & 0x40) ega->split |= 0x200;
219 ega->split+=2;
220
221 ega->hdisp = ega->crtc[1];
222 ega->hdisp++;
223
224 ega->rowoffset = ega->crtc[0x13];
225
226 printf("Recalc! %i %i %i %i %i %02X\n", ega->vtotal, ega->dispend, ega->vsyncstart, ega->split, ega->hdisp, ega->attrregs[0x16]);
227
228 if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0));
229 else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0));
230
231 disptime = ega->crtc[0] + 2;
232 _dispontime = ega->crtc[1] + 1;
233
234 printf("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, ega->crtc[1] * 8);
235 if (ega->seqregs[1] & 8)
236 {
237 disptime*=2;
238 _dispontime*=2;
239 }
240 _dispofftime = disptime - _dispontime;
241 _dispontime *= crtcconst;
242 _dispofftime *= crtcconst;
243
244 ega->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
245 ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
246 pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime / (1 << TIMER_SHIFT),
247 ega->dispofftime, (float)ega->dispofftime / (1 << TIMER_SHIFT));
248 // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4));
249 // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart);
250 // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]);
251 }
252
ega_draw_text(ega_t * ega)253 static void ega_draw_text(ega_t *ega)
254 {
255 int x, xx;
256
257 for (x = 0; x < ega->hdisp; x++)
258 {
259 int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
260 uint8_t chr = ega->vram[(ega->ma << 1) & ega->vrammask];
261 uint8_t attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
262 uint8_t dat;
263 uint32_t fg, bg;
264 uint32_t charaddr;
265
266 if (attr & 8)
267 charaddr = ega->charsetb + (chr * 128);
268 else
269 charaddr = ega->charseta + (chr * 128);
270
271 if (drawcursor)
272 {
273 bg = ega->pallook[ega->egapal[attr & 15]];
274 fg = ega->pallook[ega->egapal[attr >> 4]];
275 }
276 else
277 {
278 fg = ega->pallook[ega->egapal[attr & 15]];
279 bg = ega->pallook[ega->egapal[attr >> 4]];
280 if (attr & 0x80 && ega->attrregs[0x10] & 8)
281 {
282 bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
283 if (ega->blink & 16)
284 fg = bg;
285 }
286 }
287
288 dat = ega->vram[charaddr + (ega->sc << 2)];
289 if (ega->seqregs[1] & 8)
290 {
291 if (ega->seqregs[1] & 1)
292 {
293 for (xx = 0; xx < 8; xx++)
294 ((uint32_t *)buffer32->line[ega->displine])[((x << 4) + 32 + (xx << 1)) & 2047] =
295 ((uint32_t *)buffer32->line[ega->displine])[((x << 4) + 33 + (xx << 1)) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
296 }
297 else
298 {
299 for (xx = 0; xx < 8; xx++)
300 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 32 + (xx << 1)) & 2047] =
301 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 33 + (xx << 1)) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
302 if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
303 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 32 + 16) & 2047] =
304 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 32 + 17) & 2047] = bg;
305 else
306 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 32 + 16) & 2047] =
307 ((uint32_t *)buffer32->line[ega->displine])[((x * 18) + 32 + 17) & 2047] = (dat & 1) ? fg : bg;
308 }
309 }
310 else
311 {
312 if (ega->seqregs[1] & 1)
313 {
314 for (xx = 0; xx < 8; xx++)
315 ((uint32_t *)buffer32->line[ega->displine])[((x << 3) + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
316 }
317 else
318 {
319 for (xx = 0; xx < 8; xx++)
320 ((uint32_t *)buffer32->line[ega->displine])[((x * 9) + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
321 if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
322 ((uint32_t *)buffer32->line[ega->displine])[((x * 9) + 32 + 8) & 2047] = bg;
323 else
324 ((uint32_t *)buffer32->line[ega->displine])[((x * 9) + 32 + 8) & 2047] = (dat & 1) ? fg : bg;
325 }
326 }
327 ega->ma += 4;
328 ega->ma &= ega->vrammask;
329 }
330 }
331
ega_draw_2bpp(ega_t * ega)332 static void ega_draw_2bpp(ega_t *ega)
333 {
334 int x;
335 int offset = ((8 - ega->scrollcache) << 1) + 16;
336
337 for (x = 0; x <= ega->hdisp; x++)
338 {
339 uint8_t edat[2];
340 uint32_t addr = ega->ma;
341
342 if (!(ega->crtc[0x17] & 0x40))
343 {
344 addr = (addr << 1) & ega->vrammask;
345 addr &= ~7;
346 if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
347 addr |= 4;
348 if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
349 addr |= 4;
350 }
351 if (!(ega->crtc[0x17] & 0x01))
352 addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
353 if (!(ega->crtc[0x17] & 0x02))
354 addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
355
356 edat[0] = ega->vram[addr];
357 edat[1] = ega->vram[addr | 0x1];
358 if (ega->seqregs[1] & 4)
359 ega->ma += 2;
360 else
361 ega->ma += 4;
362
363 ega->ma &= ega->vrammask;
364
365 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 14 + offset]= ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 15 + offset] = ega->pallook[ega->egapal[edat[1] & 3]];
366 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 12 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
367 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 10 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
368 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 8 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
369 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 6 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
370 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 4 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
371 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 2 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
372 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
373 }
374 }
375
ega_draw_4bpp_lowres(ega_t * ega)376 static void ega_draw_4bpp_lowres(ega_t *ega)
377 {
378 int x;
379 int offset = ((8 - ega->scrollcache) << 1) + 16;
380
381 for (x = 0; x <= ega->hdisp; x++)
382 {
383 uint8_t edat[4];
384 uint8_t dat;
385 uint32_t addr = ega->ma;
386 int oddeven = 0;
387
388 if (!(ega->crtc[0x17] & 0x40))
389 {
390 addr = (addr << 1) & ega->vrammask;
391 if (ega->seqregs[1] & 4)
392 oddeven = (addr & 4) ? 1 : 0;
393 addr &= ~7;
394 if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
395 addr |= 4;
396 if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
397 addr |= 4;
398 }
399 if (!(ega->crtc[0x17] & 0x01))
400 addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
401 if (!(ega->crtc[0x17] & 0x02))
402 addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
403
404 if (ega->seqregs[1] & 4)
405 {
406 edat[0] = ega->vram[addr | oddeven];
407 edat[2] = ega->vram[addr | oddeven | 0x2];
408 edat[1] = edat[3] = 0;
409 ega->ma += 2;
410 }
411 else
412 {
413 edat[0] = ega->vram[addr];
414 edat[1] = ega->vram[addr | 0x1];
415 edat[2] = ega->vram[addr | 0x2];
416 edat[3] = ega->vram[addr | 0x3];
417 ega->ma += 4;
418 }
419 ega->ma &= ega->vrammask;
420
421 dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
422 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 14 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 15 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
423 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 12 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
424 dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
425 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 10 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
426 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 8 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
427 dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
428 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 6 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
429 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 4 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
430 dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
431 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 2 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
432 ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
433 }
434 }
435
ega_draw_4bpp_highres(ega_t * ega)436 static void ega_draw_4bpp_highres(ega_t *ega)
437 {
438 int x;
439 int offset = (8 - ega->scrollcache) + 24;
440
441 for (x = 0; x <= ega->hdisp; x++)
442 {
443 uint8_t edat[4];
444 uint8_t dat;
445 uint32_t addr = ega->ma;
446 int oddeven = 0;
447
448 if (!(ega->crtc[0x17] & 0x40))
449 {
450 addr = (addr << 1) & ega->vrammask;
451 if (ega->seqregs[1] & 4)
452 oddeven = (addr & 4) ? 1 : 0;
453 addr &= ~7;
454 if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
455 addr |= 4;
456 if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
457 addr |= 4;
458 }
459 if (!(ega->crtc[0x17] & 0x01))
460 addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
461 if (!(ega->crtc[0x17] & 0x02))
462 addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
463
464 if (ega->seqregs[1] & 4)
465 {
466 edat[0] = ega->vram[addr | oddeven];
467 edat[2] = ega->vram[addr | oddeven | 0x2];
468 edat[1] = edat[3] = 0;
469 ega->ma += 2;
470 }
471 else
472 {
473 edat[0] = ega->vram[addr];
474 edat[1] = ega->vram[addr | 0x1];
475 edat[2] = ega->vram[addr | 0x2];
476 edat[3] = ega->vram[addr | 0x3];
477 ega->ma += 4;
478 }
479 ega->ma &= ega->vrammask;
480
481 dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
482 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 7 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
483 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 6 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
484 dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
485 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 5 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
486 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 4 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
487 dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
488 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 3 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
489 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 2 + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
490 dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
491 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + 1 + offset] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
492 ((uint32_t *)buffer32->line[ega->displine])[(x << 3) + offset] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
493 }
494 }
495
ega_poll(void * p)496 void ega_poll(void *p)
497 {
498 ega_t *ega = (ega_t *)p;
499 int x, xx;
500
501 if (!ega->linepos)
502 {
503 ega->vidtime += ega->dispofftime;
504
505 ega->stat |= 1;
506 ega->linepos = 1;
507
508 if (ega->dispon)
509 {
510 if (ega->firstline == 2000)
511 {
512 ega->firstline = ega->displine;
513 video_wait_for_buffer();
514 }
515
516 if (ega->scrblank)
517 {
518 for (x = 0; x < ega->hdisp; x++)
519 {
520 switch (ega->seqregs[1] & 9)
521 {
522 case 0:
523 for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 9) + xx + 32] = 0;
524 break;
525 case 1:
526 for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 8) + xx + 32] = 0;
527 break;
528 case 8:
529 for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 18) + xx + 32] = 0;
530 break;
531 case 9:
532 for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[ega->displine])[(x * 16) + xx + 32] = 0;
533 break;
534 }
535 }
536 }
537 else if (!(ega->gdcreg[6] & 1))
538 {
539 if (fullchange)
540 ega_draw_text(ega);
541 }
542 else
543 {
544 switch (ega->gdcreg[5] & 0x20)
545 {
546 case 0x00:
547 if (ega->seqregs[1] & 8)
548 ega_draw_4bpp_lowres(ega);
549 else
550 ega_draw_4bpp_highres(ega);
551 break;
552 case 0x20:
553 ega_draw_2bpp(ega);
554 break;
555 }
556 }
557 if (ega->lastline < ega->displine)
558 ega->lastline = ega->displine;
559 }
560
561 ega->displine++;
562 if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines)
563 ega->stat &= ~8;
564 ega->vslines++;
565 if (ega->displine > 500)
566 ega->displine = 0;
567 }
568 else
569 {
570 ega->vidtime += ega->dispontime;
571 // if (output) printf("Display on %f\n",vidtime);
572 if (ega->dispon)
573 ega->stat &= ~1;
574 ega->linepos = 0;
575 if (ega->sc == (ega->crtc[11] & 31))
576 ega->con = 0;
577 if (ega->dispon)
578 {
579 if (ega->sc == (ega->crtc[9] & 31))
580 {
581 ega->sc = 0;
582 if (ega->sc == (ega->crtc[11] & 31))
583 ega->con = 0;
584
585 ega->maback += (ega->rowoffset << 3);
586 ega->maback &= ega->vrammask;
587 ega->ma = ega->maback;
588 }
589 else
590 {
591 ega->sc++;
592 ega->sc &= 31;
593 ega->ma = ega->maback;
594 }
595 }
596 ega->vc++;
597 ega->vc &= 1023;
598 // printf("Line now %i %i ma %05X\n",vc,displine,ma);
599 if (ega->vc == ega->split)
600 {
601 // printf("Split at line %i %i\n",displine,vc);
602 ega->ma = ega->maback = 0;
603 if (ega->attrregs[0x10] & 0x20)
604 ega->scrollcache = 0;
605 }
606 if (ega->vc == ega->dispend)
607 {
608 // printf("Display over at line %i %i\n",displine,vc);
609 ega->dispon=0;
610 if (ega->crtc[10] & 0x20) ega->cursoron = 0;
611 else ega->cursoron = ega->blink & 16;
612 if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15))
613 fullchange = 2;
614 ega->blink++;
615
616 if (fullchange)
617 fullchange--;
618 }
619 if (ega->vc == ega->vsyncstart)
620 {
621 ega->dispon = 0;
622 // printf("Vsync on at line %i %i\n",displine,vc);
623 ega->stat |= 8;
624 if (ega->seqregs[1] & 8) x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9) * 2;
625 else x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9);
626 // pclog("Cursor %02X %02X\n",crtc[10],crtc[11]);
627 // pclog("Firstline %i Lastline %i wx %i %i\n",firstline,lastline,wx,oddeven);
628 // doblit();
629 if (x != xsize || (ega->lastline - ega->firstline) != ysize)
630 {
631 xsize = x;
632 ysize = ega->lastline - ega->firstline;
633 if (xsize < 64) xsize = 656;
634 if (ysize < 32) ysize = 200;
635 if (ega->vres || ysize <= 200)
636 updatewindowsize(xsize, ysize << 1);
637 else
638 updatewindowsize(xsize, ysize);
639 }
640
641 video_blit_memtoscreen(32, 0, ega->firstline, ega->lastline, xsize, ega->lastline - ega->firstline);
642
643 ega->frames++;
644 ega->video_res_x = xsize;
645 ega->video_res_y = ysize+1;
646 if (!(ega->gdcreg[6] & 1)) /*Text mode*/
647 {
648 ega->video_res_x /= (ega->seqregs[1] & 1) ? 8 : 9;
649 ega->video_res_y /= (ega->crtc[9] & 31) + 1;
650 ega->video_bpp = 0;
651 }
652 else
653 {
654 if (ega->crtc[9] & 0x80)
655 ega->video_res_y /= 2;
656 if (!(ega->crtc[0x17] & 1))
657 ega->video_res_y *= 2;
658 ega->video_res_y /= (ega->crtc[9] & 31) + 1;
659 if (ega->seqregs[1] & 8)
660 ega->video_res_x /= 2;
661 ega->video_bpp = (ega->gdcreg[5] & 0x20) ? 2 : 4;
662 }
663
664 // wakeupblit();
665 readflash=0;
666 //framecount++;
667 ega->firstline = 2000;
668 ega->lastline = 0;
669
670 ega->maback = ega->ma = (ega->crtc[0xc] << 8)| ega->crtc[0xd];
671 ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf];
672 ega->ma <<= 2;
673 ega->maback <<= 2;
674 ega->ca <<= 2;
675 changeframecount = 2;
676 ega->vslines = 0;
677 }
678 if (ega->vc == ega->vtotal)
679 {
680 ega->vc = 0;
681 ega->sc = ega->crtc[8] & 0x1f;
682 ega->dispon = 1;
683 ega->displine = 0;
684 ega->scrollcache = ega->attrregs[0x13] & 7;
685 }
686 if (ega->sc == (ega->crtc[10] & 31))
687 ega->con = 1;
688 }
689 }
690
691
ega_write(uint32_t addr,uint8_t val,void * p)692 void ega_write(uint32_t addr, uint8_t val, void *p)
693 {
694 ega_t *ega = (ega_t *)p;
695 uint8_t vala, valb, valc, vald;
696 int writemask2 = ega->writemask;
697
698 egawrites++;
699 cycles -= video_timing_write_b;
700 cycles_lost += video_timing_write_b;
701
702 if (addr >= 0xB0000) addr &= 0x7fff;
703 else addr &= 0xffff;
704
705 if (ega->chain2_write)
706 {
707 writemask2 &= ~0xa;
708 if (addr & 1)
709 writemask2 <<= 1;
710 addr &= ~1;
711 if (addr & 0x4000)
712 addr |= 1;
713 addr &= ~0x4000;
714 }
715
716 addr <<= 2;
717
718 if (addr >= ega->vram_limit)
719 return;
720
721 if (!(ega->gdcreg[6] & 1))
722 fullchange = 2;
723
724 // pclog("%i %08X %i %i %02X %02X %02X %02X %02X\n",chain4,addr,writemode,writemask,gdcreg[8],vram[0],vram[1],vram[2],vram[3]);
725 switch (ega->writemode)
726 {
727 case 1:
728 if (writemask2 & 1) ega->vram[addr] = ega->la;
729 if (writemask2 & 2) ega->vram[addr | 0x1] = ega->lb;
730 if (writemask2 & 4) ega->vram[addr | 0x2] = ega->lc;
731 if (writemask2 & 8) ega->vram[addr | 0x3] = ega->ld;
732 break;
733 case 0:
734 if (ega->gdcreg[3] & 7)
735 val = ega_rotate[ega->gdcreg[3] & 7][val];
736
737 if (ega->gdcreg[8] == 0xff && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1])
738 {
739 if (writemask2 & 1) ega->vram[addr] = val;
740 if (writemask2 & 2) ega->vram[addr | 0x1] = val;
741 if (writemask2 & 4) ega->vram[addr | 0x2] = val;
742 if (writemask2 & 8) ega->vram[addr | 0x3] = val;
743 }
744 else
745 {
746 if (ega->gdcreg[1] & 1) vala = (ega->gdcreg[0] & 1) ? 0xff : 0;
747 else vala = val;
748 if (ega->gdcreg[1] & 2) valb = (ega->gdcreg[0] & 2) ? 0xff : 0;
749 else valb = val;
750 if (ega->gdcreg[1] & 4) valc = (ega->gdcreg[0] & 4) ? 0xff : 0;
751 else valc = val;
752 if (ega->gdcreg[1] & 8) vald = (ega->gdcreg[0] & 8) ? 0xff : 0;
753 else vald = val;
754 // pclog("Write %02X %01X %02X %02X %02X %02X %02X\n",gdcreg[3]&0x18,writemask,vala,valb,valc,vald,gdcreg[8]);
755 switch (ega->gdcreg[3] & 0x18)
756 {
757 case 0: /*Set*/
758 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
759 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
760 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
761 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
762 break;
763 case 8: /*AND*/
764 if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
765 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
766 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
767 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
768 break;
769 case 0x10: /*OR*/
770 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
771 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
772 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
773 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
774 break;
775 case 0x18: /*XOR*/
776 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
777 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
778 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
779 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
780 break;
781 }
782 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
783 }
784 break;
785 case 2:
786 if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1])
787 {
788 if (writemask2 & 1) ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
789 if (writemask2 & 2) ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
790 if (writemask2 & 4) ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
791 if (writemask2 & 8) ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
792 }
793 else
794 {
795 vala = ((val & 1) ? 0xff : 0);
796 valb = ((val & 2) ? 0xff : 0);
797 valc = ((val & 4) ? 0xff : 0);
798 vald = ((val & 8) ? 0xff : 0);
799 switch (ega->gdcreg[3] & 0x18)
800 {
801 case 0: /*Set*/
802 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]);
803 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]);
804 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]);
805 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]);
806 break;
807 case 8: /*AND*/
808 if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la;
809 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb;
810 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc;
811 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld;
812 break;
813 case 0x10: /*OR*/
814 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la;
815 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb;
816 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc;
817 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld;
818 break;
819 case 0x18: /*XOR*/
820 if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la;
821 if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb;
822 if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc;
823 if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld;
824 break;
825 }
826 }
827 break;
828 }
829 }
830
ega_read(uint32_t addr,void * p)831 uint8_t ega_read(uint32_t addr, void *p)
832 {
833 ega_t *ega = (ega_t *)p;
834 uint8_t temp, temp2, temp3, temp4;
835 int readplane = ega->readplane;
836
837 egareads++;
838 cycles -= video_timing_read_b;
839 cycles_lost += video_timing_read_b;
840 // pclog("Readega %06X ",addr);
841 if (addr >= 0xb0000) addr &= 0x7fff;
842 else addr &= 0xffff;
843
844 if (ega->chain2_read)
845 {
846 readplane = (readplane & 2) | (addr & 1);
847 addr &= ~1;
848 if (addr & 0x4000)
849 addr |= 1;
850 addr &= ~0x4000;
851 }
852
853 addr <<= 2;
854 if (addr >= ega->vram_limit)
855 return 0xff;
856
857 ega->la = ega->vram[addr];
858 ega->lb = ega->vram[addr | 0x1];
859 ega->lc = ega->vram[addr | 0x2];
860 ega->ld = ega->vram[addr | 0x3];
861 if (ega->readmode)
862 {
863 temp = ega->la;
864 temp ^= (ega->colourcompare & 1) ? 0xff : 0;
865 temp &= (ega->colournocare & 1) ? 0xff : 0;
866 temp2 = ega->lb;
867 temp2 ^= (ega->colourcompare & 2) ? 0xff : 0;
868 temp2 &= (ega->colournocare & 2) ? 0xff : 0;
869 temp3 = ega->lc;
870 temp3 ^= (ega->colourcompare & 4) ? 0xff : 0;
871 temp3 &= (ega->colournocare & 4) ? 0xff : 0;
872 temp4 = ega->ld;
873 temp4 ^= (ega->colourcompare & 8) ? 0xff : 0;
874 temp4 &= (ega->colournocare & 8) ? 0xff : 0;
875 return ~(temp | temp2 | temp3 | temp4);
876 }
877 return ega->vram[addr | readplane];
878 }
879
ega_init(ega_t * ega,int monitor_type,int is_mono)880 void ega_init(ega_t *ega, int monitor_type, int is_mono)
881 {
882 int c, d, e;
883
884 ega->vram = malloc(0x40000);
885 ega->vrammask = 0x3ffff;
886
887 for (c = 0; c < 256; c++)
888 {
889 e = c;
890 for (d = 0; d < 8; d++)
891 {
892 ega_rotate[d][c] = e;
893 e = (e >> 1) | ((e & 1) ? 0x80 : 0);
894 }
895 }
896
897 for (c = 0; c < 4; c++)
898 {
899 for (d = 0; d < 4; d++)
900 {
901 edatlookup[c][d] = 0;
902 if (c & 1) edatlookup[c][d] |= 1;
903 if (d & 1) edatlookup[c][d] |= 2;
904 if (c & 2) edatlookup[c][d] |= 0x10;
905 if (d & 2) edatlookup[c][d] |= 0x20;
906 }
907 }
908
909 if (is_mono)
910 {
911 for (c = 0; c < 256; c++)
912 {
913 switch (monitor_type >> 4)
914 {
915 case DISPLAY_GREEN:
916 switch ((c >> 3) & 3)
917 {
918 case 0:
919 pallook64[c] = pallook16[c] = makecol32(0, 0, 0);
920 break;
921 case 2:
922 pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20);
923 break;
924 case 1:
925 pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c);
926 break;
927 case 3:
928 pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d);
929 break;
930 }
931 break;
932 case DISPLAY_AMBER:
933 switch ((c >> 3) & 3)
934 {
935 case 0:
936 pallook64[c] = pallook16[c] = makecol32(0, 0, 0);
937 break;
938 case 2:
939 pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00);
940 break;
941 case 1:
942 pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00);
943 break;
944 case 3:
945 pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34);
946 break;
947 }
948 break;
949 case DISPLAY_WHITE: default:
950 switch ((c >> 3) & 3)
951 {
952 case 0:
953 pallook64[c] = pallook16[c] = makecol32(0, 0, 0);
954 break;
955 case 2:
956 pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83);
957 break;
958 case 1:
959 pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0);
960 break;
961 case 3:
962 pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed);
963 break;
964 }
965 break;
966 }
967 }
968 }
969 else
970 {
971 for (c = 0; c < 256; c++)
972 {
973 pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
974 pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
975 pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
976 pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55);
977 if ((c & 0x17) == 6)
978 pallook16[c] = makecol32(0xaa, 0x55, 0);
979 }
980 }
981 ega->pallook = pallook16;
982
983 egaswitches = monitor_type & 0xf;
984 ega->vram_limit = 256 * 1024;
985 ega->vrammask = ega->vram_limit-1;
986 }
987
ega_standalone_init()988 void *ega_standalone_init()
989 {
990 ega_t *ega = malloc(sizeof(ega_t));
991 memset(ega, 0, sizeof(ega_t));
992 int monitor_type;
993
994 rom_init(&ega->bios_rom, "ibm_6277356_ega_card_u44_27128.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
995
996 if (ega->bios_rom.rom[0x3ffe] == 0xaa && ega->bios_rom.rom[0x3fff] == 0x55)
997 {
998 int c;
999 pclog("Read EGA ROM in reverse\n");
1000
1001 for (c = 0; c < 0x2000; c++)
1002 {
1003 uint8_t temp = ega->bios_rom.rom[c];
1004 ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c];
1005 ega->bios_rom.rom[0x3fff - c] = temp;
1006 }
1007 }
1008
1009 monitor_type = device_get_config_int("monitor_type");
1010 ega_init(ega, monitor_type, (monitor_type & 0xf) == 10);
1011
1012 ega->vram_limit = device_get_config_int("memory") * 1024;
1013 ega->vrammask = ega->vram_limit-1;
1014
1015 mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega);
1016 timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega);
1017 io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega);
1018 return ega;
1019 }
1020
ega_standalone_available()1021 static int ega_standalone_available()
1022 {
1023 return rom_present("ibm_6277356_ega_card_u44_27128.bin");
1024 }
1025
ega_close(void * p)1026 void ega_close(void *p)
1027 {
1028 ega_t *ega = (ega_t *)p;
1029
1030 free(ega->vram);
1031 free(ega);
1032 }
1033
ega_speed_changed(void * p)1034 void ega_speed_changed(void *p)
1035 {
1036 ega_t *ega = (ega_t *)p;
1037
1038 ega_recalctimings(ega);
1039 }
1040
ega_add_status_info(char * s,int max_len,void * p)1041 void ega_add_status_info(char *s, int max_len, void *p)
1042 {
1043 ega_t *ega = (ega_t *)p;
1044 char temps[128];
1045
1046 if (!ega->video_bpp) strcpy(temps, "EGA in text mode\n");
1047 else sprintf(temps, "EGA colour depth : %i bpp\n", ega->video_bpp);
1048 strncat(s, temps, max_len);
1049
1050 sprintf(temps, "EGA resolution : %i x %i\n", ega->video_res_x, ega->video_res_y);
1051 strncat(s, temps, max_len);
1052
1053 sprintf(temps, "EGA refresh rate : %i Hz\n\n", ega->frames);
1054 ega->frames = 0;
1055 strncat(s, temps, max_len);
1056 }
1057
1058 static device_config_t ega_config[] =
1059 {
1060 {
1061 .name = "memory",
1062 .description = "Memory size",
1063 .type = CONFIG_SELECTION,
1064 .selection =
1065 {
1066 {
1067 .description = "64 kB",
1068 .value = 64
1069 },
1070 {
1071 .description = "128 kB",
1072 .value = 128
1073 },
1074 {
1075 .description = "256 kB",
1076 .value = 256
1077 },
1078 {
1079 .description = ""
1080 }
1081 },
1082 .default_int = 256
1083 },
1084 {
1085 .name = "monitor_type",
1086 .description = "Monitor type",
1087 .type = CONFIG_SELECTION,
1088 .selection =
1089 {
1090 {
1091 .description = "EGA Colour, 40x25",
1092 .value = 6
1093 },
1094 {
1095 .description = "EGA Colour, 80x25",
1096 .value = 7
1097 },
1098 {
1099 .description = "EGA Colour, ECD",
1100 .value = 9
1101 },
1102 {
1103 .description = "EGA Monochrome (white)",
1104 .value = 10 | (DISPLAY_WHITE << 4)
1105 },
1106 {
1107 .description = "EGA Monochrome (green)",
1108 .value = 10 | (DISPLAY_GREEN << 4)
1109 },
1110 {
1111 .description = "EGA Monochrome (amber)",
1112 .value = 10 | (DISPLAY_AMBER << 4)
1113 },
1114 {
1115 .description = ""
1116 }
1117 },
1118 .default_int = 9
1119 },
1120 {
1121 .type = -1
1122 }
1123 };
1124
1125 device_t ega_device =
1126 {
1127 "EGA",
1128 0,
1129 ega_standalone_init,
1130 ega_close,
1131 ega_standalone_available,
1132 ega_speed_changed,
1133 NULL,
1134 ega_add_status_info,
1135 ega_config
1136 };
1137