# HG changeset patch # User TomW # Date 1404160288 -3600 # Node ID f749363ad763db95da577228b10412aaf9760439 # Parent c5989dbbc2cee0c7e9b04cde4cd612541ad3ac63 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. diff -r c5989dbbc2ce -r f749363ad763 src/Makefile.mingw --- a/src/Makefile.mingw Tue Jun 24 21:15:42 2014 +0100 +++ b/src/Makefile.mingw Mon Jun 30 21:31:28 2014 +0100 @@ -19,7 +19,7 @@ vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \ vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ - win-ddraw-fs.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ + win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-video.o x86seg.o x87.o xtide.o pc.res FMOBJ = dbopl.o 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 diff -r c5989dbbc2ce -r f749363ad763 src/config.c --- a/src/config.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/config.c Mon Jun 30 21:31:28 2014 +0100 @@ -1,9 +1,194 @@ #include #include +#include #include "config.h" static char config_file[256]; +typedef struct list_t +{ + struct list_t *next; +} list_t; + +static list_t config_head; + +typedef struct section_t +{ + struct list_t list; + + char name[256]; + + struct list_t entry_head; +} section_t; + +typedef struct entry_t +{ + struct list_t list; + + char name[256]; + char data[256]; +} entry_t; + +#define list_add(new, head) \ + { \ + struct list_t *next = head; \ + \ + while (next->next) \ + next = next->next; \ + \ + (next)->next = new; \ + (new)->next = NULL; \ + } + +void config_dump() +{ + section_t *current_section; + + pclog("Config data :\n"); + + current_section = (section_t *)config_head.next; + + while (current_section) + { + entry_t *current_entry; + + pclog("[%s]\n", current_section->name); + + current_entry = (entry_t *)current_section->entry_head.next; + + while (current_entry) + { + pclog("%s = %s\n", current_entry->name, current_entry->data); + + current_entry = (entry_t *)current_entry->list.next; + } + + current_section = (section_t *)current_section->list.next; + } +} + +void config_free() +{ + section_t *current_section; + current_section = (section_t *)config_head.next; + + while (current_section) + { + section_t *next_section = (section_t *)current_section->list.next; + entry_t *current_entry; + + current_entry = (entry_t *)current_section->entry_head.next; + + while (current_entry) + { + entry_t *next_entry = (entry_t *)current_entry->list.next; + + free(current_entry); + current_entry = next_entry; + } + + free(current_section); + current_section = next_section; + } +} + +void config_load() +{ + FILE *f = fopen(config_file, "rt"); + section_t *current_section; + + memset(&config_head, 0, sizeof(list_t)); + + current_section = malloc(sizeof(section_t)); + memset(current_section, 0, sizeof(section_t)); + list_add(¤t_section->list, &config_head); + + if (!f) + return; + + while (1) + { + int c; + char buffer[256]; + + fgets(buffer, 255, f); + if (feof(f)) break; + + c = 0; + + while (buffer[c] == ' ' && buffer[c]) + c++; + + if (!buffer[c]) continue; + + if (buffer[c] == '#') /*Comment*/ + continue; + + if (buffer[c] == '[') /*Section*/ + { + section_t *new_section; + char name[256]; + int d = 0; + + c++; + while (buffer[c] != ']' && buffer[c]) + name[d++] = buffer[c++]; + + if (buffer[c] != ']') + continue; + name[d] = 0; + + new_section = malloc(sizeof(section_t)); + memset(new_section, 0, sizeof(section_t)); + strncpy(new_section->name, name, 256); + list_add(&new_section->list, &config_head); + + current_section = new_section; + +// pclog("New section : %s %p\n", name, (void *)current_section); + } + else + { + entry_t *new_entry; + char name[256]; + int d = 0, data_pos; + + while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c]) + name[d++] = buffer[c++]; + + if (!buffer[c]) continue; + name[d] = 0; + + while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) + c++; + + if (!buffer[c]) continue; + + data_pos = c; + while (buffer[c]) + { + if (buffer[c] == '\n') + buffer[c] = 0; + c++; + } + + new_entry = malloc(sizeof(entry_t)); + memset(new_entry, 0, sizeof(entry_t)); + strncpy(new_entry->name, name, 256); + strncpy(new_entry->data, &buffer[data_pos], 256); + list_add(&new_entry->list, ¤t_section->entry_head); + +// pclog("New data under section [%s] : %s = %s\n", current_section->name, new_entry->name, new_entry->data); + } + } + + fclose(f); + + config_dump(); +} + + + void set_config_file(char *s) { strcpy(config_file, s); @@ -15,132 +200,139 @@ fclose(f); } +static section_t *find_section(char *name) +{ + section_t *current_section; + char blank[] = ""; + + current_section = (section_t *)config_head.next; + if (!name) + name = blank; + + while (current_section) + { + if (!strncmp(current_section->name, name, 256)) + return current_section; + + current_section = (section_t *)current_section->list.next; + } + return NULL; +} + +static entry_t *find_entry(section_t *section, char *name) +{ + entry_t *current_entry; + + current_entry = (entry_t *)section->entry_head.next; + + while (current_entry) + { + if (!strncmp(current_entry->name, name, 256)) + return current_entry; + + current_entry = (entry_t *)current_entry->list.next; + } + return NULL; +} + +static section_t *create_section(char *name) +{ + section_t *new_section = malloc(sizeof(section_t)); + + memset(new_section, 0, sizeof(section_t)); + strncpy(new_section->name, name, 256); + list_add(&new_section->list, &config_head); + + return new_section; +} + +static entry_t *create_entry(section_t *section, char *name) +{ + entry_t *new_entry = malloc(sizeof(entry_t)); + memset(new_entry, 0, sizeof(entry_t)); + strncpy(new_entry->name, name, 256); + list_add(&new_entry->list, §ion->entry_head); + + return new_entry; +} + int get_config_int(char *head, char *name, int def) { - char buffer[256]; - char name2[256]; - FILE *f = fopen(config_file, "rt"); - int c, d; - int res = def; + section_t *section; + entry_t *entry; + int value; + + section = find_section(head); - if (!f) - return def; - -// pclog("Searching for %s\n", name); + if (!section) + return def; + + entry = find_entry(section, name); + + if (!entry) + return def; - while (1) - { - fgets(buffer, 255, f); - if (feof(f)) break; - - c = d = 0; - - while (buffer[c] == ' ' && buffer[c]) - c++; - - if (!buffer[c]) continue; - - while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c]) - name2[d++] = buffer[c++]; - - if (!buffer[c]) continue; - name2[d] = 0; - -// pclog("Comparing %s and %s\n", name, name2); - if (strcmp(name, name2)) continue; -// pclog("Found!\n"); - - while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) - c++; - - if (!buffer[c]) continue; - - sscanf(&buffer[c], "%i", &res); -// pclog("Reading value - %i\n", res); - break; - } + sscanf(entry->data, "%i", &value); - fclose(f); - return res; + return value; } -char config_return_string[256]; - char *get_config_string(char *head, char *name, char *def) { - char buffer[256]; - char name2[256]; - FILE *f = fopen(config_file, "rt"); - int c, d; + section_t *section; + entry_t *entry; + int value; + + section = find_section(head); - strcpy(config_return_string, def); - - if (!f) - return config_return_string; - -// pclog("Searching for %s\n", name); - - while (1) - { - fgets(buffer, 255, f); - if (feof(f)) break; + if (!section) + return def; - c = d = 0; - - while (buffer[c] == ' ' && buffer[c]) - c++; - - if (!buffer[c]) continue; - - while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c]) - name2[d++] = buffer[c++]; - - if (!buffer[c]) continue; - name2[d] = 0; - -// pclog("Comparing %s and %s\n", name, name2); - if (strcmp(name, name2)) continue; -// pclog("Found!\n"); + entry = find_entry(section, name); - while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c]) - c++; - - if (!buffer[c]) continue; - - strcpy(config_return_string, &buffer[c]); - - c = strlen(config_return_string) - 1; -// pclog("string len %i\n", c); - while (config_return_string[c] <= 32 && config_return_string[c]) - config_return_string[c--] = 0; - -// pclog("Reading value - %s\n", config_return_string); - break; - } - - fclose(f); - return config_return_string; + if (!entry) + return def; + + return entry->data; } void set_config_int(char *head, char *name, int val) { - FILE *f = fopen(config_file, "at"); -// if (!f) pclog("set_config_int - !f\n"); - fprintf(f, "%s = %i\n", name, val); -// pclog("Write %s = %i\n", name, val); - fclose(f); -// pclog("fclose\n"); + section_t *section; + entry_t *entry; + + section = find_section(head); + + if (!section) + section = create_section(head); + + entry = find_entry(section, name); + + if (!entry) + entry = create_entry(section, name); + + sprintf(entry->data, "%i", val); } void set_config_string(char *head, char *name, char *val) { - FILE *f = fopen(config_file, "at"); -// if (!f) pclog("set_config_string - !f\n"); - fprintf(f, "%s = %s\n", name, val); -// pclog("Write %s = %s\n", name, val); - fclose(f); + section_t *section; + entry_t *entry; + + section = find_section(head); + + if (!section) + section = create_section(head); + + entry = find_entry(section, name); + + if (!entry) + entry = create_entry(section, name); + + strncpy(entry->data, val, 256); } + char *get_filename(char *s) { int c = strlen(s) - 1; @@ -164,3 +356,32 @@ if (s[c] != '/' && s[c] != '\\') s[c] = '/'; } + +void config_save() +{ + FILE *f = fopen(config_file, "wt"); + section_t *current_section; + + current_section = (section_t *)config_head.next; + + while (current_section) + { + entry_t *current_entry; + + if (current_section->name[0]) + fprintf(f, "\n[%s]\n", current_section->name); + + current_entry = (entry_t *)current_section->entry_head.next; + + while (current_entry) + { + fprintf(f, "%s = %s\n", current_entry->name, current_entry->data); + + current_entry = (entry_t *)current_entry->list.next; + } + + current_section = (section_t *)current_section->list.next; + } + + fclose(f); +} diff -r c5989dbbc2ce -r f749363ad763 src/config.h --- a/src/config.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/config.h Mon Jun 30 21:31:28 2014 +0100 @@ -7,3 +7,8 @@ char *get_filename(char *s); void append_filename(char *dest, char *s1, char *s2, int size); void put_backslash(char *s); + +void config_load(); +void config_save(); +void config_dump(); +void config_free(); diff -r c5989dbbc2ce -r f749363ad763 src/device.c --- a/src/device.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/device.c Mon Jun 30 21:31:28 2014 +0100 @@ -1,9 +1,12 @@ #include "ibm.h" +#include "config.h" #include "device.h" static void *device_priv[256]; static device_t *devices[256]; +static device_t *current_device; + void device_init() { memset(devices, 0, sizeof(devices)); @@ -20,6 +23,8 @@ if (c >= 256) fatal("device_add : too many devices\n"); + current_device = d; + priv = d->init(); if (priv == NULL) fatal("device_add : device init failed\n"); @@ -105,3 +110,31 @@ } } } + +int device_get_config_int(char *s) +{ + device_config_t *config = current_device->config; + + while (config->type != -1) + { + if (!strcmp(s, config->name)) + return get_config_int(current_device->name, s, config->default_int); + + config++; + } + return 0; +} + +char *device_get_config_string(char *s) +{ + device_config_t *config = current_device->config; + + while (config->type != -1) + { + if (!strcmp(s, config->name)) + return get_config_string(current_device->name, s, config->default_string); + + config++; + } + return NULL; +} diff -r c5989dbbc2ce -r f749363ad763 src/device.h --- a/src/device.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/device.h Mon Jun 30 21:31:28 2014 +0100 @@ -1,3 +1,24 @@ +#define CONFIG_STRING 0 +#define CONFIG_INT 1 +#define CONFIG_BINARY 2 +#define CONFIG_SELECTION 3 + +typedef struct device_config_selection_t +{ + char description[256]; + int value; +} device_config_selection_t; + +typedef struct device_config_t +{ + char name[256]; + char description[256]; + int type; + char default_string[256]; + int default_int; + device_config_selection_t selection[16]; +} device_config_t; + typedef struct device_t { char name[50]; @@ -8,6 +29,7 @@ void (*speed_changed)(void *p); void (*force_redraw)(void *p); int (*add_status_info)(char *s, int max_len, void *p); + device_config_t *config; } device_t; void device_init(); @@ -18,6 +40,9 @@ void device_force_redraw(); char *device_add_status_info(char *s, int max_len); +int device_get_config_int(char *name); +char *device_get_config_string(char *name); + enum { DEVICE_NOT_WORKING = 1 /*Device does not currently work correctly and will be disabled in a release build*/ diff -r c5989dbbc2ce -r f749363ad763 src/pc.c --- a/src/pc.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/pc.c Mon Jun 30 21:31:28 2014 +0100 @@ -426,6 +426,9 @@ char *p; append_filename(s, pcempath, "pcem.cfg", 511); set_config_file(s); + + config_load(); + GAMEBLASTER = get_config_int(NULL, "gameblaster", 0); GUS = get_config_int(NULL, "gus", 0); SSI2001 = get_config_int(NULL, "ssi2001", 0); @@ -480,7 +483,6 @@ void saveconfig() { - config_new(); set_config_int(NULL, "gameblaster", GAMEBLASTER); set_config_int(NULL, "gus", GUS); set_config_int(NULL, "ssi2001", SSI2001); @@ -515,4 +517,6 @@ set_config_int(NULL, "hdd_heads", hdc[1].hpc); set_config_int(NULL, "hdd_cylinders", hdc[1].tracks); set_config_string(NULL, "hdd_fn", ide_fn[1]); + + config_save(); } diff -r c5989dbbc2ce -r f749363ad763 src/pc.rc --- a/src/pc.rc Tue Jun 24 21:15:42 2014 +0100 +++ b/src/pc.rc Mon Jun 30 21:31:28 2014 +0100 @@ -47,7 +47,7 @@ END END -ConfigureDlg DIALOGEX 0, 0, 232, 256 +ConfigureDlg DIALOGEX 0, 0, 232+40, 256 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Configure PCem" FONT 8, "MS Sans Serif" @@ -56,11 +56,13 @@ PUSHBUTTON "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP COMBOBOX IDC_COMBO1,62,16,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBOVID,62,36,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure", IDC_CONFIGUREVID, 224, 36, 40, 14, WS_TABSTOP COMBOBOX IDC_COMBOCPUM,62,56,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO3,62,76,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBOCHC,62,96,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBOSPD,62,116,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBOSND,62,136,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure", IDC_CONFIGURESND, 224, 136, 40, 14, WS_TABSTOP EDITTEXT IDC_MEMTEXT, 62, 152, 36, 14, ES_AUTOHSCROLL | ES_NUMBER CONTROL "", IDC_MEMSPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_SETBUDDYINT, 98, 152, 12, 14 LTEXT "MB", IDC_STATIC, 98, 152, 40, 10 diff -r c5989dbbc2ce -r f749363ad763 src/pic.c --- a/src/pic.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/pic.c Mon Jun 30 21:31:28 2014 +0100 @@ -244,6 +244,8 @@ void picint(uint16_t num) { + if (AT && num == (1 << 2)) + num = 1 << 9; // pclog("picint : %04X\n", num); // if (num == 0x10) pclog("PICINT 10\n"); if (num>0xFF) @@ -264,6 +266,11 @@ { int c = 0; while (!(num & (1 << c))) c++; + if (AT && c == 2) + { + c = 9; + num = 1 << 9; + } // pclog("INTLEVEL %04X %i\n", num, c); if (!pic_current[c]) { @@ -283,6 +290,11 @@ { int c = 0; while (!(num & (1 << c))) c++; + if (AT && c == 2) + { + c = 9; + num = 1 << 9; + } // pclog("INTC %04X %i\n", num, c); pic_current[c]=0; diff -r c5989dbbc2ce -r f749363ad763 src/resources.h --- a/src/resources.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/resources.h Mon Jun 30 21:31:28 2014 +0100 @@ -77,5 +77,10 @@ #define IDC_EDIT_C_FN 1220 #define IDC_EDIT_D_FN 1221 +#define IDC_CONFIGUREVID 1200 +#define IDC_CONFIGURESND 1201 + +#define IDC_CONFIG_BASE 1200 + #define WM_RESETD3D WM_USER #define WM_LEAVEFULLSCREEN WM_USER + 1 diff -r c5989dbbc2ce -r f749363ad763 src/sound.c --- a/src/sound.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/sound.c Mon Jun 30 21:31:28 2014 +0100 @@ -56,6 +56,16 @@ return sound_cards[card].name; } +device_t *sound_card_getdevice(int card) +{ + return sound_cards[card].device; +} + +int sound_card_has_config(int card) +{ + return sound_cards[card].device->config ? 1 : 0; +} + void sound_card_init() { if (sound_cards[sound_card_current].device) diff -r c5989dbbc2ce -r f749363ad763 src/sound.h --- a/src/sound.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/sound.h Mon Jun 30 21:31:28 2014 +0100 @@ -7,4 +7,6 @@ int sound_card_available(int card); char *sound_card_getname(int card); +struct device_t *sound_card_getdevice(int card); +int sound_card_has_config(int card); void sound_card_init(); diff -r c5989dbbc2ce -r f749363ad763 src/sound_sb.c --- a/src/sound_sb.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/sound_sb.c Mon Jun 30 21:31:28 2014 +0100 @@ -256,13 +256,16 @@ void *sb_1_init() { sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); memset(sb, 0, sizeof(sb_t)); opl2_init(&sb->opl); sb_dsp_init(&sb->dsp, SB1); - sb_dsp_setaddr(&sb->dsp, 0x0220); + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_mixer_init(&sb->mixer); - io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); return sb; @@ -270,13 +273,16 @@ void *sb_15_init() { sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); memset(sb, 0, sizeof(sb_t)); opl2_init(&sb->opl); sb_dsp_init(&sb->dsp, SB15); - sb_dsp_setaddr(&sb->dsp, 0x0220); + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_mixer_init(&sb->mixer); - io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); return sb; @@ -284,13 +290,16 @@ void *sb_2_init() { sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); memset(sb, 0, sizeof(sb_t)); opl2_init(&sb->opl); sb_dsp_init(&sb->dsp, SB2); - sb_dsp_setaddr(&sb->dsp, 0x0220); + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_mixer_init(&sb->mixer); - io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); return sb; @@ -299,17 +308,20 @@ void *sb_pro_v1_init() { sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); memset(sb, 0, sizeof(sb_t)); opl2_init(&sb->opl); sb_dsp_init(&sb->dsp, SBPRO); - sb_dsp_setaddr(&sb->dsp, 0x0220); + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_mixer_init(&sb->mixer); - io_sethandler(0x0220, 0x0002, opl2_l_read, NULL, NULL, opl2_l_write, NULL, NULL, &sb->opl); - io_sethandler(0x0222, 0x0002, opl2_r_read, NULL, NULL, opl2_r_write, NULL, NULL, &sb->opl); - io_sethandler(0x0228, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr+0, 0x0002, opl2_l_read, NULL, NULL, opl2_l_write, NULL, NULL, &sb->opl); + io_sethandler(addr+2, 0x0002, opl2_r_read, NULL, NULL, opl2_r_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0224, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); + io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); sound_add_handler(sb_opl2_poll, sb_get_buffer, sb); sb->mixer.regs[0x22] = 0xff; @@ -323,16 +335,19 @@ void *sb_pro_v2_init() { sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_int("addr"); memset(sb, 0, sizeof(sb_t)); opl3_init(&sb->opl); sb_dsp_init(&sb->dsp, SBPRO2); - sb_dsp_setaddr(&sb->dsp, 0x0220); + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_mixer_init(&sb->mixer); - io_sethandler(0x0220, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0228, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0224, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); + io_sethandler(addr+4, 0x0002, sb_pro_mixer_read, NULL, NULL, sb_pro_mixer_write, NULL, NULL, sb); sound_add_handler(sb_opl3_poll, sb_get_buffer, sb); sb->mixer.regs[0x22] = 0xff; @@ -436,6 +451,158 @@ sb_dsp_add_status_info(s, max_len, &sb->dsp); } +static device_config_t sb_config[] = +{ + { + .name = "addr", + .description = "Address", + .type = CONFIG_BINARY, + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "" + } + }, + .default_int = 0x220 + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "" + } + }, + .default_int = 7 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" + } + }, + .default_int = 1 + }, + { + .type = -1 + } +}; + +static device_config_t sb_pro_config[] = +{ + { + .name = "addr", + .description = "Address", + .type = CONFIG_BINARY, + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "" + } + }, + .default_int = 0x220 + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { + .description = "" + } + }, + .default_int = 7 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" + } + }, + .default_int = 1 + }, + { + .type = -1 + } +}; + device_t sb_1_device = { "Sound Blaster v1.0", @@ -445,7 +612,8 @@ NULL, sb_speed_changed, NULL, - sb_add_status_info + sb_add_status_info, + sb_config }; device_t sb_15_device = { @@ -456,7 +624,8 @@ NULL, sb_speed_changed, NULL, - sb_add_status_info + sb_add_status_info, + sb_config }; device_t sb_2_device = { @@ -467,7 +636,8 @@ NULL, sb_speed_changed, NULL, - sb_add_status_info + sb_add_status_info, + sb_config }; device_t sb_pro_v1_device = { @@ -478,7 +648,8 @@ NULL, sb_speed_changed, NULL, - sb_add_status_info + sb_add_status_info, + sb_pro_config }; device_t sb_pro_v2_device = { @@ -489,7 +660,8 @@ NULL, sb_speed_changed, NULL, - sb_add_status_info + sb_add_status_info, + sb_pro_config }; device_t sb_16_device = { diff -r c5989dbbc2ce -r f749363ad763 src/vid_s3_virge.c --- a/src/vid_s3_virge.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/vid_s3_virge.c Mon Jun 30 21:31:28 2014 +0100 @@ -38,6 +38,9 @@ int is_375; + int bilinear_enabled; + int memory_size; + int pixel_count, tri_count; struct @@ -2486,7 +2489,7 @@ // pclog("use tex_sample_mipmap\n"); break; case 2: case 3: - tex_sample = tex_sample_mipmap_filter; + tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap; // pclog("use tex_sample_mipmap_filter\n"); break; case 4: case 5: @@ -2494,7 +2497,7 @@ // pclog("use tex_sample_normal\n"); break; case 6: case 7: - tex_sample = tex_sample_normal_filter; + tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; // pclog("use tex_sample_normal_filter\n"); break; case (0 | 8): case (1 | 8): @@ -2506,9 +2509,9 @@ break; case (2 | 8): case (3 | 8): if (virge->is_375) - tex_sample = tex_sample_persp_mipmap_filter_375; + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; else - tex_sample = tex_sample_persp_mipmap_filter; + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; // pclog("use tex_sample_persp_mipmap_filter\n"); break; case (4 | 8): case (5 | 8): @@ -2520,9 +2523,9 @@ break; case (6 | 8): case (7 | 8): if (virge->is_375) - tex_sample = tex_sample_persp_normal_filter_375; + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; else - tex_sample = tex_sample_persp_normal_filter; + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; // pclog("use tex_sample_persp_normal_filter\n"); break; } @@ -2974,8 +2977,12 @@ { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); + + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->memory_size = device_get_config_int("memory"); + pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size); - svga_init(&virge->svga, virge, 1 << 22, /*4mb*/ + svga_init(&virge->svga, virge, virge->memory_size << 20, s3_virge_recalctimings, s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw, @@ -3029,7 +3036,17 @@ virge->virge_rev = 0; virge->virge_id = 0xe1; - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4); + switch (virge->memory_size) + { + case 2: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 4: + default: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; + } + virge->svga.crtc[0x37] = 1;// | (7 << 5); virge->svga.crtc[0x53] = 1 << 3; virge->svga.crtc[0x59] = 0x70; @@ -3046,7 +3063,11 @@ virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); - svga_init(&virge->svga, virge, 1 << 22, /*4mb*/ + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->memory_size = device_get_config_int("memory"); + pclog("bilinear_enabled=%i memory_size=%i\n", virge->bilinear_enabled, virge->memory_size); + + svga_init(&virge->svga, virge, virge->memory_size << 20, s3_virge_recalctimings, s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw, @@ -3100,7 +3121,17 @@ virge->virge_rev = 0; virge->virge_id = 0xe1; - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4); + switch (virge->memory_size) + { + case 2: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 4: + default: + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; + } +// virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4); virge->svga.crtc[0x37] = 1;// | (7 << 5); virge->svga.crtc[0x53] = 1 << 3; virge->svga.crtc[0x59] = 0x70; @@ -3174,6 +3205,39 @@ return max_len - cur_len; } +static device_config_t s3_virge_config[] = +{ + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 4 + }, + { + .type = -1 + } +}; + device_t s3_virge_device = { "Diamond Stealth 3D 2000 (S3 ViRGE)", @@ -3183,7 +3247,8 @@ s3_virge_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info + s3_virge_add_status_info, + s3_virge_config }; device_t s3_virge_375_device = @@ -3195,5 +3260,6 @@ s3_virge_375_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info + s3_virge_add_status_info, + s3_virge_config }; diff -r c5989dbbc2ce -r f749363ad763 src/video.c --- a/src/video.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/video.c Mon Jun 30 21:31:28 2014 +0100 @@ -78,6 +78,16 @@ return video_cards[card].name; } +device_t *video_card_getdevice(int card) +{ + return video_cards[card].device; +} + +int video_card_has_config(int card) +{ + return video_cards[card].device->config ? 1 : 0; +} + int video_card_getid(char *s) { int c = 0; diff -r c5989dbbc2ce -r f749363ad763 src/video.h --- a/src/video.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/video.h Mon Jun 30 21:31:28 2014 +0100 @@ -1,5 +1,7 @@ int video_card_available(int card); char *video_card_getname(int card); +struct device_t *video_card_getdevice(int card); +int video_card_has_config(int card); int video_card_getid(char *s); int video_old_to_new(int card); int video_new_to_old(int card); diff -r c5989dbbc2ce -r f749363ad763 src/win-config.c --- a/src/win-config.c Tue Jun 24 21:15:42 2014 +0100 +++ b/src/win-config.c Mon Jun 30 21:31:28 2014 +0100 @@ -7,6 +7,7 @@ #include "ibm.h" #include "cpu.h" +#include "device.h" #include "model.h" #include "resources.h" #include "sound.h" @@ -153,7 +154,19 @@ SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0); SendMessage(h, UDM_SETRANGE, 0, (1 << 16) | 256); SendMessage(h, UDM_SETPOS, 0, mem_size); + + h = GetDlgItem(hdlg, IDC_CONFIGUREVID); + if (video_card_has_config(video_old_to_new(gfxcard))) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURESND); + if (sound_card_has_config(sound_card_current)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + return TRUE; case WM_COMMAND: @@ -322,6 +335,43 @@ SendMessage(h, CB_SETCURSEL, temp_cpu, 0); } break; + + case IDC_CONFIGUREVID: + h = GetDlgItem(hdlg, IDC_COMBOVID); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp_str); + + deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(temp_str))); + break; + + case IDC_COMBOVID: + h = GetDlgItem(hdlg, IDC_COMBOVID); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp_str); + gfx = video_card_getid(temp_str); + + h = GetDlgItem(hdlg, IDC_CONFIGUREVID); + if (video_card_has_config(gfx)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_CONFIGURESND: + h = GetDlgItem(hdlg, IDC_COMBOSND); + temp_sound_card_current = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + deviceconfig_open(hdlg, (void *)sound_card_getdevice(temp_sound_card_current)); + break; + + case IDC_COMBOSND: + h = GetDlgItem(hdlg, IDC_COMBOSND); + temp_sound_card_current = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURESND); + if (sound_card_has_config(temp_sound_card_current)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; } break; } diff -r c5989dbbc2ce -r f749363ad763 src/win-deviceconfig.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/win-deviceconfig.c Mon Jun 30 21:31:28 2014 +0100 @@ -0,0 +1,317 @@ +#define BITMAP WINDOWS_BITMAP +#include +#include +#undef BITMAP + +#include "ibm.h" +#include "config.h" +#include "device.h" +#include "resources.h" +#include "win.h" + +static device_t *config_device; + +static BOOL CALLBACK deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + int id = IDC_CONFIG_BASE; + device_config_t *config = config_device->config; + int c; + + while (config->type != -1) + { + device_config_selection_t *selection = config->selection; + HWND h = GetDlgItem(hdlg, id); + int val_int; + char *val_string; + + switch (config->type) + { + case CONFIG_BINARY: + val_int = get_config_int(config_device->name, config->name, config->default_int); + + SendMessage(h, BM_SETCHECK, val_int, 0); + + id++; + break; + + case CONFIG_SELECTION: + val_int = get_config_int(config_device->name, config->name, config->default_int); + + c = 0; + while (selection->description[0]) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)selection->description); + if (val_int == selection->value) + SendMessage(h, CB_SETCURSEL, c, 0); + selection++; + c++; + } + + id += 2; + break; + } + config++; + } + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + { + int id = IDC_CONFIG_BASE; + device_config_t *config = config_device->config; + int c; + int changed = 0; + + while (config->type != -1) + { + device_config_selection_t *selection = config->selection; + HWND h = GetDlgItem(hdlg, id); + int val_int; + char *val_string; + + switch (config->type) + { + case CONFIG_BINARY: + val_int = get_config_int(config_device->name, config->name, config->default_int); + + if (val_int != SendMessage(h, BM_GETCHECK, 0, 0)) + changed = 1; + + id++; + break; + + case CONFIG_SELECTION: + val_int = get_config_int(config_device->name, config->name, config->default_int); + + c = SendMessage(h, CB_GETCURSEL, 0, 0); + + for (; c > 0; c--) + selection++; + + if (val_int != selection->value) + changed = 1; + + id += 2; + break; + } + config++; + } + + if (!changed) + { + EndDialog(hdlg, 0); + return TRUE; + } + + if (MessageBox(NULL, "This will reset PCem!\nOkay to continue?", "PCem", MB_OKCANCEL) != IDOK) + { + EndDialog(hdlg, 0); + return TRUE; + } + + id = IDC_CONFIG_BASE; + config = config_device->config; + + while (config->type != -1) + { + device_config_selection_t *selection = config->selection; + HWND h = GetDlgItem(hdlg, id); + int val_int; + char *val_string; + + switch (config->type) + { + case CONFIG_BINARY: + set_config_int(config_device->name, config->name, SendMessage(h, BM_GETCHECK, 0, 0)); + + id++; + break; + + case CONFIG_SELECTION: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + for (; c > 0; c--) + selection++; + set_config_int(config_device->name, config->name, selection->value); + + id += 2; + break; + } + config++; + } + + saveconfig(); + + resetpchard(); + + EndDialog(hdlg, 0); + return TRUE; + } + case IDCANCEL: + EndDialog(hdlg, 0); + return TRUE; + } + break; + } + return FALSE; +} + +void deviceconfig_open(HWND hwnd, device_t *device) +{ + device_config_t *config = device->config; + uint16_t *data = malloc(16384); + DLGTEMPLATE *dlg = (DLGTEMPLATE *)data; + DLGITEMTEMPLATE *item; + int y = 10; + int id = IDC_CONFIG_BASE; + + memset(data, 0, 4096); + + dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; + dlg->x = 10; + dlg->y = 10; + dlg->cx = 150; + dlg->cy = 70; + + data = (uint16_t *)(dlg + 1); + + *data++ = 0; /*no menu*/ + *data++ = 0; /*predefined dialog box class*/ + data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50); + + *data++ = 8; /*Point*/ + data += MultiByteToWideChar(CP_ACP, 0, "MS Sans Serif", -1, data, 50); + + if (((unsigned long)data) & 2) + data++; + + while (config->type != -1) + { + switch (config->type) + { + case CONFIG_BINARY: + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 80; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; // button class + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; // no creation data + + y += 20; + break; + + case CONFIG_SELECTION: + /*Combo box*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 70; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; // combo box class + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; // static class + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + y += 20; + break; + } + + if (((unsigned long)data) & 2) + data++; + + config++; + } + + dlg->cdit = (id - IDC_CONFIG_BASE) + 2; + +// DEFPUSHBUTTON "OK",IDOK,64,232,50,14, WS_TABSTOP +// PUSHBUTTON "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP + + item = (DLGITEMTEMPLATE *)data; + item->x = 20; + item->y = y; + item->cx = 50; + item->cy = 14; + item->id = IDOK; // OK button identifier + item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; // button class + + data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + item = (DLGITEMTEMPLATE *)data; + item->x = 80; + item->y = y; + item->cx = 50; + item->cy = 14; + item->id = IDCANCEL; // OK button identifier + item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; // button class + + data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); + *data++ = 0; // no creation data + + dlg->cy = y + 20; + + config_device = device; + + DialogBoxIndirect(hinstance, dlg, hwnd, deviceconfig_dlgproc); + + free(data); +} diff -r c5989dbbc2ce -r f749363ad763 src/win.h --- a/src/win.h Tue Jun 24 21:15:42 2014 +0100 +++ b/src/win.h Mon Jun 30 21:31:28 2014 +0100 @@ -24,6 +24,8 @@ void config_open(HWND hwnd); +void deviceconfig_open(HWND hwnd, struct device_t *device); + extern char openfilestring[260]; int getfile(HWND hwnd, char *f, char *fn);