PCem
view src/vid_et4000.c @ 154:d0d530adce12
Initial port to Linux (using Allegro).
64-bit fixes.
Some changes to aid portability.
A few other tweaks.
| author | TomW |
|---|---|
| date | Thu Sep 04 21:07:24 2014 +0100 |
| parents | 6f30fb98b7f2 |
| children |
line source
1 /*ET4000 emulation*/
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5 #include "io.h"
6 #include "mem.h"
7 #include "rom.h"
8 #include "video.h"
9 #include "vid_svga.h"
10 #include "vid_unk_ramdac.h"
12 #include "vid_et4000.h"
14 typedef struct et4000_t
15 {
16 svga_t svga;
17 unk_ramdac_t ramdac;
19 rom_t bios_rom;
21 uint8_t banking;
22 } et4000_t;
24 static uint8_t crtc_mask[0x40] =
25 {
26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
29 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34 };
36 void et4000_out(uint16_t addr, uint8_t val, void *p)
37 {
38 et4000_t *et4000 = (et4000_t *)p;
39 svga_t *svga = &et4000->svga;
41 uint8_t old;
43 if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
44 addr ^= 0x60;
46 // pclog("ET4000 out %04X %02X\n", addr, val);
48 switch (addr)
49 {
50 case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
51 unk_ramdac_out(addr, val, &et4000->ramdac, svga);
52 return;
54 case 0x3CD: /*Banking*/
55 svga->write_bank = (val & 0xf) * 0x10000;
56 svga->read_bank = ((val >> 4) & 0xf) * 0x10000;
57 et4000->banking = val;
58 // pclog("Banking write %08X %08X %02X\n", svga->write_bank, svga->read_bank, val);
59 return;
60 case 0x3D4:
61 svga->crtcreg = val & 0x3f;
62 return;
63 case 0x3D5:
64 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
65 old = svga->crtc[svga->crtcreg];
66 val &= crtc_mask[svga->crtcreg];
67 svga->crtc[svga->crtcreg] = val;
68 if (old != val)
69 {
70 if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
71 {
72 svga->fullchange = changeframecount;
73 svga_recalctimings(svga);
74 }
75 }
76 break;
77 }
78 svga_out(addr, val, svga);
79 }
81 uint8_t et4000_in(uint16_t addr, void *p)
82 {
83 et4000_t *et4000 = (et4000_t *)p;
84 svga_t *svga = &et4000->svga;
86 if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
87 addr ^= 0x60;
89 // if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
91 switch (addr)
92 {
93 case 0x3C5:
94 if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4;
95 break;
97 case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
98 return unk_ramdac_in(addr, &et4000->ramdac, svga);
100 case 0x3CD: /*Banking*/
101 return et4000->banking;
102 case 0x3D4:
103 return svga->crtcreg;
104 case 0x3D5:
105 return svga->crtc[svga->crtcreg];
106 }
107 return svga_in(addr, svga);
108 }
110 void et4000_recalctimings(svga_t *svga)
111 {
112 et4000_t *et4000 = (et4000_t *)svga->p;
114 svga->ma_latch |= (svga->crtc[0x33]&3)<<16;
115 if (svga->crtc[0x35] & 2) svga->vtotal += 0x400;
116 if (svga->crtc[0x35] & 4) svga->dispend += 0x400;
117 if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400;
118 if (svga->crtc[0x35] & 0x10) svga->split += 0x400;
119 if (!svga->rowoffset) svga->rowoffset = 0x100;
120 if (svga->crtc[0x3f] & 1) svga->htotal += 256;
121 if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1;
123 // pclog("Rowoffset %i\n",svga_rowoffset);
125 switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4))
126 {
127 case 0: case 1: break;
128 case 3: svga->clock = cpuclock / 40000000.0; break;
129 case 5: svga->clock = cpuclock / 65000000.0; break;
130 default: svga->clock = cpuclock / 36000000.0; break;
131 }
133 switch (svga->bpp)
134 {
135 case 15: case 16:
136 svga->hdisp /= 2;
137 break;
138 case 24:
139 svga->hdisp /= 3;
140 break;
141 }
142 }
144 void *et4000_init()
145 {
146 et4000_t *et4000 = malloc(sizeof(et4000_t));
147 memset(et4000, 0, sizeof(et4000_t));
149 rom_init(&et4000->bios_rom, "roms/et4000.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
151 io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000);
153 svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
154 et4000_recalctimings,
155 et4000_in, et4000_out,
156 NULL,
157 NULL);
159 return et4000;
160 }
162 static int et4000_available()
163 {
164 return rom_present("roms/et4000.BIN");
165 }
167 void et4000_close(void *p)
168 {
169 et4000_t *et4000 = (et4000_t *)p;
171 svga_close(&et4000->svga);
173 free(et4000);
174 }
176 void et4000_speed_changed(void *p)
177 {
178 et4000_t *et4000 = (et4000_t *)p;
180 svga_recalctimings(&et4000->svga);
181 }
183 void et4000_force_redraw(void *p)
184 {
185 et4000_t *et4000 = (et4000_t *)p;
187 et4000->svga.fullchange = changeframecount;
188 }
190 void et4000_add_status_info(char *s, int max_len, void *p)
191 {
192 et4000_t *et4000 = (et4000_t *)p;
194 svga_add_status_info(s, max_len, &et4000->svga);
195 }
197 device_t et4000_device =
198 {
199 "Tseng Labs ET4000AX",
200 0,
201 et4000_init,
202 et4000_close,
203 et4000_available,
204 et4000_speed_changed,
205 et4000_force_redraw,
206 et4000_add_status_info
207 };
