PCem
changeset 120:47132154ffe7
Added emulation of Phoenix Trio32. Based on patch from Battler.
Paradise Bahamas 64, Number Nine 9FX and Phoenix Trio32 now have configurable memory sizes.
| author | TomW |
|---|---|
| date | Wed Jul 09 21:45:42 2014 +0100 |
| parents | e4da69090d05 |
| children | 173e1f058566 |
| files | src/ibm.h src/vid_s3.c src/vid_s3.h src/video.c |
| diffstat | 4 files changed, 229 insertions(+), 52 deletions(-) [+] |
line diff
1.1 --- a/src/ibm.h Wed Jul 09 19:21:16 2014 +0100 1.2 +++ b/src/ibm.h Wed Jul 09 21:45:42 2014 +0100 1.3 @@ -346,6 +346,7 @@ 1.4 GFX_MACH64GX, /*ATI Graphics Pro Turbo (Mach64)*/ 1.5 GFX_CL_GD5429, /*Cirrus Logic CL-GD5429*/ 1.6 GFX_VIRGEDX, /*S3 Virge/DX*/ 1.7 + GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/ 1.8 1.9 GFX_MAX 1.10 };
2.1 --- a/src/vid_s3.c Wed Jul 09 19:21:16 2014 +0100 2.2 +++ b/src/vid_s3.c Wed Jul 09 21:45:42 2014 +0100 2.3 @@ -12,6 +12,22 @@ 2.4 #include "vid_svga_render.h" 2.5 #include "vid_sdac_ramdac.h" 2.6 2.7 +enum 2.8 +{ 2.9 + S3_VISION864, 2.10 + S3_TRIO32, 2.11 + S3_TRIO64 2.12 +}; 2.13 + 2.14 +enum 2.15 +{ 2.16 + VRAM_4MB = 0, 2.17 + VRAM_8MB = 3, 2.18 + VRAM_2MB = 4, 2.19 + VRAM_1MB = 6, 2.20 + VRAM_512KB = 7 2.21 +}; 2.22 + 2.23 typedef struct s3_t 2.24 { 2.25 mem_mapping_t linear_mapping; 2.26 @@ -27,7 +43,9 @@ 2.27 int width; 2.28 int bpp; 2.29 2.30 - uint8_t id, id_ext; 2.31 + int chip; 2.32 + 2.33 + uint8_t id, id_ext, id_ext_pci; 2.34 2.35 int packed_mmio; 2.36 2.37 @@ -35,6 +53,8 @@ 2.38 2.39 uint8_t pci_regs[256]; 2.40 2.41 + uint32_t vram_mask; 2.42 + 2.43 float (*getclock)(int clock, void *p); 2.44 void *getclock_p; 2.45 2.46 @@ -90,7 +110,7 @@ 2.47 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) 2.48 addr ^= 0x60; 2.49 2.50 -// pclog("S3 out %04X %02X\n", addr, val); 2.51 +// pclog("S3 out %04X %02X %04x:%08x\n", addr, val, CS, pc); 2.52 2.53 switch (addr) 2.54 { 2.55 @@ -121,7 +141,6 @@ 2.56 svga->crtcreg = val & 0x7f; 2.57 return; 2.58 case 0x3D5: 2.59 -// if (crtcreg == 0x67) pclog("Write CRTC R%02X %02X\n", crtcreg, val); 2.60 if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return; 2.61 if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; 2.62 old = svga->crtc[svga->crtcreg]; 2.63 @@ -130,7 +149,7 @@ 2.64 { 2.65 case 0x31: 2.66 s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); 2.67 - svga->vrammask = /*(val & 8) ? */0x3fffff/* : 0x3ffff*/; 2.68 + svga->vrammask = /*(val & 8) ? */s3->vram_mask/* : 0x3ffff*/; 2.69 break; 2.70 2.71 case 0x50: 2.72 @@ -184,7 +203,7 @@ 2.73 svga->hwcursor.xoff = svga->crtc[0x4e] & 63; 2.74 svga->hwcursor.yoff = svga->crtc[0x4f] & 63; 2.75 svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); 2.76 - if (gfxcard == GFX_N9_9FX && svga->bpp == 32) /*Trio64*/ 2.77 + if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32) 2.78 svga->hwcursor.x <<= 1; 2.79 break; 2.80 2.81 @@ -194,7 +213,7 @@ 2.82 break; 2.83 2.84 case 0x67: 2.85 - if (gfxcard == GFX_N9_9FX) /*Trio64*/ 2.86 + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) 2.87 { 2.88 switch (val >> 4) 2.89 { 2.90 @@ -230,7 +249,7 @@ 2.91 if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) 2.92 addr ^= 0x60; 2.93 2.94 -// if (addr != 0x3da) pclog("S3 in %04X\n", addr); 2.95 +// if (addr != 0x3da) pclog("S3 in %04X %08x:%02x\n", addr, CS, pc); 2.96 switch (addr) 2.97 { 2.98 case 0x3c5: 2.99 @@ -245,11 +264,12 @@ 2.100 case 0x3d4: 2.101 return svga->crtcreg; 2.102 case 0x3d5: 2.103 -// pclog("Read CRTC R%02X %04X:%04X\n", svga->crtcreg, CS, pc); 2.104 +// pclog("Read CRTC R%02X %02x %04X:%04X\n", svga->crtcreg, svga->crtc[svga->crtcreg], CS, pc); 2.105 switch (svga->crtcreg) 2.106 { 2.107 case 0x2d: return 0x88; /*Extended chip ID*/ 2.108 case 0x2e: return s3->id_ext; /*New chip ID*/ 2.109 + case 0x2f: return 0; /*Revision level*/ 2.110 case 0x30: return s3->id; /*Chip ID*/ 2.111 case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); 2.112 case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); 2.113 @@ -317,7 +337,7 @@ 2.114 break; 2.115 case 32: 2.116 svga->render = svga_render_32bpp_highres; 2.117 - if (gfxcard != GFX_N9_9FX) /*Trio64*/ 2.118 + if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64) 2.119 svga->hdisp /= 4; 2.120 break; 2.121 } 2.122 @@ -1084,9 +1104,9 @@ 2.123 return 0; 2.124 } 2.125 2.126 -#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & 0x3fffff]; \ 2.127 - else if (s3->bpp == 1) dat = vram_w[(addr) & 0x1fffff]; \ 2.128 - else dat = vram_l[(addr) & 0x0fffff]; 2.129 +#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ 2.130 + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ 2.131 + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; 2.132 2.133 #define MIX switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ 2.134 { \ 2.135 @@ -1109,20 +1129,20 @@ 2.136 } 2.137 2.138 2.139 -#define WRITE(addr) if (s3->bpp == 0) \ 2.140 +#define WRITE(addr) if (s3->bpp == 0) \ 2.141 { \ 2.142 - svga->vram[(addr) & 0x3fffff] = dest_dat; \ 2.143 - svga->changedvram[((addr) & 0x3fffff) >> 12] = changeframecount; \ 2.144 + svga->vram[(addr) & s3->vram_mask] = dest_dat; \ 2.145 + svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ 2.146 } \ 2.147 - else if (s3->bpp == 1) \ 2.148 + else if (s3->bpp == 1) \ 2.149 { \ 2.150 - vram_w[(addr) & 0x1fffff] = dest_dat; \ 2.151 - svga->changedvram[((addr) & 0x1fffff) >> 11] = changeframecount; \ 2.152 + vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ 2.153 + svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ 2.154 } \ 2.155 else \ 2.156 { \ 2.157 - vram_l[(addr) & 0xfffff] = dest_dat; \ 2.158 - svga->changedvram[((addr) & 0xfffff) >> 10] = changeframecount; \ 2.159 + vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ 2.160 + svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ 2.161 } 2.162 2.163 void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) 2.164 @@ -1795,7 +1815,7 @@ 2.165 case 0x00: return 0x33; /*'S3'*/ 2.166 case 0x01: return 0x53; 2.167 2.168 - case 0x02: return s3->id_ext; 2.169 + case 0x02: return s3->id_ext_pci; 2.170 case 0x03: return 0x88; 2.171 2.172 case PCI_REG_COMMAND: 2.173 @@ -1826,7 +1846,7 @@ 2.174 { 2.175 s3_t *s3 = (s3_t *)p; 2.176 svga_t *svga = &s3->svga; 2.177 - pclog("s3_pci_write: addr=%02x val=%02x\n", addr, val); 2.178 +// pclog("s3_pci_write: addr=%02x val=%02x\n", addr, val); 2.179 switch (addr) 2.180 { 2.181 case PCI_REG_COMMAND: 2.182 @@ -1852,23 +1872,46 @@ 2.183 if (s3->pci_regs[0x30] & 0x01) 2.184 { 2.185 uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); 2.186 - pclog("S3 bios_rom enabled at %08x\n", addr); 2.187 +// pclog("S3 bios_rom enabled at %08x\n", addr); 2.188 mem_mapping_set_addr(&s3->bios_rom.mapping, addr, 0x8000); 2.189 } 2.190 else 2.191 { 2.192 - pclog("S3 bios_rom disabled\n"); 2.193 +// pclog("S3 bios_rom disabled\n"); 2.194 mem_mapping_disable(&s3->bios_rom.mapping); 2.195 } 2.196 return; 2.197 } 2.198 } 2.199 2.200 -static void *s3_init(char *bios_fn) 2.201 +static int vram_sizes[] = 2.202 +{ 2.203 + 7, /*512 kB*/ 2.204 + 6, /*1 MB*/ 2.205 + 4, /*2 MB*/ 2.206 + 0, 2.207 + 0, /*4 MB*/ 2.208 + 0, 2.209 + 0, 2.210 + 0, 2.211 + 3 /*8 MB*/ 2.212 +}; 2.213 + 2.214 +static void *s3_init(char *bios_fn, int chip) 2.215 { 2.216 s3_t *s3 = malloc(sizeof(s3_t)); 2.217 svga_t *svga = &s3->svga; 2.218 + int vram; 2.219 + uint32_t vram_size; 2.220 + 2.221 memset(s3, 0, sizeof(s3_t)); 2.222 + 2.223 + vram = device_get_config_int("memory"); 2.224 + if (vram) 2.225 + vram_size = vram << 20; 2.226 + else 2.227 + vram_size = 512 << 10; 2.228 + s3->vram_mask = vram_size - 1; 2.229 2.230 rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); 2.231 if (PCI) 2.232 @@ -1878,13 +1921,16 @@ 2.233 mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3); 2.234 mem_mapping_disable(&s3->mmio_mapping); 2.235 2.236 - svga_init(&s3->svga, s3, 1 << 22, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ 2.237 + svga_init(&s3->svga, s3, vram_size, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ 2.238 s3_recalctimings, 2.239 s3_in, s3_out, 2.240 s3_hwcursor_draw, 2.241 NULL); 2.242 2.243 - svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5); 2.244 + if (PCI) 2.245 + svga->crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (vram_sizes[vram] << 5); 2.246 + else 2.247 + svga->crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (vram_sizes[vram] << 5); 2.248 svga->crtc[0x37] = 1 | (7 << 5); 2.249 2.250 s3_io_set(s3); 2.251 @@ -1896,16 +1942,18 @@ 2.252 s3->pci_regs[0x30] = 0x00; 2.253 s3->pci_regs[0x32] = 0x0c; 2.254 s3->pci_regs[0x33] = 0x00; 2.255 + 2.256 + s3->chip = chip; 2.257 2.258 return s3; 2.259 } 2.260 2.261 void *s3_bahamas64_init() 2.262 { 2.263 - s3_t *s3 = s3_init("roms/bahamas64.bin"); 2.264 + s3_t *s3 = s3_init("roms/bahamas64.bin", S3_VISION864); 2.265 2.266 s3->id = 0xc1; /*Vision864P*/ 2.267 - s3->id_ext = 0xc1; 2.268 + s3->id_ext = s3->id_ext_pci = 0xc1; 2.269 s3->packed_mmio = 0; 2.270 2.271 s3->getclock = sdac_getclock; 2.272 @@ -1921,10 +1969,10 @@ 2.273 2.274 void *s3_9fx_init() 2.275 { 2.276 - s3_t *s3 = s3_init("roms/s3_764.bin"); 2.277 + s3_t *s3 = s3_init("roms/s3_764.bin", S3_TRIO64); 2.278 2.279 s3->id = 0xe1; /*Trio64*/ 2.280 - s3->id_ext = 0x11; 2.281 + s3->id_ext = s3->id_ext_pci = 0x11; 2.282 s3->packed_mmio = 1; 2.283 2.284 s3->getclock = s3_trio64_getclock; 2.285 @@ -1938,6 +1986,26 @@ 2.286 return rom_present("roms/s3_764.bin"); 2.287 } 2.288 2.289 +void *s3_phoenix_trio32_init() 2.290 +{ 2.291 + s3_t *s3 = s3_init("roms/86C732P.bin", S3_TRIO32); 2.292 + svga_t *svga = &s3->svga; 2.293 + 2.294 + s3->id = 0xe1; /*Trio32*/ 2.295 + s3->id_ext = 0x10; 2.296 + s3->id_ext_pci = 0x11; 2.297 + s3->packed_mmio = 1; 2.298 + 2.299 + s3->getclock = s3_trio64_getclock; 2.300 + s3->getclock_p = s3; 2.301 + 2.302 + return s3; 2.303 +} 2.304 + 2.305 +int s3_phoenix_trio32_available() 2.306 +{ 2.307 + return rom_present("roms/86C732P.bin"); 2.308 +} 2.309 2.310 void s3_close(void *p) 2.311 { 2.312 @@ -1969,6 +2037,97 @@ 2.313 return svga_add_status_info(s, max_len, &s3->svga); 2.314 } 2.315 2.316 +static device_config_t s3_bahamas64_config[] = 2.317 +{ 2.318 + { 2.319 + .name = "memory", 2.320 + .description = "Memory size", 2.321 + .type = CONFIG_SELECTION, 2.322 + .selection = 2.323 + { 2.324 + { 2.325 + .description = "1 MB", 2.326 + .value = 1 2.327 + }, 2.328 + { 2.329 + .description = "2 MB", 2.330 + .value = 2 2.331 + }, 2.332 + { 2.333 + .description = "4 MB", 2.334 + .value = 4 2.335 + }, 2.336 + /*Vision864 also supports 8 MB, however the Paradise BIOS is buggy (VESA modes don't work correctly)*/ 2.337 + { 2.338 + .description = "" 2.339 + } 2.340 + }, 2.341 + .default_int = 4 2.342 + }, 2.343 + { 2.344 + .type = -1 2.345 + } 2.346 +}; 2.347 + 2.348 +static device_config_t s3_9fx_config[] = 2.349 +{ 2.350 + { 2.351 + .name = "memory", 2.352 + .description = "Memory size", 2.353 + .type = CONFIG_SELECTION, 2.354 + .selection = 2.355 + { 2.356 + { 2.357 + .description = "1 MB", 2.358 + .value = 1 2.359 + }, 2.360 + { 2.361 + .description = "2 MB", 2.362 + .value = 2 2.363 + }, 2.364 + /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ 2.365 + { 2.366 + .description = "" 2.367 + } 2.368 + }, 2.369 + .default_int = 2 2.370 + }, 2.371 + { 2.372 + .type = -1 2.373 + } 2.374 +}; 2.375 + 2.376 +static device_config_t s3_phoenix_trio32_config[] = 2.377 +{ 2.378 + { 2.379 + .name = "memory", 2.380 + .description = "Memory size", 2.381 + .type = CONFIG_SELECTION, 2.382 + .selection = 2.383 + { 2.384 + { 2.385 + .description = "512 KB", 2.386 + .value = 0 2.387 + }, 2.388 + { 2.389 + .description = "1 MB", 2.390 + .value = 1 2.391 + }, 2.392 + { 2.393 + .description = "2 MB", 2.394 + .value = 2 2.395 + }, 2.396 + { 2.397 + .description = "" 2.398 + } 2.399 + }, 2.400 + .default_int = 2 2.401 + }, 2.402 + { 2.403 + .type = -1 2.404 + } 2.405 +}; 2.406 + 2.407 device_t s3_bahamas64_device = 2.408 { 2.409 "Paradise Bahamas 64 (S3 Vision864)", 2.410 @@ -1978,7 +2137,8 @@ 2.411 s3_bahamas64_available, 2.412 s3_speed_changed, 2.413 s3_force_redraw, 2.414 - s3_add_status_info 2.415 + s3_add_status_info, 2.416 + s3_bahamas64_config 2.417 }; 2.418 2.419 device_t s3_9fx_device = 2.420 @@ -1990,5 +2150,19 @@ 2.421 s3_9fx_available, 2.422 s3_speed_changed, 2.423 s3_force_redraw, 2.424 - s3_add_status_info 2.425 + s3_add_status_info, 2.426 + s3_9fx_config 2.427 }; 2.428 + 2.429 +device_t s3_phoenix_trio32_device = 2.430 +{ 2.431 + "Phoenix S3 Trio32", 2.432 + 0, 2.433 + s3_phoenix_trio32_init, 2.434 + s3_close, 2.435 + s3_phoenix_trio32_available, 2.436 + s3_speed_changed, 2.437 + s3_force_redraw, 2.438 + s3_add_status_info, 2.439 + s3_phoenix_trio32_config 2.440 +};
3.1 --- a/src/vid_s3.h Wed Jul 09 19:21:16 2014 +0100 3.2 +++ b/src/vid_s3.h Wed Jul 09 21:45:42 2014 +0100 3.3 @@ -1,2 +1,3 @@ 3.4 device_t s3_bahamas64_device; 3.5 device_t s3_9fx_device; 3.6 +device_t s3_phoenix_trio32_device;
4.1 --- a/src/video.c Wed Jul 09 19:21:16 2014 +0100 4.2 +++ b/src/video.c Wed Jul 09 21:45:42 2014 +0100 4.3 @@ -44,25 +44,26 @@ 4.4 4.5 static VIDEO_CARD video_cards[] = 4.6 { 4.7 - {"CGA", &cga_device, GFX_CGA}, 4.8 - {"MDA", &mda_device, GFX_MDA}, 4.9 - {"Hercules", &hercules_device, GFX_HERCULES}, 4.10 - {"EGA", &ega_device, GFX_EGA}, 4.11 - {"Trident TVGA8900D", &tvga8900d_device, GFX_TVGA}, 4.12 - {"Tseng ET4000AX", &et4000_device, GFX_ET4000}, 4.13 - {"Diamond Stealth 32 (Tseng ET4000/w32p)", &et4000w32p_device, GFX_ET4000W32}, 4.14 - {"Paradise Bahamas 64 (S3 Vision864)", &s3_bahamas64_device, GFX_BAHAMAS64}, 4.15 - {"Number Nine 9FX (S3 Trio64)", &s3_9fx_device, GFX_N9_9FX}, 4.16 - {"Diamond Stealth 3D 2000 (S3 ViRGE)", &s3_virge_device, GFX_VIRGE}, 4.17 - {"S3 ViRGE/DX", &s3_virge_375_device, GFX_VIRGEDX}, 4.18 - {"Trident TGUI9440", &tgui9440_device, GFX_TGUI9440}, 4.19 - {"VGA", &vga_device, GFX_VGA}, 4.20 - {"ATI VGA Edge-16 (ATI-18800)", &ati18800_device, GFX_VGAEDGE16}, 4.21 - {"ATI VGA Charger", &ati28800_device, GFX_VGACHARGER}, 4.22 - {"OAK OTI-067", &oti067_device, GFX_OTI067}, 4.23 - {"ATI Graphics Pro Turbo (Mach64 GX)", &mach64gx_device, GFX_MACH64GX}, 4.24 - {"Cirrus Logic CL-GD5429", &gd5429_device, GFX_CL_GD5429}, 4.25 - {"", NULL, 0} 4.26 + {"ATI Graphics Pro Turbo (Mach64 GX)", &mach64gx_device, GFX_MACH64GX}, 4.27 + {"ATI VGA Charger (ATI-28800)", &ati28800_device, GFX_VGACHARGER}, 4.28 + {"ATI VGA Edge-16 (ATI-18800)", &ati18800_device, GFX_VGAEDGE16}, 4.29 + {"CGA", &cga_device, GFX_CGA}, 4.30 + {"Cirrus Logic CL-GD5429", &gd5429_device, GFX_CL_GD5429}, 4.31 + {"Diamond Stealth 32 (Tseng ET4000/w32p)", &et4000w32p_device, GFX_ET4000W32}, 4.32 + {"Diamond Stealth 3D 2000 (S3 ViRGE)", &s3_virge_device, GFX_VIRGE}, 4.33 + {"EGA", &ega_device, GFX_EGA}, 4.34 + {"Hercules", &hercules_device, GFX_HERCULES}, 4.35 + {"MDA", &mda_device, GFX_MDA}, 4.36 + {"Number Nine 9FX (S3 Trio64)", &s3_9fx_device, GFX_N9_9FX}, 4.37 + {"OAK OTI-067", &oti067_device, GFX_OTI067}, 4.38 + {"Paradise Bahamas 64 (S3 Vision864)", &s3_bahamas64_device, GFX_BAHAMAS64}, 4.39 + {"Phoenix S3 Trio32", &s3_phoenix_trio32_device, GFX_PHOENIX_TRIO32}, 4.40 + {"S3 ViRGE/DX", &s3_virge_375_device, GFX_VIRGEDX}, 4.41 + {"Trident TVGA8900D", &tvga8900d_device, GFX_TVGA}, 4.42 + {"Tseng ET4000AX", &et4000_device, GFX_ET4000}, 4.43 + {"Trident TGUI9440", &tgui9440_device, GFX_TGUI9440}, 4.44 + {"VGA", &vga_device, GFX_VGA}, 4.45 + {"", NULL, 0} 4.46 }; 4.47 4.48 int video_card_available(int card)
