PCem

view src/vid_ati28800.c @ 133:24b744b9a632

ViRGE S3D triangle rendering now uses worker thread. Fixed clipping bug on ViRGE. Fixed status window crash.
author TomW
date Tue Jul 22 21:10:39 2014 +0100
parents f22b6152c221
children
line source
1 /*ATI 28800 emulation (VGA Charger)*/
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_ati28800.h"
10 #include "vid_ati_eeprom.h"
11 #include "vid_svga.h"
12 #include "vid_svga_render.h"
14 typedef struct ati28800_t
15 {
16 svga_t svga;
17 ati_eeprom_t eeprom;
19 rom_t bios_rom;
21 uint8_t regs[256];
22 int index;
23 } ati28800_t;
25 void ati28800_out(uint16_t addr, uint8_t val, void *p)
26 {
27 ati28800_t *ati28800 = (ati28800_t *)p;
28 svga_t *svga = &ati28800->svga;
29 uint8_t old;
31 // pclog("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc);
33 if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1))
34 addr ^= 0x60;
36 switch (addr)
37 {
38 case 0x1ce:
39 ati28800->index = val;
40 break;
41 case 0x1cf:
42 ati28800->regs[ati28800->index] = val;
43 switch (ati28800->index)
44 {
45 case 0xb2:
46 case 0xbe:
47 if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/
48 {
49 svga->read_bank = ((ati28800->regs[0xb2] >> 5) & 7) * 0x10000;
50 svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
51 }
52 else /*Single bank mode*/
53 svga->read_bank = svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
54 break;
55 case 0xb3:
56 ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1);
57 break;
58 }
59 break;
61 case 0x3D4:
62 svga->crtcreg = val & 0x3f;
63 return;
64 case 0x3D5:
65 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
66 old = svga->crtc[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 ati28800_in(uint16_t addr, void *p)
82 {
83 ati28800_t *ati28800 = (ati28800_t *)p;
84 svga_t *svga = &ati28800->svga;
85 uint8_t temp;
87 // if (addr != 0x3da) pclog("ati28800_in : %04X ", addr);
89 if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
91 switch (addr)
92 {
93 case 0x1ce:
94 temp = ati28800->index;
95 break;
96 case 0x1cf:
97 switch (ati28800->index)
98 {
99 case 0xb7:
100 temp = ati28800->regs[ati28800->index] & ~8;
101 if (ati_eeprom_read(&ati28800->eeprom))
102 temp |= 8;
103 break;
105 default:
106 temp = ati28800->regs[ati28800->index];
107 break;
108 }
109 break;
111 case 0x3c2:
112 if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
113 temp = 0;
114 else
115 temp = 0x10;
116 break;
117 case 0x3D4:
118 temp = svga->crtcreg;
119 break;
120 case 0x3D5:
121 temp = svga->crtc[svga->crtcreg];
122 break;
123 default:
124 temp = svga_in(addr, svga);
125 break;
126 }
127 if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
128 return temp;
129 }
131 void ati28800_recalctimings(svga_t *svga)
132 {
133 ati28800_t *ati28800 = (ati28800_t *)svga->p;
134 pclog("ati28800_recalctimings\n");
135 if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
136 {
137 pclog("8bpp_highres\n");
138 svga->render = svga_render_8bpp_highres;
139 svga->rowoffset <<= 1;
140 svga->ma <<= 1;
141 }
142 }
144 void *ati28800_init()
145 {
146 ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
147 memset(ati28800, 0, sizeof(ati28800_t));
149 rom_init(&ati28800->bios_rom, "roms/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
151 svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
152 ati28800_recalctimings,
153 ati28800_in, ati28800_out,
154 NULL,
155 NULL);
157 io_sethandler(0x01ce, 0x0002, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, ati28800);
158 io_sethandler(0x03c0, 0x0020, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, ati28800);
160 ati28800->svga.miscout = 1;
162 ati_eeprom_load(&ati28800->eeprom, "ati28800.nvr", 0);
164 return ati28800;
165 }
167 static int ati28800_available()
168 {
169 return rom_present("roms/bios.bin");
170 }
172 void ati28800_close(void *p)
173 {
174 ati28800_t *ati28800 = (ati28800_t *)p;
176 svga_close(&ati28800->svga);
178 free(ati28800);
179 }
181 void ati28800_speed_changed(void *p)
182 {
183 ati28800_t *ati28800 = (ati28800_t *)p;
185 svga_recalctimings(&ati28800->svga);
186 }
188 void ati28800_force_redraw(void *p)
189 {
190 ati28800_t *ati28800 = (ati28800_t *)p;
192 ati28800->svga.fullchange = changeframecount;
193 }
195 void ati28800_add_status_info(char *s, int max_len, void *p)
196 {
197 ati28800_t *ati28800 = (ati28800_t *)p;
199 svga_add_status_info(s, max_len, &ati28800->svga);
200 }
202 device_t ati28800_device =
203 {
204 "ATI-28800",
205 0,
206 ati28800_init,
207 ati28800_close,
208 ati28800_available,
209 ati28800_speed_changed,
210 ati28800_force_redraw,
211 ati28800_add_status_info
212 };