PCem
view src/vid_svga.c @ 133:24b744b9a632
ViRGE S3D triangle rendering now uses worker thread.
Fixed clipping bug on ViRGE.
Fixed status window crash.
| author | TomW |
|---|---|
| date | Tue Jul 22 21:10:39 2014 +0100 |
| parents | 614f796ff7ed |
| children | d0d530adce12 |
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 svga_recalctimings(svga);
70 break;
71 case 0x3C4:
72 svga->seqaddr = val;
73 break;
74 case 0x3C5:
75 if (svga->seqaddr > 0xf) return;
76 o = svga->seqregs[svga->seqaddr & 0xf];
77 svga->seqregs[svga->seqaddr & 0xf] = val;
78 if (o != val && (svga->seqaddr & 0xf) == 1)
79 svga_recalctimings(svga);
80 switch (svga->seqaddr & 0xf)
81 {
82 case 1:
83 if (svga->scrblank && !(val & 0x20))
84 svga->fullchange = 3;
85 svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20);
86 svga_recalctimings(svga);
87 break;
88 case 2:
89 svga->writemask = val & 0xf;
90 break;
91 case 3:
92 svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2;
93 svga->charseta = ((val & 3) * 0x10000) + 2;
94 if (val & 0x10)
95 svga->charseta += 0x8000;
96 if (val & 0x20)
97 svga->charsetb += 0x8000;
98 break;
99 case 4:
100 svga->chain4 = val & 8;
101 svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
102 break;
103 }
104 break;
105 case 0x3c6:
106 svga->dac_mask = val;
107 break;
108 case 0x3C7:
109 svga->dac_read = val;
110 svga->dac_pos = 0;
111 break;
112 case 0x3C8:
113 svga->dac_write = val;
114 svga->dac_pos = 0;
115 break;
116 case 0x3C9:
117 svga->dac_status = 0;
118 svga->fullchange = changeframecount;
119 switch (svga->dac_pos)
120 {
121 case 0:
122 svga->vgapal[svga->dac_write].r = val & 63;
123 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);
124 svga->dac_pos++;
125 break;
126 case 1:
127 svga->vgapal[svga->dac_write].g = val & 63;
128 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);
129 svga->dac_pos++;
130 break;
131 case 2:
132 svga->vgapal[svga->dac_write].b = val & 63;
133 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);
134 svga->dac_pos = 0;
135 svga->dac_write = (svga->dac_write + 1) & 255;
136 break;
137 }
138 break;
139 case 0x3CE:
140 svga->gdcaddr = val;
141 break;
142 case 0x3CF:
143 o = svga->gdcreg[svga->gdcaddr & 15];
144 switch (svga->gdcaddr & 15)
145 {
146 case 2: svga->colourcompare=val; break;
147 case 4: svga->readplane=val&3; break;
148 case 5: svga->writemode=val&3; svga->readmode=val&8; break;
149 case 6:
150 // pclog("svga_out recalcmapping %p\n", svga);
151 if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
152 {
153 // pclog("Write mapping %02X\n", val);
154 switch (val&0xC)
155 {
156 case 0x0: /*128k at A0000*/
157 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
158 svga->banked_mask = 0xffff;
159 break;
160 case 0x4: /*64k at A0000*/
161 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
162 svga->banked_mask = 0xffff;
163 break;
164 case 0x8: /*32k at B0000*/
165 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
166 svga->banked_mask = 0x7fff;
167 break;
168 case 0xC: /*32k at B8000*/
169 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
170 svga->banked_mask = 0x7fff;
171 break;
172 }
173 }
174 break;
175 case 7: svga->colournocare=val; break;
176 }
177 svga->gdcreg[svga->gdcaddr & 15] = val;
178 svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
179 if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
180 svga_recalctimings(svga);
181 break;
182 }
183 }
185 uint8_t svga_in(uint16_t addr, void *p)
186 {
187 svga_t *svga = (svga_t *)p;
188 uint8_t temp;
189 // if (addr!=0x3da) pclog("Read port %04X\n",addr);
190 switch (addr)
191 {
192 case 0x3C0:
193 return svga->attraddr;
194 case 0x3C1:
195 return svga->attrregs[svga->attraddr];
196 case 0x3c2:
197 if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
198 temp = 0;
199 else
200 temp = 0x10;
201 return temp;
202 case 0x3C4:
203 return svga->seqaddr;
204 case 0x3C5:
205 return svga->seqregs[svga->seqaddr & 0xF];
206 case 0x3c6: return svga->dac_mask;
207 case 0x3c7: return svga->dac_status;
208 case 0x3c8: return svga->dac_write;
209 case 0x3c9:
210 svga->dac_status = 3;
211 switch (svga->dac_pos)
212 {
213 case 0:
214 svga->dac_pos++;
215 return svga->vgapal[svga->dac_read].r;
216 case 1:
217 svga->dac_pos++;
218 return svga->vgapal[svga->dac_read].g;
219 case 2:
220 svga->dac_pos=0;
221 svga->dac_read = (svga->dac_read + 1) & 255;
222 return svga->vgapal[(svga->dac_read - 1) & 255].b;
223 }
224 break;
225 case 0x3CC:
226 return svga->miscout;
227 case 0x3CE:
228 return svga->gdcaddr;
229 case 0x3CF:
230 return svga->gdcreg[svga->gdcaddr & 0xf];
231 case 0x3DA:
232 svga->attrff = 0;
233 if (svga->cgastat & 0x01)
234 svga->cgastat &= ~0x30;
235 else
236 svga->cgastat ^= 0x30;
237 return svga->cgastat;
238 }
239 // printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
240 return 0xFF;
241 }
243 void svga_recalctimings(svga_t *svga)
244 {
245 double crtcconst;
246 double _dispontime, _dispofftime, disptime;
247 int hdisp_old;
249 svga->vtotal = svga->crtc[6];
250 svga->dispend = svga->crtc[0x12];
251 svga->vsyncstart = svga->crtc[0x10];
252 svga->split = svga->crtc[0x18];
253 svga->vblankstart = svga->crtc[0x15];
255 if (svga->crtc[7] & 1) svga->vtotal |= 0x100;
256 if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
257 svga->vtotal += 2;
259 if (svga->crtc[7] & 2) svga->dispend |= 0x100;
260 if (svga->crtc[7] & 64) svga->dispend |= 0x200;
261 svga->dispend++;
263 if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100;
264 if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
265 svga->vsyncstart++;
267 if (svga->crtc[7] & 0x10) svga->split|=0x100;
268 if (svga->crtc[9] & 0x40) svga->split|=0x200;
269 svga->split++;
271 if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
272 if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
273 svga->vblankstart++;
275 svga->hdisp = svga->crtc[1];
276 svga->hdisp++;
278 svga->htotal = svga->crtc[0];
279 svga->htotal += 6; /*+6 is required for Tyrian*/
281 svga->rowoffset = svga->crtc[0x13];
283 svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
285 svga->lowres = svga->attrregs[0x10] & 0x40;
287 svga->interlace = 0;
289 svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd];
291 svga->hdisp_time = svga->hdisp;
292 svga->render = svga_render_blank;
293 if (!svga->scrblank)
294 {
295 if (!(svga->gdcreg[6] & 1)) /*Text mode*/
296 {
297 if (svga->seqregs[1] & 8) /*40 column*/
298 {
299 svga->render = svga_render_text_40;
300 svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
301 }
302 else
303 {
304 svga->render = svga_render_text_80;
305 svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
306 }
307 svga->hdisp_old = svga->hdisp;
308 }
309 else
310 {
311 svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
312 svga->hdisp_old = svga->hdisp;
314 switch (svga->gdcreg[5] & 0x60)
315 {
316 case 0x00: /*16 colours*/
317 if (svga->seqregs[1] & 8) /*Low res (320)*/
318 svga->render = svga_render_4bpp_lowres;
319 else
320 svga->render = svga_render_4bpp_highres;
321 break;
322 case 0x20: /*4 colours*/
323 if (svga->seqregs[1] & 8) /*Low res (320)*/
324 svga->render = svga_render_2bpp_lowres;
325 else
326 svga->render = svga_render_2bpp_highres;
327 break;
328 case 0x40: case 0x60: /*256+ colours*/
329 switch (svga->bpp)
330 {
331 case 8:
332 if (svga->lowres)
333 svga->render = svga_render_8bpp_lowres;
334 else
335 svga->render = svga_render_8bpp_highres;
336 break;
337 case 15:
338 if (svga->lowres)
339 svga->render = svga_render_15bpp_lowres;
340 else
341 svga->render = svga_render_15bpp_highres;
342 break;
343 case 16:
344 if (svga->lowres)
345 svga->render = svga_render_16bpp_lowres;
346 else
347 svga->render = svga_render_16bpp_highres;
348 break;
349 case 24:
350 if (svga->lowres)
351 svga->render = svga_render_24bpp_lowres;
352 else
353 svga->render = svga_render_24bpp_highres;
354 break;
355 case 32:
356 if (svga->lowres)
357 svga->render = svga_render_32bpp_lowres;
358 else
359 svga->render = svga_render_32bpp_highres;
360 break;
361 }
362 break;
363 }
364 }
365 }
367 // 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);
369 svga->linedbl = svga->crtc[9] & 0x80;
370 svga->rowcount = svga->crtc[9] & 31;
371 if (svga->recalctimings_ex)
372 svga->recalctimings_ex(svga);
374 if (svga->vblankstart < svga->dispend)
375 svga->dispend = svga->vblankstart;
377 crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0);
379 disptime = svga->htotal;
380 _dispontime = svga->hdisp_time;
382 // printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
383 if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; }
384 _dispofftime = disptime - _dispontime;
385 _dispontime *= crtcconst;
386 _dispofftime *= crtcconst;
388 svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
389 svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
390 /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
391 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);
392 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]);
394 pclog("svga->render %08X\n", svga->render);*/
395 }
397 extern int cyc_total;
398 void svga_poll(void *p)
399 {
400 svga_t *svga = (svga_t *)p;
401 int x;
403 if (!svga->linepos)
404 {
405 // if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
406 if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena)
407 {
408 svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
409 svga->hwcursor_oddeven = 0;
410 }
412 if (svga->displine == svga->hwcursor_latch.y+1 && svga->hwcursor_latch.ena && svga->interlace)
413 {
414 svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff;
415 svga->hwcursor_oddeven = 1;
416 }
418 if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena)
419 {
420 svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
421 svga->overlay_oddeven = 0;
422 }
423 if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace)
424 {
425 svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
426 svga->overlay_oddeven = 1;
427 }
429 svga->vidtime += svga->dispofftime;
430 // if (output) printf("Display off %f\n",vidtime);
431 svga->cgastat |= 1;
432 svga->linepos = 1;
434 if (svga->dispon)
435 {
436 svga->hdisp_on=1;
438 svga->ma &= svga->vrammask;
439 if (svga->firstline == 2000)
440 svga->firstline = svga->displine;
442 if (svga->hwcursor_on || svga->overlay_on)
443 svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = 2;
445 svga->render(svga);
447 if (svga->overlay_on)
448 {
449 svga->overlay_draw(svga, svga->displine);
450 svga->overlay_on--;
451 if (svga->overlay_on && svga->interlace)
452 svga->overlay_on--;
453 }
455 if (svga->hwcursor_on)
456 {
457 svga->hwcursor_draw(svga, svga->displine);
458 svga->hwcursor_on--;
459 if (svga->hwcursor_on && svga->interlace)
460 svga->hwcursor_on--;
461 }
463 if (svga->lastline < svga->displine)
464 svga->lastline = svga->displine;
465 }
467 // pclog("%03i %06X %06X\n",displine,ma,vrammask);
468 svga->displine++;
469 if (svga->interlace)
470 svga->displine++;
471 if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines)
472 {
473 // printf("Vsync off at line %i\n",displine);
474 svga->cgastat &= ~8;
475 }
476 svga->vslines++;
477 if (svga->displine > 1500)
478 svga->displine = 0;
479 // 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],
480 // displine, vc, ma);
481 }
482 else
483 {
484 // pclog("VC %i ma %05X\n", svga->vc, svga->ma);
485 svga->vidtime += svga->dispontime;
487 // if (output) printf("Display on %f\n",vidtime);
488 if (svga->dispon)
489 svga->cgastat &= ~1;
490 svga->hdisp_on = 0;
492 svga->linepos = 0;
493 if (svga->sc == (svga->crtc[11] & 31))
494 svga->con = 0;
495 if (svga->dispon)
496 {
497 if (svga->linedbl && !svga->linecountff)
498 {
499 svga->linecountff = 1;
500 svga->ma = svga->maback;
501 }
502 else if (svga->sc == svga->rowcount)
503 {
504 svga->linecountff = 0;
505 svga->sc = 0;
507 svga->maback += (svga->rowoffset << 3);
508 if (svga->interlace)
509 svga->maback += (svga->rowoffset << 3);
510 svga->maback &= svga->vrammask;
511 svga->ma = svga->maback;
512 }
513 else
514 {
515 svga->linecountff = 0;
516 svga->sc++;
517 svga->sc &= 31;
518 svga->ma = svga->maback;
519 }
520 }
521 svga->vc++;
522 svga->vc &= 2047;
524 if (svga->vc == svga->split)
525 {
526 // pclog("VC split\n");
527 svga->ma = svga->maback = 0;
528 if (svga->attrregs[0x10] & 0x20)
529 svga->scrollcache = 0;
530 }
531 if (svga->vc == svga->dispend)
532 {
533 // pclog("VC dispend\n");
534 svga->dispon=0;
535 if (svga->crtc[10] & 0x20) svga->cursoron = 0;
536 else svga->cursoron = svga->blink & 16;
537 if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15))
538 svga->fullchange = 2;
539 svga->blink++;
541 for (x = 0; x < (svga->vram_limit >> 12); x++)
542 {
543 if (svga->changedvram[x])
544 svga->changedvram[x]--;
545 }
546 // memset(changedvram,0,2048);
547 if (svga->fullchange)
548 svga->fullchange--;
549 }
550 if (svga->vc == svga->vsyncstart)
551 {
552 int wx, wy;
553 // pclog("VC vsync %i %i\n", svga->firstline_draw, svga->lastline_draw);
554 svga->dispon=0;
555 svga->cgastat |= 8;
556 x = svga->hdisp;
558 if (svga->interlace && !svga->oddeven) svga->lastline++;
559 if (svga->interlace && svga->oddeven) svga->firstline--;
561 wx = x;
562 wy = svga->lastline - svga->firstline;
564 svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
566 readflash = 0;
568 svga->firstline = 2000;
569 svga->lastline = 0;
571 svga->firstline_draw = 2000;
572 svga->lastline_draw = 0;
574 svga->oddeven ^= 1;
576 changeframecount = svga->interlace ? 3 : 2;
577 svga->vslines = 0;
579 if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
580 else svga->ma = svga->maback = svga->ma_latch;
581 svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf];
583 svga->ma <<= 2;
584 svga->maback <<= 2;
585 svga->ca <<= 2;
587 svga->video_res_x = wx;
588 svga->video_res_y = wy + 1;
589 // pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
590 if (!(svga->gdcreg[6] & 1)) /*Text mode*/
591 {
592 svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9;
593 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
594 svga->video_bpp = 0;
595 }
596 else
597 {
598 if (svga->crtc[9] & 0x80)
599 svga->video_res_y /= 2;
600 if (!(svga->crtc[0x17] & 1))
601 svga->video_res_y *= 2;
602 svga->video_res_y /= (svga->crtc[9] & 31) + 1;
603 if (svga->lowres)
604 svga->video_res_x /= 2;
606 switch (svga->gdcreg[5] & 0x60)
607 {
608 case 0x00: svga->video_bpp = 4; break;
609 case 0x20: svga->video_bpp = 2; break;
610 case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
611 }
612 }
613 // if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
615 // 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);
616 }
617 if (svga->vc == svga->vtotal)
618 {
619 // pclog("VC vtotal\n");
622 // printf("Frame over at line %i %i %i %i\n",displine,vc,svga_vsyncstart,svga_dispend);
623 svga->vc = 0;
624 svga->sc = 0;
625 svga->dispon = 1;
626 svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
627 svga->scrollcache = svga->attrregs[0x13] & 7;
628 svga->linecountff = 0;
630 svga->hwcursor_on = 0;
631 svga->hwcursor_latch = svga->hwcursor;
633 svga->overlay_on = 0;
634 svga->overlay_latch = svga->overlay;
635 // pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
637 // pclog("ADDR %08X\n",hwcursor_addr);
638 }
639 if (svga->sc == (svga->crtc[10] & 31))
640 svga->con = 1;
641 }
642 // printf("2 %i\n",svga_vsyncstart);
643 //pclog("svga_poll %i %i %i %i %i %i %i\n", ins, svga->dispofftime, svga->dispontime, svga->vidtime, cyc_total, svga->linepos, svga->vc);
644 }
646 int svga_init(svga_t *svga, void *p, int memsize,
647 void (*recalctimings_ex)(struct svga_t *svga),
648 uint8_t (*video_in) (uint16_t addr, void *p),
649 void (*video_out)(uint16_t addr, uint8_t val, void *p),
650 void (*hwcursor_draw)(struct svga_t *svga, int displine),
651 void (*overlay_draw)(struct svga_t *svga, int displine))
652 {
653 int c, d, e;
655 svga->p = p;
657 for (c = 0; c < 256; c++)
658 {
659 e = c;
660 for (d = 0; d < 8; d++)
661 {
662 svga_rotate[d][c] = e;
663 e = (e >> 1) | ((e & 1) ? 0x80 : 0);
664 }
665 }
666 svga->readmode = 0;
668 svga->crtc[0] = 63;
669 svga->crtc[6] = 255;
670 svga->dispontime = 1000 * (1 << TIMER_SHIFT);
671 svga->dispofftime = 1000 * (1 << TIMER_SHIFT);
672 svga->bpp = 8;
673 svga->vram = malloc(memsize);
674 svga->vram_limit = memsize;
675 svga->vrammask = memsize - 1;
676 svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
677 svga->recalctimings_ex = recalctimings_ex;
678 svga->video_in = video_in;
679 svga->video_out = video_out;
680 svga->hwcursor_draw = hwcursor_draw;
681 svga->overlay_draw = overlay_draw;
682 // _svga_recalctimings(svga);
684 mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga);
686 timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga);
687 vramp = svga->vram;
688 return 0;
689 }
691 void svga_close(svga_t *svga)
692 {
693 free(svga->changedvram);
694 free(svga->vram);
695 }
697 #define egacycles 1
698 #define egacycles2 1
699 void svga_write(uint32_t addr, uint8_t val, void *p)
700 {
701 svga_t *svga = (svga_t *)p;
702 uint8_t vala, valb, valc, vald, wm = svga->writemask;
703 int writemask2 = svga->writemask;
705 egawrites++;
707 cycles -= video_timing_b;
708 cycles_lost += video_timing_b;
710 if (svga_output) pclog("Writeega %06X ",addr);
711 addr &= svga->banked_mask;
712 addr += svga->write_bank;
714 if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
715 if (svga->chain4 || svga->fb_only)
716 {
717 writemask2=1<<(addr&3);
718 addr&=~3;
719 }
720 else
721 {
722 addr<<=2;
723 }
724 addr &= 0x7fffff;
726 if (addr >= svga->vram_limit)
727 return;
729 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]);
730 svga->changedvram[addr >> 12] = changeframecount;
732 switch (svga->writemode)
733 {
734 case 1:
735 if (writemask2 & 1) svga->vram[addr] = svga->la;
736 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
737 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
738 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
739 break;
740 case 0:
741 if (svga->gdcreg[3] & 7)
742 val = svga_rotate[svga->gdcreg[3] & 7][val];
743 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
744 {
745 if (writemask2 & 1) svga->vram[addr] = val;
746 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
747 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
748 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
749 }
750 else
751 {
752 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
753 else vala = val;
754 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
755 else valb = val;
756 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
757 else valc = val;
758 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
759 else vald = val;
761 switch (svga->gdcreg[3] & 0x18)
762 {
763 case 0: /*Set*/
764 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
765 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
766 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
767 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
768 break;
769 case 8: /*AND*/
770 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
771 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
772 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
773 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
774 break;
775 case 0x10: /*OR*/
776 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
777 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
778 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
779 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
780 break;
781 case 0x18: /*XOR*/
782 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
783 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
784 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
785 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
786 break;
787 }
788 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
789 }
790 break;
791 case 2:
792 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
793 {
794 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
795 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
796 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
797 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
798 }
799 else
800 {
801 vala = ((val & 1) ? 0xff : 0);
802 valb = ((val & 2) ? 0xff : 0);
803 valc = ((val & 4) ? 0xff : 0);
804 vald = ((val & 8) ? 0xff : 0);
805 switch (svga->gdcreg[3] & 0x18)
806 {
807 case 0: /*Set*/
808 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
809 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
810 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
811 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
812 break;
813 case 8: /*AND*/
814 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
815 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
816 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
817 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
818 break;
819 case 0x10: /*OR*/
820 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
821 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
822 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
823 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
824 break;
825 case 0x18: /*XOR*/
826 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
827 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
828 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
829 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
830 break;
831 }
832 }
833 break;
834 case 3:
835 if (svga->gdcreg[3] & 7)
836 val = svga_rotate[svga->gdcreg[3] & 7][val];
837 wm = svga->gdcreg[8];
838 svga->gdcreg[8] &= val;
840 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
841 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
842 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
843 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
844 switch (svga->gdcreg[3] & 0x18)
845 {
846 case 0: /*Set*/
847 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
848 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
849 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
850 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
851 break;
852 case 8: /*AND*/
853 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
854 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
855 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
856 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
857 break;
858 case 0x10: /*OR*/
859 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
860 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
861 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
862 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
863 break;
864 case 0x18: /*XOR*/
865 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
866 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
867 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
868 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
869 break;
870 }
871 svga->gdcreg[8] = wm;
872 break;
873 }
874 }
876 uint8_t svga_read(uint32_t addr, void *p)
877 {
878 svga_t *svga = (svga_t *)p;
879 uint8_t temp, temp2, temp3, temp4;
881 cycles -= video_timing_b;
882 cycles_lost += video_timing_b;
884 egareads++;
885 // pclog("Readega %06X ",addr);
886 addr &= svga->banked_mask;
887 addr += svga->read_bank;
889 // pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
890 // pclog("%i\n", svga->readmode);
891 if (svga->chain4 || svga->fb_only)
892 {
893 addr &= 0x7fffff;
894 if (addr >= svga->vram_limit)
895 return 0xff;
896 return svga->vram[addr];
897 }
898 else addr<<=2;
900 addr &= 0x7fffff;
902 if (addr >= svga->vram_limit)
903 return 0xff;
905 svga->la = svga->vram[addr];
906 svga->lb = svga->vram[addr | 0x1];
907 svga->lc = svga->vram[addr | 0x2];
908 svga->ld = svga->vram[addr | 0x3];
909 if (svga->readmode)
910 {
911 temp = (svga->colournocare & 1) ? 0xff : 0;
912 temp &= svga->la;
913 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
914 temp2 = (svga->colournocare & 2) ? 0xff : 0;
915 temp2 &= svga->lb;
916 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
917 temp3 = (svga->colournocare & 4) ? 0xff : 0;
918 temp3 &= svga->lc;
919 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
920 temp4 = (svga->colournocare & 8) ? 0xff : 0;
921 temp4 &= svga->ld;
922 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
923 return ~(temp | temp2 | temp3 | temp4);
924 }
925 //pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
926 return svga->vram[addr | svga->readplane];
927 }
929 void svga_write_linear(uint32_t addr, uint8_t val, void *p)
930 {
931 svga_t *svga = (svga_t *)p;
932 uint8_t vala, valb, valc, vald, wm = svga->writemask;
933 int writemask2 = svga->writemask;
935 cycles -= video_timing_b;
936 cycles_lost += video_timing_b;
938 egawrites++;
940 if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
941 if (!(svga->gdcreg[6] & 1))
942 svga->fullchange = 2;
943 if (svga->chain4 || svga->fb_only)
944 {
945 writemask2=1<<(addr&3);
946 addr&=~3;
947 }
948 else
949 {
950 addr<<=2;
951 }
952 addr &= 0x7fffff;
953 if (addr >= svga->vram_limit)
954 return;
955 if (svga_output) pclog("%08X\n", addr);
956 svga->changedvram[addr >> 12]=changeframecount;
958 switch (svga->writemode)
959 {
960 case 1:
961 if (writemask2 & 1) svga->vram[addr] = svga->la;
962 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
963 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
964 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
965 break;
966 case 0:
967 if (svga->gdcreg[3] & 7)
968 val = svga_rotate[svga->gdcreg[3] & 7][val];
969 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
970 {
971 if (writemask2 & 1) svga->vram[addr] = val;
972 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
973 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
974 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
975 }
976 else
977 {
978 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
979 else vala = val;
980 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
981 else valb = val;
982 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
983 else valc = val;
984 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
985 else vald = val;
987 switch (svga->gdcreg[3] & 0x18)
988 {
989 case 0: /*Set*/
990 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
991 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
992 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
993 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
994 break;
995 case 8: /*AND*/
996 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
997 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
998 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
999 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1000 break;
1001 case 0x10: /*OR*/
1002 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1003 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1004 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1005 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1006 break;
1007 case 0x18: /*XOR*/
1008 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1009 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1010 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1011 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1012 break;
1013 }
1014 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
1015 }
1016 break;
1017 case 2:
1018 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
1019 {
1020 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1021 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1022 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1023 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1024 }
1025 else
1026 {
1027 vala = ((val & 1) ? 0xff : 0);
1028 valb = ((val & 2) ? 0xff : 0);
1029 valc = ((val & 4) ? 0xff : 0);
1030 vald = ((val & 8) ? 0xff : 0);
1031 switch (svga->gdcreg[3] & 0x18)
1032 {
1033 case 0: /*Set*/
1034 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1035 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1036 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1037 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1038 break;
1039 case 8: /*AND*/
1040 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1041 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1042 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1043 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1044 break;
1045 case 0x10: /*OR*/
1046 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1047 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1048 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1049 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1050 break;
1051 case 0x18: /*XOR*/
1052 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1053 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1054 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1055 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1056 break;
1057 }
1058 }
1059 break;
1060 case 3:
1061 if (svga->gdcreg[3] & 7)
1062 val = svga_rotate[svga->gdcreg[3] & 7][val];
1063 wm = svga->gdcreg[8];
1064 svga->gdcreg[8] &= val;
1066 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
1067 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
1068 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
1069 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
1070 switch (svga->gdcreg[3] & 0x18)
1071 {
1072 case 0: /*Set*/
1073 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
1074 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
1075 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
1076 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
1077 break;
1078 case 8: /*AND*/
1079 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
1080 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
1081 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
1082 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
1083 break;
1084 case 0x10: /*OR*/
1085 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
1086 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
1087 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
1088 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
1089 break;
1090 case 0x18: /*XOR*/
1091 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
1092 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
1093 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
1094 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
1095 break;
1096 }
1097 svga->gdcreg[8] = wm;
1098 break;
1099 }
1100 }
1102 uint8_t svga_read_linear(uint32_t addr, void *p)
1103 {
1104 svga_t *svga = (svga_t *)p;
1105 uint8_t temp, temp2, temp3, temp4;
1107 cycles -= video_timing_b;
1108 cycles_lost += video_timing_b;
1110 egareads++;
1112 if (svga->chain4 || svga->fb_only)
1113 {
1114 addr &= 0x7fffff;
1115 if (addr >= svga->vram_limit)
1116 return 0xff;
1117 return svga->vram[addr & 0x7fffff];
1118 }
1119 else addr<<=2;
1121 addr &= 0x7fffff;
1123 if (addr >= svga->vram_limit)
1124 return 0xff;
1126 svga->la = svga->vram[addr];
1127 svga->lb = svga->vram[addr | 0x1];
1128 svga->lc = svga->vram[addr | 0x2];
1129 svga->ld = svga->vram[addr | 0x3];
1130 if (svga->readmode)
1131 {
1132 temp = (svga->colournocare & 1) ? 0xff : 0;
1133 temp &= svga->la;
1134 temp ^= (svga->colourcompare & 1) ? 0xff : 0;
1135 temp2 = (svga->colournocare & 2) ? 0xff : 0;
1136 temp2 &= svga->lb;
1137 temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
1138 temp3 = (svga->colournocare & 4) ? 0xff : 0;
1139 temp3 &= svga->lc;
1140 temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
1141 temp4 = (svga->colournocare & 8) ? 0xff : 0;
1142 temp4 &= svga->ld;
1143 temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
1144 return ~(temp | temp2 | temp3 | temp4);
1145 }
1146 //printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
1147 return svga->vram[addr | svga->readplane];
1148 }
1150 void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
1151 {
1152 // pclog("svga_doblit start\n");
1153 svga->frames++;
1154 // pclog("doblit %i %i\n", y1, y2);
1155 // pclog("svga_doblit %i %i\n", wx, svga->hdisp);
1156 if (y1 > y2)
1157 {
1158 video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize);
1159 return;
1160 }
1162 if ((wx!=xsize || wy!=ysize) && !vid_resize)
1163 {
1164 xsize=wx;
1165 ysize=wy+1;
1166 if (xsize<64) xsize=656;
1167 if (ysize<32) ysize=200;
1169 updatewindowsize(xsize,ysize);
1170 }
1171 if (vid_resize)
1172 {
1173 xsize = wx;
1174 ysize = wy + 1;
1175 }
1176 video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
1177 if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
1178 // pclog("svga_doblit end\n");
1179 }
1181 void svga_writew(uint32_t addr, uint16_t val, void *p)
1182 {
1183 svga_t *svga = (svga_t *)p;
1184 if (!svga->fast)
1185 {
1186 svga_write(addr, val, p);
1187 svga_write(addr + 1, val >> 8, p);
1188 return;
1189 }
1191 egawrites += 2;
1193 cycles -= video_timing_w;
1194 cycles_lost += video_timing_w;
1196 if (svga_output) pclog("svga_writew: %05X ", addr);
1197 addr = (addr & svga->banked_mask) + svga->write_bank;
1198 addr &= 0x7FFFFF;
1199 if (addr >= svga->vram_limit)
1200 return;
1201 if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val);
1202 svga->changedvram[addr >> 12] = changeframecount;
1203 *(uint16_t *)&svga->vram[addr] = val;
1204 }
1206 void svga_writel(uint32_t addr, uint32_t val, void *p)
1207 {
1208 svga_t *svga = (svga_t *)p;
1210 if (!svga->fast)
1211 {
1212 svga_write(addr, val, p);
1213 svga_write(addr + 1, val >> 8, p);
1214 svga_write(addr + 2, val >> 16, p);
1215 svga_write(addr + 3, val >> 24, p);
1216 return;
1217 }
1219 egawrites += 4;
1221 cycles -= video_timing_l;
1222 cycles_lost += video_timing_l;
1224 if (svga_output) pclog("svga_writel: %05X ", addr);
1225 addr = (addr & svga->banked_mask) + svga->write_bank;
1226 addr &= 0x7FFFFF;
1227 if (addr >= svga->vram_limit)
1228 return;
1229 if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val);
1231 svga->changedvram[addr >> 12] = changeframecount;
1232 *(uint32_t *)&svga->vram[addr] = val;
1233 }
1235 uint16_t svga_readw(uint32_t addr, void *p)
1236 {
1237 svga_t *svga = (svga_t *)p;
1239 if (!svga->fast)
1240 return svga_read(addr, p) | (svga_read(addr + 1, p) << 8);
1242 egareads += 2;
1244 cycles -= video_timing_w;
1245 cycles_lost += video_timing_w;
1247 // pclog("Readw %05X ", addr);
1248 addr = (addr & svga->banked_mask) + svga->read_bank;
1249 addr &= 0x7FFFFF;
1250 // pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]);
1251 if (addr >= svga->vram_limit) return 0xffff;
1253 return *(uint16_t *)&svga->vram[addr];
1254 }
1256 uint32_t svga_readl(uint32_t addr, void *p)
1257 {
1258 svga_t *svga = (svga_t *)p;
1260 if (!svga->fast)
1261 return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24);
1263 egareads += 4;
1265 cycles -= video_timing_l;
1266 cycles_lost += video_timing_l;
1268 // pclog("Readl %05X ", addr);
1269 addr = (addr & svga->banked_mask) + svga->read_bank;
1270 addr &= 0x7FFFFF;
1271 // pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]);
1272 if (addr >= svga->vram_limit) return 0xffffffff;
1274 return *(uint32_t *)&svga->vram[addr];
1275 }
1277 void svga_writew_linear(uint32_t addr, uint16_t val, void *p)
1278 {
1279 svga_t *svga = (svga_t *)p;
1281 if (!svga->fast)
1282 {
1283 svga_write_linear(addr, val, p);
1284 svga_write_linear(addr + 1, val >> 8, p);
1285 return;
1286 }
1288 egawrites += 2;
1290 cycles -= video_timing_w;
1291 cycles_lost += video_timing_w;
1293 if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val);
1294 addr &= 0x7FFFFF;
1295 if (addr >= svga->vram_limit)
1296 return;
1297 svga->changedvram[addr >> 12] = changeframecount;
1298 *(uint16_t *)&svga->vram[addr] = val;
1299 }
1301 void svga_writel_linear(uint32_t addr, uint32_t val, void *p)
1302 {
1303 svga_t *svga = (svga_t *)p;
1305 if (!svga->fast)
1306 {
1307 svga_write_linear(addr, val, p);
1308 svga_write_linear(addr + 1, val >> 8, p);
1309 svga_write_linear(addr + 2, val >> 16, p);
1310 svga_write_linear(addr + 3, val >> 24, p);
1311 return;
1312 }
1314 egawrites += 4;
1316 cycles -= video_timing_l;
1317 cycles_lost += video_timing_l;
1319 if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val);
1320 addr &= 0x7fffff;
1321 if (addr >= svga->vram_limit)
1322 return;
1323 svga->changedvram[addr >> 12] = changeframecount;
1324 *(uint32_t *)&svga->vram[addr] = val;
1325 }
1327 uint16_t svga_readw_linear(uint32_t addr, void *p)
1328 {
1329 svga_t *svga = (svga_t *)p;
1331 if (!svga->fast)
1332 return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8);
1334 egareads += 2;
1336 cycles -= video_timing_w;
1337 cycles_lost += video_timing_w;
1339 addr &= 0x7FFFFF;
1340 if (addr >= svga->vram_limit) return 0xffff;
1342 return *(uint16_t *)&svga->vram[addr];
1343 }
1345 uint32_t svga_readl_linear(uint32_t addr, void *p)
1346 {
1347 svga_t *svga = (svga_t *)p;
1349 if (!svga->fast)
1350 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);
1352 egareads += 4;
1354 cycles -= video_timing_l;
1355 cycles_lost += video_timing_l;
1357 addr &= 0x7FFFFF;
1358 if (addr >= svga->vram_limit) return 0xffffffff;
1360 return *(uint32_t *)&svga->vram[addr];
1361 }
1364 void svga_add_status_info(char *s, int max_len, void *p)
1365 {
1366 svga_t *svga = (svga_t *)p;
1367 char temps[128];
1369 if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
1370 else strcpy(temps, "SVGA unchained (possibly mode-X)\n");
1371 strncat(s, temps, max_len);
1373 if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
1374 else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
1375 strncat(s, temps, max_len);
1377 sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
1378 strncat(s, temps, max_len);
1380 sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
1381 svga->frames = 0;
1382 strncat(s, temps, max_len);
1383 }
