PCem

view src/vid_svga.c @ 125:0aa71a22757b

Fixed hang when opening status window.
author TomW
date Fri Jul 11 20:52:18 2014 +0100
parents 173e1f058566
children 614f796ff7ed
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 {
407 svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
408 svga->hwcursor_oddeven = 0;
409 }
411 if (svga->displine == svga->hwcursor_latch.y+1 && svga->hwcursor_latch.ena && svga->interlace)
412 {
413 svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
414 svga->hwcursor_oddeven = 1;
415 }
417 if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena)
418 {
419 svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
420 svga->overlay_oddeven = 0;
421 }
422 if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace)
423 {
424 svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
425 svga->overlay_oddeven = 1;
426 }
428 svga->vidtime += svga->dispofftime;
429 // if (output) printf("Display off %f\n",vidtime);
430 svga->cgastat |= 1;
431 svga->linepos = 1;
433 if (svga->dispon)
434 {
435 svga->hdisp_on=1;
437 svga->ma &= svga->vrammask;
438 if (svga->firstline == 2000)
439 svga->firstline = svga->displine;
441 if (svga->hwcursor_on || svga->overlay_on)
442 svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = 2;
444 svga->render(svga);
446 if (svga->overlay_on)
447 {
448 svga->overlay_draw(svga, svga->displine);
449 svga->overlay_on--;
450 if (svga->overlay_on && svga->interlace)
451 svga->overlay_on--;
452 }
454 if (svga->hwcursor_on)
455 {
456 svga->hwcursor_draw(svga, svga->displine);
457 svga->hwcursor_on--;
458 if (svga->hwcursor_on && svga->interlace)
459 svga->hwcursor_on--;
460 }
462 if (svga->lastline < svga->displine)
463 svga->lastline = svga->displine;
464 }
466 // pclog("%03i %06X %06X\n",displine,ma,vrammask);
467 svga->displine++;
468 if (svga->interlace)
469 svga->displine++;
470 if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines)
471 {
472 // printf("Vsync off at line %i\n",displine);
473 svga->cgastat &= ~8;
474 }
475 svga->vslines++;
476 if (svga->displine > 1500)
477 svga->displine = 0;
478 // 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],
479 // displine, vc, ma);
480 }
481 else
482 {
483 // pclog("VC %i ma %05X\n", svga->vc, svga->ma);
484 svga->vidtime += svga->dispontime;
486 // if (output) printf("Display on %f\n",vidtime);
487 if (svga->dispon)
488 svga->cgastat &= ~1;
489 svga->hdisp_on = 0;
491 svga->linepos = 0;
492 if (svga->sc == (svga->crtc[11] & 31))
493 svga->con = 0;
494 if (svga->dispon)
495 {
496 if (svga->linedbl && !svga->linecountff)
497 {
498 svga->linecountff = 1;
499 svga->ma = svga->maback;
500 }
501 else if (svga->sc == svga->rowcount)
502 {
503 svga->linecountff = 0;
504 svga->sc = 0;
506 svga->maback += (svga->rowoffset << 3);
507 if (svga->interlace)
508 svga->maback += (svga->rowoffset << 3);
509 svga->maback &= svga->vrammask;
510 svga->ma = svga->maback;
511 }
512 else
513 {
514 svga->linecountff = 0;
515 svga->sc++;
516 svga->sc &= 31;
517 svga->ma = svga->maback;
518 }
519 }
520 svga->vc++;
521 svga->vc &= 2047;
523 if (svga->vc == svga->split)
524 {
525 // pclog("VC split\n");
526 svga->ma = svga->maback = 0;
527 if (svga->attrregs[0x10] & 0x20)
528 svga->scrollcache = 0;
529 }
530 if (svga->vc == svga->dispend)
531 {
532 // pclog("VC dispend\n");
533 svga->dispon=0;
534 if (svga->crtc[10] & 0x20) svga->cursoron = 0;
535 else svga->cursoron = svga->blink & 16;
536 if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15))
537 svga->fullchange = 2;
538 svga->blink++;
540 for (x = 0; x < (svga->vram_limit >> 12); x++)
541 {
542 if (svga->changedvram[x])
543 svga->changedvram[x]--;
544 }
545 // memset(changedvram,0,2048);
546 if (svga->fullchange)
547 svga->fullchange--;
548 }
549 if (svga->vc == svga->vsyncstart)
550 {
551 int wx, wy;
552 // pclog("VC vsync %i %i\n", svga->firstline_draw, svga->lastline_draw);
553 svga->dispon=0;
554 svga->cgastat |= 8;
555 x = svga->hdisp;
557 if (svga->interlace && !svga->oddeven) svga->lastline++;
558 if (svga->interlace && svga->oddeven) svga->firstline--;
560 wx = x;
561 wy = svga->lastline - svga->firstline;
563 svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
565 readflash = 0;
567 svga->firstline = 2000;
568 svga->lastline = 0;
570 svga->firstline_draw = 2000;
571 svga->lastline_draw = 0;
573 svga->oddeven ^= 1;
575 changeframecount = svga->interlace ? 3 : 2;
576 svga->vslines = 0;
578 if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
579 else svga->ma = svga->maback = svga->ma_latch;
580 svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf];
582 svga->ma <<= 2;
583 svga->maback <<= 2;
584 svga->ca <<= 2;
586 svga->video_res_x = wx;
587 svga->video_res_y = wy + 1;
588 // pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
589 if (!(svga->gdcreg[6] & 1)) /*Text mode*/
590 {
591 svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9;
592 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
593 svga->video_bpp = 0;
594 }
595 else
596 {
597 if (svga->crtc[9] & 0x80)
598 svga->video_res_y /= 2;
599 if (!(svga->crtc[0x17] & 1))
600 svga->video_res_y *= 2;
601 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
602 if (svga->lowres)
603 svga->video_res_x /= 2;
605 switch (svga->gdcreg[5] & 0x60)
606 {
607 case 0x00: svga->video_bpp = 4; break;
608 case 0x20: svga->video_bpp = 2; break;
609 case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
610 }
611 }
612 // if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
614 // 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);
615 }
616 if (svga->vc == svga->vtotal)
617 {
618 // pclog("VC vtotal\n");
621 // printf("Frame over at line %i %i %i %i\n",displine,vc,svga_vsyncstart,svga_dispend);
622 svga->vc = 0;
623 svga->sc = 0;
624 svga->dispon = 1;
625 svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
626 svga->scrollcache = svga->attrregs[0x13] & 7;
627 svga->linecountff = 0;
629 svga->hwcursor_on = 0;
630 svga->hwcursor_latch = svga->hwcursor;
632 svga->overlay_on = 0;
633 svga->overlay_latch = svga->overlay;
634 // pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
636 // pclog("ADDR %08X\n",hwcursor_addr);
637 }
638 if (svga->sc == (svga->crtc[10] & 31))
639 svga->con = 1;
640 }
641 // printf("2 %i\n",svga_vsyncstart);
642 //pclog("svga_poll %i %i %i %i %i %i %i\n", ins, svga->dispofftime, svga->dispontime, svga->vidtime, cyc_total, svga->linepos, svga->vc);
643 }
645 int svga_init(svga_t *svga, void *p, int memsize,
646 void (*recalctimings_ex)(struct svga_t *svga),
647 uint8_t (*video_in) (uint16_t addr, void *p),
648 void (*video_out)(uint16_t addr, uint8_t val, void *p),
649 void (*hwcursor_draw)(struct svga_t *svga, int displine),
650 void (*overlay_draw)(struct svga_t *svga, int displine))
651 {
652 int c, d, e;
654 svga->p = p;
656 for (c = 0; c < 256; c++)
657 {
658 e = c;
659 for (d = 0; d < 8; d++)
660 {
661 svga_rotate[d][c] = e;
662 e = (e >> 1) | ((e & 1) ? 0x80 : 0);
663 }
664 }
665 svga->readmode = 0;
667 svga->crtc[0] = 63;
668 svga->crtc[6] = 255;
669 svga->dispontime = 1000 * (1 << TIMER_SHIFT);
670 svga->dispofftime = 1000 * (1 << TIMER_SHIFT);
671 svga->bpp = 8;
672 svga->vram = malloc(memsize);
673 svga->vram_limit = memsize;
674 svga->vrammask = memsize - 1;
675 svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
676 svga->recalctimings_ex = recalctimings_ex;
677 svga->video_in = video_in;
678 svga->video_out = video_out;
679 svga->hwcursor_draw = hwcursor_draw;
680 svga->overlay_draw = overlay_draw;
681 // _svga_recalctimings(svga);
683 mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga);
685 timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga);
686 vramp = svga->vram;
687 return 0;
688 }
690 void svga_close(svga_t *svga)
691 {
692 free(svga->changedvram);
693 free(svga->vram);
694 }
696 #define egacycles 1
697 #define egacycles2 1
698 void svga_write(uint32_t addr, uint8_t val, void *p)
699 {
700 svga_t *svga = (svga_t *)p;
701 uint8_t vala, valb, valc, vald, wm = svga->writemask;
702 int writemask2 = svga->writemask;
704 egawrites++;
706 cycles -= video_timing_b;
707 cycles_lost += video_timing_b;
709 if (svga_output) pclog("Writeega %06X ",addr);
710 addr &= svga->banked_mask;
711 addr += svga->write_bank;
713 if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
714 if (svga->chain4 || svga->fb_only)
715 {
716 writemask2=1<<(addr&3);
717 addr&=~3;
718 }
719 else
720 {
721 addr<<=2;
722 }
723 addr &= 0x7fffff;
725 if (addr >= svga->vram_limit)
726 return;
728 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]);
729 svga->changedvram[addr >> 12] = changeframecount;
731 switch (svga->writemode)
732 {
733 case 1:
734 if (writemask2 & 1) svga->vram[addr] = svga->la;
735 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
736 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
737 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
738 break;
739 case 0:
740 if (svga->gdcreg[3] & 7)
741 val = svga_rotate[svga->gdcreg[3] & 7][val];
742 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
743 {
744 if (writemask2 & 1) svga->vram[addr] = val;
745 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
746 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
747 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
748 }
749 else
750 {
751 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
752 else vala = val;
753 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
754 else valb = val;
755 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
756 else valc = val;
757 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
758 else vald = val;
760 switch (svga->gdcreg[3] & 0x18)
761 {
762 case 0: /*Set*/
763 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
764 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
765 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
766 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
767 break;
768 case 8: /*AND*/
769 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
770 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
771 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
772 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
773 break;
774 case 0x10: /*OR*/
775 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
776 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
777 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
778 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
779 break;
780 case 0x18: /*XOR*/
781 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
782 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
783 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
784 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
785 break;
786 }
787 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
788 }
789 break;
790 case 2:
791 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
792 {
793 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
794 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
795 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
796 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
797 }
798 else
799 {
800 vala = ((val & 1) ? 0xff : 0);
801 valb = ((val & 2) ? 0xff : 0);
802 valc = ((val & 4) ? 0xff : 0);
803 vald = ((val & 8) ? 0xff : 0);
804 switch (svga->gdcreg[3] & 0x18)
805 {
806 case 0: /*Set*/
807 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
808 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
809 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
810 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
811 break;
812 case 8: /*AND*/
813 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
814 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
815 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
816 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
817 break;
818 case 0x10: /*OR*/
819 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
820 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
821 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
822 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
823 break;
824 case 0x18: /*XOR*/
825 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
826 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
827 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
828 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
829 break;
830 }
831 }
832 break;
833 case 3:
834 if (svga->gdcreg[3] & 7)
835 val = svga_rotate[svga->gdcreg[3] & 7][val];
836 wm = svga->gdcreg[8];
837 svga->gdcreg[8] &= val;
839 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
840 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
841 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
842 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
843 switch (svga->gdcreg[3] & 0x18)
844 {
845 case 0: /*Set*/
846 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
847 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
848 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
849 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
850 break;
851 case 8: /*AND*/
852 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
853 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
854 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
855 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
856 break;
857 case 0x10: /*OR*/
858 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
859 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
860 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
861 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
862 break;
863 case 0x18: /*XOR*/
864 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
865 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
866 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
867 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
868 break;
869 }
870 svga->gdcreg[8] = wm;
871 break;
872 }
873 }
875 uint8_t svga_read(uint32_t addr, void *p)
876 {
877 svga_t *svga = (svga_t *)p;
878 uint8_t temp, temp2, temp3, temp4;
880 cycles -= video_timing_b;
881 cycles_lost += video_timing_b;
883 egareads++;
884 // pclog("Readega %06X ",addr);
885 addr &= svga->banked_mask;
886 addr += svga->read_bank;
888 // pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
889 // pclog("%i\n", svga->readmode);
890 if (svga->chain4 || svga->fb_only)
891 {
892 addr &= 0x7fffff;
893 if (addr >= svga->vram_limit)
894 return 0xff;
895 return svga->vram[addr];
896 }
897 else addr<<=2;
899 addr &= 0x7fffff;
901 if (addr >= svga->vram_limit)
902 return 0xff;
904 svga->la = svga->vram[addr];
905 svga->lb = svga->vram[addr | 0x1];
906 svga->lc = svga->vram[addr | 0x2];
907 svga->ld = svga->vram[addr | 0x3];
908 if (svga->readmode)
909 {
910 temp = (svga->colournocare & 1) ? 0xff : 0;
911 temp &= svga->la;
912 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
913 temp2 = (svga->colournocare & 2) ? 0xff : 0;
914 temp2 &= svga->lb;
915 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
916 temp3 = (svga->colournocare & 4) ? 0xff : 0;
917 temp3 &= svga->lc;
918 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
919 temp4 = (svga->colournocare & 8) ? 0xff : 0;
920 temp4 &= svga->ld;
921 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
922 return ~(temp | temp2 | temp3 | temp4);
923 }
924 //pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
925 return svga->vram[addr | svga->readplane];
926 }
928 void svga_write_linear(uint32_t addr, uint8_t val, void *p)
929 {
930 svga_t *svga = (svga_t *)p;
931 uint8_t vala, valb, valc, vald, wm = svga->writemask;
932 int writemask2 = svga->writemask;
934 cycles -= video_timing_b;
935 cycles_lost += video_timing_b;
937 egawrites++;
939 if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
940 if (!(svga->gdcreg[6] & 1))
941 svga->fullchange = 2;
942 if (svga->chain4 || svga->fb_only)
943 {
944 writemask2=1<<(addr&3);
945 addr&=~3;
946 }
947 else
948 {
949 addr<<=2;
950 }
951 addr &= 0x7fffff;
952 if (addr >= svga->vram_limit)
953 return;
954 if (svga_output) pclog("%08X\n", addr);
955 svga->changedvram[addr >> 12]=changeframecount;
957 switch (svga->writemode)
958 {
959 case 1:
960 if (writemask2 & 1) svga->vram[addr] = svga->la;
961 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
962 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
963 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
964 break;
965 case 0:
966 if (svga->gdcreg[3] & 7)
967 val = svga_rotate[svga->gdcreg[3] & 7][val];
968 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
969 {
970 if (writemask2 & 1) svga->vram[addr] = val;
971 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
972 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
973 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
974 }
975 else
976 {
977 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
978 else vala = val;
979 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
980 else valb = val;
981 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
982 else valc = val;
983 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
984 else vald = val;
986 switch (svga->gdcreg[3] & 0x18)
987 {
988 case 0: /*Set*/
989 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
990 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
991 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
992 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
993 break;
994 case 8: /*AND*/
995 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
996 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
997 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
998 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
999 break;
1000 case 0x10: /*OR*/
1001 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1002 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1003 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1004 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1005 break;
1006 case 0x18: /*XOR*/
1007 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1008 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1009 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1010 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1011 break;
1013 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
1015 break;
1016 case 2:
1017 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
1019 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1020 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1021 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1022 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1024 else
1026 vala = ((val & 1) ? 0xff : 0);
1027 valb = ((val & 2) ? 0xff : 0);
1028 valc = ((val & 4) ? 0xff : 0);
1029 vald = ((val & 8) ? 0xff : 0);
1030 switch (svga->gdcreg[3] & 0x18)
1032 case 0: /*Set*/
1033 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1034 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1035 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1036 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1037 break;
1038 case 8: /*AND*/
1039 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1040 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1041 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1042 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1043 break;
1044 case 0x10: /*OR*/
1045 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1046 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1047 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1048 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1049 break;
1050 case 0x18: /*XOR*/
1051 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1052 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1053 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1054 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1055 break;
1058 break;
1059 case 3:
1060 if (svga->gdcreg[3] & 7)
1061 val = svga_rotate[svga->gdcreg[3] & 7][val];
1062 wm = svga->gdcreg[8];
1063 svga->gdcreg[8] &= val;
1065 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
1066 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
1067 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
1068 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
1069 switch (svga->gdcreg[3] & 0x18)
1071 case 0: /*Set*/
1072 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1073 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1074 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1075 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1076 break;
1077 case 8: /*AND*/
1078 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1079 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1080 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1081 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1082 break;
1083 case 0x10: /*OR*/
1084 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1085 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1086 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1087 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1088 break;
1089 case 0x18: /*XOR*/
1090 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1091 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1092 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1093 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1094 break;
1096 svga->gdcreg[8] = wm;
1097 break;
1101 uint8_t svga_read_linear(uint32_t addr, void *p)
1103 svga_t *svga = (svga_t *)p;
1104 uint8_t temp, temp2, temp3, temp4;
1106 cycles -= video_timing_b;
1107 cycles_lost += video_timing_b;
1109 egareads++;
1111 if (svga->chain4 || svga->fb_only)
1113 addr &= 0x7fffff;
1114 if (addr >= svga->vram_limit)
1115 return 0xff;
1116 return svga->vram[addr & 0x7fffff];
1118 else addr<<=2;
1120 addr &= 0x7fffff;
1122 if (addr >= svga->vram_limit)
1123 return 0xff;
1125 svga->la = svga->vram[addr];
1126 svga->lb = svga->vram[addr | 0x1];
1127 svga->lc = svga->vram[addr | 0x2];
1128 svga->ld = svga->vram[addr | 0x3];
1129 if (svga->readmode)
1131 temp = (svga->colournocare & 1) ? 0xff : 0;
1132 temp &= svga->la;
1133 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
1134 temp2 = (svga->colournocare & 2) ? 0xff : 0;
1135 temp2 &= svga->lb;
1136 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
1137 temp3 = (svga->colournocare & 4) ? 0xff : 0;
1138 temp3 &= svga->lc;
1139 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
1140 temp4 = (svga->colournocare & 8) ? 0xff : 0;
1141 temp4 &= svga->ld;
1142 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
1143 return ~(temp | temp2 | temp3 | temp4);
1145 //printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
1146 return svga->vram[addr | svga->readplane];
1149 void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
1151 // pclog("svga_doblit start\n");
1152 svga->frames++;
1153 // pclog("doblit %i %i\n", y1, y2);
1154 // pclog("svga_doblit %i %i\n", wx, svga->hdisp);
1155 if (y1 > y2)
1157 video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize);
1158 return;
1161 if ((wx!=xsize || wy!=ysize) && !vid_resize)
1163 xsize=wx;
1164 ysize=wy+1;
1165 if (xsize<64) xsize=656;
1166 if (ysize<32) ysize=200;
1168 updatewindowsize(xsize,ysize);
1170 if (vid_resize)
1172 xsize = wx;
1173 ysize = wy + 1;
1175 video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
1176 if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
1177 // pclog("svga_doblit end\n");
1180 void svga_writew(uint32_t addr, uint16_t val, void *p)
1182 svga_t *svga = (svga_t *)p;
1183 if (!svga)
1184 exit(-1);
1185 if (!svga->fast)
1187 svga_write(addr, val, p);
1188 svga_write(addr + 1, val >> 8, p);
1189 return;
1192 egawrites += 2;
1194 cycles -= video_timing_w;
1195 cycles_lost += video_timing_w;
1197 if (svga_output) pclog("svga_writew: %05X ", addr);
1198 addr = (addr & svga->banked_mask) + svga->write_bank;
1199 addr &= 0x7FFFFF;
1200 if (addr >= svga->vram_limit)
1201 return;
1202 if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val);
1203 svga->changedvram[addr >> 12] = changeframecount;
1204 *(uint16_t *)&svga->vram[addr] = val;
1207 void svga_writel(uint32_t addr, uint32_t val, void *p)
1209 svga_t *svga = (svga_t *)p;
1211 if (!svga->fast)
1213 svga_write(addr, val, p);
1214 svga_write(addr + 1, val >> 8, p);
1215 svga_write(addr + 2, val >> 16, p);
1216 svga_write(addr + 3, val >> 24, p);
1217 return;
1220 egawrites += 4;
1222 cycles -= video_timing_l;
1223 cycles_lost += video_timing_l;
1225 if (svga_output) pclog("svga_writel: %05X ", addr);
1226 addr = (addr & svga->banked_mask) + svga->write_bank;
1227 addr &= 0x7FFFFF;
1228 if (addr >= svga->vram_limit)
1229 return;
1230 if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val);
1232 svga->changedvram[addr >> 12] = changeframecount;
1233 *(uint32_t *)&svga->vram[addr] = val;
1236 uint16_t svga_readw(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);
1243 egareads += 2;
1245 cycles -= video_timing_w;
1246 cycles_lost += video_timing_w;
1248 // pclog("Readw %05X ", addr);
1249 addr = (addr & svga->banked_mask) + svga->read_bank;
1250 addr &= 0x7FFFFF;
1251 // pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]);
1252 if (addr >= svga->vram_limit) return 0xffff;
1254 return *(uint16_t *)&svga->vram[addr];
1257 uint32_t svga_readl(uint32_t addr, void *p)
1259 svga_t *svga = (svga_t *)p;
1261 if (!svga->fast)
1262 return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24);
1264 egareads += 4;
1266 cycles -= video_timing_l;
1267 cycles_lost += video_timing_l;
1269 // pclog("Readl %05X ", addr);
1270 addr = (addr & svga->banked_mask) + svga->read_bank;
1271 addr &= 0x7FFFFF;
1272 // pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]);
1273 if (addr >= svga->vram_limit) return 0xffffffff;
1275 return *(uint32_t *)&svga->vram[addr];
1278 void svga_writew_linear(uint32_t addr, uint16_t val, void *p)
1280 svga_t *svga = (svga_t *)p;
1282 if (!svga->fast)
1284 svga_write_linear(addr, val, p);
1285 svga_write_linear(addr + 1, val >> 8, p);
1286 return;
1289 egawrites += 2;
1291 cycles -= video_timing_w;
1292 cycles_lost += video_timing_w;
1294 if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val);
1295 addr &= 0x7FFFFF;
1296 if (addr >= svga->vram_limit)
1297 return;
1298 svga->changedvram[addr >> 12] = changeframecount;
1299 *(uint16_t *)&svga->vram[addr] = val;
1302 void svga_writel_linear(uint32_t addr, uint32_t val, void *p)
1304 svga_t *svga = (svga_t *)p;
1306 if (!svga->fast)
1308 svga_write_linear(addr, val, p);
1309 svga_write_linear(addr + 1, val >> 8, p);
1310 svga_write_linear(addr + 2, val >> 16, p);
1311 svga_write_linear(addr + 3, val >> 24, p);
1312 return;
1315 egawrites += 4;
1317 cycles -= video_timing_l;
1318 cycles_lost += video_timing_l;
1320 if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val);
1321 addr &= 0x7fffff;
1322 if (addr >= svga->vram_limit)
1323 return;
1324 svga->changedvram[addr >> 12] = changeframecount;
1325 *(uint32_t *)&svga->vram[addr] = val;
1328 uint16_t svga_readw_linear(uint32_t addr, void *p)
1330 svga_t *svga = (svga_t *)p;
1332 if (!svga->fast)
1333 return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8);
1335 egareads += 2;
1337 cycles -= video_timing_w;
1338 cycles_lost += video_timing_w;
1340 addr &= 0x7FFFFF;
1341 if (addr >= svga->vram_limit) return 0xffff;
1343 return *(uint16_t *)&svga->vram[addr];
1346 uint32_t svga_readl_linear(uint32_t addr, void *p)
1348 svga_t *svga = (svga_t *)p;
1350 if (!svga->fast)
1351 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);
1353 egareads += 4;
1355 cycles -= video_timing_l;
1356 cycles_lost += video_timing_l;
1358 addr &= 0x7FFFFF;
1359 if (addr >= svga->vram_limit) return 0xffffffff;
1361 return *(uint32_t *)&svga->vram[addr];
1365 int svga_add_status_info(char *s, int max_len, void *p)
1367 svga_t *svga = (svga_t *)p;
1368 char temps[128];
1369 int cur_len = max_len;
1371 if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
1372 else strcpy(temps, "SVGA unchained (possibly mode-X)\n");
1373 strncat(s, temps, cur_len);
1374 cur_len -= strlen(temps);
1376 if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
1377 else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
1378 strncat(s, temps, cur_len);
1379 cur_len -= strlen(temps);
1381 sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
1382 strncat(s, temps, cur_len);
1383 cur_len -= strlen(temps);
1385 sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
1386 svga->frames = 0;
1387 strncat(s, temps, cur_len);
1388 cur_len -= strlen(temps);
1390 return max_len - cur_len;