trunk/src/emu/bus/isa/trident.c
| r32016 | r32017 | |
| 18 | 18 | { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | void trident_vga_device::device_start() |
| 22 | { |
| 23 | svga_device::device_start(); |
| 24 | vga.svga_intf.seq_regcount = 0x0f; |
| 25 | vga.svga_intf.crtc_regcount = 0x50; |
| 26 | memset(&tri, 0, sizeof(tri)); |
| 27 | } |
| 28 | |
| 29 | void trident_vga_device::device_reset() |
| 30 | { |
| 31 | svga_device::device_reset(); |
| 32 | svga.id = 0xd3; // identifies at TGUI9660XGi (closest known to the 9680) |
| 33 | tri.new_mode = false; // start up in old mode |
| 34 | } |
| 35 | |
| 36 | void trident_vga_device::trident_define_video_mode() |
| 37 | { |
| 38 | int divisor = 1; |
| 39 | int xtal; |
| 40 | |
| 41 | switch(tri.clock) |
| 42 | { |
| 43 | case 0: |
| 44 | default: xtal = XTAL_25_1748MHz; break; |
| 45 | case 1: xtal = XTAL_28_63636MHz; break; |
| 46 | case 2: xtal = 44900000; break; |
| 47 | case 3: xtal = 36000000; break; |
| 48 | case 4: xtal = 57272000; break; |
| 49 | case 5: xtal = 65000000; break; |
| 50 | case 6: xtal = 50350000; break; |
| 51 | case 7: xtal = 40000000; break; |
| 52 | case 8: xtal = 88000000; break; |
| 53 | case 9: xtal = 98000000; break; |
| 54 | case 10: xtal = 118800000; break; |
| 55 | case 11: xtal = 108000000; break; |
| 56 | case 12: xtal = 72000000; break; |
| 57 | case 13: xtal = 77000000; break; |
| 58 | case 14: xtal = 80000000; break; |
| 59 | case 15: xtal = 75000000; break; |
| 60 | } |
| 61 | |
| 62 | switch((tri.sr0d_new & 0x06) >> 1) |
| 63 | { |
| 64 | case 0: |
| 65 | default: break; // no division |
| 66 | case 1: xtal = xtal / 2; break; |
| 67 | case 2: xtal = xtal / 4; break; |
| 68 | case 3: xtal = xtal / 1.5; break; |
| 69 | } |
| 70 | |
| 71 | // TODO: determine when 8 bit modes are selected |
| 72 | svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0; |
| 73 | switch((tri.pixel_depth & 0x0c) >> 2) |
| 74 | { |
| 75 | case 0: |
| 76 | default: if(!(tri.pixel_depth & 0x10)) svga.rgb8_en = 1; break; |
| 77 | case 1: svga.rgb16_en = 1; break; // for 15 or 16 bit modes, can we tell the difference? |
| 78 | case 2: svga.rgb32_en = 1; break; |
| 79 | } |
| 80 | |
| 81 | recompute_params_clock(divisor, xtal); |
| 82 | } |
| 83 | |
| 21 | 84 | UINT8 trident_vga_device::trident_seq_reg_read(UINT8 index) |
| 22 | 85 | { |
| 23 | 86 | UINT8 res; |
| r32016 | r32017 | |
| 32 | 95 | { |
| 33 | 96 | case 0x0b: |
| 34 | 97 | res = svga.id; |
| 35 | | // TODO: new mode registers selected |
| 98 | tri.new_mode = true; |
| 36 | 99 | break; |
| 37 | | case 0x0d: |
| 38 | | res = svga.rgb15_en; |
| 100 | case 0x0c: // Power Up Mode register 1 |
| 101 | res = tri.sr0c & 0xef; |
| 102 | if(tri.port_3c3) |
| 103 | res |= 0x10; |
| 104 | case 0x0d: // Mode Control 2 |
| 105 | //res = svga.rgb15_en; |
| 106 | if(tri.new_mode) |
| 107 | res = tri.sr0d_new; |
| 108 | else |
| 109 | res = tri.sr0d_old; |
| 39 | 110 | break; |
| 111 | case 0x0e: // Mode Control 1 |
| 112 | if(tri.new_mode) |
| 113 | res = tri.sr0e_new; |
| 114 | else |
| 115 | res = tri.sr0e_old; |
| 116 | break; |
| 117 | case 0x0f: // Power Up Mode 2 |
| 118 | res = tri.sr0f; |
| 119 | break; |
| 40 | 120 | } |
| 41 | 121 | } |
| 42 | 122 | |
| r32016 | r32017 | |
| 56 | 136 | switch(index) |
| 57 | 137 | { |
| 58 | 138 | case 0x0b: |
| 59 | | // TODO: old mode registers selected |
| 139 | tri.new_mode = false; |
| 60 | 140 | break; |
| 61 | | case 0x0d: |
| 62 | | svga.rgb15_en = data & 0x30; // TODO: doesn't match documentation |
| 141 | case 0x0c: // Power Up Mode register 1 |
| 142 | if(data & 0x10) |
| 143 | tri.port_3c3 = true; // 'post port at 0x3c3' |
| 144 | else |
| 145 | tri.port_3c3 = false; // 'post port at 0x46e8' |
| 146 | tri.sr0c = data; |
| 63 | 147 | break; |
| 148 | case 0x0d: // Mode Control 2 |
| 149 | //svga.rgb15_en = data & 0x30; // TODO: doesn't match documentation |
| 150 | if(tri.new_mode) |
| 151 | { |
| 152 | tri.sr0d_new = data; |
| 153 | tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3); |
| 154 | trident_define_video_mode(); |
| 155 | } |
| 156 | else |
| 157 | tri.sr0d_old = data; |
| 158 | break; |
| 159 | case 0x0e: // Mode Control 1 |
| 160 | if(tri.new_mode) |
| 161 | { |
| 162 | tri.sr0e_new = data ^ 0x02; |
| 163 | svga.bank_w = (data & 0x0f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading |
| 164 | if(!(tri.gc0f & 0x01)) |
| 165 | svga.bank_r = (data & 0x0f) ^ 0x02; |
| 166 | // TODO: handle planar modes, where bits 0 and 2 only are used |
| 167 | } |
| 168 | else |
| 169 | { |
| 170 | tri.sr0e_old = data; |
| 171 | svga.bank_w = data & 0x06; |
| 172 | if(!(tri.gc0f & 0x01)) |
| 173 | svga.bank_r = data & 0x06; |
| 174 | } |
| 175 | break; |
| 176 | case 0x0f: // Power Up Mode 2 |
| 177 | tri.sr0f = data; |
| 178 | break; |
| 64 | 179 | } |
| 65 | 180 | } |
| 66 | 181 | } |
| 67 | 182 | |
| 183 | UINT8 trident_vga_device::trident_crtc_reg_read(UINT8 index) |
| 184 | { |
| 185 | UINT8 res; |
| 68 | 186 | |
| 187 | if(index <= 0x18) |
| 188 | res = crtc_reg_read(index); |
| 189 | else |
| 190 | { |
| 191 | switch(index) |
| 192 | { |
| 193 | case 0x1f: |
| 194 | res = tri.cr1f; |
| 195 | break; |
| 196 | case 0x38: |
| 197 | res = tri.pixel_depth; |
| 198 | break; |
| 199 | default: |
| 200 | res = vga.crtc.data[index]; |
| 201 | break; |
| 202 | } |
| 203 | } |
| 204 | return res; |
| 205 | } |
| 206 | void trident_vga_device::trident_crtc_reg_write(UINT8 index, UINT8 data) |
| 207 | { |
| 208 | if(index <= 0x18) |
| 209 | { |
| 210 | crtc_reg_write(index,data); |
| 211 | trident_define_video_mode(); |
| 212 | } |
| 213 | else |
| 214 | { |
| 215 | switch(index) |
| 216 | { |
| 217 | case 0x1f: |
| 218 | tri.cr1f = data; // "Software Programming Register" written to by software (BIOS?) |
| 219 | break; |
| 220 | case 0x38: |
| 221 | tri.pixel_depth = data; |
| 222 | trident_define_video_mode(); |
| 223 | break; |
| 224 | default: |
| 225 | logerror("Trident: 3D4 index %02x write %02x\n",index,data); |
| 226 | break; |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | UINT8 trident_vga_device::trident_gc_reg_read(UINT8 index) |
| 232 | { |
| 233 | UINT8 res; |
| 234 | |
| 235 | if(index <= 0x0d) |
| 236 | res = gc_reg_read(index); |
| 237 | else |
| 238 | { |
| 239 | switch(index) |
| 240 | { |
| 241 | case 0x0e: |
| 242 | res = tri.gc0e; |
| 243 | break; |
| 244 | case 0x0f: |
| 245 | res = tri.gc0f; |
| 246 | break; |
| 247 | default: |
| 248 | res = 0xff; |
| 249 | break; |
| 250 | } |
| 251 | } |
| 252 | return res; |
| 253 | } |
| 254 | |
| 255 | void trident_vga_device::trident_gc_reg_write(UINT8 index, UINT8 data) |
| 256 | { |
| 257 | if(index <= 0x0d) |
| 258 | gc_reg_write(index,data); |
| 259 | else |
| 260 | { |
| 261 | switch(index) |
| 262 | { |
| 263 | case 0x0e: // New Source Address Register (bit 1 is inverted here, also) |
| 264 | tri.gc0e = data ^ 0x02; |
| 265 | if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled |
| 266 | { |
| 267 | if(tri.gc0f & 0x01) // if bank regs are separated |
| 268 | svga.bank_r = (data & 0x1f) ^ 0x02; |
| 269 | } |
| 270 | break; |
| 271 | case 0x0f: |
| 272 | tri.gc0f = data; |
| 273 | break; |
| 274 | default: |
| 275 | logerror("Trident: Unimplemented GC register %02x write %02x\n",index,data); |
| 276 | break; |
| 277 | } |
| 278 | } |
| 279 | } |
| 280 | |
| 69 | 281 | READ8_MEMBER(trident_vga_device::port_03c0_r) |
| 70 | 282 | { |
| 71 | 283 | UINT8 res; |
| r32016 | r32017 | |
| 75 | 287 | case 0x05: |
| 76 | 288 | res = trident_seq_reg_read(vga.sequencer.index); |
| 77 | 289 | break; |
| 290 | case 0x0f: |
| 291 | res = trident_gc_reg_read(vga.gc.index); |
| 292 | break; |
| 78 | 293 | default: |
| 79 | 294 | res = vga_device::port_03c0_r(space,offset,mem_mask); |
| 80 | 295 | break; |
| r32016 | r32017 | |
| 90 | 305 | case 0x05: |
| 91 | 306 | trident_seq_reg_write(vga.sequencer.index,data); |
| 92 | 307 | break; |
| 308 | case 0x0f: |
| 309 | trident_gc_reg_write(vga.gc.index,data); |
| 310 | break; |
| 93 | 311 | default: |
| 94 | 312 | vga_device::port_03c0_w(space,offset,data,mem_mask); |
| 95 | 313 | break; |
| r32016 | r32017 | |
| 105 | 323 | { |
| 106 | 324 | switch(offset) |
| 107 | 325 | { |
| 326 | case 5: |
| 327 | res = trident_crtc_reg_read(vga.crtc.index); |
| 328 | break; |
| 108 | 329 | case 8: |
| 109 | | res = svga.bank_w & 0x1f; // TODO: a lot more complex than this |
| 330 | if(tri.gc0f & 0x04) // if enabled |
| 331 | res = svga.bank_w & 0x1f; |
| 332 | else |
| 333 | res = 0xff; |
| 110 | 334 | break; |
| 335 | case 9: |
| 336 | if(tri.gc0f & 0x04) // if enabled |
| 337 | if(tri.gc0f & 0x01) // and if bank regs are separated |
| 338 | res = svga.bank_r & 0x1f; |
| 339 | else |
| 340 | res = 0xff; |
| 341 | else |
| 342 | res = 0xff; |
| 343 | break; |
| 111 | 344 | default: |
| 112 | 345 | res = vga_device::port_03d0_r(space,offset,mem_mask); |
| 113 | 346 | break; |
| r32016 | r32017 | |
| 123 | 356 | { |
| 124 | 357 | switch(offset) |
| 125 | 358 | { |
| 359 | case 5: |
| 360 | vga.crtc.data[vga.crtc.index] = data; |
| 361 | trident_crtc_reg_write(vga.crtc.index,data); |
| 362 | break; |
| 126 | 363 | case 8: |
| 127 | | svga.bank_w = data & 0x1f; // TODO: a lot more complex than this |
| 364 | if(tri.gc0f & 0x04) // if enabled |
| 365 | { |
| 366 | svga.bank_w = data & 0x1f; |
| 367 | if(!(tri.gc0f & 0x01)) // if bank regs are not separated |
| 368 | svga.bank_r = data & 0x1f; // then this is also the read bank register |
| 369 | } |
| 128 | 370 | break; |
| 371 | case 9: |
| 372 | if(tri.gc0f & 0x04) // if enabled |
| 373 | { |
| 374 | if(tri.gc0f & 0x01) // and if bank regs are separated |
| 375 | svga.bank_r = data & 0x1f; |
| 376 | } |
| 377 | break; |
| 129 | 378 | default: |
| 130 | 379 | vga_device::port_03d0_w(space,offset,data,mem_mask); |
| 131 | 380 | break; |
| r32016 | r32017 | |
| 135 | 384 | |
| 136 | 385 | READ8_MEMBER(trident_vga_device::mem_r ) |
| 137 | 386 | { |
| 138 | | if (svga.rgb15_en & 0x30) |
| 387 | if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) |
| 139 | 388 | { |
| 140 | 389 | int data; |
| 141 | | if(offset & 0x10000) // TODO: old reg mode actually CAN read to the upper bank |
| 142 | | return 0; |
| 143 | | data=vga.memory[offset + (svga.bank_w*0x10000)]; |
| 390 | |
| 391 | if(tri.new_mode) // 64k from 0xA0000-0xAFFFF |
| 392 | { |
| 393 | offset &= 0xffff; |
| 394 | data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; |
| 395 | } |
| 396 | else // 128k from 0xA0000-0xBFFFF |
| 397 | { |
| 398 | data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; |
| 399 | } |
| 144 | 400 | return data; |
| 145 | 401 | } |
| 146 | 402 | |
| r32016 | r32017 | |
| 149 | 405 | |
| 150 | 406 | WRITE8_MEMBER(trident_vga_device::mem_w) |
| 151 | 407 | { |
| 152 | | if (svga.rgb15_en & 0x30) |
| 408 | if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) |
| 153 | 409 | { |
| 154 | | if(offset & 0x10000) // TODO: old reg mode actually CAN write to the upper bank |
| 155 | | return; |
| 156 | | vga.memory[offset + (svga.bank_w*0x10000)]= data; |
| 410 | if(tri.new_mode) // 64k from 0xA0000-0xAFFFF |
| 411 | { |
| 412 | offset &= 0xffff; |
| 413 | vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; |
| 414 | } |
| 415 | else // 128k from 0xA0000-0xBFFFF |
| 416 | { |
| 417 | vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; |
| 418 | } |
| 157 | 419 | return; |
| 158 | 420 | } |
| 159 | 421 | |