PCem

view src/vid_et4000w32.c @ 138:528f6c46c324

Tweaked ET4000/W32p blitter, no longer hangs in Windows NT.
author TomW
date Mon Jul 28 21:14:13 2014 +0100
parents 24b744b9a632
children
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 et4000->acl.status |= ACL_RDST;
355 switch (addr & 0x6000)
356 {
357 case 0x0000: /*MMU 0*/
358 case 0x2000: /*MMU 1*/
359 case 0x4000: /*MMU 2*/
360 bank = (addr >> 13) & 3;
361 if (et4000->mmu.ctrl & (1 << bank))
362 {
363 if (!(et4000->acl.status & ACL_XYST)) return;
364 if (et4000->acl.internal.ctrl_routing & 3)
365 {
366 if ((et4000->acl.internal.ctrl_routing & 3) == 2)
367 {
368 if (et4000->acl.mix_addr & 7)
369 et4000w32_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000);
370 else
371 et4000w32_blit(8, val, 0, 1, et4000);
372 }
373 else if ((et4000->acl.internal.ctrl_routing & 3) == 1)
374 et4000w32_blit(1, ~0, val, 2, et4000);
375 }
376 }
377 else
378 {
379 svga->vram[(addr & 0x1fff) + et4000->mmu.base[bank]] = val;
380 svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[bank]) >> 12] = changeframecount;
381 }
382 break;
383 case 0x6000:
384 switch (addr & 0x7fff)
385 {
386 case 0x7f00: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFFFF00) | val; break;
387 case 0x7f01: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFF00FF) | (val << 8); break;
388 case 0x7f02: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFF00FFFF) | (val << 16); break;
389 case 0x7f03: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00FFFFFF) | (val << 24); break;
390 case 0x7f04: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFFFF00) | val; break;
391 case 0x7f05: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFF00FF) | (val << 8); break;
392 case 0x7f06: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFF00FFFF) | (val << 16); break;
393 case 0x7f07: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00FFFFFF) | (val << 24); break;
394 case 0x7f08: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFFFF00) | val; break;
395 case 0x7f09: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFF00FF) | (val << 8); break;
396 case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break;
397 case 0x7f0d: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break;
398 case 0x7f13: et4000->mmu.ctrl=val; break;
400 case 0x7f80: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFFFF00) | val; break;
401 case 0x7f81: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFF00FF) | (val << 8); break;
402 case 0x7f82: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFF00FFFF) | (val << 16); break;
403 case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); break;
404 case 0x7f84: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFFFF00) | val; break;
405 case 0x7f85: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFF00FF) | (val << 8); break;
406 case 0x7f86: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFF00FFFF) | (val << 16); break;
407 case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); break;
408 case 0x7f88: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xFF00) | val; break;
409 case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); break;
410 case 0x7f8a: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xFF00) | val; break;
411 case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); break;
412 case 0x7f8c: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xFF00) | val; break;
413 case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); break;
414 case 0x7f8e: et4000->acl.queued.pixel_depth = val; break;
415 case 0x7f8f: et4000->acl.queued.xy_dir = val; break;
416 case 0x7f90: et4000->acl.queued.pattern_wrap = val; break;
417 case 0x7f92: et4000->acl.queued.source_wrap = val; break;
418 case 0x7f98: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xFF00) | val; break;
419 case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); break;
420 case 0x7f9a: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xFF00) | val; break;
421 case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); break;
422 case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break;
423 case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break;
424 case 0x7f9e: et4000->acl.queued.rop_bg = val; break;
425 case 0x7f9f: et4000->acl.queued.rop_fg = val; break;
426 case 0x7fa0: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFFFF00) | val; break;
427 case 0x7fa1: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFF00FF) | (val << 8); break;
428 case 0x7fa2: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFF00FFFF) | (val << 16); break;
429 case 0x7fa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00FFFFFF) | (val << 24);
430 et4000->acl.internal = et4000->acl.queued;
431 et4000w32_blit_start(et4000);
432 if (!(et4000->acl.queued.ctrl_routing & 0x43))
433 {
434 et4000w32_blit(0xFFFFFF, ~0, 0, 0, et4000);
435 }
436 if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3))
437 et4000w32_blit(4, ~0, 0, 0, et4000);
438 break;
439 case 0x7fa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break;
440 case 0x7fa5: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); break;
441 case 0x7fa6: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); break;
442 case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); break;
443 case 0x7fa8: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; break;
444 case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); break;
445 case 0x7faa: et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; break;
446 case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); break;
447 case 0x7fac: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; break;
448 case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); break;
449 case 0x7fae: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; break;
450 case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); break;
451 }
452 break;
453 }
454 }
456 uint8_t et4000w32p_mmu_read(uint32_t addr, void *p)
457 {
458 et4000w32p_t *et4000 = (et4000w32p_t *)p;
459 svga_t *svga = &et4000->svga;
460 int bank;
461 uint8_t temp;
462 // pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc);
463 switch (addr & 0x6000)
464 {
465 case 0x0000: /*MMU 0*/
466 case 0x2000: /*MMU 1*/
467 case 0x4000: /*MMU 2*/
468 bank = (addr >> 13) & 3;
469 if (et4000->mmu.ctrl & (1 << bank))
470 {
471 temp = 0xff;
472 if (et4000->acl.cpu_dat_pos)
473 {
474 et4000->acl.cpu_dat_pos--;
475 temp = et4000->acl.cpu_dat & 0xff;
476 et4000->acl.cpu_dat >>= 8;
477 }
478 if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3))
479 et4000w32_blit(4, ~0, 0, 0, et4000);
480 /*???*/
481 return temp;
482 }
483 return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]];
485 case 0x6000:
486 switch (addr&0x7fff)
487 {
488 case 0x7f00: return et4000->mmu.base[0];
489 case 0x7f01: return et4000->mmu.base[0] >> 8;
490 case 0x7f02: return et4000->mmu.base[0] >> 16;
491 case 0x7f03: return et4000->mmu.base[0] >> 24;
492 case 0x7f04: return et4000->mmu.base[1];
493 case 0x7f05: return et4000->mmu.base[1] >> 8;
494 case 0x7f06: return et4000->mmu.base[1] >> 16;
495 case 0x7f07: return et4000->mmu.base[1] >> 24;
496 case 0x7f08: return et4000->mmu.base[2];
497 case 0x7f09: return et4000->mmu.base[2] >> 8;
498 case 0x7f0a: return et4000->mmu.base[2] >> 16;
499 case 0x7f0b: return et4000->mmu.base[2] >> 24;
500 case 0x7f13: return et4000->mmu.ctrl;
502 case 0x7f36:
503 temp = et4000->acl.status;
504 et4000->acl.status &= ~ACL_RDST;
505 // 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;
506 return temp;
507 case 0x7f80: return et4000->acl.internal.pattern_addr;
508 case 0x7f81: return et4000->acl.internal.pattern_addr >> 8;
509 case 0x7f82: return et4000->acl.internal.pattern_addr >> 16;
510 case 0x7f83: return et4000->acl.internal.pattern_addr >> 24;
511 case 0x7f84: return et4000->acl.internal.source_addr;
512 case 0x7f85: return et4000->acl.internal.source_addr >> 8;
513 case 0x7f86: return et4000->acl.internal.source_addr >> 16;
514 case 0x7f87: return et4000->acl.internal.source_addr >> 24;
515 case 0x7f88: return et4000->acl.internal.pattern_off;
516 case 0x7f89: return et4000->acl.internal.pattern_off >> 8;
517 case 0x7f8a: return et4000->acl.internal.source_off;
518 case 0x7f8b: return et4000->acl.internal.source_off >> 8;
519 case 0x7f8c: return et4000->acl.internal.dest_off;
520 case 0x7f8d: return et4000->acl.internal.dest_off >> 8;
521 case 0x7f8e: return et4000->acl.internal.pixel_depth;
522 case 0x7f8f: return et4000->acl.internal.xy_dir;
523 case 0x7f90: return et4000->acl.internal.pattern_wrap;
524 case 0x7f92: return et4000->acl.internal.source_wrap;
525 case 0x7f98: return et4000->acl.internal.count_x;
526 case 0x7f99: return et4000->acl.internal.count_x >> 8;
527 case 0x7f9a: return et4000->acl.internal.count_y;
528 case 0x7f9b: return et4000->acl.internal.count_y >> 8;
529 case 0x7f9c: return et4000->acl.internal.ctrl_routing;
530 case 0x7f9d: return et4000->acl.internal.ctrl_reload;
531 case 0x7f9e: return et4000->acl.internal.rop_bg;
532 case 0x7f9f: return et4000->acl.internal.rop_fg;
533 case 0x7fa0: return et4000->acl.internal.dest_addr;
534 case 0x7fa1: return et4000->acl.internal.dest_addr >> 8;
535 case 0x7fa2: return et4000->acl.internal.dest_addr >> 16;
536 case 0x7fa3: return et4000->acl.internal.dest_addr >> 24;
537 }
538 return 0xff;
539 }
540 return 0xff;
541 }
543 static int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000};
544 static int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF};
545 static int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
547 int bltout=0;
548 void et4000w32_blit_start(et4000w32p_t *et4000)
549 {
550 // if (et4000->acl.queued.xy_dir&0x80)
551 // 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);
552 // bltout=1;
553 // bltout=(et4000->acl.internal.count_x==1541);
554 if (!(et4000->acl.queued.xy_dir & 0x20))
555 et4000->acl.internal.error = et4000->acl.internal.dmaj / 2;
556 et4000->acl.pattern_addr= et4000->acl.internal.pattern_addr;
557 et4000->acl.source_addr = et4000->acl.internal.source_addr;
558 et4000->acl.mix_addr = et4000->acl.internal.mix_addr;
559 et4000->acl.mix_back = et4000->acl.mix_addr;
560 et4000->acl.dest_addr = et4000->acl.internal.dest_addr;
561 et4000->acl.dest_back = et4000->acl.dest_addr;
562 et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0;
563 et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0;
564 et4000->acl.status |= ACL_XYST;
565 if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40))
566 et4000->acl.status |= ACL_SSO;
568 if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7])
569 {
570 et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7];
571 et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7];
572 }
573 et4000->acl.pattern_back = et4000->acl.pattern_addr;
574 if (!(et4000->acl.internal.pattern_wrap & 0x40))
575 {
576 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);
577 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);
578 }
579 et4000->acl.pattern_x_back = et4000->acl.pattern_x;
581 if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7])
582 {
583 et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7];
584 et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7];
585 }
586 et4000->acl.source_back = et4000->acl.source_addr;
587 if (!(et4000->acl.internal.source_wrap & 0x40))
588 {
589 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);
590 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);
591 }
592 et4000->acl.source_x_back = et4000->acl.source_x;
594 et4000w32_max_x[2] = ((et4000->acl.internal.pixel_depth & 0x30) == 0x20) ? 3 : 4;
596 et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3;
597 et4000->acl.cpu_dat_pos = 0;
598 et4000->acl.cpu_dat = 0;
600 et4000->acl.pix_pos = 0;
601 }
603 void et4000w32_incx(int c, et4000w32p_t *et4000)
604 {
605 et4000->acl.dest_addr += c;
606 et4000->acl.pattern_x += c;
607 et4000->acl.source_x += c;
608 et4000->acl.mix_addr += c;
609 if (et4000->acl.pattern_x >= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7])
610 et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7];
611 if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7])
612 et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7];
613 }
614 void et4000w32_decx(int c, et4000w32p_t *et4000)
615 {
616 et4000->acl.dest_addr -= c;
617 et4000->acl.pattern_x -= c;
618 et4000->acl.source_x -= c;
619 et4000->acl.mix_addr -= c;
620 if (et4000->acl.pattern_x < 0)
621 et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7];
622 if (et4000->acl.source_x < 0)
623 et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7];
624 }
625 void et4000w32_incy(et4000w32p_t *et4000)
626 {
627 et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1;
628 et4000->acl.source_addr += et4000->acl.internal.source_off + 1;
629 et4000->acl.mix_addr += et4000->acl.internal.mix_off + 1;
630 et4000->acl.dest_addr += et4000->acl.internal.dest_off + 1;
631 et4000->acl.pattern_y++;
632 if (et4000->acl.pattern_y == et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7])
633 {
634 et4000->acl.pattern_y = 0;
635 et4000->acl.pattern_addr = et4000->acl.pattern_back;
636 }
637 et4000->acl.source_y++;
638 if (et4000->acl.source_y == et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7])
639 {
640 et4000->acl.source_y = 0;
641 et4000->acl.source_addr = et4000->acl.source_back;
642 }
643 }
644 void et4000w32_decy(et4000w32p_t *et4000)
645 {
646 et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1;
647 et4000->acl.source_addr -= et4000->acl.internal.source_off + 1;
648 et4000->acl.mix_addr -= et4000->acl.internal.mix_off + 1;
649 et4000->acl.dest_addr -= et4000->acl.internal.dest_off + 1;
650 et4000->acl.pattern_y--;
651 if (et4000->acl.pattern_y < 0 && !(et4000->acl.internal.pattern_wrap & 0x40))
652 {
653 et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1;
654 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));
655 }
656 et4000->acl.source_y--;
657 if (et4000->acl.source_y < 0 && !(et4000->acl.internal.source_wrap & 0x40))
658 {
659 et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1;
660 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));;
661 }
662 }
664 void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000)
665 {
666 svga_t *svga = &et4000->svga;
667 int c,d;
668 uint8_t pattern, source, dest, out;
669 uint8_t rop;
670 int mixdat;
672 if (!(et4000->acl.status & ACL_XYST)) return;
673 // 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);
674 //pclog("Blit exec - %i %i %i\n",count,et4000->acl.internal.pos_x,et4000->acl.internal.pos_y);
675 if (et4000->acl.internal.xy_dir & 0x80) /*Line draw*/
676 {
677 while (count--)
678 {
679 if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
680 pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff];
681 source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff];
682 if (bltout) pclog("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff);
683 if (cpu_input == 2)
684 {
685 source = sdat & 0xff;
686 sdat >>= 8;
687 }
688 dest = svga->vram[et4000->acl.dest_addr & 0x1fffff];
689 out = 0;
690 if (bltout) pclog("%06X ", et4000->acl.dest_addr);
691 if ((et4000->acl.internal.ctrl_routing & 0xa) == 8)
692 {
693 mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7));
694 if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]);
695 }
696 else
697 {
698 mixdat = mix & 1;
699 mix >>= 1;
700 mix |= 0x80000000;
701 }
702 et4000->acl.mix_addr++;
703 rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg;
704 for (c = 0; c < 8; c++)
705 {
706 d = (dest & (1 << c)) ? 1 : 0;
707 if (source & (1 << c)) d |= 2;
708 if (pattern & (1 << c)) d |= 4;
709 if (rop & (1 << d)) out |= (1 << c);
710 }
711 if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out);
712 if (!(et4000->acl.internal.ctrl_routing & 0x40))
713 {
714 svga->vram[et4000->acl.dest_addr & 0x1fffff] = out;
715 svga->changedvram[(et4000->acl.dest_addr & 0x1fffff) >> 12] = changeframecount;
716 }
717 else
718 {
719 et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8));
720 et4000->acl.cpu_dat_pos++;
721 }
723 // pclog("%i %i\n",et4000->acl.pix_pos,(et4000->acl.internal.pixel_depth>>4)&3);
724 et4000->acl.pix_pos++;
725 et4000->acl.internal.pos_x++;
726 if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3))
727 {
728 if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000);
729 else et4000w32_incx(1, et4000);
730 }
731 else
732 {
733 if (et4000->acl.internal.xy_dir & 1)
734 et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000);
735 else
736 et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000);
737 et4000->acl.pix_pos = 0;
738 /*Next pixel*/
739 switch (et4000->acl.internal.xy_dir & 7)
740 {
741 case 0: case 1: /*Y+*/
742 et4000w32_incy(et4000);
743 et4000->acl.internal.pos_y++;
744 et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1;
745 break;
746 case 2: case 3: /*Y-*/
747 et4000w32_decy(et4000);
748 et4000->acl.internal.pos_y++;
749 et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1;
750 break;
751 case 4: case 6: /*X+*/
752 et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
753 //et4000->acl.internal.pos_x++;
754 break;
755 case 5: case 7: /*X-*/
756 et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
757 //et4000->acl.internal.pos_x++;
758 break;
759 }
760 et4000->acl.internal.error += et4000->acl.internal.dmin;
761 if (et4000->acl.internal.error > et4000->acl.internal.dmaj)
762 {
763 et4000->acl.internal.error -= et4000->acl.internal.dmaj;
764 switch (et4000->acl.internal.xy_dir & 7)
765 {
766 case 0: case 2: /*X+*/
767 et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
768 et4000->acl.internal.pos_x++;
769 break;
770 case 1: case 3: /*X-*/
771 et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000);
772 et4000->acl.internal.pos_x++;
773 break;
774 case 4: case 5: /*Y+*/
775 et4000w32_incy(et4000);
776 et4000->acl.internal.pos_y++;
777 break;
778 case 6: case 7: /*Y-*/
779 et4000w32_decy(et4000);
780 et4000->acl.internal.pos_y++;
781 break;
782 }
783 }
784 if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x ||
785 et4000->acl.internal.pos_y > et4000->acl.internal.count_y)
786 {
787 et4000->acl.status &= ~(ACL_XYST | ACL_SSO);
788 // pclog("Blit line over\n");
789 return;
790 }
791 }
792 }
793 }
794 else
795 {
796 while (count--)
797 {
798 if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
800 pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff];
801 source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff];
802 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);
804 if (cpu_input == 2)
805 {
806 source = sdat & 0xff;
807 sdat >>= 8;
808 }
809 dest = svga->vram[et4000->acl.dest_addr & 0x1fffff];
810 out = 0;
811 if (bltout) pclog("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr);
812 if ((et4000->acl.internal.ctrl_routing & 0xa) == 8)
813 {
814 mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7));
815 if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]);
816 }
817 else
818 {
819 mixdat = mix & 1;
820 mix >>= 1;
821 mix |= 0x80000000;
822 }
824 rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg;
825 for (c = 0; c < 8; c++)
826 {
827 d = (dest & (1 << c)) ? 1 : 0;
828 if (source & (1 << c)) d |= 2;
829 if (pattern & (1 << c)) d |= 4;
830 if (rop & (1 << d)) out |= (1 << c);
831 }
832 if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out);
833 if (!(et4000->acl.internal.ctrl_routing & 0x40))
834 {
835 svga->vram[et4000->acl.dest_addr & 0x1fffff] = out;
836 svga->changedvram[(et4000->acl.dest_addr & 0x1fffff) >> 12] = changeframecount;
837 }
838 else
839 {
840 et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8));
841 et4000->acl.cpu_dat_pos++;
842 }
844 if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000);
845 else et4000w32_incx(1, et4000);
847 et4000->acl.internal.pos_x++;
848 if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x)
849 {
850 if (et4000->acl.internal.xy_dir & 2)
851 {
852 et4000w32_decy(et4000);
853 et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1);
854 et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1);
855 }
856 else
857 {
858 et4000w32_incy(et4000);
859 et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1;
860 et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1;
861 }
863 et4000->acl.pattern_x = et4000->acl.pattern_x_back;
864 et4000->acl.source_x = et4000->acl.source_x_back;
866 et4000->acl.internal.pos_y++;
867 et4000->acl.internal.pos_x = 0;
868 if (et4000->acl.internal.pos_y > et4000->acl.internal.count_y)
869 {
870 et4000->acl.status &= ~(ACL_XYST | ACL_SSO);
871 // pclog("Blit over\n");
872 return;
873 }
874 if (cpu_input) return;
875 if (et4000->acl.internal.ctrl_routing & 0x40)
876 {
877 if (et4000->acl.cpu_dat_pos & 3)
878 et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3);
879 return;
880 }
881 }
882 }
883 }
884 }
887 void et4000w32p_hwcursor_draw(svga_t *svga, int displine)
888 {
889 int x, offset;
890 uint8_t dat;
891 offset = svga->hwcursor_latch.xoff;
892 for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4)
893 {
894 dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)];
895 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 32] = (dat & 1) ? 0xFFFFFF : 0;
896 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 32] ^= 0xFFFFFF;
897 dat >>= 2;
898 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 33] = (dat & 1) ? 0xFFFFFF : 0;
899 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 33] ^= 0xFFFFFF;
900 dat >>= 2;
901 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 34] = (dat & 1) ? 0xFFFFFF : 0;
902 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 34] ^= 0xFFFFFF;
903 dat >>= 2;
904 if (!(dat & 2)) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 35] = (dat & 1) ? 0xFFFFFF : 0;
905 else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga->hwcursor_latch.x + x + 35] ^= 0xFFFFFF;
906 dat >>= 2;
907 offset += 4;
908 }
909 svga->hwcursor_latch.addr += 16;
910 }
912 static void et4000w32p_io_remove(et4000w32p_t *et4000)
913 {
914 io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
916 io_removehandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
917 io_removehandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
918 io_removehandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
919 io_removehandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
920 io_removehandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
921 io_removehandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
922 io_removehandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
923 io_removehandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
924 }
926 static void et4000w32p_io_set(et4000w32p_t *et4000)
927 {
928 et4000w32p_io_remove(et4000);
930 io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
932 io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
933 io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
934 io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
935 io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
936 io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
937 io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
938 io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
939 io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);
940 }
942 uint8_t et4000w32p_pci_read(int func, int addr, void *p)
943 {
944 et4000w32p_t *et4000 = (et4000w32p_t *)p;
945 svga_t *svga = &et4000->svga;
947 // pclog("ET4000 PCI read %08X\n", addr);
949 switch (addr)
950 {
951 case 0x00: return 0x0c; /*Tseng Labs*/
952 case 0x01: return 0x10;
954 case 0x02: return 0x06; /*ET4000W32p Rev D*/
955 case 0x03: return 0x32;
957 case PCI_REG_COMMAND:
958 return et4000->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
960 case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
962 case 0x08: return 0; /*Revision ID*/
963 case 0x09: return 0; /*Programming interface*/
965 case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
966 case 0x0b: return 0x03;
968 case 0x10: return 0x00; /*Linear frame buffer address*/
969 case 0x11: return 0x00;
970 case 0x12: return svga->crtc[0x5a] & 0x80;
971 case 0x13: return svga->crtc[0x59];
973 case 0x30: return et4000->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
974 case 0x31: return 0x00;
975 case 0x32: return et4000->pci_regs[0x32];
976 case 0x33: return et4000->pci_regs[0x33];
977 }
978 return 0;
979 }
981 void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p)
982 {
983 et4000w32p_t *et4000 = (et4000w32p_t *)p;
985 switch (addr)
986 {
987 case PCI_REG_COMMAND:
988 et4000->pci_regs[PCI_REG_COMMAND] = val & 0x27;
989 if (val & PCI_COMMAND_IO)
990 et4000w32p_io_set(et4000);
991 else
992 et4000w32p_io_remove(et4000);
993 et4000w32p_recalcmapping(et4000);
994 break;
996 case 0x13:
997 et4000->linearbase = val << 24;
998 et4000w32p_recalcmapping(et4000);
999 break;
1001 case 0x30: case 0x32: case 0x33:
1002 et4000->pci_regs[addr] = val;
1003 if (et4000->pci_regs[0x30] & 0x01)
1005 uint32_t addr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24);
1006 pclog("ET4000 bios_rom enabled at %08x\n", addr);
1007 mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000);
1009 else
1011 pclog("ET4000 bios_rom disabled\n");
1012 mem_mapping_disable(&et4000->bios_rom.mapping);
1014 return;
1018 void *et4000w32p_init()
1020 int vram_size;
1021 et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t));
1022 memset(et4000, 0, sizeof(et4000w32p_t));
1024 vram_size = device_get_config_int("memory");
1026 et4000->interleaved = (vram_size == 2) ? 1 : 0;
1028 svga_init(&et4000->svga, et4000, vram_size << 20,
1029 et4000w32p_recalctimings,
1030 et4000w32p_in, et4000w32p_out,
1031 et4000w32p_hwcursor_draw,
1032 NULL);
1034 rom_init(&et4000->bios_rom, "roms/et4000w32.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
1035 if (PCI)
1036 mem_mapping_disable(&et4000->bios_rom.mapping);
1038 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);
1039 mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, 0, et4000);
1041 et4000w32p_io_set(et4000);
1043 pci_add(et4000w32p_pci_read, et4000w32p_pci_write, et4000);
1045 et4000->pci_regs[0x04] = 7;
1047 et4000->pci_regs[0x30] = 0x00;
1048 et4000->pci_regs[0x32] = 0x0c;
1049 et4000->pci_regs[0x33] = 0x00;
1051 return et4000;
1054 int et4000w32p_available()
1056 return rom_present("roms/et4000w32.bin");
1059 void et4000w32p_close(void *p)
1061 et4000w32p_t *et4000 = (et4000w32p_t *)p;
1063 svga_close(&et4000->svga);
1065 free(et4000);
1068 void et4000w32p_speed_changed(void *p)
1070 et4000w32p_t *et4000 = (et4000w32p_t *)p;
1072 svga_recalctimings(&et4000->svga);
1075 void et4000w32p_force_redraw(void *p)
1077 et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
1079 et4000w32p->svga.fullchange = changeframecount;
1082 void et4000w32p_add_status_info(char *s, int max_len, void *p)
1084 et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
1086 svga_add_status_info(s, max_len, &et4000w32p->svga);
1089 static device_config_t et4000w32p_config[] =
1092 .name = "memory",
1093 .description = "Memory size",
1094 .type = CONFIG_SELECTION,
1095 .selection =
1098 .description = "1 MB",
1099 .value = 1
1100 },
1102 .description = "2 MB",
1103 .value = 2
1104 },
1106 .description = ""
1108 },
1109 .default_int = 2
1110 },
1112 .type = -1
1114 };
1116 device_t et4000w32p_device =
1118 "Tseng Labs ET4000/w32p",
1119 0,
1120 et4000w32p_init,
1121 et4000w32p_close,
1122 et4000w32p_available,
1123 et4000w32p_speed_changed,
1124 et4000w32p_force_redraw,
1125 et4000w32p_add_status_info,
1126 et4000w32p_config
1127 };