PCem
view src/vid_et4000w32.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 | 528f6c46c324 |
line source
1 /*ET4000/W32p emulation (Diamond Stealth 32)*/
2 /*Known bugs :
4 - Accelerator doesn't work in planar modes
5 */
6 #include <stdlib.h>
7 #include "ibm.h"
8 #include "device.h"
9 #include "io.h"
10 #include "mem.h"
11 #include "pci.h"
12 #include "rom.h"
13 #include "video.h"
14 #include "vid_svga.h"
15 #include "vid_icd2061.h"
16 #include "vid_stg_ramdac.h"
18 typedef struct et4000w32p_t
19 {
20 mem_mapping_t linear_mapping;
21 mem_mapping_t mmu_mapping;
23 rom_t bios_rom;
25 svga_t svga;
26 stg_ramdac_t ramdac;
27 icd2061_t icd2061;
29 int index;
30 uint8_t regs[256];
31 uint32_t linearbase, linearbase_old;
33 uint8_t banking, banking2;
35 uint8_t pci_regs[256];
37 int interleaved;
39 /*Accelerator*/
40 struct
41 {
42 struct
43 {
44 uint32_t pattern_addr,source_addr,dest_addr,mix_addr;
45 uint16_t pattern_off,source_off,dest_off,mix_off;
46 uint8_t pixel_depth,xy_dir;
47 uint8_t pattern_wrap,source_wrap;
48 uint16_t count_x,count_y;
49 uint8_t ctrl_routing,ctrl_reload;
50 uint8_t rop_fg,rop_bg;
51 uint16_t pos_x,pos_y;
52 uint16_t error;
53 uint16_t dmin,dmaj;
54 } queued,internal;
55 uint32_t pattern_addr,source_addr,dest_addr,mix_addr;
56 uint32_t pattern_back,source_back,dest_back,mix_back;
57 int pattern_x,source_x;
58 int pattern_x_back,source_x_back;
59 int pattern_y,source_y;
60 uint8_t status;
61 uint64_t cpu_dat;
62 int cpu_dat_pos;
63 int pix_pos;
64 } acl;
66 struct
67 {
68 uint32_t base[3];
69 uint8_t ctrl;
70 } mmu;
71 } et4000w32p_t;
73 void et4000w32p_recalcmapping(et4000w32p_t *et4000);
75 uint8_t et4000w32p_mmu_read(uint32_t addr, void *p);
76 void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p);
78 void et4000w32p_out(uint16_t addr, uint8_t val, void *p)
79 {
80 et4000w32p_t *et4000 = (et4000w32p_t *)p;
81 svga_t *svga = &et4000->svga;
82 uint8_t old;
84 // pclog("et4000w32p_out: addr %04X val %02X %04X:%04X %02X %02X\n", addr, val, CS, pc, ram[0x487], ram[0x488]);
86 /* if (ram[0x487] == 0x62)
87 fatal("mono\n");*/
88 // if (!(addr==0x3D4 && (val&~1)==0xE) && !(addr==0x3D5 && (crtcreg&~1)==0xE)) pclog("ET4000W32p out %04X %02X %04X:%04X ",addr,val,CS,pc);
90 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
91 addr ^= 0x60;
93 // if (!(addr==0x3D4 && (val&~1)==0xE) && !(addr==0x3D5 && (crtcreg&~1)==0xE)) pclog("%04X\n",addr);
95 switch (addr)
96 {
97 case 0x3c2:
98 icd2061_write(&et4000->icd2061, (val >> 2) & 3);
99 break;
101 case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
102 stg_ramdac_out(addr, val, &et4000->ramdac, svga);
103 return;
105 case 0x3CB: /*Banking extension*/
106 svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20);
107 svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16);
108 et4000->banking2 = val;
109 return;
110 case 0x3CD: /*Banking*/
111 svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536);
112 svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536);
113 et4000->banking = val;
114 return;
115 case 0x3CF:
116 switch (svga->gdcaddr & 15)
117 {
118 case 6:
119 svga->gdcreg[svga->gdcaddr & 15] = val;
120 //et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
121 et4000w32p_recalcmapping(et4000);
122 return;
123 }
124 break;
125 case 0x3D4:
126 svga->crtcreg = val & 63;
127 return;
128 case 0x3D5:
129 // pclog("Write CRTC R%02X %02X\n", crtcreg, val);
130 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
131 old = svga->crtc[svga->crtcreg];
132 svga->crtc[svga->crtcreg] = val;
133 if (old != val)
134 {
135 if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
136 {
137 svga->fullchange = changeframecount;
138 svga_recalctimings(svga);
139 }
140 }
141 if (svga->crtcreg == 0x30)
142 {
143 et4000->linearbase = val * 0x400000;
144 // pclog("Linear base now at %08X %02X\n", et4000w32p_linearbase, val);
145 et4000w32p_recalcmapping(et4000);
146 }
147 if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36)
148 et4000w32p_recalcmapping(et4000);
149 break;
151 case 0x210A: case 0x211A: case 0x212A: case 0x213A:
152 case 0x214A: case 0x215A: case 0x216A: case 0x217A:
153 et4000->index=val;
154 return;
155 case 0x210B: case 0x211B: case 0x212B: case 0x213B:
156 case 0x214B: case 0x215B: case 0x216B: case 0x217B:
157 et4000->regs[et4000->index] = val;
158 svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8);
159 svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8);
160 svga->hwcursor.addr = (et4000->regs[0xE8] | (et4000->regs[0xE9] << 8) | ((et4000->regs[0xEA] & 7) << 16)) << 2;
161 svga->hwcursor.addr += (et4000->regs[0xE6] & 63) * 16;
162 svga->hwcursor.ena = et4000->regs[0xF7] & 0x80;
163 svga->hwcursor.xoff = et4000->regs[0xE2] & 63;
164 svga->hwcursor.yoff = et4000->regs[0xE6] & 63;
165 // pclog("HWCURSOR X %i Y %i\n",svga->hwcursor_x,svga->hwcursor_y);
166 return;
168 }
169 svga_out(addr, val, svga);
170 }
172 uint8_t et4000w32p_in(uint16_t addr, void *p)
173 {
174 et4000w32p_t *et4000 = (et4000w32p_t *)p;
175 svga_t *svga = &et4000->svga;
176 uint8_t temp;
177 // if (addr==0x3DA) pclog("In 3DA %04X(%06X):%04X\n",CS,cs,pc);
179 // pclog("ET4000W32p in %04X %04X:%04X ",addr,CS,pc);
181 // if (addr != 0x3da && addr != 0x3ba)
182 // pclog("et4000w32p_in: addr %04X %04X:%04X %02X %02X\n", addr, CS, pc, ram[0x487], ram[0x488]);
184 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
185 addr ^= 0x60;
187 // pclog("%04X\n",addr);
189 switch (addr)
190 {
191 case 0x3c5:
192 if ((svga->seqaddr & 0xf) == 7)
193 return svga->seqregs[svga->seqaddr & 0xf] | 4;
194 break;
196 case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
197 return stg_ramdac_in(addr, &et4000->ramdac, svga);
199 case 0x3CB:
200 return et4000->banking2;
201 case 0x3CD:
202 return et4000->banking;
203 case 0x3D4:
204 return svga->crtcreg;
205 case 0x3D5:
206 // pclog("Read CRTC R%02X %02X\n", crtcreg, crtc[crtcreg]);
207 return svga->crtc[svga->crtcreg];
209 case 0x3DA:
210 svga->attrff = 0;
211 svga->cgastat ^= 0x30;
212 temp = svga->cgastat & 0x39;
213 if (svga->hdisp_on) temp |= 2;
214 if (!(svga->cgastat & 8)) temp |= 0x80;
215 // pclog("3DA in %02X\n",temp);
216 return temp;
218 case 0x210A: case 0x211A: case 0x212A: case 0x213A:
219 case 0x214A: case 0x215A: case 0x216A: case 0x217A:
220 return et4000->index;
221 case 0x210B: case 0x211B: case 0x212B: case 0x213B:
222 case 0x214B: case 0x215B: case 0x216B: case 0x217B:
223 if (et4000->index==0xec)
224 return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/
225 if (et4000->index == 0xef)
226 {
227 if (PCI) return et4000->regs[0xef] | 0xe0; /*PCI*/
228 else return et4000->regs[0xef] | 0x60; /*VESA local bus*/
229 }
230 return et4000->regs[et4000->index];
231 }
232 return svga_in(addr, svga);
233 }
235 void et4000w32p_recalctimings(svga_t *svga)
236 {
237 et4000w32p_t *et4000 = (et4000w32p_t *)svga->p;
238 // pclog("Recalc %08X ",svga_ma);
239 svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16;
240 // pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3);
241 if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400;
242 if (svga->crtc[0x35] & 0x02) svga->vtotal += 0x400;
243 if (svga->crtc[0x35] & 0x04) svga->dispend += 0x400;
244 if (svga->crtc[0x35] & 0x08) svga->vsyncstart += 0x400;
245 if (svga->crtc[0x35] & 0x10) svga->split += 0x400;
246 if (svga->crtc[0x3F] & 0x80) svga->rowoffset += 0x100;
247 if (svga->crtc[0x3F] & 0x01) svga->htotal += 256;
248 if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1;
250 switch ((svga->miscout >> 2) & 3)
251 {
252 case 0: case 1: break;
253 case 2: case 3: svga->clock = cpuclock / icd2061_getfreq(&et4000->icd2061, 2); break;
254 }
256 switch (svga->bpp)
257 {
258 case 15: case 16:
259 svga->hdisp >>= 1;
260 break;
261 case 24:
262 svga->hdisp /= 3;
263 break;
264 }
265 }
267 void et4000w32p_recalcmapping(et4000w32p_t *et4000)
268 {
269 svga_t *svga = &et4000->svga;
271 if (!(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
272 {
273 pclog("Update mapping - PCI disabled\n");
274 mem_mapping_disable(&svga->mapping);
275 mem_mapping_disable(&et4000->linear_mapping);
276 mem_mapping_disable(&et4000->mmu_mapping);
277 return;
278 }
280 pclog("recalcmapping %p\n", svga);
281 if (svga->crtc[0x36] & 0x10) /*Linear frame buffer*/
282 {
283 mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000);
284 mem_mapping_disable(&svga->mapping);
285 mem_mapping_disable(&et4000->mmu_mapping);
286 }
287 else
288 {
289 int map = (svga->gdcreg[6] & 0xc) >> 2;
290 if (svga->crtc[0x36] & 0x20) map |= 4;
291 if (svga->crtc[0x36] & 0x08) map |= 8;
292 switch (map)
293 {
294 case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/
295 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
296 mem_mapping_disable(&et4000->mmu_mapping);
297 svga->banked_mask = 0xffff;
298 break;
299 case 0x1: /*64k at A0000*/
300 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
301 mem_mapping_disable(&et4000->mmu_mapping);
302 svga->banked_mask = 0xffff;
303 break;
304 case 0x2: /*32k at B0000*/
305 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
306 mem_mapping_disable(&et4000->mmu_mapping);
307 svga->banked_mask = 0x7fff;
308 break;
309 case 0x3: /*32k at B8000*/
310 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
311 mem_mapping_disable(&et4000->mmu_mapping);
312 svga->banked_mask = 0x7fff;
313 break;
314 case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/
315 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
316 mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000);
317 svga->banked_mask = 0xffff;
318 break;
319 case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/
320 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
321 mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000);
322 svga->banked_mask = 0x7fff;
323 break;
324 case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/
325 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
326 mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000);
327 svga->banked_mask = 0x7fff;
328 break;
329 }
331 mem_mapping_disable(&et4000->linear_mapping);
332 // pclog("ET4K map %02X\n", map);
333 }
334 et4000->linearbase_old = et4000->linearbase;
336 if (!et4000->interleaved && (et4000->svga.crtc[0x32] & 0x80))
337 mem_mapping_disable(&svga->mapping);
338 }
340 #define ACL_WRST 1
341 #define ACL_RDST 2
342 #define ACL_XYST 4
343 #define ACL_SSO 8
345 void et4000w32_blit_start(et4000w32p_t *et4000);
346 void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000);
348 void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p)
349 {
350 et4000w32p_t *et4000 = (et4000w32p_t *)p;
351 svga_t *svga = &et4000->svga;
352 int bank;
353 // pclog("ET4K write %08X %02X %02X %04X(%08X):%08X\n",addr,val,et4000->acl.status,et4000->acl.internal.ctrl_routing,CS,cs,pc);
354 switch (addr & 0x6000)
355 {
356 case 0x0000: /*MMU 0*/
357 case 0x2000: /*MMU 1*/
358 case 0x4000: /*MMU 2*/
359 bank = (addr >> 13) & 3;
360 if (et4000->mmu.ctrl & (1 << bank))
361 {
362 if (!(et4000->acl.status & ACL_XYST)) return;
363 if (et4000->acl.internal.ctrl_routing & 3)
364 {
365 if ((et4000->acl.internal.ctrl_routing & 3) == 2)
366 {
367 if (et4000->acl.mix_addr & 7)
368 et4000w32_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000);
369 else
370 et4000w32_blit(8, val, 0, 1, et4000);
371 }
372 else if ((et4000->acl.internal.ctrl_routing & 3) == 1)
373 et4000w32_blit(1, ~0, val, 2, et4000);
374 }
375 }
376 else
377 {
378 svga->vram[(addr & 0x1fff) + et4000->mmu.base[bank]] = val;
379 svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[bank]) >> 12] = changeframecount;
380 }
381 break;
382 case 0x6000:
383 switch (addr & 0x7fff)
384 {
385 case 0x7f00: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFFFF00) | val; break;
386 case 0x7f01: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFF00FF) | (val << 8); break;
387 case 0x7f02: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFF00FFFF) | (val << 16); break;
388 case 0x7f03: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00FFFFFF) | (val << 24); break;
389 case 0x7f04: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFFFF00) | val; break;
390 case 0x7f05: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFF00FF) | (val << 8); break;
391 case 0x7f06: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFF00FFFF) | (val << 16); break;
392 case 0x7f07: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00FFFFFF) | (val << 24); break;
393 case 0x7f08: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFFFF00) | val; break;
394 case 0x7f09: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFF00FF) | (val << 8); break;
395 case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break;
396 case 0x7f0d: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break;
397 case 0x7f13: et4000->mmu.ctrl=val; break;
399 case 0x7f80: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFFFF00) | val; break;
400 case 0x7f81: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFF00FF) | (val << 8); break;
401 case 0x7f82: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFF00FFFF) | (val << 16); break;
402 case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); break;
403 case 0x7f84: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFFFF00) | val; break;
404 case 0x7f85: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFF00FF) | (val << 8); break;
405 case 0x7f86: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFF00FFFF) | (val << 16); break;
406 case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); break;
407 case 0x7f88: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xFF00) | val; break;
408 case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); break;
409 case 0x7f8a: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xFF00) | val; break;
410 case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); break;
411 case 0x7f8c: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xFF00) | val; break;
412 case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); break;
413 case 0x7f8e: et4000->acl.queued.pixel_depth = val; break;
414 case 0x7f8f: et4000->acl.queued.xy_dir = val; break;
415 case 0x7f90: et4000->acl.queued.pattern_wrap = val; break;
416 case 0x7f92: et4000->acl.queued.source_wrap = val; break;
417 case 0x7f98: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xFF00) | val; break;
418 case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); break;
419 case 0x7f9a: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xFF00) | val; break;
420 case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); break;
421 case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break;
422 case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break;
423 case 0x7f9e: et4000->acl.queued.rop_bg = val; break;
424 case 0x7f9f: et4000->acl.queued.rop_fg = val; break;
425 case 0x7fa0: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFFFF00) | val; break;
426 case 0x7fa1: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFF00FF) | (val << 8); break;
427 case 0x7fa2: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFF00FFFF) | (val << 16); break;
428 case 0x7fa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00FFFFFF) | (val << 24);
429 et4000->acl.internal = et4000->acl.queued;
430 et4000w32_blit_start(et4000);
431 if (!(et4000->acl.queued.ctrl_routing & 0x43))
432 {
433 et4000w32_blit(0xFFFFFF, ~0, 0, 0, et4000);
434 }
435 if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3))
436 et4000w32_blit(4, ~0, 0, 0, et4000);
437 break;
438 case 0x7fa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break;
439 case 0x7fa5: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); break;
440 case 0x7fa6: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); break;
441 case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); break;
442 case 0x7fa8: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; break;
443 case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); break;
444 case 0x7faa: et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; break;
445 case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); break;
446 case 0x7fac: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; break;
447 case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); break;
448 case 0x7fae: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; break;
449 case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); break;
450 }
451 break;
452 }
453 }
455 uint8_t et4000w32p_mmu_read(uint32_t addr, void *p)
456 {
457 et4000w32p_t *et4000 = (et4000w32p_t *)p;
458 svga_t *svga = &et4000->svga;
459 int bank;
460 uint8_t temp;
461 // pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc);
462 switch (addr & 0x6000)
463 {
464 case 0x0000: /*MMU 0*/
465 case 0x2000: /*MMU 1*/
466 case 0x4000: /*MMU 2*/
467 bank = (addr >> 13) & 3;
468 if (et4000->mmu.ctrl & (1 << bank))
469 {
470 temp = 0xff;
471 if (et4000->acl.cpu_dat_pos)
472 {
473 et4000->acl.cpu_dat_pos--;
474 temp = et4000->acl.cpu_dat & 0xff;
475 et4000->acl.cpu_dat >>= 8;
476 }
477 if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3))
478 et4000w32_blit(4, ~0, 0, 0, et4000);
479 /*???*/
480 return temp;
481 }
482 return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]];
484 case 0x6000:
485 switch (addr&0x7fff)
486 {
487 case 0x7f00: return et4000->mmu.base[0];
488 case 0x7f01: return et4000->mmu.base[0] >> 8;
489 case 0x7f02: return et4000->mmu.base[0] >> 16;
490 case 0x7f03: return et4000->mmu.base[0] >> 24;
491 case 0x7f04: return et4000->mmu.base[1];
492 case 0x7f05: return et4000->mmu.base[1] >> 8;
493 case 0x7f06: return et4000->mmu.base[1] >> 16;
494 case 0x7f07: return et4000->mmu.base[1] >> 24;
495 case 0x7f08: return et4000->mmu.base[2];
496 case 0x7f09: return et4000->mmu.base[2] >> 8;
497 case 0x7f0a: return et4000->mmu.base[2] >> 16;
498 case 0x7f0b: return et4000->mmu.base[2] >> 24;
499 case 0x7f13: return et4000->mmu.ctrl;
501 case 0x7f36:
502 // pclog("Read ACL status %02X\n",et4000->acl.status);
503 // if (et4000->acl.internal.pos_x!=et4000->acl.internal.count_x || et4000->acl.internal.pos_y!=et4000->acl.internal.count_y) return et4000->acl.status | ACL_XYST;
504 return et4000->acl.status;
505 case 0x7f80: return et4000->acl.internal.pattern_addr;
506 case 0x7f81: return et4000->acl.internal.pattern_addr >> 8;
507 case 0x7f82: return et4000->acl.internal.pattern_addr >> 16;
508 case 0x7f83: return et4000->acl.internal.pattern_addr >> 24;
509 case 0x7f84: return et4000->acl.internal.source_addr;
510 case 0x7f85: return et4000->acl.internal.source_addr >> 8;
511 case 0x7f86: return et4000->acl.internal.source_addr >> 16;
512 case 0x7f87: return et4000->acl.internal.source_addr >> 24;
513 case 0x7f88: return et4000->acl.internal.pattern_off;
514 case 0x7f89: return et4000->acl.internal.pattern_off >> 8;
515 case 0x7f8a: return et4000->acl.internal.source_off;
516 case 0x7f8b: return et4000->acl.internal.source_off >> 8;
517 case 0x7f8c: return et4000->acl.internal.dest_off;
518 case 0x7f8d: return et4000->acl.internal.dest_off >> 8;
519 case 0x7f8e: return et4000->acl.internal.pixel_depth;
520 case 0x7f8f: return et4000->acl.internal.xy_dir;
521 case 0x7f90: return et4000->acl.internal.pattern_wrap;
522 case 0x7f92: return et4000->acl.internal.source_wrap;
523 case 0x7f98: return et4000->acl.internal.count_x;
524 case 0x7f99: return et4000->acl.internal.count_x >> 8;
525 case 0x7f9a: return et4000->acl.internal.count_y;
526 case 0x7f9b: return et4000->acl.internal.count_y >> 8;
527 case 0x7f9c: return et4000->acl.internal.ctrl_routing;
528 case 0x7f9d: return et4000->acl.internal.ctrl_reload;
529 case 0x7f9e: return et4000->acl.internal.rop_bg;
530 case 0x7f9f: return et4000->acl.internal.rop_fg;
531 case 0x7fa0: return et4000->acl.internal.dest_addr;
532 case 0x7fa1: return et4000->acl.internal.dest_addr >> 8;
533 case 0x7fa2: return et4000->acl.internal.dest_addr >> 16;
534 case 0x7fa3: return et4000->acl.internal.dest_addr >> 24;
535 }
536 return 0xff;
537 }
538 return 0xff;
539 }
541 static int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000};
542 static int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF};
543 static int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
545 int bltout=0;
546 void et4000w32_blit_start(et4000w32p_t *et4000)
547 {
548 // if (et4000->acl.queued.xy_dir&0x80)
549 // pclog("Blit - %02X %08X (%i,%i) %08X (%i,%i) %08X (%i,%i) %i %i %i %02X %02X %02X\n",et4000->acl.queued.xy_dir,et4000->acl.internal.pattern_addr,(et4000->acl.internal.pattern_addr/3)%640,(et4000->acl.internal.pattern_addr/3)/640,et4000->acl.internal.source_addr,(et4000->acl.internal.source_addr/3)%640,(et4000->acl.internal.source_addr/3)/640,et4000->acl.internal.dest_addr,(et4000->acl.internal.dest_addr/3)%640,(et4000->acl.internal.dest_addr/3)/640,et4000->acl.internal.xy_dir,et4000->acl.internal.count_x,et4000->acl.internal.count_y,et4000->acl.internal.rop_fg,et4000->acl.internal.rop_bg, et4000->acl.internal.ctrl_routing);
550 // bltout=1;
551 // bltout=(et4000->acl.internal.count_x==1541);
552 if (!(et4000->acl.queued.xy_dir & 0x20))
553 et4000->acl.internal.error = et4000->acl.internal.dmaj / 2;
554 et4000->acl.pattern_addr= et4000->acl.internal.pattern_addr;
555 et4000->acl.source_addr = et4000->acl.internal.source_addr;
556 et4000->acl.mix_addr = et4000->acl.internal.mix_addr;
557 et4000->acl.mix_back = et4000->acl.mix_addr;
558 et4000->acl.dest_addr = et4000->acl.internal.dest_addr;
559 et4000->acl.dest_back = et4000->acl.dest_addr;
560 et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0;
561 et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0;
562 et4000->acl.status = ACL_XYST;
563 if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40))
564 et4000->acl.status |= ACL_SSO;
566 if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7])
567 {
568 et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7];
569 et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7];
570 }
571 et4000->acl.pattern_back = et4000->acl.pattern_addr;
572 if (!(et4000->acl.internal.pattern_wrap & 0x40))
573 {
574 et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1);
575 et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1);
576 }
577 et4000->acl.pattern_x_back = et4000->acl.pattern_x;
579 if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7])
580 {
581 et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7];
582 et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7];
583 }
584 et4000->acl.source_back = et4000->acl.source_addr;
585 if (!(et4000->acl.internal.source_wrap & 0x40))
586 {
587 et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1);
588 et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1);
589 }
590 et4000->acl.source_x_back = et4000->acl.source_x;
592 et4000w32_max_x[2] = ((et4000->acl.internal.pixel_depth & 0x30) == 0x20) ? 3 : 4;
594 et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3;
595 et4000->acl.cpu_dat_pos = 0;
596 et4000->acl.cpu_dat = 0;
598 et4000->acl.pix_pos = 0;
599 }
601 void et4000w32_incx(int c, et4000w32p_t *et4000)
602 {
603 et4000->acl.dest_addr += c;
604 et4000->acl.pattern_x += c;
605 et4000->acl.source_x += c;
606 et4000->acl.mix_addr += c;
607 if (et4000->acl.pattern_x >= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7])
608 et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7];
609 if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7])
610 et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7];
611 }
612 void et4000w32_decx(int c, et4000w32p_t *et4000)
613 {
614 et4000->acl.dest_addr -= c;
615 et4000->acl.pattern_x -= c;
616 et4000->acl.source_x -= c;
617 et4000->acl.mix_addr -= c;
618 if (et4000->acl.pattern_x < 0)
619 et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7];
620 if (et4000->acl.source_x < 0)
621 et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7];
622 }
623 void et4000w32_incy(et4000w32p_t *et4000)
624 {
625 et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1;
626 et4000->acl.source_addr += et4000->acl.internal.source_off + 1;
627 et4000->acl.mix_addr += et4000->acl.internal.mix_off + 1;
628 et4000->acl.dest_addr += et4000->acl.internal.dest_off + 1;
629 et4000->acl.pattern_y++;
630 if (et4000->acl.pattern_y == et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7])
631 {
632 et4000->acl.pattern_y = 0;
633 et4000->acl.pattern_addr = et4000->acl.pattern_back;
634 }
635 et4000->acl.source_y++;
636 if (et4000->acl.source_y == et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7])
637 {
638 et4000->acl.source_y = 0;
639 et4000->acl.source_addr = et4000->acl.source_back;
640 }
641 }
642 void et4000w32_decy(et4000w32p_t *et4000)
643 {
644 et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1;
645 et4000->acl.source_addr -= et4000->acl.internal.source_off + 1;
646 et4000->acl.mix_addr -= et4000->acl.internal.mix_off + 1;
647 et4000->acl.dest_addr -= et4000->acl.internal.dest_off + 1;
648 et4000->acl.pattern_y--;
649 if (et4000->acl.pattern_y < 0 && !(et4000->acl.internal.pattern_wrap & 0x40))
650 {
651 et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1;
652 et4000->acl.pattern_addr = et4000->acl.pattern_back + (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1));
653 }
654 et4000->acl.source_y--;
655 if (et4000->acl.source_y < 0 && !(et4000->acl.internal.source_wrap & 0x40))
656 {
657 et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1;
658 et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] *(et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1));;
659 }
660 }
662 void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000)
663 {
664 svga_t *svga = &et4000->svga;
665 int c,d;
666 uint8_t pattern, source, dest, out;
667 uint8_t rop;
668 int mixdat;
670 if (!(et4000->acl.status & ACL_XYST)) return;
671 // if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",et4000->acl.internal.count_x,et4000->acl.internal.count_y,et4000->acl.dest_addr,et4000->acl.dest_addr%640,et4000->acl.dest_addr/640,et4000->acl.source_addr,et4000->acl.pattern_addr);
672 //pclog("Blit exec - %i %i %i\n",count,et4000->acl.internal.pos_x,et4000->acl.internal.pos_y);
673 if (et4000->acl.internal.xy_dir & 0x80) /*Line draw*/
674 {
675 while (count--)
676 {
677 if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
678 pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff];
679 source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff];
680 if (bltout) pclog("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff);
681 if (cpu_input == 2)
682 {
683 source = sdat & 0xff;
684 sdat >>= 8;
685 }
686 dest = svga->vram[et4000->acl.dest_addr & 0x1fffff];
687 out = 0;
688 if (bltout) pclog("%06X ", et4000->acl.dest_addr);
689 if ((et4000->acl.internal.ctrl_routing & 0xa) == 8)
690 {
691 mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7));
692 if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]);
693 }
694 else
695 {
696 mixdat = mix & 1;
697 mix >>= 1;
698 mix |= 0x80000000;
699 }
700 et4000->acl.mix_addr++;
701 rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg;
702 for (c = 0; c < 8; c++)
703 {
704 d = (dest & (1 << c)) ? 1 : 0;
705 if (source & (1 << c)) d |= 2;
706 if (pattern & (1 << c)) d |= 4;
707 if (rop & (1 << d)) out |= (1 << c);
708 }
709 if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out);
710 if (!(et4000->acl.internal.ctrl_routing & 0x40))
711 {
712 svga->vram[et4000->acl.dest_addr & 0x1fffff] = out;
713 svga->changedvram[(et4000->acl.dest_addr & 0x1fffff) >> 12] = changeframecount;
714 }
715 else
716 {
717 et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8));
718 et4000->acl.cpu_dat_pos++;
719 }
721 // pclog("%i %i\n",et4000->acl.pix_pos,(et4000->acl.internal.pixel_depth>>4)&3);
722 et4000->acl.pix_pos++;
723 et4000->acl.internal.pos_x++;
724 if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3))
725 {
726 if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000);
727 else et4000w32_incx(1, et4000);
728 }
729 else
730 {
731 if (et4000->acl.internal.xy_dir & 1)
732 et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000);
733 else
734 et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000);
735 et4000->acl.pix_pos = 0;
736 /*Next pixel*/
737 switch (et4000->acl.internal.xy_dir & 7)
738 {
739 case 0: case 1: /*Y+*/
740 et4000w32_incy(et4000);
741 et4000->acl.internal.pos_y++;
742 et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1;
743 break;
744 case 2: case 3: /*Y-*/
745 et4000w32_decy(et4000);
746 et4000->acl.internal.pos_y++;
747 et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1;
748 break;
749 case 4: case 6: /*X+*/
750 et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
751 //et4000->acl.internal.pos_x++;
752 break;
753 case 5: case 7: /*X-*/
754 et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
755 //et4000->acl.internal.pos_x++;
756 break;
757 }
758 et4000->acl.internal.error += et4000->acl.internal.dmin;
759 if (et4000->acl.internal.error > et4000->acl.internal.dmaj)
760 {
761 et4000->acl.internal.error -= et4000->acl.internal.dmaj;
762 switch (et4000->acl.internal.xy_dir & 7)
763 {
764 case 0: case 2: /*X+*/
765 et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
766 et4000->acl.internal.pos_x++;
767 break;
768 case 1: case 3: /*X-*/
769 et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
770 et4000->acl.internal.pos_x++;
771 break;
772 case 4: case 5: /*Y+*/
773 et4000w32_incy(et4000);
774 et4000->acl.internal.pos_y++;
775 break;
776 case 6: case 7: /*Y-*/
777 et4000w32_decy(et4000);
778 et4000->acl.internal.pos_y++;
779 break;
780 }
781 }
782 if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x ||
783 et4000->acl.internal.pos_y > et4000->acl.internal.count_y)
784 {
785 et4000->acl.status = 0;
786 // pclog("Blit line over\n");
787 return;
788 }
789 }
790 }
791 }
792 else
793 {
794 while (count--)
795 {
796 if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
798 pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff];
799 source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff];
800 if (bltout) pclog("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff, pattern, source);
802 if (cpu_input == 2)
803 {
804 source = sdat & 0xff;
805 sdat >>= 8;
806 }
807 dest = svga->vram[et4000->acl.dest_addr & 0x1fffff];
808 out = 0;
809 if (bltout) pclog("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr);
810 if ((et4000->acl.internal.ctrl_routing & 0xa) == 8)
811 {
812 mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7));
813 if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]);
814 }
815 else
816 {
817 mixdat = mix & 1;
818 mix >>= 1;
819 mix |= 0x80000000;
820 }
822 rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg;
823 for (c = 0; c < 8; c++)
824 {
825 d = (dest & (1 << c)) ? 1 : 0;
826 if (source & (1 << c)) d |= 2;
827 if (pattern & (1 << c)) d |= 4;
828 if (rop & (1 << d)) out |= (1 << c);
829 }
830 if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out);
831 if (!(et4000->acl.internal.ctrl_routing & 0x40))
832 {
833 svga->vram[et4000->acl.dest_addr & 0x1fffff] = out;
834 svga->changedvram[(et4000->acl.dest_addr & 0x1fffff) >> 12] = changeframecount;
835 }
836 else
837 {
838 et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8));
839 et4000->acl.cpu_dat_pos++;
840 }
842 if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000);
843 else et4000w32_incx(1, et4000);
845 et4000->acl.internal.pos_x++;
846 if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x)
847 {
848 if (et4000->acl.internal.xy_dir & 2)
849 {
850 et4000w32_decy(et4000);
851 et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1);
852 et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1);
853 }
854 else
855 {
856 et4000w32_incy(et4000);
857 et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1;
858 et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1;
859 }
861 et4000->acl.pattern_x = et4000->acl.pattern_x_back;
862 et4000->acl.source_x = et4000->acl.source_x_back;
864 et4000->acl.internal.pos_y++;
865 et4000->acl.internal.pos_x = 0;
866 if (et4000->acl.internal.pos_y > et4000->acl.internal.count_y)
867 {
868 et4000->acl.status = 0;
869 // pclog("Blit over\n");
870 return;
871 }
872 if (cpu_input) return;
873 if (et4000->acl.internal.ctrl_routing & 0x40)
874 {
875 if (et4000->acl.cpu_dat_pos & 3)
876 et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3);
877 return;
878 }
879 }
880 }
881 }
882 }
885 void et4000w32p_hwcursor_draw(svga_t *svga, int displine)
886 {
887 int x, offset;
888 uint8_t dat;
889 offset = svga->hwcursor_latch.xoff;
890 for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4)
891 {
892 dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)];
893 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 32] = (dat & 1) ? 0xFFFFFF : 0;
894 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 32] ^= 0xFFFFFF;
895 dat >>= 2;
896 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 33] = (dat & 1) ? 0xFFFFFF : 0;
897 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 33] ^= 0xFFFFFF;
898 dat >>= 2;
899 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 34] = (dat & 1) ? 0xFFFFFF : 0;
900 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 34] ^= 0xFFFFFF;
901 dat >>= 2;
902 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 35] = (dat & 1) ? 0xFFFFFF : 0;
903 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 35] ^= 0xFFFFFF;
904 dat >>= 2;
905 offset += 4;
906 }
907 svga->hwcursor_latch.addr += 16;
908 }
910 static void et4000w32p_io_remove(et4000w32p_t *et4000)
911 {
912 io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
914 io_removehandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
915 io_removehandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
916 io_removehandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
917 io_removehandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
918 io_removehandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
919 io_removehandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
920 io_removehandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
921 io_removehandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
922 }
924 static void et4000w32p_io_set(et4000w32p_t *et4000)
925 {
926 et4000w32p_io_remove(et4000);
928 io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
930 io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
931 io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
932 io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
933 io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
934 io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
935 io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
936 io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
937 io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
938 }
940 uint8_t et4000w32p_pci_read(int func, int addr, void *p)
941 {
942 et4000w32p_t *et4000 = (et4000w32p_t *)p;
943 svga_t *svga = &et4000->svga;
945 // pclog("ET4000 PCI read %08X\n", addr);
947 switch (addr)
948 {
949 case 0x00: return 0x0c; /*Tseng Labs*/
950 case 0x01: return 0x10;
952 case 0x02: return 0x06; /*ET4000W32p Rev D*/
953 case 0x03: return 0x32;
955 case PCI_REG_COMMAND:
956 return et4000->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
958 case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
960 case 0x08: return 0; /*Revision ID*/
961 case 0x09: return 0; /*Programming interface*/
963 case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
964 case 0x0b: return 0x03;
966 case 0x10: return 0x00; /*Linear frame buffer address*/
967 case 0x11: return 0x00;
968 case 0x12: return svga->crtc[0x5a] & 0x80;
969 case 0x13: return svga->crtc[0x59];
971 case 0x30: return et4000->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
972 case 0x31: return 0x00;
973 case 0x32: return et4000->pci_regs[0x32];
974 case 0x33: return et4000->pci_regs[0x33];
975 }
976 return 0;
977 }
979 void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p)
980 {
981 et4000w32p_t *et4000 = (et4000w32p_t *)p;
983 switch (addr)
984 {
985 case PCI_REG_COMMAND:
986 et4000->pci_regs[PCI_REG_COMMAND] = val & 0x27;
987 if (val & PCI_COMMAND_IO)
988 et4000w32p_io_set(et4000);
989 else
990 et4000w32p_io_remove(et4000);
991 et4000w32p_recalcmapping(et4000);
992 break;
994 case 0x13:
995 et4000->linearbase = val << 24;
996 et4000w32p_recalcmapping(et4000);
997 break;
999 case 0x30: case 0x32: case 0x33:
1000 et4000->pci_regs[addr] = val;
1001 if (et4000->pci_regs[0x30] & 0x01)
1002 {
1003 uint32_t addr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24);
1004 pclog("ET4000 bios_rom enabled at %08x\n", addr);
1005 mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000);
1006 }
1007 else
1008 {
1009 pclog("ET4000 bios_rom disabled\n");
1010 mem_mapping_disable(&et4000->bios_rom.mapping);
1011 }
1012 return;
1013 }
1014 }
1016 void *et4000w32p_init()
1017 {
1018 int vram_size;
1019 et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t));
1020 memset(et4000, 0, sizeof(et4000w32p_t));
1022 vram_size = device_get_config_int("memory");
1024 et4000->interleaved = (vram_size == 2) ? 1 : 0;
1026 svga_init(&et4000->svga, et4000, vram_size << 20,
1027 et4000w32p_recalctimings,
1028 et4000w32p_in, et4000w32p_out,
1029 et4000w32p_hwcursor_draw,
1030 NULL);
1032 rom_init(&et4000->bios_rom, "roms/et4000w32.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
1033 if (PCI)
1034 mem_mapping_disable(&et4000->bios_rom.mapping);
1036 mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &et4000->svga);
1037 mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, 0, et4000);
1039 et4000w32p_io_set(et4000);
1041 pci_add(et4000w32p_pci_read, et4000w32p_pci_write, et4000);
1043 et4000->pci_regs[0x04] = 7;
1045 et4000->pci_regs[0x30] = 0x00;
1046 et4000->pci_regs[0x32] = 0x0c;
1047 et4000->pci_regs[0x33] = 0x00;
1049 return et4000;
1050 }
1052 int et4000w32p_available()
1053 {
1054 return rom_present("roms/et4000w32.bin");
1055 }
1057 void et4000w32p_close(void *p)
1058 {
1059 et4000w32p_t *et4000 = (et4000w32p_t *)p;
1061 svga_close(&et4000->svga);
1063 free(et4000);
1064 }
1066 void et4000w32p_speed_changed(void *p)
1067 {
1068 et4000w32p_t *et4000 = (et4000w32p_t *)p;
1070 svga_recalctimings(&et4000->svga);
1071 }
1073 void et4000w32p_force_redraw(void *p)
1074 {
1075 et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
1077 et4000w32p->svga.fullchange = changeframecount;
1078 }
1080 void et4000w32p_add_status_info(char *s, int max_len, void *p)
1081 {
1082 et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
1084 svga_add_status_info(s, max_len, &et4000w32p->svga);
1085 }
1087 static device_config_t et4000w32p_config[] =
1088 {
1089 {
1090 .name = "memory",
1091 .description = "Memory size",
1092 .type = CONFIG_SELECTION,
1093 .selection =
1094 {
1095 {
1096 .description = "1 MB",
1097 .value = 1
1098 },
1099 {
1100 .description = "2 MB",
1101 .value = 2
1102 },
1103 {
1104 .description = ""
1105 }
1106 },
1107 .default_int = 2
1108 },
1109 {
1110 .type = -1
1111 }
1112 };
1114 device_t et4000w32p_device =
1115 {
1116 "Tseng Labs ET4000/w32p",
1117 0,
1118 et4000w32p_init,
1119 et4000w32p_close,
1120 et4000w32p_available,
1121 et4000w32p_speed_changed,
1122 et4000w32p_force_redraw,
1123 et4000w32p_add_status_info,
1124 et4000w32p_config
1125 };
