PCem

view src/vid_svga.c @ 115:bd2ab065dd81

Port 0x3da diagnostic bits now held static during blanking, fixes DOS 6.2/V hang.
author TomW
date Sun Jul 06 21:40:28 2014 +0100
parents c5989dbbc2ce
children 173e1f058566
line source
1 /*Generic SVGA handling*/
2 /*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
3 #include <stdlib.h>
4 #include "ibm.h"
5 #include "mem.h"
6 #include "video.h"
7 #include "vid_svga.h"
8 #include "vid_svga_render.h"
9 #include "io.h"
10 #include "timer.h"
12 #define svga_output 0
14 void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
16 extern uint8_t edatlookup[4][4];
18 uint8_t svga_rotate[8][256];
21 void svga_out(uint16_t addr, uint8_t val, void *p)
22 {
23 svga_t *svga = (svga_t *)p;
24 int c;
25 uint8_t o;
26 // printf("OUT SVGA %03X %02X %04X:%04X\n",addr,val,CS,pc);
27 switch (addr)
28 {
29 case 0x3C0:
30 if (!svga->attrff)
31 svga->attraddr = val & 31;
32 else
33 {
34 svga->attrregs[svga->attraddr & 31] = val;
35 if (svga->attraddr < 16)
36 svga->fullchange = changeframecount;
37 if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10)
38 {
39 for (c = 0; c < 16; c++)
40 {
41 if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4);
42 else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4);
43 }
44 }
45 if (svga->attraddr == 0x10)
46 svga_recalctimings(svga);
47 if (svga->attraddr == 0x12)
48 {
49 if ((val & 0xf) != svga->plane_mask)
50 svga->fullchange = changeframecount;
51 svga->plane_mask = val & 0xf;
52 }
53 }
54 svga->attrff ^= 1;
55 break;
56 case 0x3C2:
57 svga->miscout = val;
58 svga->vidclock = val & 4;// printf("3C2 write %02X\n",val);
59 if (val & 1)
60 {
61 // pclog("Remove mono handler\n");
62 io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p);
63 }
64 else
65 {
66 // pclog("Set mono handler\n");
67 io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p);
68 }
69 break;
70 case 0x3C4:
71 svga->seqaddr = val;
72 break;
73 case 0x3C5:
74 if (svga->seqaddr > 0xf) return;
75 o = svga->seqregs[svga->seqaddr & 0xf];
76 svga->seqregs[svga->seqaddr & 0xf] = val;
77 if (o != val && (svga->seqaddr & 0xf) == 1)
78 svga_recalctimings(svga);
79 switch (svga->seqaddr & 0xf)
80 {
81 case 1:
82 if (svga->scrblank && !(val & 0x20))
83 svga->fullchange = 3;
84 svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20);
85 svga_recalctimings(svga);
86 break;
87 case 2:
88 svga->writemask = val & 0xf;
89 break;
90 case 3:
91 svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2;
92 svga->charseta = ((val & 3) * 0x10000) + 2;
93 if (val & 0x10)
94 svga->charseta += 0x8000;
95 if (val & 0x20)
96 svga->charsetb += 0x8000;
97 break;
98 case 4:
99 svga->chain4 = val & 8;
100 svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
101 break;
102 }
103 break;
104 case 0x3c6:
105 svga->dac_mask = val;
106 break;
107 case 0x3C7:
108 svga->dac_read = val;
109 svga->dac_pos = 0;
110 break;
111 case 0x3C8:
112 svga->dac_write = val;
113 svga->dac_pos = 0;
114 break;
115 case 0x3C9:
116 svga->dac_status = 0;
117 svga->fullchange = changeframecount;
118 switch (svga->dac_pos)
119 {
120 case 0:
121 svga->vgapal[svga->dac_write].r = val & 63;
122 svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r * 4, svga->vgapal[svga->dac_write].g * 4, svga->vgapal[svga->dac_write].b * 4);
123 svga->dac_pos++;
124 break;
125 case 1:
126 svga->vgapal[svga->dac_write].g = val & 63;
127 svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r * 4, svga->vgapal[svga->dac_write].g * 4, svga->vgapal[svga->dac_write].b * 4);
128 svga->dac_pos++;
129 break;
130 case 2:
131 svga->vgapal[svga->dac_write].b = val & 63;
132 svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r * 4, svga->vgapal[svga->dac_write].g * 4, svga->vgapal[svga->dac_write].b * 4);
133 svga->dac_pos = 0;
134 svga->dac_write = (svga->dac_write + 1) & 255;
135 break;
136 }
137 break;
138 case 0x3CE:
139 svga->gdcaddr = val;
140 break;
141 case 0x3CF:
142 o = svga->gdcreg[svga->gdcaddr & 15];
143 switch (svga->gdcaddr & 15)
144 {
145 case 2: svga->colourcompare=val; break;
146 case 4: svga->readplane=val&3; break;
147 case 5: svga->writemode=val&3; svga->readmode=val&8; break;
148 case 6:
149 // pclog("svga_out recalcmapping %p\n", svga);
150 if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
151 {
152 // pclog("Write mapping %02X\n", val);
153 switch (val&0xC)
154 {
155 case 0x0: /*128k at A0000*/
156 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
157 svga->banked_mask = 0xffff;
158 break;
159 case 0x4: /*64k at A0000*/
160 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
161 svga->banked_mask = 0xffff;
162 break;
163 case 0x8: /*32k at B0000*/
164 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
165 svga->banked_mask = 0x7fff;
166 break;
167 case 0xC: /*32k at B8000*/
168 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
169 svga->banked_mask = 0x7fff;
170 break;
171 }
172 }
173 break;
174 case 7: svga->colournocare=val; break;
175 }
176 svga->gdcreg[svga->gdcaddr & 15] = val;
177 svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
178 if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
179 svga_recalctimings(svga);
180 break;
181 }
182 }
184 uint8_t svga_in(uint16_t addr, void *p)
185 {
186 svga_t *svga = (svga_t *)p;
187 uint8_t temp;
188 // if (addr!=0x3da) pclog("Read port %04X\n",addr);
189 switch (addr)
190 {
191 case 0x3C0:
192 return svga->attraddr;
193 case 0x3C1:
194 return svga->attrregs[svga->attraddr];
195 case 0x3c2:
196 if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
197 temp = 0;
198 else
199 temp = 0x10;
200 return temp;
201 case 0x3C4:
202 return svga->seqaddr;
203 case 0x3C5:
204 return svga->seqregs[svga->seqaddr & 0xF];
205 case 0x3c6: return svga->dac_mask;
206 case 0x3c7: return svga->dac_status;
207 case 0x3c8: return svga->dac_write;
208 case 0x3c9:
209 svga->dac_status = 3;
210 switch (svga->dac_pos)
211 {
212 case 0:
213 svga->dac_pos++;
214 return svga->vgapal[svga->dac_read].r;
215 case 1:
216 svga->dac_pos++;
217 return svga->vgapal[svga->dac_read].g;
218 case 2:
219 svga->dac_pos=0;
220 svga->dac_read = (svga->dac_read + 1) & 255;
221 return svga->vgapal[(svga->dac_read - 1) & 255].b;
222 }
223 break;
224 case 0x3CC:
225 return svga->miscout;
226 case 0x3CE:
227 return svga->gdcaddr;
228 case 0x3CF:
229 return svga->gdcreg[svga->gdcaddr & 0xf];
230 case 0x3DA:
231 svga->attrff = 0;
232 if (svga->cgastat & 0x01)
233 svga->cgastat &= ~0x30;
234 else
235 svga->cgastat ^= 0x30;
236 return svga->cgastat;
237 }
238 // printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
239 return 0xFF;
240 }
242 void svga_recalctimings(svga_t *svga)
243 {
244 double crtcconst;
245 double _dispontime, _dispofftime, disptime;
246 int hdisp_old;
248 svga->vtotal = svga->crtc[6];
249 svga->dispend = svga->crtc[0x12];
250 svga->vsyncstart = svga->crtc[0x10];
251 svga->split = svga->crtc[0x18];
252 svga->vblankstart = svga->crtc[0x15];
254 if (svga->crtc[7] & 1) svga->vtotal |= 0x100;
255 if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
256 svga->vtotal += 2;
258 if (svga->crtc[7] & 2) svga->dispend |= 0x100;
259 if (svga->crtc[7] & 64) svga->dispend |= 0x200;
260 svga->dispend++;
262 if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100;
263 if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
264 svga->vsyncstart++;
266 if (svga->crtc[7] & 0x10) svga->split|=0x100;
267 if (svga->crtc[9] & 0x40) svga->split|=0x200;
268 svga->split++;
270 if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
271 if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
272 svga->vblankstart++;
274 svga->hdisp = svga->crtc[1];
275 svga->hdisp++;
277 svga->htotal = svga->crtc[0];
278 svga->htotal += 6; /*+6 is required for Tyrian*/
280 svga->rowoffset = svga->crtc[0x13];
282 svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
284 svga->lowres = svga->attrregs[0x10] & 0x40;
286 svga->interlace = 0;
288 svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd];
290 svga->hdisp_time = svga->hdisp;
291 svga->render = svga_render_blank;
292 if (!svga->scrblank)
293 {
294 if (!(svga->gdcreg[6] & 1)) /*Text mode*/
295 {
296 if (svga->seqregs[1] & 8) /*40 column*/
297 {
298 svga->render = svga_render_text_40;
299 svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
300 }
301 else
302 {
303 svga->render = svga_render_text_80;
304 svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
305 }
306 svga->hdisp_old = svga->hdisp;
307 }
308 else
309 {
310 svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
311 svga->hdisp_old = svga->hdisp;
313 switch (svga->gdcreg[5] & 0x60)
314 {
315 case 0x00: /*16 colours*/
316 if (svga->seqregs[1] & 8) /*Low res (320)*/
317 svga->render = svga_render_4bpp_lowres;
318 else
319 svga->render = svga_render_4bpp_highres;
320 break;
321 case 0x20: /*4 colours*/
322 if (svga->seqregs[1] & 8) /*Low res (320)*/
323 svga->render = svga_render_2bpp_lowres;
324 else
325 svga->render = svga_render_2bpp_highres;
326 break;
327 case 0x40: case 0x60: /*256+ colours*/
328 switch (svga->bpp)
329 {
330 case 8:
331 if (svga->lowres)
332 svga->render = svga_render_8bpp_lowres;
333 else
334 svga->render = svga_render_8bpp_highres;
335 break;
336 case 15:
337 if (svga->lowres)
338 svga->render = svga_render_15bpp_lowres;
339 else
340 svga->render = svga_render_15bpp_highres;
341 break;
342 case 16:
343 if (svga->lowres)
344 svga->render = svga_render_16bpp_lowres;
345 else
346 svga->render = svga_render_16bpp_highres;
347 break;
348 case 24:
349 if (svga->lowres)
350 svga->render = svga_render_24bpp_lowres;
351 else
352 svga->render = svga_render_24bpp_highres;
353 break;
354 case 32:
355 if (svga->lowres)
356 svga->render = svga_render_32bpp_lowres;
357 else
358 svga->render = svga_render_32bpp_highres;
359 break;
360 }
361 break;
362 }
363 }
364 }
366 // pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
368 svga->linedbl = svga->crtc[9] & 0x80;
369 svga->rowcount = svga->crtc[9] & 31;
370 if (svga->recalctimings_ex)
371 svga->recalctimings_ex(svga);
373 if (svga->vblankstart < svga->dispend)
374 svga->dispend = svga->vblankstart;
376 crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0);
378 disptime = svga->htotal;
379 _dispontime = svga->hdisp_time;
381 // printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
382 if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; }
383 _dispofftime = disptime - _dispontime;
384 _dispontime *= crtcconst;
385 _dispofftime *= crtcconst;
387 svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
388 svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
389 /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
390 printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart);
391 printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]);
393 pclog("svga->render %08X\n", svga->render);*/
394 }
396 extern int cyc_total;
397 void svga_poll(void *p)
398 {
399 svga_t *svga = (svga_t *)p;
400 int x;
402 if (!svga->linepos)
403 {
404 // if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
405 if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena)
406 svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
408 if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena)
409 svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
411 svga->vidtime += svga->dispofftime;
412 // if (output) printf("Display off %f\n",vidtime);
413 svga->cgastat |= 1;
414 svga->linepos = 1;
416 if (svga->dispon)
417 {
418 svga->hdisp_on=1;
420 svga->ma &= svga->vrammask;
421 if (svga->firstline == 2000)
422 svga->firstline = svga->displine;
424 if (svga->hwcursor_on || svga->overlay_on)
425 svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = 2;
427 svga->render(svga);
429 if (svga->overlay_on)
430 {
431 svga->overlay_draw(svga, svga->displine);
432 svga->overlay_on--;
433 }
435 if (svga->hwcursor_on)
436 {
437 svga->hwcursor_draw(svga, svga->displine);
438 svga->hwcursor_on--;
439 }
441 if (svga->lastline < svga->displine)
442 svga->lastline = svga->displine;
443 }
445 // pclog("%03i %06X %06X\n",displine,ma,vrammask);
446 svga->displine++;
447 if (svga->interlace)
448 svga->displine++;
449 if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines)
450 {
451 // printf("Vsync off at line %i\n",displine);
452 svga->cgastat &= ~8;
453 }
454 svga->vslines++;
455 if (svga->displine > 1500)
456 svga->displine = 0;
457 // pclog("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322],
458 // displine, vc, ma);
459 }
460 else
461 {
462 // pclog("VC %i ma %05X\n", svga->vc, svga->ma);
463 svga->vidtime += svga->dispontime;
465 // if (output) printf("Display on %f\n",vidtime);
466 if (svga->dispon)
467 svga->cgastat &= ~1;
468 svga->hdisp_on = 0;
470 svga->linepos = 0;
471 if (svga->sc == (svga->crtc[11] & 31))
472 svga->con = 0;
473 if (svga->dispon)
474 {
475 if (svga->linedbl && !svga->linecountff)
476 {
477 svga->linecountff = 1;
478 svga->ma = svga->maback;
479 }
480 else if (svga->sc == svga->rowcount)
481 {
482 svga->linecountff = 0;
483 svga->sc = 0;
485 svga->maback += (svga->rowoffset << 3);
486 if (svga->interlace)
487 svga->maback += (svga->rowoffset << 3);
488 svga->maback &= svga->vrammask;
489 svga->ma = svga->maback;
490 }
491 else
492 {
493 svga->linecountff = 0;
494 svga->sc++;
495 svga->sc &= 31;
496 svga->ma = svga->maback;
497 }
498 }
499 svga->vc++;
500 svga->vc &= 2047;
502 if (svga->vc == svga->split)
503 {
504 // pclog("VC split\n");
505 svga->ma = svga->maback = 0;
506 if (svga->attrregs[0x10] & 0x20)
507 svga->scrollcache = 0;
508 }
509 if (svga->vc == svga->dispend)
510 {
511 // pclog("VC dispend\n");
512 svga->dispon=0;
513 if (svga->crtc[10] & 0x20) svga->cursoron = 0;
514 else svga->cursoron = svga->blink & 16;
515 if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15))
516 svga->fullchange = 2;
517 svga->blink++;
519 for (x = 0; x < (svga->vram_limit >> 12); x++)
520 {
521 if (svga->changedvram[x])
522 svga->changedvram[x]--;
523 }
524 // memset(changedvram,0,2048);
525 if (svga->fullchange)
526 svga->fullchange--;
527 }
528 if (svga->vc == svga->vsyncstart)
529 {
530 int wx, wy;
531 // pclog("VC vsync %i %i\n", svga->firstline_draw, svga->lastline_draw);
532 svga->dispon=0;
533 svga->cgastat |= 8;
534 x = svga->hdisp;
536 if (svga->interlace && !svga->oddeven) svga->lastline++;
537 if (svga->interlace && svga->oddeven) svga->firstline--;
539 wx = x;
540 wy = svga->lastline - svga->firstline;
542 svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
544 readflash = 0;
546 svga->firstline = 2000;
547 svga->lastline = 0;
549 svga->firstline_draw = 2000;
550 svga->lastline_draw = 0;
552 svga->oddeven ^= 1;
554 changeframecount = svga->interlace ? 3 : 2;
555 svga->vslines = 0;
557 if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
558 else svga->ma = svga->maback = svga->ma_latch;
559 svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf];
561 svga->ma <<= 2;
562 svga->maback <<= 2;
563 svga->ca <<= 2;
565 svga->video_res_x = wx;
566 svga->video_res_y = wy + 1;
567 // pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
568 if (!(svga->gdcreg[6] & 1)) /*Text mode*/
569 {
570 svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9;
571 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
572 svga->video_bpp = 0;
573 }
574 else
575 {
576 if (svga->crtc[9] & 0x80)
577 svga->video_res_y /= 2;
578 if (!(svga->crtc[0x17] & 1))
579 svga->video_res_y *= 2;
580 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
581 if (svga->lowres)
582 svga->video_res_x /= 2;
584 switch (svga->gdcreg[5] & 0x60)
585 {
586 case 0x00: svga->video_bpp = 4; break;
587 case 0x20: svga->video_bpp = 2; break;
588 case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
589 }
590 }
591 // if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
593 // pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven);
594 }
595 if (svga->vc == svga->vtotal)
596 {
597 // pclog("VC vtotal\n");
600 // printf("Frame over at line %i %i %i %i\n",displine,vc,svga_vsyncstart,svga_dispend);
601 svga->vc = 0;
602 svga->sc = 0;
603 svga->dispon = 1;
604 svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
605 svga->scrollcache = svga->attrregs[0x13] & 7;
606 svga->linecountff = 0;
608 svga->hwcursor_on = 0;
609 svga->hwcursor_latch = svga->hwcursor;
611 svga->overlay_on = 0;
612 svga->overlay_latch = svga->overlay;
613 // pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
615 // pclog("ADDR %08X\n",hwcursor_addr);
616 }
617 if (svga->sc == (svga->crtc[10] & 31))
618 svga->con = 1;
619 }
620 // printf("2 %i\n",svga_vsyncstart);
621 //pclog("svga_poll %i %i %i %i %i %i %i\n", ins, svga->dispofftime, svga->dispontime, svga->vidtime, cyc_total, svga->linepos, svga->vc);
622 }
624 int svga_init(svga_t *svga, void *p, int memsize,
625 void (*recalctimings_ex)(struct svga_t *svga),
626 uint8_t (*video_in) (uint16_t addr, void *p),
627 void (*video_out)(uint16_t addr, uint8_t val, void *p),
628 void (*hwcursor_draw)(struct svga_t *svga, int displine),
629 void (*overlay_draw)(struct svga_t *svga, int displine))
630 {
631 int c, d, e;
633 svga->p = p;
635 for (c = 0; c < 256; c++)
636 {
637 e = c;
638 for (d = 0; d < 8; d++)
639 {
640 svga_rotate[d][c] = e;
641 e = (e >> 1) | ((e & 1) ? 0x80 : 0);
642 }
643 }
644 svga->readmode = 0;
646 svga->crtc[0] = 63;
647 svga->crtc[6] = 255;
648 svga->dispontime = 1000 * (1 << TIMER_SHIFT);
649 svga->dispofftime = 1000 * (1 << TIMER_SHIFT);
650 svga->bpp = 8;
651 svga->vram = malloc(memsize);
652 svga->vram_limit = memsize;
653 svga->vrammask = memsize - 1;
654 svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
655 svga->recalctimings_ex = recalctimings_ex;
656 svga->video_in = video_in;
657 svga->video_out = video_out;
658 svga->hwcursor_draw = hwcursor_draw;
659 svga->overlay_draw = overlay_draw;
660 // _svga_recalctimings(svga);
662 mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga);
664 timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga);
665 vramp = svga->vram;
666 return 0;
667 }
669 void svga_close(svga_t *svga)
670 {
671 free(svga->changedvram);
672 free(svga->vram);
673 }
675 #define egacycles 1
676 #define egacycles2 1
677 void svga_write(uint32_t addr, uint8_t val, void *p)
678 {
679 svga_t *svga = (svga_t *)p;
680 uint8_t vala, valb, valc, vald, wm = svga->writemask;
681 int writemask2 = svga->writemask;
683 egawrites++;
685 cycles -= video_timing_b;
686 cycles_lost += video_timing_b;
688 if (svga_output) pclog("Writeega %06X ",addr);
689 addr &= svga->banked_mask;
690 addr += svga->write_bank;
692 if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
693 if (svga->chain4 || svga->fb_only)
694 {
695 writemask2=1<<(addr&3);
696 addr&=~3;
697 }
698 else
699 {
700 addr<<=2;
701 }
702 addr &= 0x7fffff;
704 if (addr >= svga->vram_limit)
705 return;
707 if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i %02X\n", addr, addr & 1023, addr >> 10, val, writemask2, svga->writemode, svga->chain4, svga->gdcreg[8]);
708 svga->changedvram[addr >> 12] = changeframecount;
710 switch (svga->writemode)
711 {
712 case 1:
713 if (writemask2 & 1) svga->vram[addr] = svga->la;
714 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
715 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
716 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
717 break;
718 case 0:
719 if (svga->gdcreg[3] & 7)
720 val = svga_rotate[svga->gdcreg[3] & 7][val];
721 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
722 {
723 if (writemask2 & 1) svga->vram[addr] = val;
724 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
725 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
726 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
727 }
728 else
729 {
730 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
731 else vala = val;
732 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
733 else valb = val;
734 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
735 else valc = val;
736 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
737 else vald = val;
739 switch (svga->gdcreg[3] & 0x18)
740 {
741 case 0: /*Set*/
742 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
743 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
744 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
745 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
746 break;
747 case 8: /*AND*/
748 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
749 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
750 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
751 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
752 break;
753 case 0x10: /*OR*/
754 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
755 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
756 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
757 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
758 break;
759 case 0x18: /*XOR*/
760 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
761 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
762 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
763 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
764 break;
765 }
766 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
767 }
768 break;
769 case 2:
770 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
771 {
772 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
773 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
774 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
775 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
776 }
777 else
778 {
779 vala = ((val & 1) ? 0xff : 0);
780 valb = ((val & 2) ? 0xff : 0);
781 valc = ((val & 4) ? 0xff : 0);
782 vald = ((val & 8) ? 0xff : 0);
783 switch (svga->gdcreg[3] & 0x18)
784 {
785 case 0: /*Set*/
786 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
787 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
788 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
789 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
790 break;
791 case 8: /*AND*/
792 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
793 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
794 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
795 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
796 break;
797 case 0x10: /*OR*/
798 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
799 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
800 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
801 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
802 break;
803 case 0x18: /*XOR*/
804 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
805 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
806 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
807 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
808 break;
809 }
810 }
811 break;
812 case 3:
813 if (svga->gdcreg[3] & 7)
814 val = svga_rotate[svga->gdcreg[3] & 7][val];
815 wm = svga->gdcreg[8];
816 svga->gdcreg[8] &= val;
818 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
819 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
820 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
821 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
822 switch (svga->gdcreg[3] & 0x18)
823 {
824 case 0: /*Set*/
825 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
826 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
827 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
828 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
829 break;
830 case 8: /*AND*/
831 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
832 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
833 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
834 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
835 break;
836 case 0x10: /*OR*/
837 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
838 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
839 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
840 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
841 break;
842 case 0x18: /*XOR*/
843 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
844 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
845 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
846 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
847 break;
848 }
849 svga->gdcreg[8] = wm;
850 break;
851 }
852 }
854 uint8_t svga_read(uint32_t addr, void *p)
855 {
856 svga_t *svga = (svga_t *)p;
857 uint8_t temp, temp2, temp3, temp4;
859 cycles -= video_timing_b;
860 cycles_lost += video_timing_b;
862 egareads++;
863 // pclog("Readega %06X ",addr);
864 addr &= svga->banked_mask;
865 addr += svga->read_bank;
867 // pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
868 // pclog("%i\n", svga->readmode);
869 if (svga->chain4 || svga->fb_only)
870 {
871 addr &= 0x7fffff;
872 if (addr >= svga->vram_limit)
873 return 0xff;
874 return svga->vram[addr];
875 }
876 else addr<<=2;
878 addr &= 0x7fffff;
880 if (addr >= svga->vram_limit)
881 return 0xff;
883 svga->la = svga->vram[addr];
884 svga->lb = svga->vram[addr | 0x1];
885 svga->lc = svga->vram[addr | 0x2];
886 svga->ld = svga->vram[addr | 0x3];
887 if (svga->readmode)
888 {
889 temp = (svga->colournocare & 1) ? 0xff : 0;
890 temp &= svga->la;
891 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
892 temp2 = (svga->colournocare & 2) ? 0xff : 0;
893 temp2 &= svga->lb;
894 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
895 temp3 = (svga->colournocare & 4) ? 0xff : 0;
896 temp3 &= svga->lc;
897 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
898 temp4 = (svga->colournocare & 8) ? 0xff : 0;
899 temp4 &= svga->ld;
900 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
901 return ~(temp | temp2 | temp3 | temp4);
902 }
903 //pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
904 return svga->vram[addr | svga->readplane];
905 }
907 void svga_write_linear(uint32_t addr, uint8_t val, void *p)
908 {
909 svga_t *svga = (svga_t *)p;
910 uint8_t vala, valb, valc, vald, wm = svga->writemask;
911 int writemask2 = svga->writemask;
913 cycles -= video_timing_b;
914 cycles_lost += video_timing_b;
916 egawrites++;
918 if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
919 if (!(svga->gdcreg[6] & 1))
920 svga->fullchange = 2;
921 if (svga->chain4 || svga->fb_only)
922 {
923 writemask2=1<<(addr&3);
924 addr&=~3;
925 }
926 else
927 {
928 addr<<=2;
929 }
930 addr &= 0x7fffff;
931 if (addr >= svga->vram_limit)
932 return;
933 if (svga_output) pclog("%08X\n", addr);
934 svga->changedvram[addr >> 12]=changeframecount;
936 switch (svga->writemode)
937 {
938 case 1:
939 if (writemask2 & 1) svga->vram[addr] = svga->la;
940 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
941 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
942 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
943 break;
944 case 0:
945 if (svga->gdcreg[3] & 7)
946 val = svga_rotate[svga->gdcreg[3] & 7][val];
947 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
948 {
949 if (writemask2 & 1) svga->vram[addr] = val;
950 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
951 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
952 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
953 }
954 else
955 {
956 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
957 else vala = val;
958 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
959 else valb = val;
960 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
961 else valc = val;
962 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
963 else vald = val;
965 switch (svga->gdcreg[3] & 0x18)
966 {
967 case 0: /*Set*/
968 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
969 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
970 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
971 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
972 break;
973 case 8: /*AND*/
974 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
975 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
976 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
977 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
978 break;
979 case 0x10: /*OR*/
980 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
981 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
982 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
983 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
984 break;
985 case 0x18: /*XOR*/
986 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
987 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
988 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
989 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
990 break;
991 }
992 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
993 }
994 break;
995 case 2:
996 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
997 {
998 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
999 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1000 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1001 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1003 else
1005 vala = ((val & 1) ? 0xff : 0);
1006 valb = ((val & 2) ? 0xff : 0);
1007 valc = ((val & 4) ? 0xff : 0);
1008 vald = ((val & 8) ? 0xff : 0);
1009 switch (svga->gdcreg[3] & 0x18)
1011 case 0: /*Set*/
1012 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1013 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1014 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1015 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1016 break;
1017 case 8: /*AND*/
1018 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1019 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1020 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1021 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1022 break;
1023 case 0x10: /*OR*/
1024 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1025 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1026 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1027 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1028 break;
1029 case 0x18: /*XOR*/
1030 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1031 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1032 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1033 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1034 break;
1037 break;
1038 case 3:
1039 if (svga->gdcreg[3] & 7)
1040 val = svga_rotate[svga->gdcreg[3] & 7][val];
1041 wm = svga->gdcreg[8];
1042 svga->gdcreg[8] &= val;
1044 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
1045 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
1046 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
1047 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
1048 switch (svga->gdcreg[3] & 0x18)
1050 case 0: /*Set*/
1051 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1052 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1053 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1054 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1055 break;
1056 case 8: /*AND*/
1057 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1058 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1059 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1060 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1061 break;
1062 case 0x10: /*OR*/
1063 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1064 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1065 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1066 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1067 break;
1068 case 0x18: /*XOR*/
1069 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1070 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1071 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1072 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1073 break;
1075 svga->gdcreg[8] = wm;
1076 break;
1080 uint8_t svga_read_linear(uint32_t addr, void *p)
1082 svga_t *svga = (svga_t *)p;
1083 uint8_t temp, temp2, temp3, temp4;
1085 cycles -= video_timing_b;
1086 cycles_lost += video_timing_b;
1088 egareads++;
1090 if (svga->chain4 || svga->fb_only)
1092 addr &= 0x7fffff;
1093 if (addr >= svga->vram_limit)
1094 return 0xff;
1095 return svga->vram[addr & 0x7fffff];
1097 else addr<<=2;
1099 addr &= 0x7fffff;
1101 if (addr >= svga->vram_limit)
1102 return 0xff;
1104 svga->la = svga->vram[addr];
1105 svga->lb = svga->vram[addr | 0x1];
1106 svga->lc = svga->vram[addr | 0x2];
1107 svga->ld = svga->vram[addr | 0x3];
1108 if (svga->readmode)
1110 temp = (svga->colournocare & 1) ? 0xff : 0;
1111 temp &= svga->la;
1112 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
1113 temp2 = (svga->colournocare & 2) ? 0xff : 0;
1114 temp2 &= svga->lb;
1115 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
1116 temp3 = (svga->colournocare & 4) ? 0xff : 0;
1117 temp3 &= svga->lc;
1118 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
1119 temp4 = (svga->colournocare & 8) ? 0xff : 0;
1120 temp4 &= svga->ld;
1121 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
1122 return ~(temp | temp2 | temp3 | temp4);
1124 //printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
1125 return svga->vram[addr | svga->readplane];
1128 void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
1130 // pclog("svga_doblit start\n");
1131 svga->frames++;
1132 // pclog("doblit %i %i\n", y1, y2);
1133 // pclog("svga_doblit %i %i\n", wx, svga->hdisp);
1134 if (y1 > y2)
1136 video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize);
1137 return;
1140 if ((wx!=xsize || wy!=ysize) && !vid_resize)
1142 xsize=wx;
1143 ysize=wy+1;
1144 if (xsize<64) xsize=656;
1145 if (ysize<32) ysize=200;
1147 updatewindowsize(xsize,ysize);
1149 if (vid_resize)
1151 xsize = wx;
1152 ysize = wy + 1;
1154 video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
1155 if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
1156 // pclog("svga_doblit end\n");
1159 void svga_writew(uint32_t addr, uint16_t val, void *p)
1161 svga_t *svga = (svga_t *)p;
1162 if (!svga)
1163 exit(-1);
1164 if (!svga->fast)
1166 svga_write(addr, val, p);
1167 svga_write(addr + 1, val >> 8, p);
1168 return;
1171 egawrites += 2;
1173 cycles -= video_timing_w;
1174 cycles_lost += video_timing_w;
1176 if (svga_output) pclog("svga_writew: %05X ", addr);
1177 addr = (addr & svga->banked_mask) + svga->write_bank;
1178 addr &= 0x7FFFFF;
1179 if (addr >= svga->vram_limit)
1180 return;
1181 if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val);
1182 svga->changedvram[addr >> 12] = changeframecount;
1183 *(uint16_t *)&svga->vram[addr] = val;
1186 void svga_writel(uint32_t addr, uint32_t val, void *p)
1188 svga_t *svga = (svga_t *)p;
1190 if (!svga->fast)
1192 svga_write(addr, val, p);
1193 svga_write(addr + 1, val >> 8, p);
1194 svga_write(addr + 2, val >> 16, p);
1195 svga_write(addr + 3, val >> 24, p);
1196 return;
1199 egawrites += 4;
1201 cycles -= video_timing_l;
1202 cycles_lost += video_timing_l;
1204 if (svga_output) pclog("svga_writel: %05X ", addr);
1205 addr = (addr & svga->banked_mask) + svga->write_bank;
1206 addr &= 0x7FFFFF;
1207 if (addr >= svga->vram_limit)
1208 return;
1209 if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val);
1211 svga->changedvram[addr >> 12] = changeframecount;
1212 *(uint32_t *)&svga->vram[addr] = val;
1215 uint16_t svga_readw(uint32_t addr, void *p)
1217 svga_t *svga = (svga_t *)p;
1219 if (!svga->fast)
1220 return svga_read(addr, p) | (svga_read(addr + 1, p) << 8);
1222 egareads += 2;
1224 cycles -= video_timing_w;
1225 cycles_lost += video_timing_w;
1227 // pclog("Readw %05X ", addr);
1228 addr = (addr & svga->banked_mask) + svga->read_bank;
1229 addr &= 0x7FFFFF;
1230 // pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]);
1231 if (addr >= svga->vram_limit) return 0xffff;
1233 return *(uint16_t *)&svga->vram[addr];
1236 uint32_t svga_readl(uint32_t addr, void *p)
1238 svga_t *svga = (svga_t *)p;
1240 if (!svga->fast)
1241 return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24);
1243 egareads += 4;
1245 cycles -= video_timing_l;
1246 cycles_lost += video_timing_l;
1248 // pclog("Readl %05X ", addr);
1249 addr = (addr & svga->banked_mask) + svga->read_bank;
1250 addr &= 0x7FFFFF;
1251 // pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]);
1252 if (addr >= svga->vram_limit) return 0xffffffff;
1254 return *(uint32_t *)&svga->vram[addr];
1257 void svga_writew_linear(uint32_t addr, uint16_t val, void *p)
1259 svga_t *svga = (svga_t *)p;
1261 if (!svga->fast)
1263 svga_write_linear(addr, val, p);
1264 svga_write_linear(addr + 1, val >> 8, p);
1265 return;
1268 egawrites += 2;
1270 cycles -= video_timing_w;
1271 cycles_lost += video_timing_w;
1273 if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val);
1274 addr &= 0x7FFFFF;
1275 if (addr >= svga->vram_limit)
1276 return;
1277 svga->changedvram[addr >> 12] = changeframecount;
1278 *(uint16_t *)&svga->vram[addr] = val;
1281 void svga_writel_linear(uint32_t addr, uint32_t val, void *p)
1283 svga_t *svga = (svga_t *)p;
1285 if (!svga->fast)
1287 svga_write_linear(addr, val, p);
1288 svga_write_linear(addr + 1, val >> 8, p);
1289 svga_write_linear(addr + 2, val >> 16, p);
1290 svga_write_linear(addr + 3, val >> 24, p);
1291 return;
1294 egawrites += 4;
1296 cycles -= video_timing_l;
1297 cycles_lost += video_timing_l;
1299 if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val);
1300 addr &= 0x7fffff;
1301 if (addr >= svga->vram_limit)
1302 return;
1303 svga->changedvram[addr >> 12] = changeframecount;
1304 *(uint32_t *)&svga->vram[addr] = val;
1307 uint16_t svga_readw_linear(uint32_t addr, void *p)
1309 svga_t *svga = (svga_t *)p;
1311 if (!svga->fast)
1312 return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8);
1314 egareads += 2;
1316 cycles -= video_timing_w;
1317 cycles_lost += video_timing_w;
1319 addr &= 0x7FFFFF;
1320 if (addr >= svga->vram_limit) return 0xffff;
1322 return *(uint16_t *)&svga->vram[addr];
1325 uint32_t svga_readl_linear(uint32_t addr, void *p)
1327 svga_t *svga = (svga_t *)p;
1329 if (!svga->fast)
1330 return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8) | (svga_read_linear(addr + 2, p) << 16) | (svga_read_linear(addr + 3, p) << 24);
1332 egareads += 4;
1334 cycles -= video_timing_l;
1335 cycles_lost += video_timing_l;
1337 addr &= 0x7FFFFF;
1338 if (addr >= svga->vram_limit) return 0xffffffff;
1340 return *(uint32_t *)&svga->vram[addr];
1344 int svga_add_status_info(char *s, int max_len, void *p)
1346 svga_t *svga = (svga_t *)p;
1347 char temps[128];
1348 int cur_len = max_len;
1349 int len;
1351 if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
1352 else strcpy(temps, "SVGA unchained (possibly mode-X)\n");
1353 strncat(s, temps, cur_len);
1354 cur_len -= len;
1356 if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
1357 else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
1358 strncat(s, temps, cur_len);
1359 cur_len -= strlen(temps);
1361 sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
1362 strncat(s, temps, cur_len);
1363 cur_len -= strlen(temps);
1365 sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
1366 svga->frames = 0;
1367 strncat(s, temps, cur_len);
1368 cur_len -= strlen(temps);
1370 return max_len - cur_len;