1 /*Trident TGUI9400CXi & TGUI9440 emulation*/
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5 #include "io.h"
6 #include "mem.h"
7 #include "pci.h"
8 #include "rom.h"
9 #include "thread.h"
10 #include "video.h"
11 #include "vid_svga.h"
12 #include "vid_svga_render.h"
13 #include "vid_tkd8001_ramdac.h"
14 #include "vid_tgui9440.h"
15 
16 /*TGUI9400CXi has extended write modes, controlled by extended GDC registers :
17 
18   GDC[0x10] - Control
19         bit 0 - pixel width (1 = 16 bit, 0 = 8 bit)
20         bit 1 - mono->colour expansion (1 = enabled, 0 = disabled)
21         bit 2 - mono->colour expansion transparency (1 = tranparent, 0 = opaque)
22         bit 3 - extended latch copy
23   GDC[0x11] - Background colour (low byte)
24   GDC[0x12] - Background colour (high byte)
25   GDC[0x14] - Foreground colour (low byte)
26   GDC[0x15] - Foreground colour (high byte)
27   GDC[0x17] - Write mask (low byte)
28   GDC[0x18] - Write mask (high byte)
29 
30   Mono->colour expansion will expand written data 8:1 to 8/16 consecutive bytes.
31   MSB is processed first. On word writes, low byte is processed first. 1 bits write
32   foreground colour, 0 bits write background colour unless transparency is enabled.
33   If the relevant bit is clear in the write mask then the data is not written.
34 
35   With 16-bit pixel width, each bit still expands to one byte, so the TGUI driver
36   doubles up monochrome data.
37 
38   While there is room in the register map for three byte colours, I don't believe
39   24-bit colour is supported. The TGUI9440 blitter has the same limitation.
40 
41   I don't think double word writes are supported.
42 
43   Extended latch copy uses an internal 16 byte latch. Reads load the latch, writing
44   writes out 16 bytes. I don't think the access size or host data has any affect,
45   but the Windows 3.1 driver always reads bytes and write words of 0xffff.*/
46 
47 #define EXT_CTRL_16BIT            0x01
48 #define EXT_CTRL_MONO_EXPANSION   0x02
49 #define EXT_CTRL_MONO_TRANSPARENT 0x04
50 #define EXT_CTRL_LATCH_COPY       0x08
51 
52 #define FIFO_SIZE 65536
53 #define FIFO_MASK (FIFO_SIZE - 1)
54 #define FIFO_ENTRY_SIZE (1 << 31)
55 
56 #define FIFO_ENTRIES (tgui->fifo_write_idx - tgui->fifo_read_idx)
57 #define FIFO_FULL    ((tgui->fifo_write_idx - tgui->fifo_read_idx) >= FIFO_SIZE)
58 #define FIFO_EMPTY   (tgui->fifo_read_idx == tgui->fifo_write_idx)
59 
60 #define FIFO_TYPE 0xff000000
61 #define FIFO_ADDR 0x00ffffff
62 
63 enum
64 {
65         TGUI_9400CXI = 0,
66         TGUI_9440
67 };
68 
69 enum
70 {
71         FIFO_INVALID       = (0x00 << 24),
72         FIFO_WRITE_BYTE    = (0x01 << 24),
73         FIFO_WRITE_FB_BYTE = (0x04 << 24),
74         FIFO_WRITE_FB_WORD = (0x05 << 24),
75         FIFO_WRITE_FB_LONG = (0x06 << 24)
76 };
77 
78 typedef struct
79 {
80         uint32_t addr_type;
81         uint32_t val;
82 } fifo_entry_t;
83 
84 typedef struct tgui_t
85 {
86         mem_mapping_t linear_mapping;
87         mem_mapping_t accel_mapping;
88 
89         rom_t bios_rom;
90 
91         svga_t svga;
92 
93         tkd8001_ramdac_t ramdac; /*TGUI9400CXi*/
94 
95         int type;
96 
97         struct
98         {
99         	uint16_t src_x, src_y;
100         	uint16_t dst_x, dst_y;
101         	uint16_t size_x, size_y;
102         	uint16_t fg_col, bg_col;
103         	uint8_t rop;
104         	uint16_t flags;
105         	uint8_t pattern[0x80];
106         	int command;
107         	int offset;
108         	uint8_t ger22;
109 
110         	int x, y;
111         	uint32_t src, dst, src_old, dst_old;
112         	int pat_x, pat_y;
113         	int use_src;
114 
115         	int pitch, bpp;
116 
117                 uint16_t tgui_pattern[8][8];
118         } accel;
119 
120         uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/
121         uint8_t copy_latch[16];
122 
123         uint8_t tgui_3d8, tgui_3d9;
124         int oldmode;
125         uint8_t oldctrl1;
126         uint8_t oldctrl2,newctrl2;
127 
128         uint32_t linear_base, linear_size;
129 
130         int ramdac_state;
131         uint8_t ramdac_ctrl;
132 
133         int clock_m, clock_n, clock_k;
134 
135         uint32_t vram_size, vram_mask;
136 
137         fifo_entry_t fifo[FIFO_SIZE];
138         volatile int fifo_read_idx, fifo_write_idx;
139 
140         thread_t *fifo_thread;
141         event_t *wake_fifo_thread;
142         event_t *fifo_not_full_event;
143 
144         int blitter_busy;
145         uint64_t blitter_time;
146         uint64_t status_time;
147 
148         volatile int write_blitter;
149 } tgui_t;
150 
151 void tgui_recalcmapping(tgui_t *tgui);
152 
153 static void fifo_thread(void *param);
154 
155 uint8_t tgui_accel_read(uint32_t addr, void *priv);
156 uint16_t tgui_accel_read_w(uint32_t addr, void *priv);
157 uint32_t tgui_accel_read_l(uint32_t addr, void *priv);
158 
159 void tgui_accel_write(uint32_t addr, uint8_t val, void *priv);
160 void tgui_accel_write_w(uint32_t addr, uint16_t val, void *priv);
161 void tgui_accel_write_l(uint32_t addr, uint32_t val, void *priv);
162 
163 void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv);
164 void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv);
165 void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv);
166 
167 static uint8_t tgui_ext_linear_read(uint32_t addr, void *p);
168 static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p);
169 static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p);
170 static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p);
171 
172 static uint8_t tgui_ext_read(uint32_t addr, void *p);
173 static void tgui_ext_write(uint32_t addr, uint8_t val, void *p);
174 static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p);
175 static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p);
176 
tgui_out(uint16_t addr,uint8_t val,void * p)177 void tgui_out(uint16_t addr, uint8_t val, void *p)
178 {
179         tgui_t *tgui = (tgui_t *)p;
180         svga_t *svga = &tgui->svga;
181 
182         uint8_t old;
183 
184 //	pclog("tgui_out : %04X %02X  %04X:%04X  %i\n", addr, val, CS,pc, svga->bpp);
185         if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60;
186 
187         switch (addr)
188         {
189                 case 0x3C5:
190                 switch (svga->seqaddr & 0xf)
191                 {
192                         case 0xB:
193                         tgui->oldmode=1;
194                         break;
195                         case 0xC:
196                         if (svga->seqregs[0xe] & 0x80)
197                         svga->seqregs[0xc] = val;
198                         break;
199                         case 0xd:
200                         if (tgui->oldmode)
201                                 tgui->oldctrl2 = val;
202                         else
203                                 tgui->newctrl2=val;
204                         break;
205                         case 0xE:
206                         if (tgui->oldmode)
207                                 tgui->oldctrl1 = val;
208                         else
209                         {
210                                 svga->seqregs[0xe] = val ^ 2;
211                                 svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536;
212                                 if (!(svga->gdcreg[0xf] & 1))
213                                         svga->read_bank = svga->write_bank;
214                         }
215                         return;
216                 }
217                 break;
218 
219                 case 0x3C6:
220                 if (tgui->type == TGUI_9400CXI)
221                 {
222                         tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga);
223                         return;
224                 }
225                 if (tgui->ramdac_state == 4)
226                 {
227                         tgui->ramdac_state = 0;
228                         tgui->ramdac_ctrl = val;
229                         switch (tgui->ramdac_ctrl & 0xf0)
230                         {
231                                 case 0x10:
232                                 svga->bpp = 15;
233                                 break;
234                                 case 0x30:
235                                 svga->bpp = 16;
236                                 break;
237                                 case 0xd0:
238                                 svga->bpp = 24;
239                                 break;
240                                 default:
241                                 svga->bpp = 8;
242                                 break;
243                         }
244                         return;
245                 }
246                 case 0x3C7: case 0x3C8: case 0x3C9:
247                 if (tgui->type == TGUI_9400CXI)
248                 {
249                         tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga);
250                         return;
251                 }
252                 tgui->ramdac_state = 0;
253 		break;
254 
255                 case 0x3CF:
256                 if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32)
257                 {
258                         old = tgui->ext_gdc_regs[svga->gdcaddr & 15];
259                         tgui->ext_gdc_regs[svga->gdcaddr & 15] = val;
260                         if (svga->gdcaddr == 16)
261 				tgui_recalcmapping(tgui);
262                         return;
263                 }
264                 switch (svga->gdcaddr & 15)
265                 {
266 			case 0x6:
267 			if (svga->gdcreg[6] != val)
268 			{
269 				svga->gdcreg[6] = val;
270 				tgui_recalcmapping(tgui);
271 			}
272 			return;
273 
274                         case 0xE:
275                         svga->gdcreg[0xe] = val ^ 2;
276                         if ((svga->gdcreg[0xf] & 1) == 1)
277                            svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536;
278                         break;
279                         case 0xF:
280                         if (val & 1) svga->read_bank = (svga->gdcreg[0xe]  & 0xf)  *65536;
281                         else         svga->read_bank = (svga->seqregs[0xe] & 0xf)  *65536;
282                         svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536;
283                         break;
284                 }
285                 break;
286                 case 0x3D4:
287 		svga->crtcreg = val & 0x7f;
288                 return;
289                 case 0x3D5:
290                 if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
291                         return;
292                 if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
293                         val = (svga->crtc[7] & ~0x10) | (val & 0x10);
294                 old = svga->crtc[svga->crtcreg];
295                 svga->crtc[svga->crtcreg] = val;
296 //                if (svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X\n", svga->crtcreg, val);
297                 if (old != val)
298                 {
299                         if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
300                         {
301                                 svga->fullchange = changeframecount;
302                                 svga_recalctimings(svga);
303                         }
304                 }
305                 switch (svga->crtcreg)
306                 {
307 			case 0x21:
308 			if (old != val)
309 			{
310                                 if (!PCI)
311                                 {
312                                         tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20;
313                                         tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000;
314                                         tgui->svga.decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff;
315                                 }
316         			tgui_recalcmapping(tgui);
317                         }
318 			break;
319 
320 			case 0x40: case 0x41: case 0x42: case 0x43:
321 			case 0x44: case 0x45: case 0x46: case 0x47:
322                         if (tgui->type >= TGUI_9440)
323                         {
324         			svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff;
325         			svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff;
326         			svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f;
327         			svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f;
328         			svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x7) << 18) | (svga->hwcursor.yoff * 8);
329                         }
330 			break;
331 
332 			case 0x50:
333                         if (tgui->type >= TGUI_9440)
334                         {
335         			svga->hwcursor.ena = val & 0x80;
336         			svga->hwcursor.xsize = (val & 1) ? 64 : 32;
337         			svga->hwcursor.ysize = (val & 1) ? 64 : 32;
338                         }
339 			break;
340 		}
341                 return;
342                 case 0x3D8:
343                 tgui->tgui_3d8 = val;
344                 if (svga->gdcreg[0xf] & 4)
345                 {
346                         svga->write_bank = (val & 0x1f) * 65536;
347 //                                pclog("SVGAWBANK 3D8 %08X %04X:%04X\n",svgawbank,CS,pc);
348                         if (!(svga->gdcreg[0xf] & 1))
349                         {
350                                 svga->read_bank = (val & 0x1f) * 65536;
351 //                                        pclog("SVGARBANK 3D8 %08X %04X:%04X\n",svgarbank,CS,pc);
352                         }
353                 }
354                 return;
355                 case 0x3D9:
356                 tgui->tgui_3d9 = val;
357                 if ((svga->gdcreg[0xf] & 5) == 5)
358                 {
359                         svga->read_bank = (val & 0x1F) * 65536;
360 //                                pclog("SVGARBANK 3D9 %08X %04X:%04X\n",svgarbank,CS,pc);
361                 }
362                 return;
363 
364                 case 0x43c8:
365                 tgui->clock_n = val & 0x7f;
366                 tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7);
367                 break;
368                 case 0x43c9:
369                 tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e);
370                 tgui->clock_k = (val & 0x10) >> 4;
371                 break;
372         }
373         svga_out(addr, val, svga);
374 }
375 
tgui_in(uint16_t addr,void * p)376 uint8_t tgui_in(uint16_t addr, void *p)
377 {
378         tgui_t *tgui = (tgui_t *)p;
379         svga_t *svga = &tgui->svga;
380 
381 //        if (addr != 0x3da) pclog("tgui_in : %04X  %04X:%04X\n", addr, CS,pc);
382 
383         if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60;
384 
385         switch (addr)
386         {
387                 case 0x3C5:
388                 if ((svga->seqaddr & 0xf) == 0xb)
389                 {
390 //                        printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
391                         tgui->oldmode = 0;
392                         switch (tgui->type)
393                         {
394                                 case TGUI_9400CXI:
395                                 return 0x93; /*TGUI9400CXi*/
396                                 case TGUI_9440:
397                                 return 0xe3; /*TGUI9440AGi*/
398                         }
399                 }
400                 if ((svga->seqaddr & 0xf) == 0xc)
401                 {
402 //                        printf("Read Trident Power Up 1 %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
403 //                        return 0x20; /*2 DRAM banks*/
404                 }
405                 if ((svga->seqaddr & 0xf) == 0xd)
406                 {
407                         if (tgui->oldmode)
408                                 return tgui->oldctrl2;
409                         return tgui->newctrl2;
410                 }
411                 if ((svga->seqaddr & 0xf) == 0xe)
412                 {
413                         if (tgui->oldmode)
414                                 return tgui->oldctrl1;
415                 }
416                 break;
417                 case 0x3C6:
418                 if (tgui->type == TGUI_9400CXI)
419                         return tkd8001_ramdac_in(addr, &tgui->ramdac, svga);
420                 if (tgui->ramdac_state == 4)
421                         return tgui->ramdac_ctrl;
422                 tgui->ramdac_state++;
423                 break;
424                 case 0x3C7: case 0x3C8: case 0x3C9:
425                 if (tgui->type == TGUI_9400CXI)
426                         return tkd8001_ramdac_in(addr, &tgui->ramdac, svga);
427                 tgui->ramdac_state = 0;
428                 break;
429                 case 0x3CF:
430                 if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32)
431                         return tgui->ext_gdc_regs[svga->gdcaddr & 15];
432                 break;
433                 case 0x3D4:
434                 return svga->crtcreg;
435                 case 0x3D5:
436                 return svga->crtc[svga->crtcreg];
437                 case 0x3d8:
438 		return tgui->tgui_3d8;
439 		case 0x3d9:
440 		return tgui->tgui_3d9;
441         }
442         return svga_in(addr, svga);
443 }
444 
tgui_recalctimings(svga_t * svga)445 void tgui_recalctimings(svga_t *svga)
446 {
447         tgui_t *tgui = (tgui_t *)svga->p;
448 
449         if (svga->crtc[0x29] & 0x10)
450                 svga->rowoffset += 0x100;
451 
452         if (tgui->type >= TGUI_9440 && svga->bpp == 24)
453                 svga->hdisp = (svga->crtc[1] + 1) * 8;
454 
455         if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000;
456         if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000;
457         if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000;
458 
459         if (tgui->oldctrl2 & 0x10)
460                 svga->rowoffset <<= 1;
461         if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40))
462                 svga->ma_latch <<= 1;
463 
464         if (tgui->oldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/
465            svga->lowres=0;
466 
467 	svga->lowres = !(svga->crtc[0x2a] & 0x40);
468 
469         svga->interlace = svga->crtc[0x1e] & 4;
470         if (svga->interlace && tgui->type < TGUI_9440)
471                 svga->rowoffset >>= 1;
472 
473         if (svga->crtc[0x17] & 4)
474         {
475                 svga->vtotal *= 2;
476                 svga->dispend *= 2;
477                 svga->vsyncstart *= 2;
478                 svga->split *= 2;
479                 svga->vblankstart *= 2;
480         }
481 
482         if (tgui->type >= TGUI_9440)
483         {
484                 if (svga->miscout & 8)
485                         svga->clock = cpuclock / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k)));
486 
487                 if (svga->gdcreg[0xf] & 0x08)
488                         svga->clock *= 2;
489                 else if (svga->gdcreg[0xf] & 0x40)
490                         svga->clock *= 3;
491         }
492         else
493         {
494                 switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8))
495                 {
496                         case 0x02: svga->clock = cpuclock/ 44900000.0; break;
497                         case 0x03: svga->clock = cpuclock/ 36000000.0; break;
498                         case 0x04: svga->clock = cpuclock/ 57272000.0; break;
499                         case 0x05: svga->clock = cpuclock/ 65000000.0; break;
500                         case 0x06: svga->clock = cpuclock/ 50350000.0; break;
501                         case 0x07: svga->clock = cpuclock/ 40000000.0; break;
502                         case 0x08: svga->clock = cpuclock/ 88000000.0; break;
503                         case 0x09: svga->clock = cpuclock/ 98000000.0; break;
504                         case 0x0a: svga->clock = cpuclock/118800000.0; break;
505                         case 0x0b: svga->clock = cpuclock/108000000.0; break;
506                         case 0x0c: svga->clock = cpuclock/ 72000000.0; break;
507                         case 0x0d: svga->clock = cpuclock/ 77000000.0; break;
508                         case 0x0e: svga->clock = cpuclock/ 80000000.0; break;
509                         case 0x0f: svga->clock = cpuclock/ 75000000.0; break;
510                 }
511                 if (svga->gdcreg[0xf] & 0x08)
512                 {
513                         svga->htotal *= 2;
514                         svga->hdisp *= 2;
515                         svga->hdisp_time *= 2;
516                 }
517         }
518 
519         if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40))
520         {
521                 switch (svga->bpp)
522                 {
523                         case 8:
524                         svga->render = svga_render_8bpp_highres;
525                         break;
526                         case 15:
527                         svga->render = svga_render_15bpp_highres;
528                         if (tgui->type < TGUI_9440)
529                                 svga->hdisp /= 2;
530                         break;
531                         case 16:
532                         svga->render = svga_render_16bpp_highres;
533                         if (tgui->type < TGUI_9440)
534                                 svga->hdisp /= 2;
535                         break;
536                         case 24:
537                         svga->render = svga_render_24bpp_highres;
538                         if (tgui->type < TGUI_9440)
539                                 svga->hdisp = (svga->hdisp * 2) / 3;
540                         break;
541                 }
542         }
543 }
544 
tgui_recalcmapping(tgui_t * tgui)545 void tgui_recalcmapping(tgui_t *tgui)
546 {
547         svga_t *svga = &tgui->svga;
548 
549 //	pclog("tgui_recalcmapping : %02X %02X\n", svga->crtc[0x21], svga->gdcreg[6]);
550 
551         if (tgui->type == TGUI_9400CXI)
552         {
553                 if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY)
554                 {
555                         mem_mapping_set_handler(&tgui->linear_mapping,
556                                         tgui_ext_linear_read, NULL, NULL,
557                                         tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel);
558                         mem_mapping_set_handler(&svga->mapping,
559                                         tgui_ext_read, NULL, NULL,
560                                         tgui_ext_write, tgui_ext_writew, tgui_ext_writel);
561                 }
562                 else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION)
563                 {
564                         mem_mapping_set_handler(&tgui->linear_mapping,
565                                         svga_read_linear, svga_readw_linear, svga_readl_linear,
566                                         tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel);
567                         mem_mapping_set_handler(&svga->mapping,
568                                         svga_read, svga_readw, svga_readl,
569                                         tgui_ext_write, tgui_ext_writew, tgui_ext_writel);
570                 }
571                 else
572                 {
573                         mem_mapping_set_handler(&tgui->linear_mapping,
574                                         svga_read_linear,  svga_readw_linear,  svga_readl_linear,
575                                         svga_write_linear, svga_writew_linear, svga_writel_linear);
576                         mem_mapping_set_handler(&svga->mapping,
577                                         svga_read, svga_readw, svga_readl,
578                                         svga_write, svga_writew, svga_writel);
579                 }
580         }
581 
582 	if (svga->crtc[0x21] & 0x20)
583 	{
584                 mem_mapping_disable(&svga->mapping);
585                 mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size);
586 //		pclog("Trident linear framebuffer at %08X - size %06X\n", tgui->linear_base, tgui->linear_size);
587                 if (tgui->type >= TGUI_9440)
588                 {
589                         mem_mapping_enable(&tgui->accel_mapping);
590                         mem_mapping_disable(&svga->mapping);
591                 }
592                 else
593                 {
594                         switch (svga->gdcreg[6] & 0xC)
595                         {
596                                 case 0x0: /*128k at A0000*/
597                                 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
598                                 svga->banked_mask = 0xffff;
599                                 break;
600                                 case 0x4: /*64k at A0000*/
601                                 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
602                                 svga->banked_mask = 0xffff;
603                                 break;
604                                 case 0x8: /*32k at B0000*/
605                                 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
606                                 svga->banked_mask = 0x7fff;
607                                 break;
608                                 case 0xC: /*32k at B8000*/
609                                 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
610                                 svga->banked_mask = 0x7fff;
611                                 break;
612         		}
613                 }
614 	}
615 	else
616 	{
617 //                                pclog("Write mapping %02X\n", val);
618                 mem_mapping_disable(&tgui->linear_mapping);
619                 mem_mapping_disable(&tgui->accel_mapping);
620                 switch (svga->gdcreg[6] & 0xC)
621                 {
622                         case 0x0: /*128k at A0000*/
623                         mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
624                         svga->banked_mask = 0xffff;
625                         break;
626                         case 0x4: /*64k at A0000*/
627                         mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
628                         mem_mapping_enable(&tgui->accel_mapping);
629                         svga->banked_mask = 0xffff;
630                         break;
631                         case 0x8: /*32k at B0000*/
632                         mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
633                         svga->banked_mask = 0x7fff;
634                         break;
635                         case 0xC: /*32k at B8000*/
636                         mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
637                         svga->banked_mask = 0x7fff;
638                         break;
639 		}
640         }
641 }
642 
tgui_hwcursor_draw(svga_t * svga,int displine)643 void tgui_hwcursor_draw(svga_t *svga, int displine)
644 {
645         uint32_t dat[2];
646         int xx;
647         int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
648 
649         if (svga->interlace && svga->hwcursor_oddeven)
650                 svga->hwcursor_latch.addr += 8;
651 
652         dat[0] = (svga->vram[svga->hwcursor_latch.addr]     << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
653         dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7];
654         for (xx = 0; xx < 32; xx++)
655         {
656                 if (offset >= svga->hwcursor_latch.x)
657                 {
658                         if (!(dat[0] & 0x80000000))
659                                 ((uint32_t *)buffer32->line[displine])[offset + 32]  = (dat[1] & 0x80000000) ? 0xffffff : 0;
660                         else if (dat[1] & 0x80000000)
661                                 ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
662 //                        pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
663                 }
664 
665                 offset++;
666                 dat[0] <<= 1;
667                 dat[1] <<= 1;
668         }
669         svga->hwcursor_latch.addr += 8;
670 
671         if (svga->interlace && !svga->hwcursor_oddeven)
672                 svga->hwcursor_latch.addr += 8;
673 }
674 
tgui_pci_read(int func,int addr,void * p)675 uint8_t tgui_pci_read(int func, int addr, void *p)
676 {
677         tgui_t *tgui = (tgui_t *)p;
678 
679 //        pclog("Trident PCI read %08X\n", addr);
680 
681         switch (addr)
682         {
683                 case 0x00: return 0x23; /*Trident*/
684                 case 0x01: return 0x10;
685 
686                 case 0x02: return 0x40; /*TGUI9440 (9682)*/
687                 case 0x03: return 0x94;
688 
689                 case 0x04: return 0x03; /*Respond to IO and memory accesses*/
690 
691                 case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
692 
693                 case 0x08: return 0; /*Revision ID*/
694                 case 0x09: return 0; /*Programming interface*/
695 
696                 case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
697                 case 0x0b: return 0x03;
698 
699                 case 0x10: return 0x00; /*Linear frame buffer address*/
700                 case 0x11: return 0x00;
701                 case 0x12: return tgui->linear_base >> 16;
702                 case 0x13: return tgui->linear_base >> 24;
703 
704                 case 0x30: return 0x01; /*BIOS ROM address*/
705                 case 0x31: return 0x00;
706                 case 0x32: return 0x0C;
707                 case 0x33: return 0x00;
708         }
709         return 0;
710 }
711 
tgui_pci_write(int func,int addr,uint8_t val,void * p)712 void tgui_pci_write(int func, int addr, uint8_t val, void *p)
713 {
714         tgui_t *tgui = (tgui_t *)p;
715         svga_t *svga = &tgui->svga;
716 
717 //        pclog("Trident PCI write %08X %02X\n", addr, val);
718 
719         switch (addr)
720         {
721                 case 0x12:
722                 tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16);
723                 tgui->linear_size = 2 << 20;
724                 tgui->svga.decode_mask = 0x1fffff;
725                 svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4);
726                 tgui_recalcmapping(tgui);
727                 break;
728                 case 0x13:
729                 tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24);
730                 tgui->linear_size = 2 << 20;
731                 tgui->svga.decode_mask = 0x1fffff;
732                 svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6);
733                 tgui_recalcmapping(tgui);
734                 break;
735         }
736 }
737 
tgui_init(char * bios_fn,int type,int mem_size)738 static void *tgui_init(char *bios_fn, int type, int mem_size)
739 {
740         tgui_t *tgui = malloc(sizeof(tgui_t));
741         memset(tgui, 0, sizeof(tgui_t));
742 
743         if (mem_size)
744                 tgui->vram_size = mem_size;
745         else
746                 tgui->vram_size = device_get_config_int("memory") << 20;
747         tgui->vram_mask = tgui->vram_size - 1;
748 
749         tgui->type = type;
750 
751         rom_init(&tgui->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
752 
753         svga_init(&tgui->svga, tgui, tgui->vram_size,
754                    tgui_recalctimings,
755                    tgui_in, tgui_out,
756                    tgui_hwcursor_draw,
757                    NULL);
758 
759         mem_mapping_add(&tgui->linear_mapping, 0,       0,      svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, 0, &tgui->svga);
760         mem_mapping_add(&tgui->accel_mapping,  0xbc000, 0x4000, tgui_accel_read,  tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write,  tgui_accel_write_w, tgui_accel_write_l, NULL, 0,  tgui);
761         mem_mapping_disable(&tgui->accel_mapping);
762 
763         io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui);
764         if (tgui->type >= TGUI_9440)
765                 io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui);
766 
767         if (tgui->type >= TGUI_9440)
768                 pci_add(tgui_pci_read, tgui_pci_write, tgui);
769 
770         tgui->wake_fifo_thread = thread_create_event();
771         tgui->fifo_not_full_event = thread_create_event();
772         tgui->fifo_thread = thread_create(fifo_thread, tgui);
773 
774         return tgui;
775 }
776 
tgui9400cxi_init()777 static void *tgui9400cxi_init()
778 {
779         return tgui_init("9400CXI.vbi", TGUI_9400CXI, 0);
780 }
781 
tgui9400cxi_elx_init()782 static void *tgui9400cxi_elx_init()
783 {
784         /*Try combined ROM dump first. If not present, use seperated dump*/
785         FILE *f = romfopen("elx_pc425x/elx_pc425x.bin", "rb");
786         if (f)
787         {
788                 fclose(f);
789                 return tgui_init("elx_pc425x/elx_pc425x.bin", TGUI_9400CXI, 512 << 10);
790         }
791 
792         return tgui_init("elx_pc425x/elx_pc425x_vbios.bin", TGUI_9400CXI, 512 << 10);
793 }
794 
tgui9440_init()795 static void *tgui9440_init()
796 {
797         return tgui_init("9440.vbi", TGUI_9440, 0);
798 }
799 
tgui9400cxi_available()800 static int tgui9400cxi_available()
801 {
802         return rom_present("9400CXI.vbi");
803 }
804 
tgui9440_available()805 static int tgui9440_available()
806 {
807         return rom_present("9440.vbi");
808 }
809 
tgui_close(void * p)810 void tgui_close(void *p)
811 {
812         tgui_t *tgui = (tgui_t *)p;
813 
814         svga_close(&tgui->svga);
815 
816         thread_kill(tgui->fifo_thread);
817         thread_destroy_event(tgui->wake_fifo_thread);
818         thread_destroy_event(tgui->fifo_not_full_event);
819 
820         free(tgui);
821 }
822 
tgui_speed_changed(void * p)823 void tgui_speed_changed(void *p)
824 {
825         tgui_t *tgui = (tgui_t *)p;
826 
827         svga_recalctimings(&tgui->svga);
828 }
829 
tgui_force_redraw(void * p)830 void tgui_force_redraw(void *p)
831 {
832         tgui_t *tgui = (tgui_t *)p;
833 
834         tgui->svga.fullchange = changeframecount;
835 }
836 
837 
tgui_ext_linear_read(uint32_t addr,void * p)838 static uint8_t tgui_ext_linear_read(uint32_t addr, void *p)
839 {
840         svga_t *svga = (svga_t *)p;
841         tgui_t *tgui = (tgui_t *)svga->p;
842         int c;
843 
844         cycles -= video_timing_read_b;
845         cycles_lost += video_timing_read_b;
846 
847         addr &= svga->decode_mask;
848         if (addr >= svga->vram_max)
849                 return 0xff;
850 
851         addr &= ~0xf;
852         for (c = 0; c < 16; c++)
853                 tgui->copy_latch[c] = svga->vram[addr+c];
854 
855         return svga->vram[addr & svga->vram_mask];
856 }
857 
tgui_ext_read(uint32_t addr,void * p)858 static uint8_t tgui_ext_read(uint32_t addr, void *p)
859 {
860         svga_t *svga = (svga_t *)p;
861 
862         addr = (addr & svga->banked_mask) + svga->read_bank;
863 
864         return tgui_ext_linear_read(addr, svga);
865 }
866 
tgui_ext_linear_write(uint32_t addr,uint8_t val,void * p)867 static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
868 {
869         svga_t *svga = (svga_t *)p;
870         tgui_t *tgui = (tgui_t *)svga->p;
871         int c;
872         uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]};
873         uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]};
874         uint8_t mask = tgui->ext_gdc_regs[7];
875 
876         cycles -= video_timing_write_b;
877         cycles_lost += video_timing_write_b;
878 
879         addr &= svga->decode_mask;
880         if (addr >= svga->vram_max)
881                 return;
882         addr &= svga->vram_mask;
883         addr &= ~0x7;
884         svga->changedvram[addr >> 12] = changeframecount;
885 
886         switch (tgui->ext_gdc_regs[0] & 0xf)
887         {
888                 /*8-bit mono->colour expansion, unmasked*/
889                 case 2:
890                 for (c = 7; c >= 0; c--)
891                 {
892                         if (mask & (1 << c))
893                                 *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
894                         addr++;
895                 }
896                 break;
897 
898                 /*16-bit mono->colour expansion, unmasked*/
899                 case 3:
900                 for (c = 7; c >= 0; c--)
901                 {
902                         if (mask & (1 << c))
903                                 *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
904                         addr++;
905                 }
906                 break;
907 
908                 /*8-bit mono->colour expansion, masked*/
909                 case 6:
910                 for (c = 7; c >= 0; c--)
911                 {
912                         if ((val & mask) & (1 << c))
913                                 *(uint8_t *)&svga->vram[addr] = fg[0];
914                         addr++;
915                 }
916                 break;
917 
918                 /*16-bit mono->colour expansion, masked*/
919                 case 7:
920                 for (c = 7; c >= 0; c--)
921                 {
922                         if ((val & mask) & (1 << c))
923                                 *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
924                         addr++;
925                 }
926                 break;
927 
928                 case 0x8: case 0x9: case 0xa: case 0xb:
929                 case 0xc: case 0xd: case 0xe: case 0xf:
930                 addr &= ~0xf;
931                 for (c = 0; c < 16; c++)
932                         *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
933                 break;
934         }
935 }
936 
tgui_ext_linear_writew(uint32_t addr,uint16_t val,void * p)937 static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
938 {
939         svga_t *svga = (svga_t *)p;
940         tgui_t *tgui = (tgui_t *)svga->p;
941         int c;
942         uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]};
943         uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]};
944         uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8];
945 
946         cycles -= video_timing_write_w;
947         cycles_lost += video_timing_write_w;
948 
949         addr &= svga->decode_mask;
950         if (addr >= svga->vram_max)
951                 return;
952         addr &= svga->vram_mask;
953         addr &= ~0xf;
954         svga->changedvram[addr >> 12] = changeframecount;
955 
956         val = (val >> 8) | (val << 8);
957 
958         switch (tgui->ext_gdc_regs[0] & 0xf)
959         {
960                 /*8-bit mono->colour expansion, unmasked*/
961                 case 2:
962                 for (c = 15; c >= 0; c--)
963                 {
964                         if (mask & (1 << c))
965                                 *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
966                         addr++;
967                 }
968                 break;
969 
970                 /*16-bit mono->colour expansion, unmasked*/
971                 case 3:
972                 for (c = 15; c >= 0; c--)
973                 {
974                         if (mask & (1 << c))
975                                 *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
976                         addr++;
977                 }
978                 break;
979 
980                 /*8-bit mono->colour expansion, masked*/
981                 case 6:
982                 for (c = 15; c >= 0; c--)
983                 {
984                         if ((val & mask) & (1 << c))
985                                 *(uint8_t *)&svga->vram[addr] = fg[0];
986                         addr++;
987                 }
988                 break;
989 
990                 /*16-bit mono->colour expansion, masked*/
991                 case 7:
992                 for (c = 15; c >= 0; c--)
993                 {
994                         if ((val & mask) & (1 << c))
995                                 *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
996                         addr++;
997                 }
998                 break;
999 
1000                 case 0x8: case 0x9: case 0xa: case 0xb:
1001                 case 0xc: case 0xd: case 0xe: case 0xf:
1002                 for (c = 0; c < 16; c++)
1003                         *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
1004                 break;
1005         }
1006 }
1007 
tgui_ext_linear_writel(uint32_t addr,uint32_t val,void * p)1008 static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p)
1009 {
1010         tgui_ext_linear_writew(addr, val, p);
1011 }
1012 
tgui_ext_write(uint32_t addr,uint8_t val,void * p)1013 static void tgui_ext_write(uint32_t addr, uint8_t val, void *p)
1014 {
1015         svga_t *svga = (svga_t *)p;
1016 
1017         addr = (addr & svga->banked_mask) + svga->read_bank;
1018 
1019         tgui_ext_linear_write(addr, val, svga);
1020 }
tgui_ext_writew(uint32_t addr,uint16_t val,void * p)1021 static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p)
1022 {
1023         svga_t *svga = (svga_t *)p;
1024 
1025         addr = (addr & svga->banked_mask) + svga->read_bank;
1026 
1027         tgui_ext_linear_writew(addr, val, svga);
1028 }
tgui_ext_writel(uint32_t addr,uint32_t val,void * p)1029 static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p)
1030 {
1031         svga_t *svga = (svga_t *)p;
1032 
1033         addr = (addr & svga->banked_mask) + svga->read_bank;
1034 
1035         tgui_ext_linear_writel(addr, val, svga);
1036 }
1037 
1038 
1039 enum
1040 {
1041 	TGUI_BITBLT = 1
1042 };
1043 
1044 enum
1045 {
1046         TGUI_SRCCPU = 0,
1047 
1048 	TGUI_SRCDISP = 0x04,	/*Source is from display*/
1049 	TGUI_PATMONO = 0x20,	/*Pattern is monochrome and needs expansion*/
1050 	TGUI_SRCMONO = 0x40,	/*Source is monochrome from CPU and needs expansion*/
1051 	TGUI_TRANSENA  = 0x1000, /*Transparent (no draw when source == bg col)*/
1052 	TGUI_TRANSREV  = 0x2000, /*Reverse fg/bg for transparent*/
1053 	TGUI_SOLIDFILL = 0x4000	/*Pattern all zero?*/
1054 };
1055 
1056 #define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \
1057                         else                     dat = vram_w[addr & 0xfffff];
1058 
1059 #define MIX() do \
1060 	{								\
1061 		out = 0;						\
1062         	for (c=0;c<16;c++)					\
1063 	        {							\
1064 			d=(dst_dat & (1<<c)) ? 1:0;			\
1065                        	if (src_dat & (1<<c)) d|=2;			\
1066                	        if (pat_dat & (1<<c)) d|=4;			\
1067                         if (tgui->accel.rop & (1<<d)) out|=(1<<c);	\
1068 	        }							\
1069 	} while (0)
1070 
1071 #define WRITE(addr, dat)        if (tgui->accel.bpp == 0)                                                \
1072                                 {                                                                       \
1073                                         svga->vram[addr & 0x1fffff] = dat;                                    \
1074                                         svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount;      \
1075                                 }                                                                       \
1076                                 else                                                                    \
1077                                 {                                                                       \
1078                                         vram_w[addr & 0xfffff] = dat;                                   \
1079                                         svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount;        \
1080                                 }
1081 
tgui_accel_command(int count,uint32_t cpu_dat,tgui_t * tgui)1082 void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
1083 {
1084         svga_t *svga = &tgui->svga;
1085 	int x, y;
1086 	int c, d;
1087 	uint16_t src_dat, dst_dat, pat_dat;
1088 	uint16_t out;
1089 	int xdir = (tgui->accel.flags & 0x200) ? -1 : 1;
1090 	int ydir = (tgui->accel.flags & 0x100) ? -1 : 1;
1091 	uint16_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col;
1092         uint16_t *vram_w = (uint16_t *)svga->vram;
1093 
1094 	if (tgui->accel.bpp == 0)
1095                 trans_col &= 0xff;
1096 
1097 	if (count != -1 && !tgui->accel.x && (tgui->accel.flags & TGUI_SRCMONO))
1098 	{
1099 		count -= tgui->accel.offset;
1100 		cpu_dat <<= tgui->accel.offset;
1101 	}
1102 	if (count == -1)
1103 	{
1104 		tgui->accel.x = tgui->accel.y = 0;
1105 	}
1106 	if (tgui->accel.flags & TGUI_SOLIDFILL)
1107 	{
1108 //		pclog("SOLIDFILL\n");
1109 		for (y = 0; y < 8; y++)
1110 		{
1111 			for (x = 0; x < 8; x++)
1112 			{
1113 				tgui->accel.tgui_pattern[y][x] = tgui->accel.fg_col;
1114 			}
1115 		}
1116 	}
1117 	else if (tgui->accel.flags & TGUI_PATMONO)
1118 	{
1119 //		pclog("PATMONO\n");
1120 		for (y = 0; y < 8; y++)
1121 		{
1122 			for (x = 0; x < 8; x++)
1123 			{
1124 				tgui->accel.tgui_pattern[y][x] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col;
1125 			}
1126 		}
1127 	}
1128 	else
1129 	{
1130                 if (tgui->accel.bpp == 0)
1131                 {
1132 //        		pclog("OTHER 8-bit\n");
1133         		for (y = 0; y < 8; y++)
1134         		{
1135         			for (x = 0; x < 8; x++)
1136         			{
1137         				tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x + y*8];
1138         			}
1139                         }
1140 		}
1141 		else
1142                 {
1143 //        		pclog("OTHER 16-bit\n");
1144         		for (y = 0; y < 8; y++)
1145         		{
1146         			for (x = 0; x < 8; x++)
1147         			{
1148         				tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x*2 + y*16] | (tgui->accel.pattern[x*2 + y*16 + 1] << 8);
1149         			}
1150                         }
1151 		}
1152 	}
1153 /*	for (y = 0; y < 8; y++)
1154 	{
1155 		if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tgui->accel.tgui_pattern[y][0], tgui->accel.tgui_pattern[y][1], tgui->accel.tgui_pattern[y][2], tgui->accel.tgui_pattern[y][3], tgui->accel.tgui_pattern[y][4], tgui->accel.tgui_pattern[y][5], tgui->accel.tgui_pattern[y][6], tgui->accel.tgui_pattern[y][7]);
1156 	}*/
1157 //	if (count == -1) pclog("Command %i %i %p\n", tgui->accel.command, TGUI_BITBLT, tgui);
1158         switch (tgui->accel.command)
1159 	{
1160 		case TGUI_BITBLT:
1161 //		if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tgui->accel.src_x, tgui->accel.src_y, tgui->accel.dst_x, tgui->accel.dst_y, tgui->accel.size_x, tgui->accel.size_y, tgui->accel.flags);
1162 		if (count == -1)
1163 		{
1164 			tgui->accel.src = tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch);
1165 			tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch);
1166 			tgui->accel.pat_x = tgui->accel.dst_x;
1167 			tgui->accel.pat_y = tgui->accel.dst_y;
1168 		}
1169 
1170 		switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP))
1171 		{
1172 			case TGUI_SRCCPU:
1173 			if (count == -1)
1174 			{
1175 //				pclog("Blit start  TGUI_SRCCPU\n");
1176 				if (svga->crtc[0x21] & 0x20)
1177 				{
1178                                         tgui->write_blitter = 1;
1179                                 }
1180 				if (tgui->accel.use_src)
1181                                         return;
1182 			}
1183 			else
1184 			     count >>= 3;
1185 //			pclog("TGUI_SRCCPU\n");
1186 			while (count)
1187 			{
1188 				if (tgui->accel.bpp == 0)
1189 				{
1190                                         src_dat = cpu_dat >> 24;
1191                                         cpu_dat <<= 8;
1192                                 }
1193                                 else
1194                                 {
1195                                         src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00);
1196                                         cpu_dat <<= 16;
1197                                         count--;
1198                                 }
1199 				READ(tgui->accel.dst, dst_dat);
1200 				pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7];
1201 
1202                                 if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
1203                                 {
1204         				MIX();
1205 
1206                                         WRITE(tgui->accel.dst, out);
1207                                 }
1208 
1209 //				pclog("  %i,%i  %02X %02X %02X  %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out);
1210 
1211 				tgui->accel.src += xdir;
1212 				tgui->accel.dst += xdir;
1213 				tgui->accel.pat_x += xdir;
1214 
1215 				tgui->accel.x++;
1216 				if (tgui->accel.x > tgui->accel.size_x)
1217 				{
1218 					tgui->accel.x = 0;
1219 					tgui->accel.y++;
1220 
1221 					tgui->accel.pat_x = tgui->accel.dst_x;
1222 
1223 					tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
1224 					tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
1225 					tgui->accel.pat_y += ydir;
1226 
1227 					if (tgui->accel.y > tgui->accel.size_y)
1228 					{
1229 						if (svga->crtc[0x21] & 0x20)
1230 						{
1231                                                         tgui->write_blitter = 0;
1232 						}
1233 						return;
1234 					}
1235 					if (tgui->accel.use_src)
1236                                                 return;
1237 				}
1238 				count--;
1239 			}
1240 			break;
1241 
1242 			case TGUI_SRCMONO | TGUI_SRCCPU:
1243 			if (count == -1)
1244 			{
1245 //				pclog("Blit start  TGUI_SRCMONO | TGUI_SRCCPU\n");
1246 				if (svga->crtc[0x21] & 0x20)
1247 				{
1248                                         tgui->write_blitter = 1;
1249                                 }
1250 
1251 //                                pclog(" %i\n", tgui->accel.command);
1252 				if (tgui->accel.use_src)
1253                                         return;
1254 			}
1255 //			pclog("TGUI_SRCMONO | TGUI_SRCCPU\n");
1256 			while (count)
1257 			{
1258 				src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col);
1259 				if (tgui->accel.bpp == 0)
1260 				    src_dat &= 0xff;
1261 
1262 				READ(tgui->accel.dst, dst_dat);
1263 				pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7];
1264 
1265                                 if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
1266                                 {
1267         				MIX();
1268 
1269 				        WRITE(tgui->accel.dst, out);
1270                                 }
1271 //				pclog("  %i,%i  %02X %02X %02X  %02X %i\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out, (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col));
1272 				cpu_dat <<= 1;
1273 				tgui->accel.src += xdir;
1274 				tgui->accel.dst += xdir;
1275 				tgui->accel.pat_x += xdir;
1276 
1277 				tgui->accel.x++;
1278 				if (tgui->accel.x > tgui->accel.size_x)
1279 				{
1280 					tgui->accel.x = 0;
1281 					tgui->accel.y++;
1282 
1283 					tgui->accel.pat_x = tgui->accel.dst_x;
1284 
1285 					tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
1286 					tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
1287 					tgui->accel.pat_y += ydir;
1288 
1289 					if (tgui->accel.y > tgui->accel.size_y)
1290 					{
1291 						if (svga->crtc[0x21] & 0x20)
1292 						{
1293                                                         tgui->write_blitter = 0;
1294 						}
1295 						return;
1296 					}
1297 					if (tgui->accel.use_src)
1298                                                 return;
1299 				}
1300 				count--;
1301 			}
1302 			break;
1303 
1304 			default:
1305 			while (count)
1306 			{
1307 				READ(tgui->accel.src, src_dat);
1308 				READ(tgui->accel.dst, dst_dat);
1309 				pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7];
1310 
1311                                 if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)
1312                                 {
1313         				MIX();
1314 
1315                                         WRITE(tgui->accel.dst, out);
1316                                 }
1317 //                                pclog("  %i,%i  %02X %02X %02X  %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out);
1318 
1319 				tgui->accel.src += xdir;
1320 				tgui->accel.dst += xdir;
1321 				tgui->accel.pat_x += xdir;
1322 
1323 				tgui->accel.x++;
1324 				if (tgui->accel.x > tgui->accel.size_x)
1325 				{
1326 					tgui->accel.x = 0;
1327 					tgui->accel.y++;
1328 
1329 					tgui->accel.pat_x = tgui->accel.dst_x;
1330 
1331 					tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch);
1332 					tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch);
1333 					tgui->accel.pat_y += ydir;
1334 
1335 					if (tgui->accel.y > tgui->accel.size_y)
1336 						return;
1337 				}
1338 				count--;
1339 			}
1340 			break;
1341 		}
1342 		break;
1343 	}
1344 }
1345 
tgui_accel_write_fifo(tgui_t * tgui,uint32_t addr,uint8_t val)1346 static void tgui_accel_write_fifo(tgui_t *tgui, uint32_t addr, uint8_t val)
1347 {
1348 	switch (addr & 0xff)
1349 	{
1350                 case 0x22:
1351                 tgui->accel.ger22 = val;
1352                 tgui->accel.pitch = 512 << ((val >> 2) & 3);
1353                 tgui->accel.bpp = (val & 3) ? 1 : 0;
1354                 tgui->accel.pitch >>= tgui->accel.bpp;
1355                 break;
1356 
1357 		case 0x24: /*Command*/
1358 		tgui->accel.command = val;
1359 		tgui_accel_command(-1, 0, tgui);
1360 		break;
1361 
1362 		case 0x27: /*ROP*/
1363 		tgui->accel.rop = val;
1364 		tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33);
1365 //		pclog("Write ROP %02X %i\n", val, tgui->accel.use_src);
1366 		break;
1367 
1368 		case 0x28: /*Flags*/
1369 		tgui->accel.flags = (tgui->accel.flags & 0xff00) | val;
1370 		break;
1371 		case 0x29: /*Flags*/
1372 		tgui->accel.flags = (tgui->accel.flags & 0xff) | (val << 8);
1373 		break;
1374 
1375 		case 0x2b:
1376 		tgui->accel.offset = val & 7;
1377 		break;
1378 
1379 		case 0x2c: /*Foreground colour*/
1380 		tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00) | val;
1381 		break;
1382 		case 0x2d: /*Foreground colour*/
1383 		tgui->accel.fg_col = (tgui->accel.fg_col & 0xff) | (val << 8);
1384 		break;
1385 
1386 		case 0x30: /*Background colour*/
1387 		tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00) | val;
1388 		break;
1389 		case 0x31: /*Background colour*/
1390 		tgui->accel.bg_col = (tgui->accel.bg_col & 0xff) | (val << 8);
1391 		break;
1392 
1393 		case 0x38: /*Dest X*/
1394 		tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val;
1395 		break;
1396 		case 0x39: /*Dest X*/
1397 		tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8);
1398 		break;
1399 		case 0x3a: /*Dest Y*/
1400 		tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val;
1401 		break;
1402 		case 0x3b: /*Dest Y*/
1403 		tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8);
1404 		break;
1405 
1406 		case 0x3c: /*Src X*/
1407 		tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val;
1408 		break;
1409 		case 0x3d: /*Src X*/
1410 		tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8);
1411 		break;
1412 		case 0x3e: /*Src Y*/
1413 		tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val;
1414 		break;
1415 		case 0x3f: /*Src Y*/
1416 		tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8);
1417 		break;
1418 
1419 		case 0x40: /*Size X*/
1420 		tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val;
1421 		break;
1422 		case 0x41: /*Size X*/
1423 		tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8);
1424 		break;
1425 		case 0x42: /*Size Y*/
1426 		tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val;
1427 		break;
1428 		case 0x43: /*Size Y*/
1429 		tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8);
1430 		break;
1431 
1432 		case 0x80: case 0x81: case 0x82: case 0x83:
1433 		case 0x84: case 0x85: case 0x86: case 0x87:
1434 		case 0x88: case 0x89: case 0x8a: case 0x8b:
1435 		case 0x8c: case 0x8d: case 0x8e: case 0x8f:
1436 		case 0x90: case 0x91: case 0x92: case 0x93:
1437 		case 0x94: case 0x95: case 0x96: case 0x97:
1438 		case 0x98: case 0x99: case 0x9a: case 0x9b:
1439 		case 0x9c: case 0x9d: case 0x9e: case 0x9f:
1440 		case 0xa0: case 0xa1: case 0xa2: case 0xa3:
1441 		case 0xa4: case 0xa5: case 0xa6: case 0xa7:
1442 		case 0xa8: case 0xa9: case 0xaa: case 0xab:
1443 		case 0xac: case 0xad: case 0xae: case 0xaf:
1444 		case 0xb0: case 0xb1: case 0xb2: case 0xb3:
1445 		case 0xb4: case 0xb5: case 0xb6: case 0xb7:
1446 		case 0xb8: case 0xb9: case 0xba: case 0xbb:
1447 		case 0xbc: case 0xbd: case 0xbe: case 0xbf:
1448 		case 0xc0: case 0xc1: case 0xc2: case 0xc3:
1449 		case 0xc4: case 0xc5: case 0xc6: case 0xc7:
1450 		case 0xc8: case 0xc9: case 0xca: case 0xcb:
1451 		case 0xcc: case 0xcd: case 0xce: case 0xcf:
1452 		case 0xd0: case 0xd1: case 0xd2: case 0xd3:
1453 		case 0xd4: case 0xd5: case 0xd6: case 0xd7:
1454 		case 0xd8: case 0xd9: case 0xda: case 0xdb:
1455 		case 0xdc: case 0xdd: case 0xde: case 0xdf:
1456 		case 0xe0: case 0xe1: case 0xe2: case 0xe3:
1457 		case 0xe4: case 0xe5: case 0xe6: case 0xe7:
1458 		case 0xe8: case 0xe9: case 0xea: case 0xeb:
1459 		case 0xec: case 0xed: case 0xee: case 0xef:
1460 		case 0xf0: case 0xf1: case 0xf2: case 0xf3:
1461 		case 0xf4: case 0xf5: case 0xf6: case 0xf7:
1462 		case 0xf8: case 0xf9: case 0xfa: case 0xfb:
1463 		case 0xfc: case 0xfd: case 0xfe: case 0xff:
1464 		tgui->accel.pattern[addr & 0x7f] = val;
1465 		break;
1466 	}
1467 }
1468 
tgui_accel_write_fifo_fb_b(tgui_t * tgui,uint32_t addr,uint8_t val)1469 static void tgui_accel_write_fifo_fb_b(tgui_t *tgui, uint32_t addr, uint8_t val)
1470 {
1471 	tgui_accel_command(8, val << 24, tgui);
1472 }
tgui_accel_write_fifo_fb_w(tgui_t * tgui,uint32_t addr,uint16_t val)1473 static void tgui_accel_write_fifo_fb_w(tgui_t *tgui, uint32_t addr, uint16_t val)
1474 {
1475         tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui);
1476 }
tgui_accel_write_fifo_fb_l(tgui_t * tgui,uint32_t addr,uint32_t val)1477 static void tgui_accel_write_fifo_fb_l(tgui_t *tgui, uint32_t addr, uint32_t val)
1478 {
1479 	tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui);
1480 }
1481 
fifo_thread(void * param)1482 static void fifo_thread(void *param)
1483 {
1484         tgui_t *tgui = (tgui_t *)param;
1485 
1486         while (1)
1487         {
1488                 thread_set_event(tgui->fifo_not_full_event);
1489                 thread_wait_event(tgui->wake_fifo_thread, -1);
1490                 thread_reset_event(tgui->wake_fifo_thread);
1491                 tgui->blitter_busy = 1;
1492                 while (!FIFO_EMPTY)
1493                 {
1494                         uint64_t start_time = timer_read();
1495                         uint64_t end_time;
1496                         fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_read_idx & FIFO_MASK];
1497 
1498                         switch (fifo->addr_type & FIFO_TYPE)
1499                         {
1500                                 case FIFO_WRITE_BYTE:
1501                                 tgui_accel_write_fifo(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
1502                                 break;
1503                                 case FIFO_WRITE_FB_BYTE:
1504                                 tgui_accel_write_fifo_fb_b(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
1505                                 break;
1506                                 case FIFO_WRITE_FB_WORD:
1507                                 tgui_accel_write_fifo_fb_w(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
1508                                 break;
1509                                 case FIFO_WRITE_FB_LONG:
1510                                 tgui_accel_write_fifo_fb_l(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
1511                                 break;
1512                         }
1513 
1514                         tgui->fifo_read_idx++;
1515                         fifo->addr_type = FIFO_INVALID;
1516 
1517                         if (FIFO_ENTRIES > 0xe000)
1518                                 thread_set_event(tgui->fifo_not_full_event);
1519 
1520                         end_time = timer_read();
1521                         tgui->blitter_time += end_time - start_time;
1522                 }
1523                 tgui->blitter_busy = 0;
1524         }
1525 }
1526 
wake_fifo_thread(tgui_t * tgui)1527 static inline void wake_fifo_thread(tgui_t *tgui)
1528 {
1529         thread_set_event(tgui->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
1530 }
1531 
tgui_wait_fifo_idle(tgui_t * tgui)1532 static void tgui_wait_fifo_idle(tgui_t *tgui)
1533 {
1534         while (!FIFO_EMPTY)
1535         {
1536                 wake_fifo_thread(tgui);
1537                 thread_wait_event(tgui->fifo_not_full_event, 1);
1538         }
1539 }
1540 
tgui_queue(tgui_t * tgui,uint32_t addr,uint32_t val,uint32_t type)1541 static void tgui_queue(tgui_t *tgui, uint32_t addr, uint32_t val, uint32_t type)
1542 {
1543         fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_write_idx & FIFO_MASK];
1544 
1545         if (FIFO_FULL)
1546         {
1547                 thread_reset_event(tgui->fifo_not_full_event);
1548                 if (FIFO_FULL)
1549                 {
1550                         thread_wait_event(tgui->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
1551                 }
1552         }
1553 
1554         fifo->val = val;
1555         fifo->addr_type = (addr & FIFO_ADDR) | type;
1556 
1557         tgui->fifo_write_idx++;
1558 
1559         if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
1560                 wake_fifo_thread(tgui);
1561 }
1562 
1563 
tgui_accel_write(uint32_t addr,uint8_t val,void * p)1564 void tgui_accel_write(uint32_t addr, uint8_t val, void *p)
1565 {
1566         tgui_t *tgui = (tgui_t *)p;
1567 //	pclog("tgui_accel_write : %08X %02X  %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode);
1568 	if ((addr & ~0xff) != 0xbff00)
1569 		return;
1570 	tgui_queue(tgui, addr, val, FIFO_WRITE_BYTE);
1571 }
1572 
tgui_accel_write_w(uint32_t addr,uint16_t val,void * p)1573 void tgui_accel_write_w(uint32_t addr, uint16_t val, void *p)
1574 {
1575         tgui_t *tgui = (tgui_t *)p;
1576 //	pclog("tgui_accel_write_w %08X %04X\n", addr, val);
1577 	tgui_accel_write(addr, val, tgui);
1578 	tgui_accel_write(addr + 1, val >> 8, tgui);
1579 }
1580 
tgui_accel_write_l(uint32_t addr,uint32_t val,void * p)1581 void tgui_accel_write_l(uint32_t addr, uint32_t val, void *p)
1582 {
1583         tgui_t *tgui = (tgui_t *)p;
1584 //	pclog("tgui_accel_write_l %08X %08X\n", addr, val);
1585 	tgui_accel_write(addr, val, tgui);
1586 	tgui_accel_write(addr + 1, val >> 8, tgui);
1587 	tgui_accel_write(addr + 2, val >> 16, tgui);
1588 	tgui_accel_write(addr + 3, val >> 24, tgui);
1589 }
1590 
tgui_accel_read(uint32_t addr,void * p)1591 uint8_t tgui_accel_read(uint32_t addr, void *p)
1592 {
1593         tgui_t *tgui = (tgui_t *)p;
1594 //	pclog("tgui_accel_read : %08X\n", addr);
1595 	if ((addr & ~0xff) != 0xbff00)
1596 		return 0xff;
1597 	if ((addr & 0xff) != 0x20)
1598 	       tgui_wait_fifo_idle(tgui);
1599 	switch (addr & 0xff)
1600 	{
1601 		case 0x20: /*Status*/
1602 		if (!FIFO_EMPTY)
1603 		      return 1 << 5;
1604 		return 0;
1605 
1606 		case 0x27: /*ROP*/
1607 		return tgui->accel.rop;
1608 
1609 		case 0x28: /*Flags*/
1610 		return tgui->accel.flags & 0xff;
1611 		case 0x29: /*Flags*/
1612 		return tgui->accel.flags >> 8;
1613 
1614 		case 0x2b:
1615 		return tgui->accel.offset;
1616 
1617 		case 0x2c: /*Background colour*/
1618 		return tgui->accel.bg_col & 0xff;
1619 		case 0x2d: /*Background colour*/
1620 		return tgui->accel.bg_col >> 8;
1621 
1622 		case 0x30: /*Foreground colour*/
1623 		return tgui->accel.fg_col & 0xff;
1624 		case 0x31: /*Foreground colour*/
1625 		return tgui->accel.fg_col >> 8;
1626 
1627 		case 0x38: /*Dest X*/
1628 		return tgui->accel.dst_x & 0xff;
1629 		case 0x39: /*Dest X*/
1630 		return tgui->accel.dst_x >> 8;
1631 		case 0x3a: /*Dest Y*/
1632 		return tgui->accel.dst_y & 0xff;
1633 		case 0x3b: /*Dest Y*/
1634 		return tgui->accel.dst_y >> 8;
1635 
1636 		case 0x3c: /*Src X*/
1637 		return tgui->accel.src_x & 0xff;
1638 		case 0x3d: /*Src X*/
1639 		return tgui->accel.src_x >> 8;
1640 		case 0x3e: /*Src Y*/
1641 		return tgui->accel.src_y & 0xff;
1642 		case 0x3f: /*Src Y*/
1643 		return tgui->accel.src_y >> 8;
1644 
1645 		case 0x40: /*Size X*/
1646 		return tgui->accel.size_x & 0xff;
1647 		case 0x41: /*Size X*/
1648 		return tgui->accel.size_x >> 8;
1649 		case 0x42: /*Size Y*/
1650 		return tgui->accel.size_y & 0xff;
1651 		case 0x43: /*Size Y*/
1652 		return tgui->accel.size_y >> 8;
1653 
1654 		case 0x80: case 0x81: case 0x82: case 0x83:
1655 		case 0x84: case 0x85: case 0x86: case 0x87:
1656 		case 0x88: case 0x89: case 0x8a: case 0x8b:
1657 		case 0x8c: case 0x8d: case 0x8e: case 0x8f:
1658 		case 0x90: case 0x91: case 0x92: case 0x93:
1659 		case 0x94: case 0x95: case 0x96: case 0x97:
1660 		case 0x98: case 0x99: case 0x9a: case 0x9b:
1661 		case 0x9c: case 0x9d: case 0x9e: case 0x9f:
1662 		case 0xa0: case 0xa1: case 0xa2: case 0xa3:
1663 		case 0xa4: case 0xa5: case 0xa6: case 0xa7:
1664 		case 0xa8: case 0xa9: case 0xaa: case 0xab:
1665 		case 0xac: case 0xad: case 0xae: case 0xaf:
1666 		case 0xb0: case 0xb1: case 0xb2: case 0xb3:
1667 		case 0xb4: case 0xb5: case 0xb6: case 0xb7:
1668 		case 0xb8: case 0xb9: case 0xba: case 0xbb:
1669 		case 0xbc: case 0xbd: case 0xbe: case 0xbf:
1670 		case 0xc0: case 0xc1: case 0xc2: case 0xc3:
1671 		case 0xc4: case 0xc5: case 0xc6: case 0xc7:
1672 		case 0xc8: case 0xc9: case 0xca: case 0xcb:
1673 		case 0xcc: case 0xcd: case 0xce: case 0xcf:
1674 		case 0xd0: case 0xd1: case 0xd2: case 0xd3:
1675 		case 0xd4: case 0xd5: case 0xd6: case 0xd7:
1676 		case 0xd8: case 0xd9: case 0xda: case 0xdb:
1677 		case 0xdc: case 0xdd: case 0xde: case 0xdf:
1678 		case 0xe0: case 0xe1: case 0xe2: case 0xe3:
1679 		case 0xe4: case 0xe5: case 0xe6: case 0xe7:
1680 		case 0xe8: case 0xe9: case 0xea: case 0xeb:
1681 		case 0xec: case 0xed: case 0xee: case 0xef:
1682 		case 0xf0: case 0xf1: case 0xf2: case 0xf3:
1683 		case 0xf4: case 0xf5: case 0xf6: case 0xf7:
1684 		case 0xf8: case 0xf9: case 0xfa: case 0xfb:
1685 		case 0xfc: case 0xfd: case 0xfe: case 0xff:
1686 		return tgui->accel.pattern[addr & 0x7f];
1687 	}
1688 	return 0xff;
1689 }
1690 
tgui_accel_read_w(uint32_t addr,void * p)1691 uint16_t tgui_accel_read_w(uint32_t addr, void *p)
1692 {
1693         tgui_t *tgui = (tgui_t *)p;
1694 //	pclog("tgui_accel_read_w %08X\n", addr);
1695 	return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8);
1696 }
1697 
tgui_accel_read_l(uint32_t addr,void * p)1698 uint32_t tgui_accel_read_l(uint32_t addr, void *p)
1699 {
1700         tgui_t *tgui = (tgui_t *)p;
1701 //	pclog("tgui_accel_read_l %08X\n", addr);
1702 	return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16);
1703 }
1704 
tgui_accel_write_fb_b(uint32_t addr,uint8_t val,void * p)1705 void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p)
1706 {
1707         svga_t *svga = (svga_t *)p;
1708         tgui_t *tgui = (tgui_t *)svga->p;
1709 
1710         if (tgui->write_blitter)
1711         	tgui_queue(tgui, addr, val, FIFO_WRITE_FB_BYTE);
1712         else
1713                 svga_write_linear(addr, val, svga);
1714 }
1715 
tgui_accel_write_fb_w(uint32_t addr,uint16_t val,void * p)1716 void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p)
1717 {
1718         svga_t *svga = (svga_t *)p;
1719         tgui_t *tgui = (tgui_t *)svga->p;
1720 
1721         if (tgui->write_blitter)
1722         	tgui_queue(tgui, addr, val, FIFO_WRITE_FB_WORD);
1723         else
1724                 svga_writew_linear(addr, val, svga);
1725 }
1726 
tgui_accel_write_fb_l(uint32_t addr,uint32_t val,void * p)1727 void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p)
1728 {
1729         svga_t *svga = (svga_t *)p;
1730         tgui_t *tgui = (tgui_t *)svga->p;
1731 
1732         if (tgui->write_blitter)
1733         	tgui_queue(tgui, addr, val, FIFO_WRITE_FB_LONG);
1734         else
1735                 svga_writel_linear(addr, val, svga);
1736 }
1737 
tgui_add_status_info(char * s,int max_len,void * p)1738 void tgui_add_status_info(char *s, int max_len, void *p)
1739 {
1740         tgui_t *tgui = (tgui_t *)p;
1741         char temps[256];
1742         uint64_t new_time = timer_read();
1743         uint64_t status_diff = new_time - tgui->status_time;
1744         tgui->status_time = new_time;
1745 
1746         svga_add_status_info(s, max_len, &tgui->svga);
1747 
1748         sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)tgui->blitter_time * 100.0) / timer_freq, ((double)tgui->blitter_time * 100.0) / status_diff);
1749         strncat(s, temps, max_len);
1750 
1751         tgui->blitter_time = 0;
1752 }
1753 
1754 static device_config_t tgui9440_config[] =
1755 {
1756         {
1757                 .name = "memory",
1758                 .description = "Memory size",
1759                 .type = CONFIG_SELECTION,
1760                 .selection =
1761                 {
1762                         {
1763                                 .description = "1 MB",
1764                                 .value = 1
1765                         },
1766                         {
1767                                 .description = "2 MB",
1768                                 .value = 2
1769                         },
1770                         {
1771                                 .description = ""
1772                         }
1773                 },
1774                 .default_int = 2
1775         },
1776         {
1777                 .type = -1
1778         }
1779 };
1780 
1781 device_t tgui9400cxi_device =
1782 {
1783         "Trident TGUI 9400CXi",
1784         0,
1785         tgui9400cxi_init,
1786         tgui_close,
1787         tgui9400cxi_available,
1788         tgui_speed_changed,
1789         tgui_force_redraw,
1790         tgui_add_status_info,
1791         tgui9440_config
1792 };
1793 
1794 device_t tgui9400cxi_elx_device =
1795 {
1796         "Trident TGUI 9400CXi (Elonex PC-425X)",
1797         0,
1798         tgui9400cxi_elx_init,
1799         tgui_close,
1800         tgui9400cxi_available,
1801         tgui_speed_changed,
1802         tgui_force_redraw,
1803         tgui_add_status_info,
1804         tgui9440_config
1805 };
1806 
1807 device_t tgui9440_device =
1808 {
1809         "Trident TGUI 9440",
1810         0,
1811         tgui9440_init,
1812         tgui_close,
1813         tgui9440_available,
1814         tgui_speed_changed,
1815         tgui_force_redraw,
1816         tgui_add_status_info,
1817         tgui9440_config
1818 };
1819