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.
This commit is contained in:
TomW 2014-06-30 21:31:28 +01:00
commit 2207f704dd
18 changed files with 1061 additions and 123 deletions

View file

@ -19,7 +19,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
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

View file

@ -1,9 +1,194 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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(&current_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, &current_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 @@ void config_new()
fclose(f);
}
int get_config_int(char *head, char *name, int def)
static section_t *find_section(char *name)
{
char buffer[256];
char name2[256];
FILE *f = fopen(config_file, "rt");
int c, d;
int res = def;
section_t *current_section;
char blank[] = "";
if (!f)
return def;
// pclog("Searching for %s\n", name);
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");
current_section = (section_t *)config_head.next;
if (!name)
name = blank;
while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])
c++;
if (!buffer[c]) continue;
while (current_section)
{
if (!strncmp(current_section->name, name, 256))
return current_section;
sscanf(&buffer[c], "%i", &res);
// pclog("Reading value - %i\n", res);
break;
current_section = (section_t *)current_section->list.next;
}
fclose(f);
return res;
return NULL;
}
char config_return_string[256];
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, &section->entry_head);
return new_entry;
}
int get_config_int(char *head, char *name, int def)
{
section_t *section;
entry_t *entry;
int value;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
sscanf(entry->data, "%i", &value);
return value;
}
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;
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;
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");
section_t *section;
entry_t *entry;
int value;
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;
}
section = find_section(head);
fclose(f);
return config_return_string;
if (!section)
return def;
entry = find_entry(section, name);
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 @@ void put_backslash(char *s)
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);
}

View file

@ -7,3 +7,8 @@ void set_config_string(char *head, char *name, char *val);
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();

View file

@ -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 @@ void device_add(device_t *d)
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 @@ char *device_add_status_info(char *s, int max_len)
}
}
}
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;
}

View file

@ -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 @@ typedef struct device_t
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_speed_changed();
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*/

View file

@ -426,6 +426,9 @@ void loadconfig()
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 loadconfig()
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 @@ void saveconfig()
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();
}

View file

@ -47,7 +47,7 @@ BEGIN
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 @@ BEGIN
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

View file

@ -244,6 +244,8 @@ int pic_current[16];
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 @@ void picintlevel(uint16_t num)
{
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 @@ void picintc(uint16_t num)
{
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;

View file

@ -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

View file

@ -56,6 +56,16 @@ char *sound_card_getname(int card)
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)

View file

@ -7,4 +7,6 @@ extern int sound_card_current;
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();

View file

@ -256,13 +256,16 @@ void sb_mixer_init(sb_mixer_t *mixer)
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_1_init()
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_15_init()
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_2_init()
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_v1_init()
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 @@ int sb_add_status_info(char *s, int max_len, void *p)
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 @@ device_t sb_1_device =
NULL,
sb_speed_changed,
NULL,
sb_add_status_info
sb_add_status_info,
sb_config
};
device_t sb_15_device =
{
@ -456,7 +624,8 @@ device_t sb_15_device =
NULL,
sb_speed_changed,
NULL,
sb_add_status_info
sb_add_status_info,
sb_config
};
device_t sb_2_device =
{
@ -467,7 +636,8 @@ device_t sb_2_device =
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 @@ device_t sb_pro_v1_device =
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 @@ device_t sb_pro_v2_device =
NULL,
sb_speed_changed,
NULL,
sb_add_status_info
sb_add_status_info,
sb_pro_config
};
device_t sb_16_device =
{

View file

@ -38,6 +38,9 @@ typedef struct virge_t
int is_375;
int bilinear_enabled;
int memory_size;
int pixel_count, tri_count;
struct
@ -2486,7 +2489,7 @@ static void s3_virge_triangle(virge_t *virge)
// 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 @@ static void s3_virge_triangle(virge_t *virge)
// 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 @@ static void s3_virge_triangle(virge_t *virge)
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 @@ static void s3_virge_triangle(virge_t *virge)
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 @@ static void *s3_virge_init()
{
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 @@ static void *s3_virge_init()
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 @@ static void *s3_virge_375_init()
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 @@ static void *s3_virge_375_init()
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 @@ static int s3_virge_add_status_info(char *s, int max_len, void *p)
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 @@ device_t s3_virge_device =
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 @@ device_t s3_virge_375_device =
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
};

View file

@ -78,6 +78,16 @@ char *video_card_getname(int card)
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;

View file

@ -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);

View file

@ -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 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
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 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
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;
}

317
src/win-deviceconfig.c Normal file
View file

@ -0,0 +1,317 @@
#define BITMAP WINDOWS_BITMAP
#include <windows.h>
#include <windowsx.h>
#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);
}

View file

@ -24,6 +24,8 @@ void hdconf_open(HWND hwnd);
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);