PCem
view src/vid_cl5429.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 | f22b6152c221 |
| children |
line source
1 /*Cirrus Logic CL-GD5429 emulation*/
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5 #include "io.h"
6 #include "mem.h"
7 #include "rom.h"
8 #include "video.h"
9 #include "vid_cl5429.h"
10 #include "vid_svga.h"
11 #include "vid_svga_render.h"
12 #include "vid_unk_ramdac.h"
14 typedef struct gd5429_t
15 {
16 mem_mapping_t mmio_mapping;
18 svga_t svga;
20 rom_t bios_rom;
22 uint32_t bank[2];
23 uint32_t mask;
25 struct
26 {
27 uint16_t bg_col, fg_col;
28 uint16_t width, height;
29 uint16_t dst_pitch, src_pitch;
30 uint32_t dst_addr, src_addr;
31 uint8_t mask, mode, rop;
33 uint32_t dst_addr_backup, src_addr_backup;
34 uint16_t width_backup, height_internal;
35 int x_count;
36 } blt;
38 } gd5429_t;
40 void gd5429_write(uint32_t addr, uint8_t val, void *p);
41 uint8_t gd5429_read(uint32_t addr, void *p);
43 void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p);
44 uint8_t gd5429_mmio_read(uint32_t addr, void *p);
46 void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p);
47 void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p);
49 void gd5429_recalc_banking(gd5429_t *gd5429);
50 void gd5429_recalc_mapping(gd5429_t *gd5429);
52 void gd5429_out(uint16_t addr, uint8_t val, void *p)
53 {
54 gd5429_t *gd5429 = (gd5429_t *)p;
55 svga_t *svga = &gd5429->svga;
56 uint8_t old;
58 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
59 addr ^= 0x60;
61 // pclog("gd5429 out %04X %02X\n", addr, val);
63 switch (addr)
64 {
65 case 0x3c4:
66 svga->seqaddr = val;
67 break;
68 case 0x3c5:
69 if (svga->seqaddr > 5)
70 {
71 svga->seqregs[svga->seqaddr & 0x1f] = val;
72 switch (svga->seqaddr & 0x1f)
73 {
74 case 0x10: case 0x30: case 0x50: case 0x70:
75 case 0x90: case 0xb0: case 0xd0: case 0xf0:
76 svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7);
77 pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x);
78 break;
79 case 0x11: case 0x31: case 0x51: case 0x71:
80 case 0x91: case 0xb1: case 0xd1: case 0xf1:
81 svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7);
82 pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y);
83 break;
84 case 0x12:
85 svga->hwcursor.ena = val & 1;
86 pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena);
87 break;
88 case 0x13:
89 svga->hwcursor.addr = 0x1fc000 + ((val & 0x3f) * 256);
90 pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr);
91 break;
93 case 0x17:
94 gd5429_recalc_mapping(gd5429);
95 break;
96 }
97 return;
98 }
99 break;
101 case 0x3cf:
102 if (svga->gdcaddr == 5)
103 {
104 svga->gdcreg[5] = val;
105 if (svga->gdcreg[0xb] & 0x04)
106 svga->writemode = svga->gdcreg[5] & 7;
107 else
108 svga->writemode = svga->gdcreg[5] & 3;
109 svga->readmode = val & 8;
110 // pclog("writemode = %i\n", svga->writemode);
111 return;
112 }
113 if (svga->gdcaddr == 6)
114 {
115 if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
116 {
117 svga->gdcreg[6] = val;
118 gd5429_recalc_mapping(gd5429);
119 }
120 svga->gdcreg[6] = val;
121 return;
122 }
123 if (svga->gdcaddr > 8)
124 {
125 svga->gdcreg[svga->gdcaddr & 0x3f] = val;
126 switch (svga->gdcaddr)
127 {
128 case 0x09: case 0x0a: case 0x0b:
129 gd5429_recalc_banking(gd5429);
130 if (svga->gdcreg[0xb] & 0x04)
131 svga->writemode = svga->gdcreg[5] & 7;
132 else
133 svga->writemode = svga->gdcreg[5] & 3;
134 break;
135 }
136 return;
137 }
138 break;
140 case 0x3D4:
141 svga->crtcreg = val & 0x3f;
142 return;
143 case 0x3D5:
144 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
145 old = svga->crtc[svga->crtcreg];
146 svga->crtc[svga->crtcreg] = val;
148 if (old != val)
149 {
150 if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
151 {
152 svga->fullchange = changeframecount;
153 svga_recalctimings(svga);
154 }
155 }
156 break;
157 }
158 svga_out(addr, val, svga);
159 }
161 uint8_t gd5429_in(uint16_t addr, void *p)
162 {
163 gd5429_t *gd5429 = (gd5429_t *)p;
164 svga_t *svga = &gd5429->svga;
166 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1))
167 addr ^= 0x60;
169 // if (addr != 0x3da) pclog("IN gd5429 %04X\n", addr);
171 switch (addr)
172 {
173 case 0x3c5:
174 if (svga->seqaddr > 5)
175 {
176 switch (svga->seqaddr)
177 {
178 case 6:
179 return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
180 }
181 return svga->seqregs[svga->seqaddr & 0x3f];
182 }
183 break;
185 case 0x3cf:
186 if (svga->gdcaddr > 8)
187 {
188 return svga->gdcreg[svga->gdcaddr & 0x3f];
189 }
190 break;
192 case 0x3D4:
193 return svga->crtcreg;
194 case 0x3D5:
195 switch (svga->crtcreg)
196 {
197 case 0x27: /*ID*/
198 return 0x9c; /*GD5429*/
199 }
200 return svga->crtc[svga->crtcreg];
201 }
202 return svga_in(addr, svga);
203 }
205 void gd5429_recalc_banking(gd5429_t *gd5429)
206 {
207 svga_t *svga = &gd5429->svga;
209 if (svga->gdcreg[0xb] & 0x20)
210 gd5429->bank[0] = (svga->gdcreg[0x09] & 0x7f) << 14;
211 else
212 gd5429->bank[0] = svga->gdcreg[0x09] << 12;
214 if (svga->gdcreg[0xb] & 0x01)
215 {
216 if (svga->gdcreg[0xb] & 0x20)
217 gd5429->bank[1] = (svga->gdcreg[0x0a] & 0x7f) << 14;
218 else
219 gd5429->bank[1] = svga->gdcreg[0x0a] << 12;
220 }
221 else
222 gd5429->bank[1] = gd5429->bank[0] + 0x8000;
223 }
225 void gd5429_recalc_mapping(gd5429_t *gd5429)
226 {
227 svga_t *svga = &gd5429->svga;
229 pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04);
230 switch (svga->gdcreg[6] & 0x0C)
231 {
232 case 0x0: /*128k at A0000*/
233 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
234 mem_mapping_disable(&gd5429->mmio_mapping);
235 svga->banked_mask = 0xffff;
236 break;
237 case 0x4: /*64k at A0000*/
238 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
239 if (svga->seqregs[0x17] & 0x04)
240 mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100);
241 svga->banked_mask = 0xffff;
242 break;
243 case 0x8: /*32k at B0000*/
244 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
245 mem_mapping_disable(&gd5429->mmio_mapping);
246 svga->banked_mask = 0x7fff;
247 break;
248 case 0xC: /*32k at B8000*/
249 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
250 mem_mapping_disable(&gd5429->mmio_mapping);
251 svga->banked_mask = 0x7fff;
252 break;
253 }
254 }
256 void gd5429_recalctimings(svga_t *svga)
257 {
258 gd5429_t *gd5429 = (gd5429_t *)svga->p;
260 if (svga->seqregs[7] & 0x01)
261 {
262 svga->render = svga_render_8bpp_highres;
263 }
265 svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
266 pclog("MA now %05X %02X\n", svga->ma_latch, svga->crtc[0x1b]);
267 }
269 void gd5429_hwcursor_draw(svga_t *svga, int displine)
270 {
271 int x;
272 uint8_t dat[2];
273 int xx;
274 int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
276 pclog("HWcursor %i %i %i %i %x %02X %02X\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, offset, displine, svga->hwcursor_latch.addr, vram[svga->hwcursor_latch.addr], vram[svga->hwcursor_latch.addr + 0x80]);
277 for (x = 0; x < 32; x += 8)
278 {
279 dat[0] = svga->vram[svga->hwcursor_latch.addr];
280 dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
281 for (xx = 0; xx < 8; xx++)
282 {
283 if (offset >= svga->hwcursor_latch.x)
284 {
285 if (dat[1] & 0x80)
286 ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
287 if (dat[0] & 0x80)
288 ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
289 }
291 offset++;
292 dat[0] <<= 1;
293 dat[1] <<= 1;
294 }
295 svga->hwcursor_latch.addr++;
296 }
297 }
300 void gd5429_write_linear(uint32_t addr, uint8_t val, void *p);
302 void gd5429_write(uint32_t addr, uint8_t val, void *p)
303 {
304 gd5429_t *gd5429 = (gd5429_t *)p;
305 svga_t *svga = &gd5429->svga;
306 // pclog("gd5429_write : %05X %02X ", addr, val);
307 addr &= svga->banked_mask;
308 addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
309 // pclog("%08X\n", addr);
310 gd5429_write_linear(addr, val, p);
311 }
313 uint8_t gd5429_read(uint32_t addr, void *p)
314 {
315 gd5429_t *gd5429 = (gd5429_t *)p;
316 svga_t *svga = &gd5429->svga;
317 uint8_t ret;
318 // pclog("gd5429_read : %05X ", addr);
319 addr &= svga->banked_mask;
320 addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
321 ret = svga_read_linear(addr, &gd5429->svga);
322 // pclog("%08X %02X\n", addr, ret);
323 return ret;
324 }
326 void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
327 {
328 gd5429_t *gd5429 = (gd5429_t *)p;
329 svga_t *svga = &gd5429->svga;
330 uint8_t vala, valb, valc, vald, wm = svga->writemask;
331 int writemask2 = svga->writemask;
333 cycles -= video_timing_b;
334 cycles_lost += video_timing_b;
336 egawrites++;
338 // if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
339 if (!(svga->gdcreg[6] & 1))
340 svga->fullchange = 2;
341 if (svga->chain4 && (svga->writemode < 4))
342 {
343 writemask2 = 1 << (addr & 3);
344 addr &= ~3;
345 }
346 else
347 {
348 addr <<= 2;
349 }
350 addr &= 0x7fffff;
351 if (addr >= svga->vram_limit)
352 return;
353 // if (svga_output) pclog("%08X\n", addr);
354 svga->changedvram[addr >> 12] = changeframecount;
356 switch (svga->writemode)
357 {
358 case 4:
359 pclog("Writemode 4 : %X ", addr);
360 addr <<= 1;
361 svga->changedvram[addr >> 12] = changeframecount;
362 pclog("%X %X\n", addr, val);
363 if (val & 0x80)
364 svga->vram[addr + 0] = svga->gdcreg[1];
365 if (val & 0x40)
366 svga->vram[addr + 1] = svga->gdcreg[1];
367 if (val & 0x20)
368 svga->vram[addr + 2] = svga->gdcreg[1];
369 if (val & 0x10)
370 svga->vram[addr + 3] = svga->gdcreg[1];
371 if (val & 0x08)
372 svga->vram[addr + 4] = svga->gdcreg[1];
373 if (val & 0x04)
374 svga->vram[addr + 5] = svga->gdcreg[1];
375 if (val & 0x02)
376 svga->vram[addr + 6] = svga->gdcreg[1];
377 if (val & 0x01)
378 svga->vram[addr + 7] = svga->gdcreg[1];
379 break;
381 case 5:
382 pclog("Writemode 5 : %X ", addr);
383 addr <<= 1;
384 svga->changedvram[addr >> 12] = changeframecount;
385 pclog("%X %X\n", addr, val);
386 svga->vram[addr + 0] = (val & 0x80) ? svga->gdcreg[1] : svga->gdcreg[0];
387 svga->vram[addr + 1] = (val & 0x40) ? svga->gdcreg[1] : svga->gdcreg[0];
388 svga->vram[addr + 2] = (val & 0x20) ? svga->gdcreg[1] : svga->gdcreg[0];
389 svga->vram[addr + 3] = (val & 0x10) ? svga->gdcreg[1] : svga->gdcreg[0];
390 svga->vram[addr + 4] = (val & 0x08) ? svga->gdcreg[1] : svga->gdcreg[0];
391 svga->vram[addr + 5] = (val & 0x04) ? svga->gdcreg[1] : svga->gdcreg[0];
392 svga->vram[addr + 6] = (val & 0x02) ? svga->gdcreg[1] : svga->gdcreg[0];
393 svga->vram[addr + 7] = (val & 0x01) ? svga->gdcreg[1] : svga->gdcreg[0];
394 break;
396 case 1:
397 if (writemask2 & 1) svga->vram[addr] = svga->la;
398 if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
399 if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
400 if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
401 break;
402 case 0:
403 if (svga->gdcreg[3] & 7)
404 val = svga_rotate[svga->gdcreg[3] & 7][val];
405 if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
406 {
407 if (writemask2 & 1) svga->vram[addr] = val;
408 if (writemask2 & 2) svga->vram[addr | 0x1] = val;
409 if (writemask2 & 4) svga->vram[addr | 0x2] = val;
410 if (writemask2 & 8) svga->vram[addr | 0x3] = val;
411 }
412 else
413 {
414 if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
415 else vala = val;
416 if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
417 else valb = val;
418 if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
419 else valc = val;
420 if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
421 else vald = val;
423 switch (svga->gdcreg[3] & 0x18)
424 {
425 case 0: /*Set*/
426 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
427 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
428 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
429 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
430 break;
431 case 8: /*AND*/
432 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
433 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
434 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
435 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
436 break;
437 case 0x10: /*OR*/
438 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
439 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
440 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
441 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
442 break;
443 case 0x18: /*XOR*/
444 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
445 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
446 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
447 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
448 break;
449 }
450 // pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
451 }
452 break;
453 case 2:
454 if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
455 {
456 if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
457 if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
458 if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
459 if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
460 }
461 else
462 {
463 vala = ((val & 1) ? 0xff : 0);
464 valb = ((val & 2) ? 0xff : 0);
465 valc = ((val & 4) ? 0xff : 0);
466 vald = ((val & 8) ? 0xff : 0);
467 switch (svga->gdcreg[3] & 0x18)
468 {
469 case 0: /*Set*/
470 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
471 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
472 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
473 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
474 break;
475 case 8: /*AND*/
476 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
477 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
478 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
479 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
480 break;
481 case 0x10: /*OR*/
482 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
483 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
484 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
485 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
486 break;
487 case 0x18: /*XOR*/
488 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
489 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
490 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
491 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
492 break;
493 }
494 }
495 break;
496 case 3:
497 if (svga->gdcreg[3] & 7)
498 val = svga_rotate[svga->gdcreg[3] & 7][val];
499 wm = svga->gdcreg[8];
500 svga->gdcreg[8] &= val;
502 vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
503 valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
504 valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
505 vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
506 switch (svga->gdcreg[3] & 0x18)
507 {
508 case 0: /*Set*/
509 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
510 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
511 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
512 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
513 break;
514 case 8: /*AND*/
515 if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
516 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
517 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
518 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
519 break;
520 case 0x10: /*OR*/
521 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
522 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
523 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
524 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
525 break;
526 case 0x18: /*XOR*/
527 if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
528 if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
529 if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
530 if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
531 break;
532 }
533 svga->gdcreg[8] = wm;
534 break;
535 }
536 }
538 void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
539 {
540 gd5429_t *gd5429 = (gd5429_t *)p;
541 svga_t *svga = &gd5429->svga;
543 pclog("gd5429_start_blit %i\n", count);
544 if (count == -1)
545 {
546 gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr;
547 gd5429->blt.src_addr_backup = gd5429->blt.src_addr;
548 gd5429->blt.width_backup = gd5429->blt.width;
549 gd5429->blt.height_internal = gd5429->blt.height;
550 gd5429->blt.x_count = gd5429->blt.mask & 7;
551 pclog("gd5429_start_blit : size %i, %i\n", gd5429->blt.width, gd5429->blt.height);
553 if (gd5429->blt.mode & 0x04)
554 {
555 // pclog("blt.mode & 0x04\n");
556 mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l);
557 mem_mapping_set_p(&svga->mapping, gd5429);
558 return;
559 }
560 else
561 {
562 mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
563 mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
564 gd5429_recalc_mapping(gd5429);
565 }
566 }
568 while (count)
569 {
570 uint8_t src, dst;
571 int mask;
573 if (gd5429->blt.mode & 0x04)
574 {
575 if (gd5429->blt.mode & 0x80)
576 {
577 src = (cpu_dat & 0x80) ? gd5429->blt.fg_col : gd5429->blt.bg_col;
578 mask = cpu_dat & 0x80;
579 cpu_dat <<= 1;
580 count--;
581 }
582 else
583 {
584 src = cpu_dat & 0xff;
585 cpu_dat >>= 8;
586 count -= 8;
587 mask = 1;
588 }
589 }
590 else
591 {
592 switch (gd5429->blt.mode & 0xc0)
593 {
594 case 0x00:
595 src = svga->vram[gd5429->blt.src_addr & svga->vrammask];
596 gd5429->blt.src_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
597 mask = 1;
598 break;
599 case 0x40:
600 src = svga->vram[(gd5429->blt.src_addr & (svga->vrammask & ~7)) | (gd5429->blt.dst_addr & 7)];
601 mask = 1;
602 break;
603 case 0x80:
604 mask = svga->vram[gd5429->blt.src_addr & svga->vrammask] & (0x80 >> gd5429->blt.x_count);
605 src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col;
606 gd5429->blt.x_count++;
607 if (gd5429->blt.x_count == 8)
608 {
609 gd5429->blt.x_count = 0;
610 gd5429->blt.src_addr++;
611 }
612 break;
613 case 0xc0:
614 mask = svga->vram[gd5429->blt.src_addr & svga->vrammask] & (0x80 >> (gd5429->blt.dst_addr & 7));
615 src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col;
616 break;
617 }
618 count--;
619 }
620 dst = svga->vram[gd5429->blt.dst_addr & svga->vrammask];
621 svga->changedvram[(gd5429->blt.dst_addr & svga->vrammask) >> 12] = changeframecount;
623 pclog("Blit %i,%i %06X %06X %06X %02X %02X %02X %02X ", gd5429->blt.width, gd5429->blt.height_internal, gd5429->blt.src_addr, gd5429->blt.dst_addr, gd5429->blt.src_addr & svga->vrammask, svga->vram[gd5429->blt.src_addr & svga->vrammask], 0x80 >> (gd5429->blt.dst_addr & 7), src, dst);
624 switch (gd5429->blt.rop)
625 {
626 case 0x00: dst = 0; break;
627 case 0x05: dst = src & dst; break;
628 case 0x06: dst = dst; break;
629 case 0x09: dst = src & ~dst; break;
630 case 0x0b: dst = ~ dst; break;
631 case 0x0d: dst = src; break;
632 case 0x0e: dst = 0xff; break;
633 case 0x50: dst = ~ src & dst; break;
634 case 0x59: dst = src ^ dst; break;
635 case 0x6d: dst = src | dst; break;
636 case 0x90: dst = ~(src | dst); break;
637 case 0x95: dst = ~(src ^ dst); break;
638 case 0xad: dst = src | ~dst; break;
639 case 0xd0: dst = ~src; break;
640 case 0xd6: dst = ~src | dst; break;
641 case 0xda: dst = ~(src & dst); break;
642 }
643 pclog("%02X %02X\n", dst, mask);
645 if ((gd5429->blt.width_backup - gd5429->blt.width) >= (gd5429->blt.mask & 7) &&
646 !((gd5429->blt.mode & 0x08) && !mask))
647 svga->vram[gd5429->blt.dst_addr & svga->vrammask] = dst;
649 gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
651 gd5429->blt.width--;
653 if (gd5429->blt.width == 0xffff)
654 {
655 gd5429->blt.width = gd5429->blt.width_backup;
657 gd5429->blt.dst_addr = gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.dst_pitch : gd5429->blt.dst_pitch);
659 switch (gd5429->blt.mode & 0xc0)
660 {
661 case 0x00:
662 gd5429->blt.src_addr = gd5429->blt.src_addr_backup = gd5429->blt.src_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.src_pitch : gd5429->blt.src_pitch);
663 break;
664 case 0x40:
665 gd5429->blt.src_addr = ((gd5429->blt.src_addr + ((gd5429->blt.mode & 0x01) ? -8 : 8)) & 0x38) | (gd5429->blt.src_addr & ~0x38);
666 break;
667 case 0x80:
668 if (gd5429->blt.x_count != 0)
669 {
670 gd5429->blt.x_count = 0;
671 gd5429->blt.src_addr++;
672 }
673 break;
674 case 0xc0:
675 gd5429->blt.src_addr = ((gd5429->blt.src_addr + ((gd5429->blt.mode & 0x01) ? -1 : 1)) & 7) | (gd5429->blt.src_addr & ~7);
676 break;
677 }
679 gd5429->blt.height_internal--;
680 if (gd5429->blt.height_internal == 0xffff)
681 {
682 if (gd5429->blt.mode & 0x04)
683 {
684 mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
685 mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
686 gd5429_recalc_mapping(gd5429);
687 }
688 return;
689 }
691 if (gd5429->blt.mode & 0x04)
692 return;
693 }
694 }
695 }
697 void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p)
698 {
699 gd5429_t *gd5429 = (gd5429_t *)p;
701 pclog("MMIO write %08X %02X\n", addr, val);
702 switch (addr & 0xff)
703 {
704 case 0x00:
705 gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xff00) | val;
706 break;
707 case 0x01:
708 gd5429->blt.bg_col = (gd5429->blt.bg_col & 0x00ff) | (val << 8);
709 break;
711 case 0x04:
712 gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xff00) | val;
713 break;
714 case 0x05:
715 gd5429->blt.fg_col = (gd5429->blt.fg_col & 0x00ff) | (val << 8);
716 break;
718 case 0x08:
719 gd5429->blt.width = (gd5429->blt.width & 0xff00) | val;
720 break;
721 case 0x09:
722 gd5429->blt.width = (gd5429->blt.width & 0x00ff) | (val << 8);
723 break;
724 case 0x0a:
725 gd5429->blt.height = (gd5429->blt.height & 0xff00) | val;
726 break;
727 case 0x0b:
728 gd5429->blt.height = (gd5429->blt.height & 0x00ff) | (val << 8);
729 break;
730 case 0x0c:
731 gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0xff00) | val;
732 break;
733 case 0x0d:
734 gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0x00ff) | (val << 8);
735 break;
736 case 0x0e:
737 gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0xff00) | val;
738 break;
739 case 0x0f:
740 gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0x00ff) | (val << 8);
741 break;
743 case 0x10:
744 gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xffff00) | val;
745 break;
746 case 0x11:
747 gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xff00ff) | (val << 8);
748 break;
749 case 0x12:
750 gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0x00ffff) | (val << 16);
751 break;
753 case 0x14:
754 gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xffff00) | val;
755 break;
756 case 0x15:
757 gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xff00ff) | (val << 8);
758 break;
759 case 0x16:
760 gd5429->blt.src_addr = (gd5429->blt.src_addr & 0x00ffff) | (val << 16);
761 break;
763 case 0x17:
764 gd5429->blt.mask = val;
765 break;
766 case 0x18:
767 gd5429->blt.mode = val;
768 break;
770 case 0x1a:
771 gd5429->blt.rop = val;
772 break;
774 case 0x40:
775 if (val & 0x02)
776 gd5429_start_blit(0, -1, gd5429);
777 break;
778 }
779 }
781 uint8_t gd5429_mmio_read(uint32_t addr, void *p)
782 {
783 gd5429_t *gd5429 = (gd5429_t *)p;
785 pclog("MMIO read %08X\n", addr);
786 switch (addr & 0xff)
787 {
788 case 0x40: /*BLT status*/
789 return 0;
790 }
791 return 0xff; /*All other registers read-only*/
792 }
794 void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p)
795 {
796 pclog("gd5429_blt_write_w %08X %08X\n", addr, val);
797 gd5429_start_blit(val, 16, p);
798 }
800 void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p)
801 {
802 gd5429_t *gd5429 = (gd5429_t *)p;
804 pclog("gd5429_blt_write_l %08X %08X %04X %04X\n", addr, val, ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00), ((val >> 24) & 0x00ff) | ((val >> 8) & 0xff00));
805 if ((gd5429->blt.mode & 0x84) == 0x84)
806 {
807 gd5429_start_blit( val & 0xff, 8, p);
808 gd5429_start_blit((val >> 8) & 0xff, 8, p);
809 gd5429_start_blit((val >> 16) & 0xff, 8, p);
810 gd5429_start_blit((val >> 24) & 0xff, 8, p);
811 }
812 else
813 gd5429_start_blit(val, 32, p);
814 }
816 void *gd5429_init()
817 {
818 gd5429_t *gd5429 = malloc(sizeof(gd5429_t));
819 svga_t *svga = &gd5429->svga;
820 memset(gd5429, 0, sizeof(gd5429_t));
822 rom_init(&gd5429->bios_rom, "roms/5429.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
824 svga_init(&gd5429->svga, gd5429, 1 << 21, /*2mb*/
825 gd5429_recalctimings,
826 gd5429_in, gd5429_out,
827 gd5429_hwcursor_draw,
828 NULL);
830 mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
831 mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
833 mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, NULL, NULL, gd5429_mmio_write, NULL, NULL, NULL, 0, gd5429);
835 io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
837 svga->hwcursor.yoff = 32;
838 svga->hwcursor.xoff = 0;
840 gd5429->bank[1] = 0x8000;
842 return gd5429;
843 }
845 static int gd5429_available()
846 {
847 return rom_present("roms/5429.vbi");
848 }
850 void gd5429_close(void *p)
851 {
852 gd5429_t *gd5429 = (gd5429_t *)p;
854 svga_close(&gd5429->svga);
856 free(gd5429);
857 }
859 void gd5429_speed_changed(void *p)
860 {
861 gd5429_t *gd5429 = (gd5429_t *)p;
863 svga_recalctimings(&gd5429->svga);
864 }
866 void gd5429_force_redraw(void *p)
867 {
868 gd5429_t *gd5429 = (gd5429_t *)p;
870 gd5429->svga.fullchange = changeframecount;
871 }
873 void gd5429_add_status_info(char *s, int max_len, void *p)
874 {
875 gd5429_t *gd5429 = (gd5429_t *)p;
877 svga_add_status_info(s, max_len, &gd5429->svga);
878 }
880 device_t gd5429_device =
881 {
882 "Cirrus Logic GD5429",
883 DEVICE_NOT_WORKING,
884 gd5429_init,
885 gd5429_close,
886 gd5429_available,
887 gd5429_speed_changed,
888 gd5429_force_redraw,
889 gd5429_add_status_info
890 };
