PCem
view src/vid_paradise.c @ 131:f22b6152c221
Fixed memory mapping on ISA video cards - should now work on Award 430VX PCI.
| author | TomW |
|---|---|
| date | Wed Jul 16 20:00:34 2014 +0100 |
| parents | 036dc3a418ac |
| children | 24b744b9a632 |
line source
1 /*Paradise VGA emulation
3 PC2086, PC3086 use PVGA1A
4 MegaPC uses W90C11A
5 */
6 #include <stdlib.h>
7 #include "ibm.h"
8 #include "device.h"
9 #include "mem.h"
10 #include "rom.h"
11 #include "video.h"
12 #include "vid_paradise.h"
13 #include "vid_svga.h"
14 #include "vid_svga_render.h"
15 #include "vid_unk_ramdac.h"
17 typedef struct paradise_t
18 {
19 svga_t svga;
21 rom_t bios_rom;
23 enum
24 {
25 PVGA1A = 0,
26 WD90C11
27 } type;
29 uint32_t read_bank[4], write_bank[4];
30 } paradise_t;
32 void paradise_write(uint32_t addr, uint8_t val, void *p);
33 uint8_t paradise_read(uint32_t addr, void *p);
34 void paradise_remap(paradise_t *paradise);
37 void paradise_out(uint16_t addr, uint8_t val, void *p)
38 {
39 paradise_t *paradise = (paradise_t *)p;
40 svga_t *svga = ¶dise->svga;
41 uint8_t old;
43 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
44 addr ^= 0x60;
45 // output = 3;
46 // pclog("Paradise out %04X %02X %04X:%04X\n", addr, val, CS, pc);
47 switch (addr)
48 {
49 case 0x3c5:
50 if (svga->seqaddr > 7)
51 {
52 if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
53 return;
54 svga->seqregs[svga->seqaddr & 0x1f] = val;
55 if (svga->seqaddr == 0x11)
56 paradise_remap(paradise);
57 return;
58 }
59 break;
61 case 0x3cf:
62 if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
63 {
64 if ((svga->gdcreg[0xf] & 7) != 5)
65 return;
66 }
67 if (svga->gdcaddr == 6)
68 {
69 if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
70 {
71 // pclog("Write mapping %02X\n", val);
72 switch (val&0xC)
73 {
74 case 0x0: /*128k at A0000*/
75 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
76 svga->banked_mask = 0xffff;
77 break;
78 case 0x4: /*64k at A0000*/
79 mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
80 svga->banked_mask = 0xffff;
81 break;
82 case 0x8: /*32k at B0000*/
83 mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
84 svga->banked_mask = 0x7fff;
85 break;
86 case 0xC: /*32k at B8000*/
87 mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
88 svga->banked_mask = 0x7fff;
89 break;
90 }
91 }
92 svga->gdcreg[6] = val;
93 paradise_remap(paradise);
94 return;
95 }
96 if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa)
97 {
98 svga->gdcreg[svga->gdcaddr] = val;
99 paradise_remap(paradise);
100 return;
101 }
102 if (svga->gdcaddr == 0xe)
103 {
104 svga->gdcreg[0xe] = val;
105 paradise_remap(paradise);
106 return;
107 }
108 break;
110 case 0x3D4:
111 if (paradise->type == PVGA1A)
112 svga->crtcreg = val & 0x1f;
113 else
114 svga->crtcreg = val & 0x3f;
115 return;
116 case 0x3D5:
117 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80)
118 return;
119 if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5)
120 return;
121 if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37)
122 return;
123 old = svga->crtc[svga->crtcreg];
124 svga->crtc[svga->crtcreg] = val;
126 if (old != val)
127 {
128 if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
129 {
130 svga->fullchange = changeframecount;
131 svga_recalctimings(¶dise->svga);
132 }
133 }
134 break;
135 }
136 svga_out(addr, val, svga);
137 }
139 uint8_t paradise_in(uint16_t addr, void *p)
140 {
141 paradise_t *paradise = (paradise_t *)p;
142 svga_t *svga = ¶dise->svga;
144 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
145 addr ^= 0x60;
147 // if (addr != 0x3da) pclog("Paradise in %04X\n", addr);
148 switch (addr)
149 {
150 case 0x3c2:
151 return 0x10;
153 case 0x3c5:
154 if (svga->seqaddr > 7)
155 {
156 if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
157 return 0xff;
158 if (svga->seqaddr > 0x12)
159 return 0xff;
160 return svga->seqregs[svga->seqaddr & 0x1f];
161 }
162 break;
164 case 0x3cf:
165 if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
166 {
167 if (svga->gdcreg[0xf] & 0x10)
168 return 0xff;
169 switch (svga->gdcaddr)
170 {
171 case 0xf:
172 return (svga->gdcreg[0xf] & 0x17) | 0x80;
173 }
174 }
175 break;
177 case 0x3D4:
178 return svga->crtcreg;
179 case 0x3D5:
180 if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80)
181 return 0xff;
182 return svga->crtc[svga->crtcreg];
183 }
184 return svga_in(addr, svga);
185 }
187 void paradise_remap(paradise_t *paradise)
188 {
189 svga_t *svga = ¶dise->svga;
191 if (svga->seqregs[0x11] & 0x80)
192 {
193 // pclog("Remap 1\n");
194 paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
195 paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
196 paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
197 paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
198 }
199 else if (svga->gdcreg[0xe] & 0x08)
200 {
201 if (svga->gdcreg[0x6] & 0xc)
202 {
203 // pclog("Remap 2\n");
204 paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
205 paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
206 paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
207 paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
208 }
209 else
210 {
211 // pclog("Remap 3\n");
212 paradise->read_bank[0] = paradise->write_bank[0] = (svga->gdcreg[0xa] & 0x7f) << 12;
213 paradise->read_bank[1] = paradise->write_bank[1] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
214 paradise->read_bank[2] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
215 paradise->read_bank[3] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
216 }
217 }
218 else
219 {
220 // pclog("Remap 4\n");
221 paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
222 paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
223 paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
224 paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
225 }
226 // pclog("Remap - %04X %04X\n", paradise->read_bank[0], paradise->write_bank[0]);
227 }
229 void paradise_recalctimings(svga_t *svga)
230 {
231 svga->lowres = !(svga->gdcreg[0xe] & 0x01);
232 if (svga->bpp == 8 && !svga->lowres)
233 svga->render = svga_render_8bpp_highres;
234 }
236 #define egacycles 1
237 #define egacycles2 1
238 void paradise_write(uint32_t addr, uint8_t val, void *p)
239 {
240 paradise_t *paradise = (paradise_t *)p;
241 // pclog("paradise_write : %05X %02X ", addr, val);
242 addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
243 // pclog("%08X\n", addr);
244 svga_write_linear(addr, val, ¶dise->svga);
245 }
247 uint8_t paradise_read(uint32_t addr, void *p)
248 {
249 paradise_t *paradise = (paradise_t *)p;
250 // pclog("paradise_read : %05X ", addr);
251 addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
252 // pclog("%08X\n", addr);
253 return svga_read_linear(addr, ¶dise->svga);
254 }
256 void *paradise_pvga1a_init()
257 {
258 paradise_t *paradise = malloc(sizeof(paradise_t));
259 svga_t *svga = ¶dise->svga;
260 memset(paradise, 0, sizeof(paradise_t));
262 io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
264 svga_init(¶dise->svga, paradise, 1 << 18, /*256kb*/
265 NULL,
266 paradise_in, paradise_out,
267 NULL,
268 NULL);
270 mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
271 mem_mapping_set_p(¶dise->svga.mapping, paradise);
273 svga->crtc[0x31] = 'W';
274 svga->crtc[0x32] = 'D';
275 svga->crtc[0x33] = '9';
276 svga->crtc[0x34] = '0';
277 svga->crtc[0x35] = 'C';
279 svga->bpp = 8;
280 svga->miscout = 1;
282 paradise->type = PVGA1A;
284 return paradise;
285 }
287 void *paradise_wd90c11_init()
288 {
289 paradise_t *paradise = malloc(sizeof(paradise_t));
290 svga_t *svga = ¶dise->svga;
291 memset(paradise, 0, sizeof(paradise_t));
293 io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
295 svga_init(¶dise->svga, paradise, 1 << 19, /*512kb*/
296 paradise_recalctimings,
297 paradise_in, paradise_out,
298 NULL,
299 NULL);
301 mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
302 mem_mapping_set_p(¶dise->svga.mapping, paradise);
304 svga->crtc[0x31] = 'W';
305 svga->crtc[0x32] = 'D';
306 svga->crtc[0x33] = '9';
307 svga->crtc[0x34] = '0';
308 svga->crtc[0x35] = 'C';
309 svga->crtc[0x36] = '1';
310 svga->crtc[0x37] = '1';
312 svga->bpp = 8;
313 svga->miscout = 1;
315 paradise->type = WD90C11;
317 return paradise;
318 }
320 static void *paradise_pvga1a_pc2086_init()
321 {
322 paradise_t *paradise = paradise_pvga1a_init();
324 if (paradise)
325 rom_init(¶dise->bios_rom, "roms/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
327 return paradise;
328 }
329 static void *paradise_pvga1a_pc3086_init()
330 {
331 paradise_t *paradise = paradise_pvga1a_init();
333 if (paradise)
334 rom_init(¶dise->bios_rom, "roms/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
336 return paradise;
337 }
339 static void *paradise_wd90c11_megapc_init()
340 {
341 paradise_t *paradise = paradise_wd90c11_init();
343 if (paradise)
344 rom_init_interleaved(¶dise->bios_rom,
345 "roms/megapc/41651-bios lo.u18",
346 "roms/megapc/211253-bios hi.u19",
347 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
349 return paradise;
350 }
352 void paradise_close(void *p)
353 {
354 paradise_t *paradise = (paradise_t *)p;
356 svga_close(¶dise->svga);
358 free(paradise);
359 }
361 void paradise_speed_changed(void *p)
362 {
363 paradise_t *paradise = (paradise_t *)p;
365 svga_recalctimings(¶dise->svga);
366 }
368 void paradise_force_redraw(void *p)
369 {
370 paradise_t *paradise = (paradise_t *)p;
372 paradise->svga.fullchange = changeframecount;
373 }
375 int paradise_add_status_info(char *s, int max_len, void *p)
376 {
377 paradise_t *paradise = (paradise_t *)p;
379 return svga_add_status_info(s, max_len, ¶dise->svga);
380 }
382 device_t paradise_pvga1a_pc2086_device =
383 {
384 "Paradise PVGA1A (Amstrad PC2086)",
385 0,
386 paradise_pvga1a_pc2086_init,
387 paradise_close,
388 NULL,
389 paradise_speed_changed,
390 paradise_force_redraw,
391 paradise_add_status_info
392 };
393 device_t paradise_pvga1a_pc3086_device =
394 {
395 "Paradise PVGA1A (Amstrad PC3086)",
396 0,
397 paradise_pvga1a_pc3086_init,
398 paradise_close,
399 NULL,
400 paradise_speed_changed,
401 paradise_force_redraw,
402 paradise_add_status_info
403 };
404 device_t paradise_wd90c11_megapc_device =
405 {
406 "Paradise WD90C11 (Amstrad MegaPC)",
407 0,
408 paradise_wd90c11_megapc_init,
409 paradise_close,
410 NULL,
411 paradise_speed_changed,
412 paradise_force_redraw,
413 paradise_add_status_info
414 };
