Files
86Box/src/config.c

2663 lines
57 KiB
C
Raw Normal View History

/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Configuration file handler.
*
* Version: @(#)config.c 1.0.12 2017/10/02
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Overdoze,
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*
* NOTE: Forcing config files to be in Unicode encoding breaks
* it on Windows XP, and possibly also Vista. Use the
* -DANSI_CFG for use on these systems.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <inttypes.h>
#include "ibm.h"
#include "cpu/cpu.h"
#include "nvr.h"
#include "config.h"
#include "device.h"
#include "lpt.h"
#include "cdrom/cdrom.h"
#include "disk/hdd.h"
#include "disk/hdc.h"
#include "disk/hdc_ide.h"
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "game/gameport.h"
#include "machine/machine.h"
#include "mouse.h"
#include "network/network.h"
#include "scsi/scsi.h"
#include "win/plat_joystick.h"
#include "win/plat_midi.h"
#include "sound/midi.h"
#include "sound/snd_dbopl.h"
#include "sound/snd_mpu401.h"
#include "sound/snd_opl.h"
#include "sound/sound.h"
#include "video/video.h"
#include "win/win.h"
#include "win/win_language.h"
typedef struct _list_
{
struct _list_ *next;
} list_t;
typedef struct
{
list_t list;
char name[256];
list_t entry_head;
} section_t;
typedef struct
{
list_t list;
char name[256];
char data[256];
wchar_t wdata[256];
} entry_t;
#define list_add(new, head) \
{ \
list_t *next = head; \
\
while (next->next != NULL) \
next = next->next; \
\
(next)->next = new; \
(new)->next = NULL; \
}
#define list_delete(old, head) \
{ \
list_t *next = head; \
\
while ((next)->next != old) \
{ \
next = (next)->next; \
} \
\
(next)->next = (old)->next; \
}
wchar_t config_file_default[256];
static list_t config_head;
static section_t *
find_section(char *name)
{
section_t *sec;
char blank[] = "";
sec = (section_t *)config_head.next;
if (name == NULL)
name = blank;
while (sec != NULL)
{
if (! strncmp(sec->name, name, 256))
return(sec);
sec = (section_t *)sec->list.next;
}
return(NULL);
}
static entry_t *
find_entry(section_t *section, char *name)
{
entry_t *ent;
ent = (entry_t *)section->entry_head.next;
while (ent != NULL)
{
if (! strncmp(ent->name, name, 256))
return(ent);
ent = (entry_t *)ent->list.next;
}
return(NULL);
}
static int
entries_num(section_t *section)
{
entry_t *ent;
int i = 0;
ent = (entry_t *)section->entry_head.next;
while (ent != NULL)
{
if (strlen(ent->name) > 0)
{
i++;
}
ent = (entry_t *)ent->list.next;
}
return(i);
}
static void
delete_section_if_empty(char *head)
{
section_t *section;
section = find_section(head);
if (section == NULL) return;
if (entries_num(section) == 0)
{
list_delete(&section->list, &config_head);
free(section);
}
}
static section_t *
create_section(char *name)
{
section_t *ns = malloc(sizeof(section_t));
memset(ns, 0x00, sizeof(section_t));
strncpy(ns->name, name, 256);
list_add(&ns->list, &config_head);
return(ns);
}
static entry_t *
create_entry(section_t *section, char *name)
{
entry_t *ne = malloc(sizeof(entry_t));
memset(ne, 0x00, sizeof(entry_t));
strncpy(ne->name, name, 256);
list_add(&ne->list, &section->entry_head);
return(ne);
}
#if 0
static void
config_free(void)
{
section_t *sec;
sec = (section_t *)config_head.next;
while (sec != NULL)
{
section_t *ns = (section_t *)sec->list.next;
entry_t *ent;
ent = (entry_t *)sec->entry_head.next;
while (ent != NULL)
{
entry_t *nent = (entry_t *)ent->list.next;
free(ent);
ent = nent;
}
free(sec);
sec = ns;
}
}
#endif
/* Read and parse the configuration file into memory. */
static int
config_read(wchar_t *fn)
{
section_t *current_section;
char sname[256], ename[256];
wchar_t cfgbuffer[1024];
section_t *new_section;
entry_t *new_entry;
FILE *f;
int c;
int sd = 0, ed = 0, data_pos;
#ifdef ANSI_CFG
f = _wfopen(fn, L"rt");
#else
f = _wfopen(fn, L"rt, ccs=UNICODE");
#endif
if (!f)
return 0;
current_section = malloc(sizeof(section_t));
memset(current_section, 0x00, sizeof(section_t));
memset(&config_head, 0x00, sizeof(list_t));
list_add(&current_section->list, &config_head);
while (1)
{
memset(cfgbuffer, 0, sizeof(cfgbuffer));
fgetws(cfgbuffer, 255, f);
if (feof(f)) break;
c = 0;
while (cfgbuffer[c] == L' ')
c++;
if (cfgbuffer[c] == L'\0') continue;
if ((cfgbuffer[c] == L'#') || (cfgbuffer[c] == L';')) {
/*Comment*/
continue;
}
if (cfgbuffer[c] == L'[') /*Section*/
{
sd = 0;
c++;
while (cfgbuffer[c] != L']' && cfgbuffer[c])
wctomb(&(sname[sd++]), cfgbuffer[c++]);
if (cfgbuffer[c] != L']')
continue;
sname[sd] = 0;
new_section = malloc(sizeof(section_t));
memset(new_section, 0x00, sizeof(section_t));
strncpy(new_section->name, sname, 256);
list_add(&new_section->list, &config_head);
current_section = new_section;
}
else
{
ed = 0;
while (cfgbuffer[c] != L'=' && cfgbuffer[c] != L' ' && cfgbuffer[c])
wctomb(&(ename[ed++]), cfgbuffer[c++]);
if (cfgbuffer[c] == L'\0') continue;
ename[ed] = 0;
while ((cfgbuffer[c] == L'=' || cfgbuffer[c] == L' ') && cfgbuffer[c])
c++;
if (!cfgbuffer[c]) continue;
data_pos = c;
while (cfgbuffer[c])
{
if (cfgbuffer[c] == L'\n')
cfgbuffer[c] = L'\0';
c++;
}
new_entry = malloc(sizeof(entry_t));
memset(new_entry, 0, sizeof(entry_t));
strncpy(new_entry->name, ename, 256);
memcpy(new_entry->wdata, &cfgbuffer[data_pos], 512);
new_entry->wdata[255] = L'\0';
wcstombs(new_entry->data, new_entry->wdata, sizeof(new_entry->data));
new_entry->data[255] = '\0';
list_add(&new_entry->list, &current_section->entry_head);
}
}
(void)fclose(f);
config_dump();
return 1;
}
/*
* Write the in-memory configuration to disk.
* This is a public function, because the Settings UI
* want to directly write the configuration after it
* has changed it.
*/
void
config_write(wchar_t *fn)
{
wchar_t wname[512];
section_t *sec;
FILE *f;
int fl = 0;
#ifdef ANSI_CFG
f = _wfopen(fn, L"wt");
#else
f = _wfopen(fn, L"wt, ccs=UNICODE");
#endif
if (f == NULL) return;
sec = (section_t *)config_head.next;
while (sec != NULL)
{
entry_t *ent;
if (sec->name[0])
{
mbstowcs(wname, sec->name, strlen(sec->name)+1);
if (fl)
fwprintf(f, L"\n[%ws]\n", wname);
else
fwprintf(f, L"[%ws]\n", wname);
fl++;
}
ent = (entry_t *)sec->entry_head.next;
while (ent != NULL)
{
if (ent->name[0])
{
mbstowcs(wname, ent->name, strlen(ent->name)+1);
if (ent->wdata[0] == L'\0')
fwprintf(f, L"%ws = \n", wname);
else
fwprintf(f, L"%ws = %ws\n", wname, ent->wdata);
fl++;
}
ent = (entry_t *)ent->list.next;
}
sec = (section_t *)sec->list.next;
}
(void)fclose(f);
}
#if NOT_USED
static void
config_new(void)
{
#ifdef ANSI_CFG
FILE *f = _wfopen(config_file, L"wt");
#else
FILE *f = _wfopen(config_file, L"wt, ccs=UNICODE");
#endif
(void)fclose(f);
}
#endif
/* Load "General" section. */
static void
load_general(void)
{
char *cat = "General";
char temp[512];
char *p;
vid_resize = !!config_get_int(cat, "vid_resize", 0);
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "vid_renderer", "d3d9");
if (p != NULL)
{
strcpy(temp, p);
}
if (!strcmp(temp, "ddraw"))
{
vid_api = 0;
}
else
{
vid_api = 1;
}
config_delete_var(cat, "vid_api");
video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0);
video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0);
force_43 = !!config_get_int(cat, "force_43", 0);
scale = config_get_int(cat, "scale", 1);
if (scale > 3)
{
scale = 3;
}
enable_overscan = !!config_get_int(cat, "enable_overscan", 0);
vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0);
video_grayscale = config_get_int(cat, "video_grayscale", 0);
video_graytype = config_get_int(cat, "video_graytype", 0);
window_remember = config_get_int(cat, "window_remember", 0);
if (window_remember)
{
p = config_get_string(cat, "window_coordinates", NULL);
if (p == NULL)
p = "0, 0, 0, 0";
sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y);
}
else
{
config_delete_var(cat, "window_remember");
config_delete_var(cat, "window_coordinates");
window_w = window_h = window_x = window_y = 0;
}
#ifndef __unix
/*
* Currently, 86Box is English (US) only, but in the future
* (version 1.30 at the earliest) other languages will be
* added, therefore it is better to future-proof the code.
*/
dwLanguage = config_get_hex16(cat, "language", 0x0409);
#endif
}
/* Load "Machine" section. */
static void
load_machine(void)
{
char *cat = "Machine";
char *p;
p = config_get_string(cat, "machine", NULL);
if (p != NULL)
{
machine = machine_get_machine_from_internal_name(p);
}
else
machine = 0;
if (machine >= machine_count())
machine = machine_count() - 1;
/* This is for backwards compatibility. */
p = config_get_string(cat, "model", NULL);
if (p != NULL)
{
/* Detect the old model typo and fix it, so that old configurations don't braek. */
if (strcmp(p, "p55r2p4") == 0)
{
machine = machine_get_machine_from_internal_name("p55t2p4");
}
else
{
machine = machine_get_machine_from_internal_name(p);
}
config_delete_var(cat, "model");
}
if (machine >= machine_count())
machine = machine_count() - 1;
romset = machine_getromset();
cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0);
cpu = config_get_int(cat, "cpu", 0);
cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0);
mem_size = config_get_int(cat, "mem_size", 4096);
if (mem_size < (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram))
mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram);
if (mem_size > 1048576)
{
mem_size = 1048576;
}
cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0);
enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0);
enable_sync = !!config_get_int(cat, "enable_sync", 1);
/* Remove this after a while.. */
if (config_get_string(cat, "nvr_path", NULL) != NULL)
config_delete_var(cat, "nvr_path");
}
/* Load "Video" section. */
static void
load_video(void)
{
char *cat = "Video";
char *p;
p = config_get_string(cat, "gfxcard", NULL);
if (p != NULL)
gfxcard = video_get_video_from_internal_name(p);
else
gfxcard = 0;
video_speed = config_get_int(cat, "video_speed", 3);
voodoo_enabled = !!config_get_int(cat, "voodoo", 0);
}
/* Load "Input Devices" section. */
static void
load_input_devices(void)
{
char *cat = "Input devices";
char temp[512];
int c, d;
char *p;
p = config_get_string(cat, "mouse_type", NULL);
if (p != NULL)
mouse_type = mouse_get_from_internal_name(p);
else
mouse_type = 0;
joystick_type = config_get_int(cat, "joystick_type", 7);
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++)
{
sprintf(temp, "joystick_%i_nr", c);
joystick_state[c].plat_joystick_nr = config_get_int(cat, temp, 0);
if (joystick_state[c].plat_joystick_nr)
{
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
{
sprintf(temp, "joystick_%i_axis_%i", c, d);
joystick_state[c].axis_mapping[d] = config_get_int(cat, temp, d);
}
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
{
sprintf(temp, "joystick_%i_button_%i", c, d);
joystick_state[c].button_mapping[d] = config_get_int(cat, temp, d);
}
for (d = 0; d < joystick_get_pov_count(joystick_type); d++)
{
sprintf(temp, "joystick_%i_pov_%i", c, d);
p = config_get_string(cat, temp, "0, 0");
joystick_state[c].pov_mapping[d][0] = joystick_state[c].pov_mapping[d][1] = 0;
sscanf(p, "%i, %i", &joystick_state[c].pov_mapping[d][0], &joystick_state[c].pov_mapping[d][1]);
}
}
}
}
/* Load "Sound" section. */
static void
load_sound(void)
{
char *cat = "Sound";
char temp[512];
char *p;
p = config_get_string(cat, "sndcard", NULL);
if (p != NULL)
sound_card_current = sound_card_get_from_internal_name(p);
else
sound_card_current = 0;
p = (char *)config_get_string(cat, "midi_device", NULL);
if (p != NULL)
midi_device_current = midi_device_get_from_internal_name(p);
else
midi_device_current = 0;
mpu401_standalone_enable = !!config_get_int(cat, "mpu401_standalone", 0);
SSI2001 = !!config_get_int(cat, "ssi2001", 0);
GAMEBLASTER = !!config_get_int(cat, "gameblaster", 0);
GUS = !!config_get_int(cat, "gus", 0);
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "opl3_type", "dbopl");
if (p != NULL)
{
strcpy(temp, p);
}
if (!strcmp(temp, "nukedopl") || !strcmp(temp, "1"))
{
opl3_type = 1;
}
else
{
opl3_type = 0;
}
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "sound_type", "float");
if (p != NULL)
{
strcpy(temp, p);
}
if (!strcmp(temp, "float") || !strcmp(temp, "1"))
{
sound_is_float = 1;
}
else
{
sound_is_float = 0;
}
}
/* Load "Network" section. */
static void
load_network(void)
{
char *cat = "Network";
char temp[512];
char *p;
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "net_type", "none");
if (p != NULL)
{
strcpy(temp, p);
}
if (!strcmp(temp, "slirp") || !strcmp(temp, "2"))
{
network_type = NET_TYPE_SLIRP;
}
else if (!strcmp(temp, "pcap") || !strcmp(temp, "1"))
{
network_type = NET_TYPE_PCAP;
}
else
{
network_type = NET_TYPE_NONE;
}
memset(network_pcap, '\0', sizeof(network_pcap));
p = config_get_string(cat, "net_pcap_device", "none");
if (p != NULL)
if ((network_dev_to_id(p) == -1) || (network_ndev == 1))
{
if ((network_ndev == 1) && strcmp(network_pcap, "none"))
{
msgbox_error(ghwnd, IDS_2140);
}
else if (network_dev_to_id(p) == -1)
{
msgbox_error(ghwnd, IDS_2141);
}
strcpy(network_pcap, "none");
}
else
{
strcpy(network_pcap, p);
}
else
strcpy(network_pcap, "none");
p = config_get_string(cat, "net_card", NULL);
if (p != NULL)
network_card = network_card_get_from_internal_name(p);
else
network_card = 0;
}
/* Load "Ports" section. */
static void
load_ports(void)
{
char *cat = "Ports (COM & LPT)";
char *p;
serial_enabled[0] = !!config_get_int(cat, "serial1_enabled", 1);
serial_enabled[1] = !!config_get_int(cat, "serial2_enabled", 1);
lpt_enabled = !!config_get_int(cat, "lpt_enabled", 1);
p = (char *)config_get_string(cat, "lpt1_device", "none");
if (p != NULL)
strcpy(lpt1_device_name, p);
else
strcpy(lpt1_device_name, "none");
}
/* Load "Other Peripherals" section. */
static void
load_other_peripherals(void)
{
char *cat = "Other peripherals";
char temp[512];
char *p;
int c;
p = config_get_string(cat, "scsicard", NULL);
if (p != NULL)
scsi_card_current = scsi_card_get_from_internal_name(p);
else
scsi_card_current = 0;
memset(hdc_name, '\0', sizeof(hdc_name));
p = config_get_string(cat, "hdc", NULL);
if (p == NULL) {
p = config_get_string(cat, "hdd_controller", NULL);
if (p != NULL)
config_delete_var(cat, "hdd_controller");
}
if (p == NULL) {
if (machines[machine].flags & MACHINE_HAS_HDC)
strcpy(hdc_name, "internal");
else
strcpy(hdc_name, "none");
} else
strcpy(hdc_name, p);
config_set_string(cat, "hdc", hdc_name);
memset(temp, '\0', sizeof(temp));
for (c = 2; c < 4; c++)
{
sprintf(temp, "ide_%02i", c + 1);
p = config_get_string(cat, temp, NULL);
if (p == NULL)
p = "0, 00";
sscanf(p, "%i, %02i", &ide_enable[c], &ide_irq[c]);
}
serial_enabled[0] = !!config_get_int(cat, "serial1_enabled", 1);
config_delete_var(cat, "serial1_enabled");
serial_enabled[1] = !!config_get_int(cat, "serial2_enabled", 1);
config_delete_var(cat, "serial2_enabled");
lpt_enabled = !!config_get_int(cat, "lpt_enabled", 1);
config_delete_var(cat, "lpt_enabled");
bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0);
}
/* FIXME: this should be in HDD somewhere. --FvK */
/* will be moved to hdd.c */
int
hdd_string_to_bus(char *str, int cdrom)
{
if (! strcmp(str, "none"))
{
return HDD_BUS_DISABLED;
}
if (! strcmp(str, "mfm"))
{
if (cdrom) goto no_mfm_cdrom;
return HDD_BUS_MFM;
}
/* FIXME: delete 'rll' in a year or so.. --FvK */
if (!strcmp(str, "esdi") || !strcmp(str, "rll"))
{
if (cdrom) goto no_mfm_cdrom;
return HDD_BUS_ESDI;
}
if (! strcmp(str, "ide_pio_only"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "ide"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "atapi_pio_only"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "atapi"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "eide"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "xtide"))
{
return HDD_BUS_XTIDE;
}
if (! strcmp(str, "atide"))
{
return HDD_BUS_IDE_PIO_ONLY;
}
if (! strcmp(str, "ide_pio_and_dma"))
{
return HDD_BUS_IDE_PIO_AND_DMA;
}
if (! strcmp(str, "atapi_pio_and_dma"))
{
return HDD_BUS_IDE_PIO_AND_DMA;
}
if (! strcmp(str, "scsi"))
{
return HDD_BUS_SCSI;
}
if (! strcmp(str, "removable"))
{
if (cdrom) goto no_mfm_cdrom;
return HDD_BUS_SCSI_REMOVABLE;
}
if (! strcmp(str, "scsi_removable"))
{
if (cdrom) goto no_mfm_cdrom;
return HDD_BUS_SCSI_REMOVABLE;
}
if (! strcmp(str, "removable_scsi"))
{
if (cdrom) goto no_mfm_cdrom;
return HDD_BUS_SCSI_REMOVABLE;
}
if (! strcmp(str, "usb"))
{
msgbox_error(ghwnd, IDS_4110);
return 0;
}
return 0;
no_mfm_cdrom:
msgbox_error(ghwnd, IDS_4114);
return 0;
}
char *
hdd_bus_to_string(int bus, int cdrom)
{
switch (bus)
{
case HDD_BUS_DISABLED:
default:
return "none";
break;
case HDD_BUS_MFM:
return "mfm";
break;
case HDD_BUS_XTIDE:
return "xtide";
break;
case HDD_BUS_ESDI:
return "esdi";
break;
case HDD_BUS_IDE_PIO_ONLY:
return cdrom ? "atapi_pio_only" : "ide_pio_only";
break;
case HDD_BUS_IDE_PIO_AND_DMA:
return cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma";
break;
case HDD_BUS_SCSI:
return "scsi";
break;
case HDD_BUS_SCSI_REMOVABLE:
return "scsi_removable";
break;
}
}
/* FIXME: this should be in HDD. --FvK */
int
hdd_is_valid(int c)
{
if (hdd[c].bus == HDD_BUS_DISABLED)
{
return 0;
}
if ((wcslen(hdd[c].fn) == 0) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE))
{
return 0;
}
if ((hdd[c].tracks == 0) || (hdd[c].hpc == 0) || (hdd[c].spt == 0))
{
return 0;
}
return 1;
}
static int
tally_char(char *string, char c)
{
int i = 0;
int tally = 0;
if (string == NULL)
{
return 0;
}
if (strlen(string) == 0)
{
return 0;
}
for (i = 0; i < strlen(string); i++)
{
if (string[i] == c)
{
tally++;
}
}
return tally;
}
/* Load "Hard Disks" section. */
static void
load_hard_disks(void)
{
char *cat = "Hard disks";
char temps[512];
char temps2[512];
char s[512];
int c;
char *p;
wchar_t *wp;
int max_spt, max_hpc, max_tracks;
int board = 0, dev = 0;
memset(temps, '\0', sizeof(temps));
for (c = 0; c < HDD_NUM; c++)
{
sprintf(temps, "hdd_%02i_parameters", c + 1);
p = config_get_string(cat, temps, NULL);
if (p == NULL)
p = "0, 0, 0, 0, none";
if (tally_char(p, ',') == 3)
{
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, s);
hdd[c].wp = 0;
}
else
{
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, (int *)&hdd[c].wp, s);
}
hdd[c].bus = hdd_string_to_bus(s, 0);
switch(hdd[c].bus)
{
case HDD_BUS_DISABLED:
default:
max_spt = max_hpc = max_tracks = 0;
break;
case HDD_BUS_MFM:
max_spt = 17;
max_hpc = 15;
max_tracks = 1023;
break;
case HDD_BUS_ESDI:
case HDD_BUS_XTIDE:
max_spt = 63;
max_hpc = 16;
max_tracks = 1023;
break;
case HDD_BUS_IDE_PIO_ONLY:
case HDD_BUS_IDE_PIO_AND_DMA:
max_spt = 63;
max_hpc = 16;
max_tracks = 266305;
break;
case HDD_BUS_SCSI:
case HDD_BUS_SCSI_REMOVABLE:
max_spt = 99;
max_hpc = 255;
max_tracks = 266305;
break;
}
if (hdd[c].spt > max_spt)
hdd[c].spt = max_spt;
if (hdd[c].hpc > max_hpc)
hdd[c].hpc = max_hpc;
if (hdd[c].tracks > max_tracks)
hdd[c].tracks = max_tracks;
/* MFM/RLL */
sprintf(temps, "hdd_%02i_mfm_channel", c + 1);
if (hdd[c].bus == HDD_BUS_MFM)
hdd[c].mfm_channel = !!config_get_int(cat, temps, c & 1);
else
config_delete_var(cat, temps);
/* XT IDE */
sprintf(temps, "hdd_%02i_xtide_channel", c + 1);
if (hdd[c].bus == HDD_BUS_XTIDE)
hdd[c].xtide_channel = !!config_get_int(cat, temps, c & 1);
else
config_delete_var(cat, temps);
/* ESDI */
sprintf(temps, "hdd_%02i_esdi_channel", c + 1);
if (hdd[c].bus == HDD_BUS_ESDI)
hdd[c].esdi_channel = !!config_get_int(cat, temps, c & 1);
else
config_delete_var(cat, temps);
/* IDE */
sprintf(temps, "hdd_%02i_ide_channel", c + 1);
if ((hdd[c].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[c].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
sprintf(temps2, "%01u:%01u", c >> 1, c & 1);
p = config_get_string(cat, temps, temps2);
if (strstr(p, ":") == NULL)
{
sscanf(p, "%i", (int *)&hdd[c].ide_channel);
hdd[c].ide_channel &= 7;
}
else
{
sscanf(p, "%01u:%01u", &board, &dev);
board &= 3;
dev &= 1;
hdd[c].ide_channel = (board << 1) + dev;
}
if (hdd[c].ide_channel > 7)
hdd[c].ide_channel = 7;
}
else
{
config_delete_var(cat, temps);
}
/* SCSI */
sprintf(temps, "hdd_%02i_scsi_location", c + 1);
if ((hdd[c].bus == HDD_BUS_SCSI) || (hdd[c].bus == HDD_BUS_SCSI_REMOVABLE))
{
sprintf(temps2, "%02u:%02u", c, 0);
p = config_get_string(cat, temps, temps2);
sscanf(p, "%02u:%02u", (int *)&hdd[c].scsi_id, (int *)&hdd[c].scsi_lun);
if (hdd[c].scsi_id > 15)
hdd[c].scsi_id = 15;
if (hdd[c].scsi_lun > 7)
hdd[c].scsi_lun = 7;
}
else
{
config_delete_var(cat, temps);
}
memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn));
memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn));
sprintf(temps, "hdd_%02i_fn", c + 1);
wp = config_get_wstring(cat, temps, L"");
#if 0
/*
* NOTE:
* Temporary hack to remove the absolute
* path currently saved in most config
* files. We should remove this before
* finalizing this release! --FvK
*/
if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) {
/*
* Yep, its absolute and prefixed
* with the CFG path. Just strip
* that off for now...
*/
wcscpy((wchar_t *)hdd[c].fn, &wp[wcslen(cfg_path)]);
} else
#endif
memcpy(hdd[c].fn, wp, (wcslen(wp) << 1) + 2);
/* If the hard disk is in any way empty or invalid, mark the relevant variables for deletion. */
if (! hdd_is_valid(c))
{
sprintf(temps, "hdd_%02i_parameters", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_preide_channels", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_ide_channels", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_scsi_location", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_fn", c+1);
config_delete_var(cat, temps);
}
sprintf(temps, "hdd_%02i_mfm_channel", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_ide_channel", c+1);
config_delete_var(cat, temps);
}
}
/* Load "Removable Devices" section. */
static void
load_removable_devices(void)
{
char *cat = "Removable devices";
char temps[512];
char temps2[512];
char s[512];
int c;
char *p;
wchar_t *wp;
unsigned int board = 0, dev = 0;
for (c = 0; c < FDD_NUM; c++)
{
sprintf(temps, "fdd_%02i_type", c + 1);
p = config_get_string(cat, temps, (c < 2) ? "525_2dd" : "none");
fdd_set_type(c, fdd_get_from_internal_name(p));
if (fdd_get_type(c) > 13)
2017-07-27 15:38:07 +02:00
{
fdd_set_type(c, 13);
}
sprintf(temps, "fdd_%02i_fn", c + 1);
wp = config_get_wstring(cat, temps, L"");
#if 0
/*
* NOTE:
* Temporary hack to remove the absolute
* path currently saved in most config
* files. We should remove this before
* finalizing this release! --FvK
*/
if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) {
/*
* Yep, its absolute and prefixed
* with the EXE path. Just strip
* that off for now...
*/
wcscpy((wchar_t *)floppyfns[c], &wp[wcslen(cfg_path)]);
} else
#endif
memcpy(floppyfns[c], wp, (wcslen(wp) << 1) + 2);
printf("Floppy: %ws\n", floppyfns[c]);
sprintf(temps, "fdd_%02i_writeprot", c + 1);
ui_writeprot[c] = !!config_get_int(cat, temps, 0);
sprintf(temps, "fdd_%02i_turbo", c + 1);
fdd_set_turbo(c, !!config_get_int(cat, temps, 0));
sprintf(temps, "fdd_%02i_check_bpb", c + 1);
fdd_set_check_bpb(c, !!config_get_int(cat, temps, 1));
/* Check, whether each value is default, if yes, delete it so that only non-default values will later be saved. */
if (fdd_get_type(c) == ((c < 2) ? 2 : 0))
{
sprintf(temps, "fdd_%02i_type", c + 1);
config_delete_var(cat, temps);
}
if (wcslen(floppyfns[c]) == 0)
{
sprintf(temps, "fdd_%02i_fn", c + 1);
config_delete_var(cat, temps);
}
if (ui_writeprot[c] == 0)
{
sprintf(temps, "fdd_%02i_writeprot", c + 1);
config_delete_var(cat, temps);
}
if (fdd_get_turbo(c) == 0)
{
sprintf(temps, "fdd_%02i_turbo", c + 1);
config_delete_var(cat, temps);
}
if (fdd_get_check_bpb(c) == 1)
{
sprintf(temps, "fdd_%02i_check_bpb", c + 1);
config_delete_var(cat, temps);
}
}
memset(temps, 0, 512);
for (c = 0; c < CDROM_NUM; c++)
{
sprintf(temps, "cdrom_%02i_host_drive", c + 1);
cdrom_drives[c].host_drive = config_get_int(cat, temps, 0);
cdrom_drives[c].prev_host_drive = cdrom_drives[c].host_drive;
sprintf(temps, "cdrom_%02i_parameters", c + 1);
p = config_get_string(cat, temps, NULL);
if (p != NULL)
{
sscanf(p, "%u, %s", &cdrom_drives[c].sound_on, s);
}
else
{
sscanf("0, none", "%u, %s", &cdrom_drives[c].sound_on, s);
}
cdrom_drives[c].bus_type = hdd_string_to_bus(s, 1);
sprintf(temps, "cdrom_%02i_ide_channel", c + 1);
if ((cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))
{
sprintf(temps2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1);
p = config_get_string(cat, temps, temps2);
if (strstr(p, ":") == NULL)
{
sscanf(p, "%i", (int *)&hdd[c].ide_channel);
cdrom_drives[c].ide_channel &= 7;
}
else
{
sscanf(p, "%02u:%02u", &board, &dev);
board &= 3;
dev &= 1;
cdrom_drives[c].ide_channel = (board << 1) + dev;
}
if (cdrom_drives[c].ide_channel > 7)
{
cdrom_drives[c].ide_channel = 7;
}
}
else
{
config_delete_var(cat, temps);
}
sprintf(temps, "cdrom_%02i_scsi_location", c + 1);
if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI)
{
sprintf(temps2, "%02u:%02u", c + 2, 0);
p = config_get_string(cat, temps, temps2);
sscanf(p, "%02u:%02u", &cdrom_drives[c].scsi_device_id, &cdrom_drives[c].scsi_device_lun);
if (cdrom_drives[c].scsi_device_id > 15)
{
cdrom_drives[c].scsi_device_id = 15;
}
if (cdrom_drives[c].scsi_device_lun > 7)
{
cdrom_drives[c].scsi_device_lun = 7;
}
}
else
{
config_delete_var(cat, temps);
}
sprintf(temps, "cdrom_%02i_image_path", c + 1);
wp = config_get_wstring(cat, temps, L"");
#if 0
/*
* NOTE:
* Temporary hack to remove the absolute
* path currently saved in most config
* files. We should remove this before
* finalizing this release! --FvK
*/
if (! wcsnicmp(wp, cfg_path, wcslen(cfg_path))) {
/*
* Yep, its absolute and prefixed
* with the EXE path. Just strip
* that off for now...
*/
wcscpy((wchar_t *)cdrom_image[c].image_path, &wp[wcslen(cfg_path)]);
} else
#endif
memcpy(cdrom_image[c].image_path, wp, (wcslen(wp) << 1) + 2);
wcscpy(cdrom_image[c].prev_image_path, cdrom_image[c].image_path);
if (cdrom_drives[c].host_drive < 'A')
{
cdrom_drives[c].host_drive = 0;
}
if ((cdrom_drives[c].host_drive == 0x200) && (wcslen(cdrom_image[c].image_path) == 0))
{
cdrom_drives[c].host_drive = 0;
}
/* If the CD-ROM is disabled, delete all its variables. */
if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED)
{
sprintf(temps, "cdrom_%02i_host_drive", c + 1);
config_delete_var(cat, temps);
sprintf(temps, "cdrom_%02i_parameters", c + 1);
config_delete_var(cat, temps);
sprintf(temps, "cdrom_%02i_ide_channel", c + 1);
config_delete_var(cat, temps);
sprintf(temps, "cdrom_%02i_scsi_location", c + 1);
config_delete_var(cat, temps);
sprintf(temps, "cdrom_%02i_image_path", c + 1);
config_delete_var(cat, temps);
}
sprintf(temps, "cdrom_%02i_iso_path", c + 1);
config_delete_var(cat, temps);
}
}
/* Load the specified or a default configuration file. */
void
config_load(wchar_t *fn)
{
int i = 0;
if (fn == NULL)
fn = config_file_default;
pclog("Loading config file '%ws'..\n", fn);
i = config_read(fn);
if (i == 0)
{
cpu = 0;
#ifndef __unix
dwLanguage = 0x0409;
#endif
scale = 1;
vid_api = 1;
enable_sync = 1;
joystick_type = 7;
strcpy(hdc_name, "none");
serial_enabled[0] = 1;
serial_enabled[1] = 1;
lpt_enabled = 1;
fdd_set_type(0, 2);
fdd_set_type(1, 2);
mem_size = 640;
pclog("Config file not present or invalid!\n");
return;
}
/* General */
load_general();
/* Machine */
load_machine();
/* Video */
load_video();
/* Input devices */
load_input_devices();
/* Sound */
load_sound();
/* Network */
load_network();
/* Ports (COM & LPT) */
load_ports();
/* Other peripherals */
load_other_peripherals();
/* Hard disks */
load_hard_disks();
/* Removable devices */
load_removable_devices();
pclog("Config loaded.\n");
}
/* Save "General" section. */
static void
save_general(void)
{
char *cat = "General";
char temp[512];
config_set_int(cat, "vid_resize", vid_resize);
if (vid_resize == 0)
{
config_delete_var(cat, "vid_resize");
}
if (vid_api == 1)
{
config_delete_var(cat, "vid_renderer");
}
else
{
switch(vid_api)
{
case 0:
config_set_string(cat, "vid_renderer", "ddraw");
break;
case 1:
default:
config_set_string(cat, "vid_renderer", "d3d9");
break;
}
}
if (video_fullscreen_scale == 0)
{
config_delete_var(cat, "video_fullscreen_scale");
}
else
{
config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale);
}
if (video_fullscreen_first == 0)
{
config_delete_var(cat, "video_fullscreen_first");
}
else
{
config_set_int(cat, "video_fullscreen_first", video_fullscreen_first);
}
if (force_43 == 0)
{
config_delete_var(cat, "force_43");
}
else
{
config_set_int(cat, "force_43", force_43);
}
if (scale == 1)
{
config_delete_var(cat, "scale");
}
else
{
config_set_int(cat, "scale", scale);
}
if (enable_overscan == 0)
{
config_delete_var(cat, "enable_overscan");
}
else
{
config_set_int(cat, "enable_overscan", enable_overscan);
}
if (vid_cga_contrast == 0)
{
config_delete_var(cat, "vid_cga_contrast");
}
else
{
config_set_int(cat, "vid_cga_contrast", vid_cga_contrast);
}
if (video_grayscale == 0)
{
config_delete_var(cat, "video_grayscale");
}
else
{
config_set_int(cat, "video_grayscale", video_grayscale);
}
if (video_graytype == 0)
{
config_delete_var(cat, "video_graytype");
}
else
{
config_set_int(cat, "video_graytype", video_graytype);
}
if (window_remember)
{
config_set_int(cat, "window_remember", window_remember);
sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y);
config_set_string(cat, "window_coordinates", temp);
}
else
{
config_delete_var(cat, "window_remember");
config_delete_var(cat, "window_coordinates");
}
#ifndef __unix
if (dwLanguage == 0x0409)
{
config_delete_var(cat, "language");
}
else
{
config_set_hex16(cat, "language", dwLanguage);
}
#endif
delete_section_if_empty(cat);
}
/* Save "Machine" section. */
static void
save_machine(void)
{
char *cat = "Machine";
config_set_string(cat, "machine", machine_get_internal_name());
if (cpu_manufacturer == 0)
{
config_delete_var(cat, "cpu_manufacturer");
}
else
{
config_set_int(cat, "cpu_manufacturer", cpu_manufacturer);
}
if (cpu == 0)
{
config_delete_var(cat, "cpu");
}
else
{
config_set_int(cat, "cpu", cpu);
}
if (cpu_waitstates == 0)
{
config_delete_var(cat, "cpu_waitstates");
}
else
{
config_set_int(cat, "cpu_waitstates", cpu_waitstates);
}
if (mem_size == 4096)
{
config_delete_var(cat, "mem_size");
}
else
{
config_set_int(cat, "mem_size", mem_size);
}
config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec);
if (enable_external_fpu == 0)
{
config_delete_var(cat, "cpu_enable_fpu");
}
else
{
config_set_int(cat, "cpu_enable_fpu", enable_external_fpu);
}
if (enable_sync == 1)
{
config_delete_var(cat, "enable_sync");
}
else
{
config_set_int(cat, "enable_sync", enable_sync);
}
delete_section_if_empty(cat);
}
/* Save "Video" section. */
static void
save_video(void)
{
char *cat = "Video";
config_set_string(cat, "gfxcard", video_get_internal_name(video_old_to_new(gfxcard)));
if (video_speed == 3)
{
config_delete_var(cat, "video_speed");
}
else
{
config_set_int(cat, "video_speed", video_speed);
}
if (voodoo_enabled == 0)
{
config_delete_var(cat, "voodoo");
}
else
{
config_set_int(cat, "voodoo", voodoo_enabled);
}
delete_section_if_empty(cat);
}
/* Save "Input Devices" section. */
static void
save_input_devices(void)
{
char *cat = "Input devices";
char temp[512];
char s[512];
int c, d;
config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type));
if ((joystick_type == 0) || (joystick_type == 7))
{
if (joystick_type == 7)
{
config_delete_var(cat, "joystick_type");
}
else
{
config_set_int(cat, "joystick_type", joystick_type);
}
for (c = 0; c < 16; c++)
{
sprintf(s, "joystick_%i_nr", c);
config_delete_var(cat, s);
for (d = 0; d < 16; d++)
{
sprintf(s, "joystick_%i_axis_%i", c, d);
config_delete_var(cat, s);
}
for (d = 0; d < 16; d++)
{
sprintf(s, "joystick_%i_button_%i", c, d);
config_delete_var(cat, s);
}
for (d = 0; d < 16; d++)
{
sprintf(s, "joystick_%i_pov_%i", c, d);
config_delete_var(cat, s);
}
}
}
else
{
config_set_int(cat, "joystick_type", joystick_type);
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++)
{
sprintf(s, "joystick_%i_nr", c);
config_set_int(cat, s, joystick_state[c].plat_joystick_nr);
if (joystick_state[c].plat_joystick_nr)
{
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
{
sprintf(s, "joystick_%i_axis_%i", c, d);
config_set_int(cat, s, joystick_state[c].axis_mapping[d]);
}
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
{
sprintf(s, "joystick_%i_button_%i", c, d);
config_set_int(cat, s, joystick_state[c].button_mapping[d]);
}
for (d = 0; d < joystick_get_pov_count(joystick_type); d++)
{
sprintf(s, "joystick_%i_pov_%i", c, d);
sprintf(temp, "%i, %i", joystick_state[c].pov_mapping[d][0], joystick_state[c].pov_mapping[d][1]);
config_set_string(cat, s, temp);
}
}
}
}
delete_section_if_empty(cat);
}
/* Save "Sound" section. */
static void
save_sound(void)
{
char *cat = "Sound";
if (sound_card_current == 0)
{
config_delete_var(cat, "sndcard");
}
else
{
config_set_string(cat, "sndcard", sound_card_get_internal_name(sound_card_current));
}
if (!strcmp(midi_device_get_internal_name(midi_device_current), "none"))
{
config_delete_var(cat, "midi_device");
}
else
{
config_set_string(cat, "midi_device", midi_device_get_internal_name(midi_device_current));
}
if (mpu401_standalone_enable == 0)
{
config_delete_var(cat, "mpu401_standalone");
}
else
{
config_set_int(cat, "mpu401_standalone", mpu401_standalone_enable);
}
if (SSI2001 == 0)
{
config_delete_var(cat, "ssi2001");
}
else
{
config_set_int(cat, "ssi2001", SSI2001);
}
if (GAMEBLASTER == 0)
{
config_delete_var(cat, "gameblaster");
}
else
{
config_set_int(cat, "gameblaster", GAMEBLASTER);
}
if (GUS == 0)
{
config_delete_var(cat, "gus");
}
else
{
config_set_int(cat, "gus", GUS);
}
if (opl3_type == 0)
{
config_delete_var(cat, "opl3_type");
}
else
{
config_set_string(cat, "opl3_type", (opl3_type == 1) ? "nukedopl" : "dbopl");
}
if (sound_is_float == 1)
{
config_delete_var(cat, "sound_type");
}
else
{
config_set_string(cat, "sound_type", (sound_is_float == 1) ? "float" : "int16");
}
delete_section_if_empty(cat);
}
/* Save "Network" section. */
static void
save_network(void)
{
char *cat = "Network";
if (network_type == NET_TYPE_NONE)
{
config_delete_var(cat, "net_type");
}
else
{
config_set_string(cat, "net_type", (network_type == NET_TYPE_SLIRP) ? "slirp" : "pcap");
}
if (network_pcap[0] != '\0')
{
if (!strcmp(network_pcap, "none"))
{
config_delete_var(cat, "net_pcap_device");
}
else
{
config_set_string(cat, "net_pcap_device", network_pcap);
}
}
else
{
/* config_set_string(cat, "net_pcap_device", "none"); */
config_delete_var(cat, "net_pcap_device");
}
if (network_card == 0)
{
config_delete_var(cat, "net_card");
}
else
{
config_set_string(cat, "net_card", network_card_get_internal_name(network_card));
}
delete_section_if_empty(cat);
}
/* Save "Ports" section. */
static void
save_ports(void)
{
char *cat = "Ports (COM & LPT)";
if (serial_enabled[0])
{
config_delete_var(cat, "serial1_enabled");
}
else
{
config_set_int(cat, "serial1_enabled", serial_enabled[0]);
}
if (serial_enabled[1])
{
config_delete_var(cat, "serial2_enabled");
}
else
{
config_set_int(cat, "serial2_enabled", serial_enabled[1]);
}
if (lpt_enabled)
{
config_delete_var(cat, "lpt_enabled");
}
else
{
config_set_int(cat, "lpt_enabled", lpt_enabled);
}
if (!strcmp(lpt1_device_name, "none"))
{
config_delete_var(cat, "lpt1_device");
}
else
{
config_set_string(cat, "lpt1_device", lpt1_device_name);
}
delete_section_if_empty(cat);
}
/* Save "Other Peripherals" section. */
static void
save_other_peripherals(void)
{
char *cat = "Other peripherals";
char temps[512];
char temps2[512];
int c;
if (scsi_card_current == 0)
{
config_delete_var(cat, "scsicard");
}
else
{
config_set_string(cat, "scsicard", scsi_card_get_internal_name(scsi_card_current));
}
config_set_string(cat, "hdc", hdc_name);
memset(temps, '\0', sizeof(temps));
for (c = 2; c < 4; c++)
{
sprintf(temps, "ide_%02i", c + 1);
sprintf(temps2, "%i, %02i", !!ide_enable[c], ide_irq[c]);
if (ide_enable[c] == 0)
{
config_delete_var(cat, temps);
}
else
{
config_set_string(cat, temps, temps2);
}
}
if (bugger_enabled == 0)
{
config_delete_var(cat, "bugger_enabled");
}
else
{
config_set_int(cat, "bugger_enabled", bugger_enabled);
}
delete_section_if_empty(cat);
}
/* Save "Hard Disks" section. */
static void
save_hard_disks(void)
{
char *cat = "Hard disks";
char temps[24];
char temps2[64];
int c;
char *p;
memset(temps, 0, sizeof(temps));
for (c = 0; c < HDD_NUM; c++)
{
sprintf(temps, "hdd_%02i_parameters", c+1);
if (! hdd_is_valid(c))
{
config_delete_var(cat, temps);
}
else
{
p = hdd_bus_to_string(hdd[c].bus, 0);
sprintf(temps2, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s",
hdd[c].spt, hdd[c].hpc, hdd[c].tracks, hdd[c].wp, p);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_mfm_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_MFM))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdd[c].mfm_channel);
}
sprintf(temps, "hdd_%02i_xtide_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_XTIDE))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdd[c].xtide_channel);
}
sprintf(temps, "hdd_%02i_esdi_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_ESDI))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdd[c].esdi_channel);
}
sprintf(temps, "hdd_%02i_ide_channel", c + 1);
if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdd[c].bus != HDD_BUS_IDE_PIO_AND_DMA)))
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_scsi_location", c + 1);
if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)))
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%02u:%02u", hdd[c].scsi_id, hdd[c].scsi_lun);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_fn", c+1);
if (! hdd_is_valid(c) || (wcslen(hdd[c].fn) == 0))
{
config_delete_var(cat, temps);
}
else
{
config_set_wstring(cat, temps, hdd[c].fn);
}
}
delete_section_if_empty(cat);
}
/* Save "Removable Devices" section. */
static void
save_removable_devices(void)
{
char *cat = "Removable devices";
char temps[512];
char temps2[512];
int c;
memset(temps, '\0', sizeof(temps));
for (c = 0; c < FDD_NUM; c++)
{
sprintf(temps, "fdd_%02i_type", c + 1);
if (fdd_get_type(c) == ((c < 2) ? 2 : 0))
{
config_delete_var(cat, temps);
}
else
{
config_set_string(cat, temps, fdd_get_internal_name(fdd_get_type(c)));
}
sprintf(temps, "fdd_%02i_fn", c + 1);
if (wcslen(floppyfns[c]) == 0)
{
config_delete_var(cat, temps);
ui_writeprot[c] = 0;
sprintf(temps, "fdd_%02i_writeprot", c + 1);
config_delete_var(cat, temps);
}
else
{
config_set_wstring(cat, temps, floppyfns[c]);
}
sprintf(temps, "fdd_%02i_writeprot", c + 1);
if (ui_writeprot[c] == 0)
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, ui_writeprot[c]);
}
sprintf(temps, "fdd_%02i_turbo", c + 1);
if (fdd_get_turbo(c) == 0)
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, fdd_get_turbo(c));
}
sprintf(temps, "fdd_%02i_check_bpb", c + 1);
if (fdd_get_check_bpb(c) == 1)
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, fdd_get_check_bpb(c));
}
}
memset(temps, '\0', sizeof(temps));
for (c = 0; c < CDROM_NUM; c++)
{
sprintf(temps, "cdrom_%02i_host_drive", c + 1);
if ((cdrom_drives[c].bus_type == 0) || (cdrom_drives[c].host_drive < 'A') || ((cdrom_drives[c].host_drive > 'Z') && (cdrom_drives[c].host_drive != 200)))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, cdrom_drives[c].host_drive);
}
sprintf(temps, "cdrom_%02i_parameters", c + 1);
if (cdrom_drives[c].bus_type == 0)
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%u, %s", cdrom_drives[c].sound_on, hdd_bus_to_string(cdrom_drives[c].bus_type, 1));
config_set_string(cat, temps, temps2);
}
sprintf(temps, "cdrom_%02i_ide_channel", c + 1);
if ((cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_ONLY) && (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_AND_DMA))
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%01u:%01u", cdrom_drives[c].ide_channel >> 1, cdrom_drives[c].ide_channel & 1);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "cdrom_%02i_scsi_location", c + 1);
if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI)
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%02u:%02u", cdrom_drives[c].scsi_device_id, cdrom_drives[c].scsi_device_lun);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "cdrom_%02i_image_path", c + 1);
if ((cdrom_drives[c].bus_type == 0) || (wcslen(cdrom_image[c].image_path) == 0))
{
config_delete_var(cat, temps);
}
else
{
config_set_wstring(cat, temps, cdrom_image[c].image_path);
}
}
delete_section_if_empty(cat);
}
void
config_save(void)
{
/* General */
save_general();
/* Machine */
save_machine();
/* Video */
save_video();
/* Input devices */
save_input_devices();
/* Sound */
save_sound();
/* Network */
save_network();
/* Ports (COM & LPT) */
save_ports();
/* Other peripherals */
save_other_peripherals();
/* Hard disks */
save_hard_disks();
/* Removable devices */
save_removable_devices();
config_write(config_file_default);
}
void
config_dump(void)
{
section_t *sec;
pclog("Config data :\n");
sec = (section_t *)config_head.next;
while (sec != NULL)
{
entry_t *ent;
if (sec->name && sec->name[0])
pclog("[%s]\n", sec->name);
ent = (entry_t *)sec->entry_head.next;
while (ent != NULL)
{
pclog("%s = %s\n", ent->name, ent->data);
ent = (entry_t *)ent->list.next;
}
sec = (section_t *)sec->list.next;
}
}
void
config_delete_var(char *head, char *name)
{
section_t *section;
entry_t *entry;
section = find_section(head);
if (section == NULL) return;
entry = find_entry(section, name);
if (entry == NULL) return;
list_delete(&entry->list, &section->entry_head);
free(entry);
}
int
config_get_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;
}
int
config_get_hex16(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, "%04X", &value);
return value;
}
int
config_get_hex20(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, "%05X", &value);
return value;
}
int
config_get_mac(char *head, char *name, int def)
{
section_t *section;
entry_t *entry;
int val0 = 0, val1 = 0, val2 = 0;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2);
return (val0 << 16) + (val1 << 8) + val2;
}
char *
config_get_string(char *head, char *name, char *def)
{
section_t *section;
entry_t *entry;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
return entry->data;
}
wchar_t *
config_get_wstring(char *head, char *name, wchar_t *def)
{
section_t *section;
entry_t *entry;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
return entry->wdata;
}
void
config_set_int(char *head, char *name, int val)
{
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);
mbstowcs(entry->wdata, entry->data, 512);
}
void
config_set_hex16(char *head, char *name, int val)
{
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, "%04X", val);
mbstowcs(entry->wdata, entry->data, 512);
}
void
config_set_hex20(char *head, char *name, int val)
{
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, "%05X", val);
mbstowcs(entry->wdata, entry->data, 512);
}
void
config_set_mac(char *head, char *name, int val)
{
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, "%02x:%02x:%02x",
(val>>16)&0xff, (val>>8)&0xff, val&0xff);
mbstowcs(entry->wdata, entry->data, 512);
}
void
config_set_string(char *head, char *name, char *val)
{
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);
mbstowcs(entry->wdata, entry->data, 256);
}
void
config_set_wstring(char *head, char *name, wchar_t *val)
{
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);
memcpy(entry->wdata, val, 512);
}
/* FIXME: should be moved elsewhere. --FvK */
char *
get_filename(char *s)
{
int c = strlen(s) - 1;
while (c > 0)
{
if (s[c] == '/' || s[c] == '\\')
return &s[c+1];
c--;
}
return s;
}
/* FIXME: should be moved elsewhere. --FvK */
wchar_t *
get_filename_w(wchar_t *s)
{
int c = wcslen(s) - 1;
while (c > 0)
{
if (s[c] == L'/' || s[c] == L'\\')
return &s[c+1];
c--;
}
return s;
}
/* FIXME: should be moved elsewhere. --FvK */
void
append_filename(char *dest, char *s1, char *s2, int size)
{
sprintf(dest, "%s%s", s1, s2);
}
/* FIXME: should be moved elsewhere. --FvK */
void
append_filename_w(wchar_t *dest, wchar_t *s1, wchar_t *s2, int size)
{
_swprintf(dest, L"%s%s", s1, s2);
}
/* FIXME: should be moved elsewhere. --FvK */
void
put_backslash(char *s)
{
int c = strlen(s) - 1;
if (s[c] != '/' && s[c] != '\\')
s[c] = '/';
}
/* FIXME: should be moved elsewhere. --FvK */
void
put_backslash_w(wchar_t *s)
{
int c = wcslen(s) - 1;
if (s[c] != L'/' && s[c] != L'\\')
s[c] = L'/';
}
/* FIXME: should be moved elsewhere. --FvK */
char *
get_extension(char *s)
{
int c = strlen(s) - 1;
if (c <= 0)
return s;
while (c && s[c] != '.')
c--;
if (!c)
return &s[strlen(s)];
return &s[c+1];
}
/* FIXME: should be moved elsewhere. --FvK */
wchar_t
*get_extension_w(wchar_t *s)
{
int c = wcslen(s) - 1;
if (c <= 0)
return s;
while (c && s[c] != L'.')
c--;
if (!c)
return &s[wcslen(s)];
return &s[c+1];
}