PCem

changeset 113:f749363ad763

Added per-device configuration. Reworked configuration parser a bit. Added configuration for S3 ViRGE and 8-bit Sound Blasters. IRQ 2 routed to IRQ 9 on AT machines.
author TomW
date Mon Jun 30 21:31:28 2014 +0100
parents c5989dbbc2ce
children 9834054948fc
files src/Makefile.mingw src/config.c src/config.h src/device.c src/device.h src/pc.c src/pc.rc src/pic.c src/resources.h src/sound.c src/sound.h src/sound_sb.c src/vid_s3_virge.c src/video.c src/video.h src/win-config.c src/win-deviceconfig.c src/win.h
diffstat 18 files changed, 1077 insertions(+), 139 deletions(-) [+]
line diff
     1.1 --- a/src/Makefile.mingw	Tue Jun 24 21:15:42 2014 +0100
     1.2 +++ b/src/Makefile.mingw	Mon Jun 30 21:31:28 2014 +0100
     1.3 @@ -19,7 +19,7 @@
     1.4  	vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \
     1.5  	vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \
     1.6  	vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
     1.7 -	win-ddraw-fs.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \
     1.8 +	win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \
     1.9  	win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
    1.10  FMOBJ = dbopl.o
    1.11  SIDOBJ = convolve.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
     2.1 --- a/src/config.c	Tue Jun 24 21:15:42 2014 +0100
     2.2 +++ b/src/config.c	Mon Jun 30 21:31:28 2014 +0100
     2.3 @@ -1,9 +1,194 @@
     2.4  #include <stdio.h>
     2.5  #include <string.h>
     2.6 +#include <stdlib.h>
     2.7  #include "config.h"
     2.8  
     2.9  static char config_file[256];
    2.10  
    2.11 +typedef struct list_t
    2.12 +{
    2.13 +        struct list_t *next;
    2.14 +} list_t;
    2.15 +
    2.16 +static list_t config_head;
    2.17 +
    2.18 +typedef struct section_t
    2.19 +{
    2.20 +        struct list_t list;
    2.21 +        
    2.22 +        char name[256];
    2.23 +        
    2.24 +        struct list_t entry_head;
    2.25 +} section_t;
    2.26 +
    2.27 +typedef struct entry_t
    2.28 +{
    2.29 +        struct list_t list;
    2.30 +        
    2.31 +        char name[256];
    2.32 +        char data[256];
    2.33 +} entry_t;
    2.34 +
    2.35 +#define list_add(new, head)                             \
    2.36 +        {                                               \
    2.37 +                struct list_t *next = head;             \
    2.38 +                                                        \
    2.39 +                while (next->next)                      \
    2.40 +                        next = next->next;              \
    2.41 +                                                        \
    2.42 +                (next)->next = new;                     \
    2.43 +                (new)->next = NULL;                     \
    2.44 +        }
    2.45 +
    2.46 +void config_dump()
    2.47 +{
    2.48 +        section_t *current_section;
    2.49 +        
    2.50 +        pclog("Config data :\n");
    2.51 +        
    2.52 +        current_section = (section_t *)config_head.next;
    2.53 +        
    2.54 +        while (current_section)
    2.55 +        {
    2.56 +                entry_t *current_entry;
    2.57 +                
    2.58 +                pclog("[%s]\n", current_section->name);
    2.59 +                
    2.60 +                current_entry = (entry_t *)current_section->entry_head.next;
    2.61 +                
    2.62 +                while (current_entry)
    2.63 +                {
    2.64 +                        pclog("%s = %s\n", current_entry->name, current_entry->data);
    2.65 +
    2.66 +                        current_entry = (entry_t *)current_entry->list.next;
    2.67 +                }
    2.68 +
    2.69 +                current_section = (section_t *)current_section->list.next;
    2.70 +        }
    2.71 +}
    2.72 +
    2.73 +void config_free()
    2.74 +{
    2.75 +        section_t *current_section;
    2.76 +        current_section = (section_t *)config_head.next;
    2.77 +        
    2.78 +        while (current_section)
    2.79 +        {
    2.80 +                section_t *next_section = (section_t *)current_section->list.next;
    2.81 +                entry_t *current_entry;
    2.82 +                
    2.83 +                current_entry = (entry_t *)current_section->entry_head.next;
    2.84 +                
    2.85 +                while (current_entry)
    2.86 +                {
    2.87 +                        entry_t *next_entry = (entry_t *)current_entry->list.next;
    2.88 +                        
    2.89 +                        free(current_entry);
    2.90 +                        current_entry = next_entry;
    2.91 +                }
    2.92 +
    2.93 +                free(current_section);                
    2.94 +                current_section = next_section;
    2.95 +        }
    2.96 +}
    2.97 +
    2.98 +void config_load()
    2.99 +{
   2.100 +        FILE *f = fopen(config_file, "rt");
   2.101 +        section_t *current_section;
   2.102 +        
   2.103 +        memset(&config_head, 0, sizeof(list_t));
   2.104 +
   2.105 +        current_section = malloc(sizeof(section_t));
   2.106 +        memset(current_section, 0, sizeof(section_t));
   2.107 +        list_add(&current_section->list, &config_head);
   2.108 +
   2.109 +        if (!f)
   2.110 +                return;
   2.111 +
   2.112 +        while (1)
   2.113 +        {
   2.114 +                int c;
   2.115 +                char buffer[256];
   2.116 +
   2.117 +                fgets(buffer, 255, f);
   2.118 +                if (feof(f)) break;
   2.119 +                
   2.120 +                c = 0;
   2.121 +                
   2.122 +                while (buffer[c] == ' ' && buffer[c])
   2.123 +                      c++;
   2.124 +
   2.125 +                if (!buffer[c]) continue;
   2.126 +                
   2.127 +                if (buffer[c] == '#') /*Comment*/
   2.128 +                        continue;
   2.129 +
   2.130 +                if (buffer[c] == '[') /*Section*/
   2.131 +                {
   2.132 +                        section_t *new_section;
   2.133 +                        char name[256];
   2.134 +                        int d = 0;
   2.135 +                        
   2.136 +                        c++;
   2.137 +                        while (buffer[c] != ']' && buffer[c])
   2.138 +                                name[d++] = buffer[c++];
   2.139 +
   2.140 +                        if (buffer[c] != ']')
   2.141 +                                continue;
   2.142 +                        name[d] = 0;
   2.143 +                        
   2.144 +                        new_section = malloc(sizeof(section_t));
   2.145 +                        memset(new_section, 0, sizeof(section_t));
   2.146 +                        strncpy(new_section->name, name, 256);
   2.147 +                        list_add(&new_section->list, &config_head);
   2.148 +                        
   2.149 +                        current_section = new_section;
   2.150 +                        
   2.151 +//                        pclog("New section : %s %p\n", name, (void *)current_section);
   2.152 +                }
   2.153 +                else
   2.154 +                {
   2.155 +                        entry_t *new_entry;
   2.156 +                        char name[256];
   2.157 +                        int d = 0, data_pos;
   2.158 +
   2.159 +                        while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
   2.160 +                                name[d++] = buffer[c++];
   2.161 +                
   2.162 +                        if (!buffer[c]) continue;
   2.163 +                        name[d] = 0;
   2.164 +
   2.165 +                        while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])
   2.166 +                                c++;
   2.167 +                        
   2.168 +                        if (!buffer[c]) continue;
   2.169 +                        
   2.170 +                        data_pos = c;
   2.171 +                        while (buffer[c])
   2.172 +                        {
   2.173 +                                if (buffer[c] == '\n')
   2.174 +                                        buffer[c] = 0;
   2.175 +                                c++;
   2.176 +                        }
   2.177 +
   2.178 +                        new_entry = malloc(sizeof(entry_t));
   2.179 +                        memset(new_entry, 0, sizeof(entry_t));
   2.180 +                        strncpy(new_entry->name, name, 256);
   2.181 +                        strncpy(new_entry->data, &buffer[data_pos], 256);
   2.182 +                        list_add(&new_entry->list, &current_section->entry_head);
   2.183 +
   2.184 +//                        pclog("New data under section [%s] : %s = %s\n", current_section->name, new_entry->name, new_entry->data);
   2.185 +                }
   2.186 +        }
   2.187 +        
   2.188 +        fclose(f);
   2.189 +        
   2.190 +        config_dump();
   2.191 +}
   2.192 +
   2.193 +
   2.194 +
   2.195  void set_config_file(char *s)
   2.196  {
   2.197          strcpy(config_file, s);
   2.198 @@ -15,132 +200,139 @@
   2.199          fclose(f);
   2.200  }
   2.201  
   2.202 +static section_t *find_section(char *name)
   2.203 +{
   2.204 +        section_t *current_section;
   2.205 +        char blank[] = "";
   2.206 +        
   2.207 +        current_section = (section_t *)config_head.next;
   2.208 +        if (!name)
   2.209 +                name = blank;
   2.210 +
   2.211 +        while (current_section)
   2.212 +        {
   2.213 +                if (!strncmp(current_section->name, name, 256))
   2.214 +                        return current_section;
   2.215 +                
   2.216 +                current_section = (section_t *)current_section->list.next;
   2.217 +        }
   2.218 +        return NULL;
   2.219 +}
   2.220 +
   2.221 +static entry_t *find_entry(section_t *section, char *name)
   2.222 +{
   2.223 +        entry_t *current_entry;
   2.224 +        
   2.225 +        current_entry = (entry_t *)section->entry_head.next;
   2.226 +        
   2.227 +        while (current_entry)
   2.228 +        {
   2.229 +                if (!strncmp(current_entry->name, name, 256))
   2.230 +                        return current_entry;
   2.231 +
   2.232 +                current_entry = (entry_t *)current_entry->list.next;
   2.233 +        }
   2.234 +        return NULL;
   2.235 +}
   2.236 +
   2.237 +static section_t *create_section(char *name)
   2.238 +{
   2.239 +        section_t *new_section = malloc(sizeof(section_t));
   2.240 +
   2.241 +        memset(new_section, 0, sizeof(section_t));
   2.242 +        strncpy(new_section->name, name, 256);
   2.243 +        list_add(&new_section->list, &config_head);
   2.244 +        
   2.245 +        return new_section;
   2.246 +}
   2.247 +
   2.248 +static entry_t *create_entry(section_t *section, char *name)
   2.249 +{
   2.250 +        entry_t *new_entry = malloc(sizeof(entry_t));
   2.251 +        memset(new_entry, 0, sizeof(entry_t));
   2.252 +        strncpy(new_entry->name, name, 256);
   2.253 +        list_add(&new_entry->list, &section->entry_head);
   2.254 +        
   2.255 +        return new_entry;
   2.256 +}
   2.257 +        
   2.258  int get_config_int(char *head, char *name, int def)
   2.259  {
   2.260 -        char buffer[256];
   2.261 -        char name2[256];
   2.262 -        FILE *f = fopen(config_file, "rt");
   2.263 -        int c, d;
   2.264 -        int res = def;
   2.265 +        section_t *section;
   2.266 +        entry_t *entry;
   2.267 +        int value;
   2.268 +
   2.269 +        section = find_section(head);
   2.270          
   2.271 -        if (!f)
   2.272 -           return def;
   2.273 -           
   2.274 -//        pclog("Searching for %s\n", name);
   2.275 +        if (!section)
   2.276 +                return def;
   2.277 +                
   2.278 +        entry = find_entry(section, name);
   2.279 +
   2.280 +        if (!entry)
   2.281 +                return def;
   2.282          
   2.283 -        while (1)
   2.284 -        {
   2.285 -                fgets(buffer, 255, f);
   2.286 -                if (feof(f)) break;
   2.287 -                
   2.288 -                c = d = 0;
   2.289 -                
   2.290 -                while (buffer[c] == ' ' && buffer[c])
   2.291 -                      c++;
   2.292 -                      
   2.293 -                if (!buffer[c]) continue;
   2.294 -                
   2.295 -                while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
   2.296 -                        name2[d++] = buffer[c++];
   2.297 -                
   2.298 -                if (!buffer[c]) continue;
   2.299 -                name2[d] = 0;
   2.300 -                
   2.301 -//                pclog("Comparing %s and %s\n", name, name2);
   2.302 -                if (strcmp(name, name2)) continue;
   2.303 -//                pclog("Found!\n");
   2.304 -
   2.305 -                while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])                
   2.306 -                        c++;
   2.307 -                        
   2.308 -                if (!buffer[c]) continue;
   2.309 -                
   2.310 -                sscanf(&buffer[c], "%i", &res);
   2.311 -//                pclog("Reading value - %i\n", res);
   2.312 -                break;
   2.313 -        }
   2.314 +        sscanf(entry->data, "%i", &value);
   2.315          
   2.316 -        fclose(f);
   2.317 -        return res;
   2.318 +        return value;
   2.319  }
   2.320  
   2.321 -char config_return_string[256];
   2.322 -
   2.323  char *get_config_string(char *head, char *name, char *def)
   2.324  {
   2.325 -        char buffer[256];
   2.326 -        char name2[256];
   2.327 -        FILE *f = fopen(config_file, "rt");
   2.328 -        int c, d;
   2.329 +        section_t *section;
   2.330 +        entry_t *entry;
   2.331 +        int value;
   2.332 +
   2.333 +        section = find_section(head);
   2.334          
   2.335 -        strcpy(config_return_string, def);
   2.336 -        
   2.337 -        if (!f)
   2.338 -           return config_return_string;
   2.339 -           
   2.340 -//        pclog("Searching for %s\n", name);
   2.341 -        
   2.342 -        while (1)
   2.343 -        {
   2.344 -                fgets(buffer, 255, f);
   2.345 -                if (feof(f)) break;
   2.346 +        if (!section)
   2.347 +                return def;
   2.348                  
   2.349 -                c = d = 0;
   2.350 -                
   2.351 -                while (buffer[c] == ' ' && buffer[c])
   2.352 -                      c++;
   2.353 -                      
   2.354 -                if (!buffer[c]) continue;
   2.355 -                
   2.356 -                while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
   2.357 -                        name2[d++] = buffer[c++];
   2.358 -                
   2.359 -                if (!buffer[c]) continue;
   2.360 -                name2[d] = 0;
   2.361 -                
   2.362 -//                pclog("Comparing %s and %s\n", name, name2);
   2.363 -                if (strcmp(name, name2)) continue;
   2.364 -//                pclog("Found!\n");
   2.365 +        entry = find_entry(section, name);
   2.366  
   2.367 -                while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])                
   2.368 -                        c++;
   2.369 -                        
   2.370 -                if (!buffer[c]) continue;
   2.371 -                
   2.372 -                strcpy(config_return_string, &buffer[c]);
   2.373 -                
   2.374 -                c = strlen(config_return_string) - 1;
   2.375 -//                pclog("string len %i\n", c);
   2.376 -                while (config_return_string[c] <= 32 && config_return_string[c]) 
   2.377 -                      config_return_string[c--] = 0;
   2.378 -
   2.379 -//                pclog("Reading value - %s\n", config_return_string);
   2.380 -                break;
   2.381 -        }
   2.382 -        
   2.383 -        fclose(f);
   2.384 -        return config_return_string;
   2.385 +        if (!entry)
   2.386 +                return def;
   2.387 +       
   2.388 +        return entry->data; 
   2.389  }
   2.390  
   2.391  void set_config_int(char *head, char *name, int val)
   2.392  {
   2.393 -        FILE *f = fopen(config_file, "at");
   2.394 -//        if (!f) pclog("set_config_int - !f\n");
   2.395 -        fprintf(f, "%s = %i\n", name, val);
   2.396 -//        pclog("Write %s = %i\n", name, val);
   2.397 -        fclose(f);
   2.398 -//        pclog("fclose\n");
   2.399 +        section_t *section;
   2.400 +        entry_t *entry;
   2.401 +
   2.402 +        section = find_section(head);
   2.403 +        
   2.404 +        if (!section)
   2.405 +                section = create_section(head);
   2.406 +                
   2.407 +        entry = find_entry(section, name);
   2.408 +
   2.409 +        if (!entry)
   2.410 +                entry = create_entry(section, name);
   2.411 +
   2.412 +        sprintf(entry->data, "%i", val);
   2.413  }
   2.414  
   2.415  void set_config_string(char *head, char *name, char *val)
   2.416  {
   2.417 -        FILE *f = fopen(config_file, "at");
   2.418 -//        if (!f) pclog("set_config_string - !f\n");
   2.419 -        fprintf(f, "%s = %s\n", name, val);
   2.420 -//        pclog("Write %s = %s\n", name, val);
   2.421 -        fclose(f);
   2.422 +        section_t *section;
   2.423 +        entry_t *entry;
   2.424 +
   2.425 +        section = find_section(head);
   2.426 +        
   2.427 +        if (!section)
   2.428 +                section = create_section(head);
   2.429 +                
   2.430 +        entry = find_entry(section, name);
   2.431 +
   2.432 +        if (!entry)
   2.433 +                entry = create_entry(section, name);
   2.434 +
   2.435 +        strncpy(entry->data, val, 256);
   2.436  }
   2.437  
   2.438 +
   2.439  char *get_filename(char *s)
   2.440  {
   2.441          int c = strlen(s) - 1;
   2.442 @@ -164,3 +356,32 @@
   2.443          if (s[c] != '/' && s[c] != '\\')
   2.444             s[c] = '/';
   2.445  }
   2.446 +
   2.447 +void config_save()
   2.448 +{
   2.449 +        FILE *f = fopen(config_file, "wt");
   2.450 +        section_t *current_section;
   2.451 +        
   2.452 +        current_section = (section_t *)config_head.next;
   2.453 +        
   2.454 +        while (current_section)
   2.455 +        {
   2.456 +                entry_t *current_entry;
   2.457 +                
   2.458 +                if (current_section->name[0])
   2.459 +                        fprintf(f, "\n[%s]\n", current_section->name);
   2.460 +                
   2.461 +                current_entry = (entry_t *)current_section->entry_head.next;
   2.462 +                
   2.463 +                while (current_entry)
   2.464 +                {
   2.465 +                        fprintf(f, "%s = %s\n", current_entry->name, current_entry->data);
   2.466 +
   2.467 +                        current_entry = (entry_t *)current_entry->list.next;
   2.468 +                }
   2.469 +
   2.470 +                current_section = (section_t *)current_section->list.next;
   2.471 +        }
   2.472 +        
   2.473 +        fclose(f);
   2.474 +}
     3.1 --- a/src/config.h	Tue Jun 24 21:15:42 2014 +0100
     3.2 +++ b/src/config.h	Mon Jun 30 21:31:28 2014 +0100
     3.3 @@ -7,3 +7,8 @@
     3.4  char *get_filename(char *s);
     3.5  void append_filename(char *dest, char *s1, char *s2, int size);
     3.6  void put_backslash(char *s);
     3.7 +
     3.8 +void config_load();
     3.9 +void config_save();
    3.10 +void config_dump();
    3.11 +void config_free();
     4.1 --- a/src/device.c	Tue Jun 24 21:15:42 2014 +0100
     4.2 +++ b/src/device.c	Mon Jun 30 21:31:28 2014 +0100
     4.3 @@ -1,9 +1,12 @@
     4.4  #include "ibm.h"
     4.5 +#include "config.h"
     4.6  #include "device.h"
     4.7  
     4.8  static void *device_priv[256];
     4.9  static device_t *devices[256];
    4.10  
    4.11 +static device_t *current_device;
    4.12 +
    4.13  void device_init()
    4.14  {
    4.15          memset(devices, 0, sizeof(devices));
    4.16 @@ -20,6 +23,8 @@
    4.17          if (c >= 256)
    4.18                  fatal("device_add : too many devices\n");
    4.19          
    4.20 +        current_device = d;
    4.21 +        
    4.22          priv = d->init();
    4.23          if (priv == NULL)
    4.24                  fatal("device_add : device init failed\n");
    4.25 @@ -105,3 +110,31 @@
    4.26                  }
    4.27          }
    4.28  }
    4.29 +
    4.30 +int device_get_config_int(char *s)
    4.31 +{
    4.32 +        device_config_t *config = current_device->config;
    4.33 +        
    4.34 +        while (config->type != -1)
    4.35 +        {
    4.36 +                if (!strcmp(s, config->name))
    4.37 +                        return get_config_int(current_device->name, s, config->default_int);
    4.38 +
    4.39 +                config++;
    4.40 +        }
    4.41 +        return 0;
    4.42 +}
    4.43 +
    4.44 +char *device_get_config_string(char *s)
    4.45 +{
    4.46 +        device_config_t *config = current_device->config;
    4.47 +        
    4.48 +        while (config->type != -1)
    4.49 +        {
    4.50 +                if (!strcmp(s, config->name))
    4.51 +                        return get_config_string(current_device->name, s, config->default_string);
    4.52 +
    4.53 +                config++;
    4.54 +        }
    4.55 +        return NULL;
    4.56 +}
     5.1 --- a/src/device.h	Tue Jun 24 21:15:42 2014 +0100
     5.2 +++ b/src/device.h	Mon Jun 30 21:31:28 2014 +0100
     5.3 @@ -1,3 +1,24 @@
     5.4 +#define CONFIG_STRING 0
     5.5 +#define CONFIG_INT 1
     5.6 +#define CONFIG_BINARY 2
     5.7 +#define CONFIG_SELECTION 3
     5.8 +
     5.9 +typedef struct device_config_selection_t
    5.10 +{
    5.11 +        char description[256];
    5.12 +        int value;
    5.13 +} device_config_selection_t;
    5.14 +
    5.15 +typedef struct device_config_t
    5.16 +{
    5.17 +        char name[256];
    5.18 +        char description[256];
    5.19 +        int type;
    5.20 +        char default_string[256];
    5.21 +        int default_int;
    5.22 +        device_config_selection_t selection[16];
    5.23 +} device_config_t;
    5.24 +
    5.25  typedef struct device_t
    5.26  {
    5.27          char name[50];
    5.28 @@ -8,6 +29,7 @@
    5.29          void (*speed_changed)(void *p);
    5.30          void (*force_redraw)(void *p);
    5.31          int  (*add_status_info)(char *s, int max_len, void *p);
    5.32 +        device_config_t *config;
    5.33  } device_t;
    5.34  
    5.35  void device_init();
    5.36 @@ -18,6 +40,9 @@
    5.37  void device_force_redraw();
    5.38  char *device_add_status_info(char *s, int max_len);
    5.39  
    5.40 +int device_get_config_int(char *name);
    5.41 +char *device_get_config_string(char *name);
    5.42 +
    5.43  enum
    5.44  {
    5.45          DEVICE_NOT_WORKING = 1 /*Device does not currently work correctly and will be disabled in a release build*/
     6.1 --- a/src/pc.c	Tue Jun 24 21:15:42 2014 +0100
     6.2 +++ b/src/pc.c	Mon Jun 30 21:31:28 2014 +0100
     6.3 @@ -426,6 +426,9 @@
     6.4          char *p;
     6.5          append_filename(s, pcempath, "pcem.cfg", 511);
     6.6          set_config_file(s);
     6.7 +        
     6.8 +        config_load();
     6.9 +        
    6.10          GAMEBLASTER = get_config_int(NULL, "gameblaster", 0);
    6.11          GUS = get_config_int(NULL, "gus", 0);
    6.12          SSI2001 = get_config_int(NULL, "ssi2001", 0);
    6.13 @@ -480,7 +483,6 @@
    6.14  
    6.15  void saveconfig()
    6.16  {
    6.17 -        config_new();
    6.18          set_config_int(NULL, "gameblaster", GAMEBLASTER);
    6.19          set_config_int(NULL, "gus", GUS);
    6.20          set_config_int(NULL, "ssi2001", SSI2001);
    6.21 @@ -515,4 +517,6 @@
    6.22          set_config_int(NULL, "hdd_heads", hdc[1].hpc);
    6.23          set_config_int(NULL, "hdd_cylinders", hdc[1].tracks);
    6.24          set_config_string(NULL, "hdd_fn", ide_fn[1]);
    6.25 +        
    6.26 +        config_save();
    6.27  }
     7.1 --- a/src/pc.rc	Tue Jun 24 21:15:42 2014 +0100
     7.2 +++ b/src/pc.rc	Mon Jun 30 21:31:28 2014 +0100
     7.3 @@ -47,7 +47,7 @@
     7.4          END
     7.5  END
     7.6  
     7.7 -ConfigureDlg DIALOGEX 0, 0, 232, 256
     7.8 +ConfigureDlg DIALOGEX 0, 0, 232+40, 256
     7.9  STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    7.10  CAPTION "Configure PCem"
    7.11  FONT 8, "MS Sans Serif"
    7.12 @@ -56,11 +56,13 @@
    7.13      PUSHBUTTON      "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP
    7.14      COMBOBOX        IDC_COMBO1,62,16,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.15      COMBOBOX        IDC_COMBOVID,62,36,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.16 +    PUSHBUTTON      "Configure", IDC_CONFIGUREVID, 224, 36, 40, 14, WS_TABSTOP
    7.17      COMBOBOX        IDC_COMBOCPUM,62,56,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.18      COMBOBOX        IDC_COMBO3,62,76,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.19      COMBOBOX        IDC_COMBOCHC,62,96,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.20      COMBOBOX        IDC_COMBOSPD,62,116,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.21      COMBOBOX        IDC_COMBOSND,62,136,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
    7.22 +    PUSHBUTTON      "Configure", IDC_CONFIGURESND, 224, 136, 40, 14, WS_TABSTOP
    7.23      EDITTEXT        IDC_MEMTEXT, 62, 152, 36, 14, ES_AUTOHSCROLL | ES_NUMBER
    7.24      CONTROL         "", IDC_MEMSPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_SETBUDDYINT, 98, 152, 12, 14
    7.25      LTEXT           "MB", IDC_STATIC, 98, 152, 40, 10
     8.1 --- a/src/pic.c	Tue Jun 24 21:15:42 2014 +0100
     8.2 +++ b/src/pic.c	Mon Jun 30 21:31:28 2014 +0100
     8.3 @@ -244,6 +244,8 @@
     8.4  
     8.5  void picint(uint16_t num)
     8.6  {
     8.7 +        if (AT && num == (1 << 2))
     8.8 +                num = 1 << 9;
     8.9  //        pclog("picint : %04X\n", num);
    8.10  //        if (num == 0x10) pclog("PICINT 10\n");
    8.11          if (num>0xFF)
    8.12 @@ -264,6 +266,11 @@
    8.13  {
    8.14          int c = 0;
    8.15          while (!(num & (1 << c))) c++;
    8.16 +        if (AT && c == 2)
    8.17 +        {
    8.18 +                c = 9;
    8.19 +                num = 1 << 9;
    8.20 +        }
    8.21  //        pclog("INTLEVEL %04X %i\n", num, c);
    8.22          if (!pic_current[c])
    8.23          {
    8.24 @@ -283,6 +290,11 @@
    8.25  {
    8.26          int c = 0;
    8.27          while (!(num & (1 << c))) c++;
    8.28 +        if (AT && c == 2)
    8.29 +        {
    8.30 +                c = 9;
    8.31 +                num = 1 << 9;
    8.32 +        }
    8.33  //        pclog("INTC %04X %i\n", num, c);
    8.34          pic_current[c]=0;
    8.35  
     9.1 --- a/src/resources.h	Tue Jun 24 21:15:42 2014 +0100
     9.2 +++ b/src/resources.h	Mon Jun 30 21:31:28 2014 +0100
     9.3 @@ -77,5 +77,10 @@
     9.4  #define IDC_EDIT_C_FN   1220
     9.5  #define IDC_EDIT_D_FN   1221
     9.6  
     9.7 +#define IDC_CONFIGUREVID 1200
     9.8 +#define IDC_CONFIGURESND 1201
     9.9 +
    9.10 +#define IDC_CONFIG_BASE 1200
    9.11 +
    9.12  #define WM_RESETD3D WM_USER
    9.13  #define WM_LEAVEFULLSCREEN WM_USER + 1
    10.1 --- a/src/sound.c	Tue Jun 24 21:15:42 2014 +0100
    10.2 +++ b/src/sound.c	Mon Jun 30 21:31:28 2014 +0100
    10.3 @@ -56,6 +56,16 @@
    10.4          return sound_cards[card].name;
    10.5  }
    10.6  
    10.7 +device_t *sound_card_getdevice(int card)
    10.8 +{
    10.9 +        return sound_cards[card].device;
   10.10 +}
   10.11 +
   10.12 +int sound_card_has_config(int card)
   10.13 +{
   10.14 +        return sound_cards[card].device->config ? 1 : 0;
   10.15 +}
   10.16 +
   10.17  void sound_card_init()
   10.18  {
   10.19          if (sound_cards[sound_card_current].device)
    11.1 --- a/src/sound.h	Tue Jun 24 21:15:42 2014 +0100
    11.2 +++ b/src/sound.h	Mon Jun 30 21:31:28 2014 +0100
    11.3 @@ -7,4 +7,6 @@
    11.4  
    11.5  int sound_card_available(int card);
    11.6  char *sound_card_getname(int card);
    11.7 +struct device_t *sound_card_getdevice(int card);
    11.8 +int sound_card_has_config(int card);
    11.9  void sound_card_init();
    12.1 --- a/src/sound_sb.c	Tue Jun 24 21:15:42 2014 +0100
    12.2 +++ b/src/sound_sb.c	Mon Jun 30 21:31:28 2014 +0100
    12.3 @@ -256,13 +256,16 @@
    12.4  void *sb_1_init()
    12.5  {
    12.6          sb_t *sb = malloc(sizeof(sb_t));
    12.7 +        uint16_t addr = device_get_config_int("addr");        
    12.8          memset(sb, 0, sizeof(sb_t));
    12.9          
   12.10          opl2_init(&sb->opl);
   12.11          sb_dsp_init(&sb->dsp, SB1);
   12.12 -        sb_dsp_setaddr(&sb->dsp, 0x0220);
   12.13 +        sb_dsp_setaddr(&sb->dsp, addr);
   12.14 +        sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
   12.15 +        sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
   12.16          sb_mixer_init(&sb->mixer);
   12.17 -        io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.18 +        io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.19          io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.20          sound_add_handler(sb_opl2_poll, sb_get_buffer, sb);
   12.21          return sb;
   12.22 @@ -270,13 +273,16 @@
   12.23  void *sb_15_init()
   12.24  {
   12.25          sb_t *sb = malloc(sizeof(sb_t));
   12.26 +        uint16_t addr = device_get_config_int("addr");
   12.27          memset(sb, 0, sizeof(sb_t));
   12.28  
   12.29          opl2_init(&sb->opl);
   12.30          sb_dsp_init(&sb->dsp, SB15);
   12.31 -        sb_dsp_setaddr(&sb->dsp, 0x0220);
   12.32 +        sb_dsp_setaddr(&sb->dsp, addr);
   12.33 +        sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
   12.34 +        sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
   12.35          sb_mixer_init(&sb->mixer);
   12.36 -        io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.37 +        io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.38          io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.39          sound_add_handler(sb_opl2_poll, sb_get_buffer, sb);
   12.40          return sb;
   12.41 @@ -284,13 +290,16 @@
   12.42  void *sb_2_init()
   12.43  {
   12.44          sb_t *sb = malloc(sizeof(sb_t));
   12.45 +        uint16_t addr = device_get_config_int("addr");
   12.46          memset(sb, 0, sizeof(sb_t));
   12.47  
   12.48          opl2_init(&sb->opl);
   12.49          sb_dsp_init(&sb->dsp, SB2);
   12.50 -        sb_dsp_setaddr(&sb->dsp, 0x0220);
   12.51 +        sb_dsp_setaddr(&sb->dsp, addr);
   12.52 +        sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
   12.53 +        sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
   12.54          sb_mixer_init(&sb->mixer);
   12.55 -        io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.56 +        io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.57          io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
   12.58          sound_add_handler(sb_opl2_poll, sb_get_buffer, sb);
   12.59          return sb;
   12.60 @@ -299,17 +308,20 @@
   12.61  void *sb_pro_v1_init()
   12.62  {
   12.63          sb_t *sb = malloc(sizeof(sb_t));
   12.64 +        uint16_t addr = device_get_config_int("addr");
   12.65          memset(sb, 0, sizeof(sb_t));
   12.66  
   12.67          opl2_init(&sb->opl);
   12.68          sb_dsp_init(&sb->dsp, SBPRO);
   12.69 -        sb_dsp_setaddr(&sb->dsp, 0x0220);
   12.70 +        sb_dsp_setaddr(&sb->dsp, addr);
   12.71 +        sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
   12.72 +        sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
   12.73          sb_mixer_init(&sb->mixer);
   12.74 -        io_sethandler(0x0220, 0x0002, opl2_l_read, NULL, NULL, opl2_l_write, NULL, NULL, &sb->opl);
   12.75 -        io_sethandler(0x0222, 0x0002, opl2_r_read, NULL, NULL, opl2_r_write, NULL, NULL, &sb->opl);
   12.76 -        io_sethandler(0x0228, 0x0002, opl2_read,   NULL, NULL, opl2_write,   NULL, NULL, &sb->opl);
   12.77 +        io_sethandler(addr+0, 0x0002, opl2_l_read, NULL, NULL, opl2_l_write, NULL, NULL, &sb->opl);
   12.78 +        io_sethandler(addr+2, 0x0002, opl2_r_read, NULL, NULL, opl2_r_write, NULL, NULL, &sb->opl);
   12.79 +        io_sethandler(addr+8, 0x0002, opl2_read,   NULL, NULL, opl2_write,   NULL, NULL, &sb->opl);
   12.80          io_sethandler(0x0388, 0x0002, opl2_read,   NULL, NULL, opl2_write,   NULL, NULL, &sb->opl);
   12.81 -        io_sethandler(0x0224, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb);
   12.82 +        io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb);
   12.83          sound_add_handler(sb_opl2_poll, sb_get_buffer, sb);
   12.84  
   12.85          sb->mixer.regs[0x22] = 0xff;
   12.86 @@ -323,16 +335,19 @@
   12.87  void *sb_pro_v2_init()
   12.88  {
   12.89          sb_t *sb = malloc(sizeof(sb_t));
   12.90 +        uint16_t addr = device_get_config_int("addr");
   12.91          memset(sb, 0, sizeof(sb_t));
   12.92  
   12.93          opl3_init(&sb->opl);
   12.94          sb_dsp_init(&sb->dsp, SBPRO2);
   12.95 -        sb_dsp_setaddr(&sb->dsp, 0x0220);
   12.96 +        sb_dsp_setaddr(&sb->dsp, addr);
   12.97 +        sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
   12.98 +        sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
   12.99          sb_mixer_init(&sb->mixer);
  12.100 -        io_sethandler(0x0220, 0x0004, opl3_read,   NULL, NULL, opl3_write,   NULL, NULL, &sb->opl);
  12.101 -        io_sethandler(0x0228, 0x0002, opl3_read,   NULL, NULL, opl3_write,   NULL, NULL, &sb->opl);
  12.102 +        io_sethandler(addr+0, 0x0004, opl3_read,   NULL, NULL, opl3_write,   NULL, NULL, &sb->opl);
  12.103 +        io_sethandler(addr+8, 0x0002, opl3_read,   NULL, NULL, opl3_write,   NULL, NULL, &sb->opl);
  12.104          io_sethandler(0x0388, 0x0002, opl3_read,   NULL, NULL, opl3_write,   NULL, NULL, &sb->opl);
  12.105 -        io_sethandler(0x0224, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb);
  12.106 +        io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb);
  12.107          sound_add_handler(sb_opl3_poll, sb_get_buffer, sb);
  12.108  
  12.109          sb->mixer.regs[0x22] = 0xff;
  12.110 @@ -436,6 +451,158 @@
  12.111          sb_dsp_add_status_info(s, max_len, &sb->dsp);
  12.112  }
  12.113  
  12.114 +static device_config_t sb_config[] =
  12.115 +{
  12.116 +        {
  12.117 +                .name = "addr",
  12.118 +                .description = "Address",
  12.119 +                .type = CONFIG_BINARY,
  12.120 +                .type = CONFIG_SELECTION,
  12.121 +                .selection =
  12.122 +                {
  12.123 +                        {
  12.124 +                                .description = "0x220",
  12.125 +                                .value = 0x220
  12.126 +                        },
  12.127 +                        {
  12.128 +                                .description = "0x240",
  12.129 +                                .value = 0x240
  12.130 +                        },
  12.131 +                        {
  12.132 +                                .description = ""
  12.133 +                        }
  12.134 +                },
  12.135 +                .default_int = 0x220
  12.136 +        },
  12.137 +        {
  12.138 +                .name = "irq",
  12.139 +                .description = "IRQ",
  12.140 +                .type = CONFIG_SELECTION,
  12.141 +                .selection =
  12.142 +                {
  12.143 +                        {
  12.144 +                                .description = "IRQ 2",
  12.145 +                                .value = 2
  12.146 +                        },
  12.147 +                        {
  12.148 +                                .description = "IRQ 3",
  12.149 +                                .value = 3
  12.150 +                        },
  12.151 +                        {
  12.152 +                                .description = "IRQ 5",
  12.153 +                                .value = 5
  12.154 +                        },
  12.155 +                        {
  12.156 +                                .description = "IRQ 7",
  12.157 +                                .value = 7
  12.158 +                        },
  12.159 +                        {
  12.160 +                                .description = ""
  12.161 +                        }
  12.162 +                },
  12.163 +                .default_int = 7
  12.164 +        },
  12.165 +        {
  12.166 +                .name = "dma",
  12.167 +                .description = "DMA",
  12.168 +                .type = CONFIG_SELECTION,
  12.169 +                .selection =
  12.170 +                {
  12.171 +                        {
  12.172 +                                .description = "DMA 1",
  12.173 +                                .value = 1
  12.174 +                        },
  12.175 +                        {
  12.176 +                                .description = "DMA 3",
  12.177 +                                .value = 3
  12.178 +                        },
  12.179 +                        {
  12.180 +                                .description = ""
  12.181 +                        }
  12.182 +                },
  12.183 +                .default_int = 1
  12.184 +        },
  12.185 +        {
  12.186 +                .type = -1
  12.187 +        }
  12.188 +};
  12.189 +
  12.190 +static device_config_t sb_pro_config[] =
  12.191 +{
  12.192 +        {
  12.193 +                .name = "addr",
  12.194 +                .description = "Address",
  12.195 +                .type = CONFIG_BINARY,
  12.196 +                .type = CONFIG_SELECTION,
  12.197 +                .selection =
  12.198 +                {
  12.199 +                        {
  12.200 +                                .description = "0x220",
  12.201 +                                .value = 0x220
  12.202 +                        },
  12.203 +                        {
  12.204 +                                .description = "0x240",
  12.205 +                                .value = 0x240
  12.206 +                        },
  12.207 +                        {
  12.208 +                                .description = ""
  12.209 +                        }
  12.210 +                },
  12.211 +                .default_int = 0x220
  12.212 +        },
  12.213 +        {
  12.214 +                .name = "irq",
  12.215 +                .description = "IRQ",
  12.216 +                .type = CONFIG_SELECTION,
  12.217 +                .selection =
  12.218 +                {
  12.219 +                        {
  12.220 +                                .description = "IRQ 2",
  12.221 +                                .value = 2
  12.222 +                        },
  12.223 +                        {
  12.224 +                                .description = "IRQ 5",
  12.225 +                                .value = 5
  12.226 +                        },
  12.227 +                        {
  12.228 +                                .description = "IRQ 7",
  12.229 +                                .value = 7
  12.230 +                        },
  12.231 +                        {
  12.232 +                                .description = "IRQ 10",
  12.233 +                                .value = 10
  12.234 +                        },
  12.235 +                        {
  12.236 +                                .description = ""
  12.237 +                        }
  12.238 +                },
  12.239 +                .default_int = 7
  12.240 +        },
  12.241 +        {
  12.242 +                .name = "dma",
  12.243 +                .description = "DMA",
  12.244 +                .type = CONFIG_SELECTION,
  12.245 +                .selection =
  12.246 +                {
  12.247 +                        {
  12.248 +                                .description = "DMA 1",
  12.249 +                                .value = 1
  12.250 +                        },
  12.251 +                        {
  12.252 +                                .description = "DMA 3",
  12.253 +                                .value = 3
  12.254 +                        },
  12.255 +                        {
  12.256 +                                .description = ""
  12.257 +                        }
  12.258 +                },
  12.259 +                .default_int = 1
  12.260 +        },
  12.261 +        {
  12.262 +                .type = -1
  12.263 +        }
  12.264 +};
  12.265 +
  12.266  device_t sb_1_device =
  12.267  {
  12.268          "Sound Blaster v1.0",
  12.269 @@ -445,7 +612,8 @@
  12.270          NULL,
  12.271          sb_speed_changed,
  12.272          NULL,
  12.273 -        sb_add_status_info
  12.274 +        sb_add_status_info,
  12.275 +        sb_config
  12.276  };
  12.277  device_t sb_15_device =
  12.278  {
  12.279 @@ -456,7 +624,8 @@
  12.280          NULL,
  12.281          sb_speed_changed,
  12.282          NULL,
  12.283 -        sb_add_status_info
  12.284 +        sb_add_status_info,
  12.285 +        sb_config
  12.286  };
  12.287  device_t sb_2_device =
  12.288  {
  12.289 @@ -467,7 +636,8 @@
  12.290          NULL,
  12.291          sb_speed_changed,
  12.292          NULL,
  12.293 -        sb_add_status_info
  12.294 +        sb_add_status_info,
  12.295 +        sb_config
  12.296  };
  12.297  device_t sb_pro_v1_device =
  12.298  {
  12.299 @@ -478,7 +648,8 @@
  12.300          NULL,
  12.301          sb_speed_changed,
  12.302          NULL,
  12.303 -        sb_add_status_info
  12.304 +        sb_add_status_info,
  12.305 +        sb_pro_config
  12.306  };
  12.307  device_t sb_pro_v2_device =
  12.308  {
  12.309 @@ -489,7 +660,8 @@
  12.310          NULL,
  12.311          sb_speed_changed,
  12.312          NULL,
  12.313 -        sb_add_status_info
  12.314 +        sb_add_status_info,
  12.315 +        sb_pro_config
  12.316  };
  12.317  device_t sb_16_device =
  12.318  {
    13.1 --- a/src/vid_s3_virge.c	Tue Jun 24 21:15:42 2014 +0100
    13.2 +++ b/src/vid_s3_virge.c	Mon Jun 30 21:31:28 2014 +0100
    13.3 @@ -38,6 +38,9 @@
    13.4  
    13.5          int is_375;
    13.6  
    13.7 +        int bilinear_enabled;
    13.8 +        int memory_size;
    13.9 +        
   13.10          int pixel_count, tri_count;
   13.11                          
   13.12          struct
   13.13 @@ -2486,7 +2489,7 @@
   13.14  //                pclog("use tex_sample_mipmap\n");
   13.15                  break;
   13.16                  case 2: case 3:
   13.17 -                tex_sample = tex_sample_mipmap_filter;
   13.18 +                tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap;
   13.19  //                pclog("use tex_sample_mipmap_filter\n");
   13.20                  break;
   13.21                  case 4: case 5:
   13.22 @@ -2494,7 +2497,7 @@
   13.23  //                pclog("use tex_sample_normal\n");
   13.24                  break;
   13.25                  case 6: case 7:
   13.26 -                tex_sample = tex_sample_normal_filter;
   13.27 +                tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal;
   13.28  //                pclog("use tex_sample_normal_filter\n");
   13.29                  break;
   13.30                  case (0 | 8): case (1 | 8):
   13.31 @@ -2506,9 +2509,9 @@
   13.32                  break;
   13.33                  case (2 | 8): case (3 | 8):
   13.34                  if (virge->is_375)
   13.35 -                        tex_sample = tex_sample_persp_mipmap_filter_375;
   13.36 +                        tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375;
   13.37                  else
   13.38 -                        tex_sample = tex_sample_persp_mipmap_filter;
   13.39 +                        tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap;
   13.40  //                pclog("use tex_sample_persp_mipmap_filter\n");
   13.41                  break;
   13.42                  case (4 | 8): case (5 | 8):
   13.43 @@ -2520,9 +2523,9 @@
   13.44                  break;
   13.45                  case (6 | 8): case (7 | 8):
   13.46                  if (virge->is_375)
   13.47 -                        tex_sample = tex_sample_persp_normal_filter_375;
   13.48 +                        tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375;
   13.49                  else
   13.50 -                        tex_sample = tex_sample_persp_normal_filter;
   13.51 +                        tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal;
   13.52  //                pclog("use tex_sample_persp_normal_filter\n");
   13.53                  break;
   13.54          }
   13.55 @@ -2974,8 +2977,12 @@
   13.56  {
   13.57          virge_t *virge = malloc(sizeof(virge_t));
   13.58          memset(virge, 0, sizeof(virge_t));
   13.59 +
   13.60 +        virge->bilinear_enabled = device_get_config_int("bilinear");
   13.61 +        virge->memory_size = device_get_config_int("memory");
   13.62 +        pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size);
   13.63          
   13.64 -        svga_init(&virge->svga, virge, 1 << 22, /*4mb*/
   13.65 +        svga_init(&virge->svga, virge, virge->memory_size << 20,
   13.66                     s3_virge_recalctimings,
   13.67                     s3_virge_in, s3_virge_out,
   13.68                     s3_virge_hwcursor_draw,
   13.69 @@ -3029,7 +3036,17 @@
   13.70          virge->virge_rev = 0;
   13.71          virge->virge_id = 0xe1;
   13.72  
   13.73 -        virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4);
   13.74 +        switch (virge->memory_size)
   13.75 +        {
   13.76 +                case 2:
   13.77 +                virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5);
   13.78 +                break;
   13.79 +                case 4:
   13.80 +                default:
   13.81 +                virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5);
   13.82 +                break;
   13.83 +        }
   13.84 +                
   13.85          virge->svga.crtc[0x37] = 1;// | (7 << 5);
   13.86          virge->svga.crtc[0x53] = 1 << 3;
   13.87          virge->svga.crtc[0x59] = 0x70;
   13.88 @@ -3046,7 +3063,11 @@
   13.89          virge_t *virge = malloc(sizeof(virge_t));
   13.90          memset(virge, 0, sizeof(virge_t));
   13.91          
   13.92 -        svga_init(&virge->svga, virge, 1 << 22, /*4mb*/
   13.93 +        virge->bilinear_enabled = device_get_config_int("bilinear");
   13.94 +        virge->memory_size = device_get_config_int("memory");
   13.95 +        pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size);
   13.96 +
   13.97 +        svga_init(&virge->svga, virge, virge->memory_size << 20,
   13.98                     s3_virge_recalctimings,
   13.99                     s3_virge_in, s3_virge_out,
  13.100                     s3_virge_hwcursor_draw,
  13.101 @@ -3100,7 +3121,17 @@
  13.102          virge->virge_rev = 0;
  13.103          virge->virge_id = 0xe1;
  13.104  
  13.105 -        virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4);
  13.106 +        switch (virge->memory_size)
  13.107 +        {
  13.108 +                case 2:
  13.109 +                virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5);
  13.110 +                break;
  13.111 +                case 4:
  13.112 +                default:
  13.113 +                virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5);
  13.114 +                break;
  13.115 +        }
  13.116 +//        virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4);
  13.117          virge->svga.crtc[0x37] = 1;// | (7 << 5);
  13.118          virge->svga.crtc[0x53] = 1 << 3;
  13.119          virge->svga.crtc[0x59] = 0x70;
  13.120 @@ -3174,6 +3205,39 @@
  13.121          return max_len - cur_len;
  13.122  }
  13.123  
  13.124 +static device_config_t s3_virge_config[] =
  13.125 +{
  13.126 +        {
  13.127 +                .name = "bilinear",
  13.128 +                .description = "Bilinear filtering",
  13.129 +                .type = CONFIG_BINARY,
  13.130 +                .default_int = 1
  13.131 +        },
  13.132 +        {
  13.133 +                .name = "memory",
  13.134 +                .description = "Memory size",
  13.135 +                .type = CONFIG_SELECTION,
  13.136 +                .selection =
  13.137 +                {
  13.138 +                        {
  13.139 +                                .description = "2 MB",
  13.140 +                                .value = 2
  13.141 +                        },
  13.142 +                        {
  13.143 +                                .description = "4 MB",
  13.144 +                                .value = 4
  13.145 +                        },
  13.146 +                        {
  13.147 +                                .description = ""
  13.148 +                        }
  13.149 +                },
  13.150 +                .default_int = 4
  13.151 +        },
  13.152 +        {
  13.153 +                .type = -1
  13.154 +        }
  13.155 +};
  13.156 +
  13.157  device_t s3_virge_device =
  13.158  {
  13.159          "Diamond Stealth 3D 2000 (S3 ViRGE)",
  13.160 @@ -3183,7 +3247,8 @@
  13.161          s3_virge_available,
  13.162          s3_virge_speed_changed,
  13.163          s3_virge_force_redraw,
  13.164 -        s3_virge_add_status_info
  13.165 +        s3_virge_add_status_info,
  13.166 +        s3_virge_config
  13.167  };
  13.168  
  13.169  device_t s3_virge_375_device =
  13.170 @@ -3195,5 +3260,6 @@
  13.171          s3_virge_375_available,
  13.172          s3_virge_speed_changed,
  13.173          s3_virge_force_redraw,
  13.174 -        s3_virge_add_status_info
  13.175 +        s3_virge_add_status_info,
  13.176 +        s3_virge_config
  13.177  };
    14.1 --- a/src/video.c	Tue Jun 24 21:15:42 2014 +0100
    14.2 +++ b/src/video.c	Mon Jun 30 21:31:28 2014 +0100
    14.3 @@ -78,6 +78,16 @@
    14.4          return video_cards[card].name;
    14.5  }
    14.6  
    14.7 +device_t *video_card_getdevice(int card)
    14.8 +{
    14.9 +        return video_cards[card].device;
   14.10 +}
   14.11 +
   14.12 +int video_card_has_config(int card)
   14.13 +{
   14.14 +        return video_cards[card].device->config ? 1 : 0;
   14.15 +}
   14.16 +
   14.17  int video_card_getid(char *s)
   14.18  {
   14.19          int c = 0;
    15.1 --- a/src/video.h	Tue Jun 24 21:15:42 2014 +0100
    15.2 +++ b/src/video.h	Mon Jun 30 21:31:28 2014 +0100
    15.3 @@ -1,5 +1,7 @@
    15.4  int video_card_available(int card);
    15.5  char *video_card_getname(int card);
    15.6 +struct device_t *video_card_getdevice(int card);
    15.7 +int video_card_has_config(int card);
    15.8  int video_card_getid(char *s);
    15.9  int video_old_to_new(int card);
   15.10  int video_new_to_old(int card);
    16.1 --- a/src/win-config.c	Tue Jun 24 21:15:42 2014 +0100
    16.2 +++ b/src/win-config.c	Mon Jun 30 21:31:28 2014 +0100
    16.3 @@ -7,6 +7,7 @@
    16.4  
    16.5  #include "ibm.h"
    16.6  #include "cpu.h"
    16.7 +#include "device.h"
    16.8  #include "model.h"
    16.9  #include "resources.h"
   16.10  #include "sound.h"
   16.11 @@ -153,7 +154,19 @@
   16.12                  SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0);
   16.13                  SendMessage(h, UDM_SETRANGE, 0, (1 << 16) | 256);
   16.14                  SendMessage(h, UDM_SETPOS, 0, mem_size);
   16.15 +
   16.16 +                h = GetDlgItem(hdlg, IDC_CONFIGUREVID);
   16.17 +                if (video_card_has_config(video_old_to_new(gfxcard)))
   16.18 +                        EnableWindow(h, TRUE);
   16.19 +                else
   16.20 +                        EnableWindow(h, FALSE);
   16.21                  
   16.22 +                h = GetDlgItem(hdlg, IDC_CONFIGURESND);
   16.23 +                if (sound_card_has_config(sound_card_current))
   16.24 +                        EnableWindow(h, TRUE);
   16.25 +                else
   16.26 +                        EnableWindow(h, FALSE);
   16.27 +                        
   16.28                  return TRUE;
   16.29                  
   16.30                  case WM_COMMAND:
   16.31 @@ -322,6 +335,43 @@
   16.32                                  SendMessage(h, CB_SETCURSEL, temp_cpu, 0);
   16.33                          }
   16.34                          break;
   16.35 +                        
   16.36 +                        case IDC_CONFIGUREVID:
   16.37 +                        h = GetDlgItem(hdlg, IDC_COMBOVID);
   16.38 +                        SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp_str);
   16.39 +                        
   16.40 +                        deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(temp_str)));
   16.41 +                        break;
   16.42 +                        
   16.43 +                        case IDC_COMBOVID:
   16.44 +                        h = GetDlgItem(hdlg, IDC_COMBOVID);
   16.45 +                        SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp_str);
   16.46 +                        gfx = video_card_getid(temp_str);
   16.47 +                        
   16.48 +                        h = GetDlgItem(hdlg, IDC_CONFIGUREVID);
   16.49 +                        if (video_card_has_config(gfx))
   16.50 +                                EnableWindow(h, TRUE);
   16.51 +                        else
   16.52 +                                EnableWindow(h, FALSE);
   16.53 +                        break;                                
   16.54 +
   16.55 +                        case IDC_CONFIGURESND:
   16.56 +                        h = GetDlgItem(hdlg, IDC_COMBOSND);
   16.57 +                        temp_sound_card_current = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)];
   16.58 +                        
   16.59 +                        deviceconfig_open(hdlg, (void *)sound_card_getdevice(temp_sound_card_current));
   16.60 +                        break;
   16.61 +                        
   16.62 +                        case IDC_COMBOSND:
   16.63 +                        h = GetDlgItem(hdlg, IDC_COMBOSND);
   16.64 +                        temp_sound_card_current = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)];
   16.65 +                        
   16.66 +                        h = GetDlgItem(hdlg, IDC_CONFIGURESND);
   16.67 +                        if (sound_card_has_config(temp_sound_card_current))
   16.68 +                                EnableWindow(h, TRUE);
   16.69 +                        else
   16.70 +                                EnableWindow(h, FALSE);
   16.71 +                        break;                                
   16.72                  }
   16.73                  break;
   16.74          }
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/win-deviceconfig.c	Mon Jun 30 21:31:28 2014 +0100
    17.3 @@ -0,0 +1,317 @@
    17.4 +#define BITMAP WINDOWS_BITMAP
    17.5 +#include <windows.h>
    17.6 +#include <windowsx.h>
    17.7 +#undef BITMAP
    17.8 +
    17.9 +#include "ibm.h"
   17.10 +#include "config.h"
   17.11 +#include "device.h"
   17.12 +#include "resources.h"
   17.13 +#include "win.h"
   17.14 +
   17.15 +static device_t *config_device;
   17.16 +
   17.17 +static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
   17.18 +{
   17.19 +        switch (message)
   17.20 +        {
   17.21 +                case WM_INITDIALOG:
   17.22 +                {
   17.23 +                        int id = IDC_CONFIG_BASE;
   17.24 +                        device_config_t *config = config_device->config;
   17.25 +                        int c;
   17.26 +
   17.27 +                        while (config->type != -1)
   17.28 +                        {
   17.29 +                                device_config_selection_t *selection = config->selection;
   17.30 +                                HWND h = GetDlgItem(hdlg, id);
   17.31 +                                int val_int;
   17.32 +                                char *val_string;
   17.33 +                                
   17.34 +                                switch (config->type)
   17.35 +                                {
   17.36 +                                        case CONFIG_BINARY:
   17.37 +                                        val_int = get_config_int(config_device->name, config->name, config->default_int);
   17.38 +                                        
   17.39 +                                        SendMessage(h, BM_SETCHECK, val_int, 0);
   17.40 +                                                
   17.41 +                                        id++;
   17.42 +                                        break;
   17.43 +                                     
   17.44 +                                        case CONFIG_SELECTION:
   17.45 +                                        val_int = get_config_int(config_device->name, config->name, config->default_int);
   17.46 +                                        
   17.47 +                                        c = 0;
   17.48 +                                        while (selection->description[0])
   17.49 +                                        {
   17.50 +                                                SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)selection->description);
   17.51 +                                                if (val_int == selection->value)
   17.52 +                                                        SendMessage(h, CB_SETCURSEL, c, 0);
   17.53 +                                                selection++;
   17.54 +                                                c++;
   17.55 +                                        }
   17.56 +                                        
   17.57 +                                        id += 2;
   17.58 +                                        break;
   17.59 +                                }
   17.60 +                                config++;
   17.61 +                        }
   17.62 +                }
   17.63 +                return TRUE;
   17.64 +                
   17.65 +                case WM_COMMAND:
   17.66 +                switch (LOWORD(wParam))
   17.67 +                {
   17.68 +                        case IDOK:
   17.69 +                        {
   17.70 +                                int id = IDC_CONFIG_BASE;
   17.71 +                                device_config_t *config = config_device->config;
   17.72 +                                int c;
   17.73 +                                int changed = 0;
   17.74 +                                
   17.75 +                                while (config->type != -1)
   17.76 +                                {
   17.77 +                                        device_config_selection_t *selection = config->selection;
   17.78 +                                        HWND h = GetDlgItem(hdlg, id);
   17.79 +                                        int val_int;
   17.80 +                                        char *val_string;
   17.81 +                                
   17.82 +                                        switch (config->type)
   17.83 +                                        {
   17.84 +                                                case CONFIG_BINARY:
   17.85 +                                                val_int = get_config_int(config_device->name, config->name, config->default_int);
   17.86 +
   17.87 +                                                if (val_int != SendMessage(h, BM_GETCHECK, 0, 0))
   17.88 +                                                        changed = 1;
   17.89 +                                                
   17.90 +                                                id++;
   17.91 +                                                break;
   17.92 +                                     
   17.93 +                                                case CONFIG_SELECTION:
   17.94 +                                                val_int = get_config_int(config_device->name, config->name, config->default_int);
   17.95 +
   17.96 +                                                c = SendMessage(h, CB_GETCURSEL, 0, 0);
   17.97 +
   17.98 +                                                for (; c > 0; c--)
   17.99 +                                                        selection++;
  17.100 +
  17.101 +                                                if (val_int != selection->value)
  17.102 +                                                        changed = 1;
  17.103 +                                        
  17.104 +                                                id += 2;
  17.105 +                                                break;
  17.106 +                                        }
  17.107 +                                        config++;
  17.108 +                                }
  17.109 +                                
  17.110 +                                if (!changed)
  17.111 +                                {
  17.112 +                                        EndDialog(hdlg, 0);
  17.113 +                                        return TRUE;
  17.114 +                                }
  17.115 +                                        
  17.116 +                                if (MessageBox(NULL, "This will reset PCem!\nOkay to continue?", "PCem", MB_OKCANCEL) != IDOK)
  17.117 +                                {
  17.118 +                                        EndDialog(hdlg, 0);
  17.119 +                                        return TRUE;
  17.120 +                                }
  17.121 +
  17.122 +                                id = IDC_CONFIG_BASE;
  17.123 +                                config = config_device->config;
  17.124 +                                
  17.125 +                                while (config->type != -1)
  17.126 +                                {
  17.127 +                                        device_config_selection_t *selection = config->selection;
  17.128 +                                        HWND h = GetDlgItem(hdlg, id);
  17.129 +                                        int val_int;
  17.130 +                                        char *val_string;
  17.131 +                                
  17.132 +                                        switch (config->type)
  17.133 +                                        {
  17.134 +                                                case CONFIG_BINARY:
  17.135 +                                                set_config_int(config_device->name, config->name, SendMessage(h, BM_GETCHECK, 0, 0));
  17.136 +                                                
  17.137 +                                                id++;
  17.138 +                                                break;
  17.139 +                                     
  17.140 +                                                case CONFIG_SELECTION:
  17.141 +                                                c = SendMessage(h, CB_GETCURSEL, 0, 0);
  17.142 +                                                for (; c > 0; c--)
  17.143 +                                                        selection++;
  17.144 +                                                set_config_int(config_device->name, config->name, selection->value);
  17.145 +                                        
  17.146 +                                                id += 2;
  17.147 +                                                break;
  17.148 +                                        }
  17.149 +                                        config++;
  17.150 +                                }
  17.151 +
  17.152 +                                saveconfig();
  17.153 +                        
  17.154 +                                resetpchard();
  17.155 +
  17.156 +                                EndDialog(hdlg, 0);
  17.157 +                                return TRUE;
  17.158 +                        }
  17.159 +                        case IDCANCEL:
  17.160 +                        EndDialog(hdlg, 0);
  17.161 +                        return TRUE;
  17.162 +                }
  17.163 +                break;
  17.164 +        }
  17.165 +        return FALSE;
  17.166 +}
  17.167 +
  17.168 +void deviceconfig_open(HWND hwnd, device_t *device)
  17.169 +{
  17.170 +        device_config_t *config = device->config;
  17.171 +        uint16_t *data = malloc(16384);
  17.172 +        DLGTEMPLATE *dlg = (DLGTEMPLATE *)data;
  17.173 +        DLGITEMTEMPLATE *item;
  17.174 +        int y = 10;
  17.175 +        int id = IDC_CONFIG_BASE;
  17.176 +
  17.177 +        memset(data, 0, 4096);
  17.178 +        
  17.179 +        dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU;
  17.180 +        dlg->x  = 10;
  17.181 +        dlg->y  = 10;
  17.182 +        dlg->cx = 150;
  17.183 +        dlg->cy = 70;
  17.184 +        
  17.185 +        data = (uint16_t *)(dlg + 1);
  17.186 +        
  17.187 +        *data++ = 0; /*no menu*/
  17.188 +        *data++ = 0; /*predefined dialog box class*/
  17.189 +        data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50);
  17.190 +
  17.191 +        *data++ = 8; /*Point*/
  17.192 +        data += MultiByteToWideChar(CP_ACP, 0, "MS Sans Serif", -1, data, 50);
  17.193 +        
  17.194 +        if (((unsigned long)data) & 2)
  17.195 +                data++;
  17.196 +
  17.197 +        while (config->type != -1)
  17.198 +        {
  17.199 +                switch (config->type)
  17.200 +                {
  17.201 +                        case CONFIG_BINARY:
  17.202 +                        item = (DLGITEMTEMPLATE *)data;
  17.203 +                        item->x = 10;
  17.204 +                        item->y = y;
  17.205 +                        item->id = id++;
  17.206 +                
  17.207 +                        item->cx = 80;
  17.208 +                        item->cy = 15;
  17.209 +
  17.210 +                        item->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX;
  17.211 +
  17.212 +                        data = (uint16_t *)(item + 1);
  17.213 +                        *data++ = 0xFFFF;
  17.214 +                        *data++ = 0x0080;    // button class
  17.215 +
  17.216 +                        data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256);
  17.217 +                        *data++ = 0;              // no creation data
  17.218 +                        
  17.219 +                        y += 20;
  17.220 +                        break;
  17.221 +
  17.222 +                        case CONFIG_SELECTION:
  17.223 +                        /*Combo box*/
  17.224 +                        item = (DLGITEMTEMPLATE *)data;
  17.225 +                        item->x = 70;
  17.226 +                        item->y = y;
  17.227 +                        item->id = id++;
  17.228 +                
  17.229 +                        item->cx = 70;
  17.230 +                        item->cy = 150;
  17.231 +
  17.232 +                        item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL;
  17.233 +
  17.234 +                        data = (uint16_t *)(item + 1);
  17.235 +                        *data++ = 0xFFFF;
  17.236 +                        *data++ = 0x0085;    // combo box class
  17.237 +
  17.238 +                        data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256);
  17.239 +                        *data++ = 0;              // no creation data
  17.240 +                        
  17.241 +                        if (((unsigned long)data) & 2)
  17.242 +                                data++;
  17.243 +
  17.244 +                        /*Static text*/
  17.245 +                        item = (DLGITEMTEMPLATE *)data;
  17.246 +                        item->x = 10;
  17.247 +                        item->y = y;
  17.248 +                        item->id = id++;
  17.249 +                
  17.250 +                        item->cx = 60;
  17.251 +                        item->cy = 15;
  17.252 +
  17.253 +                        item->style = WS_CHILD | WS_VISIBLE;
  17.254 +
  17.255 +                        data = (uint16_t *)(item + 1);
  17.256 +                        *data++ = 0xFFFF;
  17.257 +                        *data++ = 0x0082;    // static class
  17.258 +
  17.259 +                        data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256);
  17.260 +                        *data++ = 0;              // no creation data
  17.261 +                        
  17.262 +                        if (((unsigned long)data) & 2)
  17.263 +                                data++;
  17.264 +
  17.265 +                        y += 20;
  17.266 +                        break;
  17.267 +                }
  17.268 +
  17.269 +                if (((unsigned long)data) & 2)
  17.270 +                        data++;
  17.271 +
  17.272 +                config++;
  17.273 +        }
  17.274 +
  17.275 +        dlg->cdit = (id - IDC_CONFIG_BASE) + 2;
  17.276 +
  17.277 +//    DEFPUSHBUTTON   "OK",IDOK,64,232,50,14, WS_TABSTOP
  17.278 +//    PUSHBUTTON      "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP
  17.279 +
  17.280 +        item = (DLGITEMTEMPLATE *)data;
  17.281 +        item->x = 20;
  17.282 +        item->y = y;
  17.283 +        item->cx = 50;
  17.284 +        item->cy = 14;
  17.285 +        item->id = IDOK;  // OK button identifier
  17.286 +        item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
  17.287 +
  17.288 +        data = (uint16_t *)(item + 1);
  17.289 +        *data++ = 0xFFFF;
  17.290 +        *data++ = 0x0080;    // button class
  17.291 +
  17.292 +        data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50);
  17.293 +        *data++ = 0;              // no creation data
  17.294 +
  17.295 +        if (((unsigned long)data) & 2)
  17.296 +                data++;
  17.297 +                
  17.298 +        item = (DLGITEMTEMPLATE *)data;
  17.299 +        item->x = 80;
  17.300 +        item->y = y;
  17.301 +        item->cx = 50;
  17.302 +        item->cy = 14;
  17.303 +        item->id = IDCANCEL;  // OK button identifier
  17.304 +        item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
  17.305 +
  17.306 +        data = (uint16_t *)(item + 1);
  17.307 +        *data++ = 0xFFFF;
  17.308 +        *data++ = 0x0080;    // button class
  17.309 +
  17.310 +        data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50);
  17.311 +        *data++ = 0;              // no creation data
  17.312 +
  17.313 +        dlg->cy = y + 20;
  17.314 +        
  17.315 +        config_device = device;
  17.316 +        
  17.317 +        DialogBoxIndirect(hinstance, dlg, hwnd, deviceconfig_dlgproc);
  17.318 +
  17.319 +        free(data);
  17.320 +}
    18.1 --- a/src/win.h	Tue Jun 24 21:15:42 2014 +0100
    18.2 +++ b/src/win.h	Mon Jun 30 21:31:28 2014 +0100
    18.3 @@ -24,6 +24,8 @@
    18.4  
    18.5  void config_open(HWND hwnd);
    18.6  
    18.7 +void deviceconfig_open(HWND hwnd, struct device_t *device);
    18.8 +
    18.9  extern char openfilestring[260];
   18.10  
   18.11  int getfile(HWND hwnd, char *f, char *fn);