Subversion Repositories pentevo

Rev

Rev 1146 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "std.h"
  2.  
  3. #include <io.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6.  
  7. #include "emul.h"
  8. #include "vars.h"
  9. #include "memory.h"
  10. #include "debug.h"
  11. #include "dbglabls.h"
  12. #include "draw.h"
  13. #include "dx.h"
  14. #include "fontatm2.h"
  15. #include "snapshot.h"
  16. #include "sndrender/sndcounter.h"
  17. #include "sndrender/dev_moonsound.h"
  18. #include "sound.h"
  19. #include "sdcard.h"
  20. #include "gs.h"
  21. #include "zc.h"
  22. #include "util.h"
  23. #include "init.h"
  24. #include "config.h"
  25. #include "zxusbnet.h"
  26.  
  27. char load_errors;
  28.  
  29. void loadkeys(action*);
  30. void loadzxkeys(CONFIG*);
  31. void load_arch(const char*);
  32.  
  33. static unsigned load_rom(const char *path, unsigned char *bank, unsigned max_banks = 1)
  34. {
  35.    if (!*path) { norom: memset(bank, 0xFF, max_banks*PAGE); return 0; }
  36.    char tmp[FILENAME_MAX]; strcpy(tmp, path);
  37.    char *x = strrchr(tmp+2, ':');
  38.    unsigned page = 0;
  39.    if (x) { *x = 0; page = unsigned(atoi(x+1)); }
  40.    if (max_banks == 16) page *= 16; // bank for scorp prof.rom
  41.  
  42.    FILE *ff = fopen(tmp, "rb");
  43.  
  44.    if (!ff) {
  45.       errmsg("ROM file %s not found", tmp);
  46.    err:
  47.       load_errors = 1;
  48.       goto norom;
  49.    }
  50.  
  51.    if (fseek(ff, long(page*PAGE), SEEK_SET)) {
  52. badrom:
  53.       fclose(ff);
  54.       errmsg("Incorrect ROM file: %s", path);
  55.       goto err;
  56.    }
  57.  
  58.    size_t size = fread(bank, 1, max_banks*PAGE, ff);
  59.    if (!size || (size & (PAGE-1))) goto badrom;
  60.  
  61.    fclose(ff);
  62.    return unsigned(size / 1024);
  63. }
  64.  
  65. void load_atm_font()
  66. {
  67.    FILE *ff = fopen("SGEN.ROM", "rb");
  68.    if (!ff)
  69.    {
  70.        memcpy(fontatm2, fontatm2_default, sizeof(fontatm2));
  71.        return;
  72.    }
  73.    unsigned char font[0x800];
  74.    size_t sz = fread(font, 1, 0x800, ff);
  75.    if (sz == 0x800) {
  76.       color(CONSCLR_INFO);
  77.       printf("using ATM font from external SGEN.ROM\n");
  78.       for (unsigned chr = 0; chr < 0x100; chr++)
  79.          for (unsigned l = 0; l < 8; l++)
  80.             fontatm2[chr+l*0x100] = font[chr*8+l];
  81.    }
  82.    fclose(ff);
  83. }
  84.  
  85. static void load_atariset()
  86. {
  87.    memset(temp.ataricolors, 0, sizeof temp.ataricolors);
  88.    if (!conf.atariset[0])
  89.        return;
  90.    char defs[4000]; *defs = 0; // =12*256, strlen("07:aabbccdd,")=12
  91.    char keyname[80];
  92.    sprintf(keyname, "atari.%s", conf.atariset);
  93.    GetPrivateProfileString("COLORS", keyname, nil, defs, sizeof defs, ininame);
  94.    if (!*defs)
  95.        conf.atariset[0] = 0;
  96.    for (char *ptr = defs; *ptr; )
  97.    {
  98.       if (ptr[2] != ':')
  99.           return;
  100.       for (int i = 0; i < 11; i++)
  101.          if (i != 2 && !ishex(ptr[i]))
  102.              return;
  103.       unsigned index, val;
  104.       sscanf(ptr, "%02X:%08X", &index, &val);
  105.       temp.ataricolors[index] = val;
  106.       // temp.ataricolors[(index*16 + index/16) & 0xFF] = val; // swap ink-paper
  107.       ptr += 12;
  108.       if (ptr [-1] != ',')
  109.           return;
  110.    }
  111. }
  112.  
  113. void addpath(char *dst, const char *fname)
  114. {
  115.    if (!fname)
  116.        fname = dst;
  117.    else
  118.        strcpy(dst, fname);
  119.    if (!*fname)
  120.        return; // empty filenames have special meaning
  121.    if (fname[1] == ':' || (fname[0] == '\\' || fname[1] == '\\'))
  122.        return; // already full name
  123.  
  124.    char tmp[FILENAME_MAX];
  125.    GetModuleFileName(nullptr, tmp, sizeof tmp);
  126.    char *xx = strrchr(tmp, '\\');
  127.    if (*fname == '?')
  128.        *xx = 0; // "?" to get exe directory
  129.    else
  130.        strcpy(xx+1, fname);
  131.    strcpy(dst, tmp);
  132. }
  133.  
  134. void save_nv()
  135. {
  136.    char line[FILENAME_MAX]; addpath(line, "CMOS");
  137.    FILE *f0 = fopen(line, "wb");
  138.    if(f0)
  139.    {
  140.        fwrite(cmos, 1, sizeof cmos, f0);
  141.        fclose(f0);
  142.    }
  143.  
  144.    addpath(line, "NVRAM");
  145.    if((f0 = fopen(line, "wb")))
  146.    {
  147.        fwrite(nvram, 1, sizeof nvram, f0);
  148.        fclose(f0);
  149.    }
  150. }
  151.  
  152. void load_romset(CONFIG *conf, const char *romset)
  153. {
  154.    char sec[0x200];
  155.    sprintf(sec, "ROM.%s", romset);
  156.    GetPrivateProfileString(sec, "sos", nil, conf->sos_rom_path, sizeof conf->sos_rom_path, ininame);
  157.    GetPrivateProfileString(sec, "dos", nil, conf->dos_rom_path, sizeof conf->dos_rom_path, ininame);
  158.    GetPrivateProfileString(sec, "128", nil, conf->zx128_rom_path, sizeof conf->zx128_rom_path, ininame);
  159.    GetPrivateProfileString(sec, "sys", nil, conf->sys_rom_path, sizeof conf->sys_rom_path, ininame);
  160.    addpath(conf->sos_rom_path);
  161.    addpath(conf->dos_rom_path);
  162.    addpath(conf->zx128_rom_path);
  163.    addpath(conf->sys_rom_path);
  164. }
  165.  
  166. static void add_presets(const char *section, const char *prefix0, unsigned *num, char **tab, unsigned char *curr)
  167. {
  168.    *num = 0;
  169.    char buf[0x7F00], defval[64];
  170.    GetPrivateProfileSection(section, buf, sizeof buf, ininame);
  171.    GetPrivateProfileString(section, prefix0, "none", defval, sizeof defval, ininame);
  172.    char *p = strchr(defval, ';');
  173.    if (p) *p = 0;
  174.  
  175.    for (p = defval+strlen(defval)-1; p>=defval && *p == ' '; *p-- = 0);
  176.  
  177.    char prefix[0x200];
  178.    strcpy(prefix, prefix0);
  179.    strcat(prefix, ".");
  180.    size_t plen = strlen(prefix);
  181.    for (char *ptr = buf; *ptr; )
  182.    {
  183.       if (!strnicmp(ptr, prefix, plen))
  184.       {
  185.          ptr += plen;
  186.          tab[*num] = setptr;
  187.          while (*ptr && *ptr != '=')
  188.              *setptr++ = *ptr++;
  189.          *setptr++ = 0;
  190.  
  191.          if (!stricmp(tab[*num], defval))
  192.              *curr = (unsigned char)*num;
  193.          (*num)++;
  194.       }
  195.       while (*ptr) ptr++;
  196.       ptr++;
  197.    }
  198. }
  199.  
  200. void load_ula_preset()
  201. {
  202.    if (conf.ula_preset >= num_ula) return;
  203.    char line[128], name[64];
  204.    sprintf(name, "PRESET.%s", ulapreset[conf.ula_preset]);
  205.    static char defaults[] = "71680,17989,224,50,32,0,0,0,0,0,320,240,24,32,384,288,48,64";
  206.    GetPrivateProfileString("ULA", name, defaults, line, sizeof line, ininame);
  207.    unsigned t1, t2, t3, t4, t5;
  208.    sscanf(line, "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", &/*conf.frame*/frametime/*Alone Coder*/, &conf.paper,
  209.        &conf.t_line, &conf.intfq, &conf.intlen, &t1, &t2, &t3, &t4, &t5,
  210.        &conf.mcx_small, &conf.mcy_small, &conf.b_top_small, &conf.b_left_small,
  211.        &conf.mcx_full, &conf.mcy_full, &conf.b_top_full, &conf.b_left_full);
  212.    conf.even_M1 = (unsigned char)t1; conf.border_4T = (unsigned char)t2;
  213.    conf.floatbus = (unsigned char)t3; conf.floatdos = (unsigned char)t4;
  214.    conf.portff = t5 & 1;
  215.  
  216.    if(conf.mcx_small < 256)
  217.        conf.mcx_small = 256;
  218.    if(conf.mcy_small < 192)
  219.        conf.mcy_small = 192;
  220.  
  221.    if(conf.mcx_full < 256)
  222.        conf.mcx_full = 256;
  223.    if(conf.mcy_full < 192)
  224.        conf.mcy_full = 192;
  225.  
  226.    if(conf.b_left_full & 7)
  227.    {
  228.        err_printf("PRESET.%s:b_left_full not multiple of 8\n", ulapreset[conf.ula_preset]);
  229.        exit();
  230.    }
  231. }
  232.  
  233. void load_ay_stereo()
  234. {
  235.    char line[128], name[64]; sprintf(name, "STEREO.%s", aystereo[conf.sound.ay_stereo]);
  236.    GetPrivateProfileString("AY", name, "100,10,66,66,10,100", line, sizeof line, ininame);
  237.    unsigned *stereo = conf.sound.ay_stereo_tab;
  238.    sscanf(line, "%u,%u,%u,%u,%u,%u", stereo+0, stereo+1, stereo+2, stereo+3, stereo+4, stereo+5);
  239. }
  240.  
  241. void load_ay_vols()
  242. {
  243.    char line[512] = { 0 };
  244.    static char defaults[] = "0000,0340,04C0,06F2,0A44,0F13,1510,227E,289F,414E,5B21,7258,905E,B550,D7A0,FFFF";
  245.    char name[64]; sprintf(name, "VOLTAB.%s", ayvols[conf.sound.ay_vols]);
  246.    GetPrivateProfileString("AY", name, defaults, line, sizeof line, ininame);
  247.    if (line[74] != ',') strcpy(line, defaults);
  248.    if (line[79] == ',') { // YM
  249.       for (int i = 0; i < 32; i++)
  250.          sscanf(line+i*5, "%X", &conf.sound.ay_voltab[i]);
  251.    } else { // AY
  252.        for(int i = 0; i < 16; i++)
  253.        {
  254.            sscanf(line + i * 5, "%X", &conf.sound.ay_voltab[2 * i]);
  255.            conf.sound.ay_voltab[2 * i + 1] = conf.sound.ay_voltab[2 * i];
  256.        }
  257.    }
  258. }
  259.  
  260. #if (defined _MSC_VER)
  261. int strcasecmp(char const *s1, char const *s2)
  262. {
  263.         return ::_stricmp(s1, s2);
  264. }
  265. #endif
  266.  
  267.  
  268. void load_config(const char *fname)
  269. {
  270.    char line[FILENAME_MAX];
  271.    load_errors = 0;
  272.  
  273.    GetModuleFileName(nullptr, ininame, sizeof(ininame));
  274.  
  275.    //strlwr(ininame); // WHAT'S THIS FOR???
  276.    
  277.    // this was a flawed code since strstr searches FIRST occurence!
  278.    //*(unsigned*)(strstr(ininame, ".exe")+1) = WORD4('i','n','i',0);
  279.  
  280.    // make default config name: for EXENAME64.exe or EXENAME.exe that will be EXENAME.ini
  281.    size_t ininame_len = strlen(ininame);
  282.    const char const_64_exe[] = "64.exe";
  283.    const char const_exe[] = ".exe";
  284.    const char const_ini[] = ".ini";
  285.    //
  286.    if( !strcasecmp(ininame + ininame_len - sizeof(const_64_exe) + 1, const_64_exe) )
  287.         memcpy(ininame + ininame_len - sizeof(const_64_exe) + 1, const_ini, sizeof(const_ini)); // fix last "64.exe" to ".ini"
  288.    else if( !strcasecmp(ininame + ininame_len - sizeof(const_exe) + 1, const_exe) )
  289.         memcpy(ininame + ininame_len - sizeof(const_exe) + 1, const_ini, sizeof(const_ini)); // fix last ".exe" to ".ini"
  290.  
  291.    if (fname && *fname) {
  292.       char *dst = strrchr(ininame, '\\');
  293.       if (strchr(fname, '/') || strchr(fname, '\\')) dst = ininame; else dst++;
  294.       strcpy(dst, fname);
  295.    }
  296.    color(CONSCLR_DEFAULT); printf("ini: ");
  297.    color(CONSCLR_INFO);    printf("%s\n", ininame);
  298.  
  299.    if (GetFileAttributes(ininame) == INVALID_FILE_ATTRIBUTES) errexit("config file not found");
  300.  
  301.    static const char* misc = "MISC";
  302.    static const char* video = "VIDEO";
  303.    static const char* ula = "ULA";
  304.    static const char* beta128 = "Beta128";
  305.    static const char* USBZXNET = "USBZXNET";
  306.    static const char* debug = "DEBUG";
  307.    static const char* leds = "LEDS";
  308.    static const char* sound = "SOUND";
  309.    static const char* input = "INPUT";
  310.    static const char* colors = "COLORS";
  311.    static const char* ay = "AY";
  312.    static const char* saa1099 = "SAA1099";
  313.    static const char* hdd = "HDD";
  314.    static const char* rom = "ROM";
  315.    static const char* ngs = "NGS";
  316.    static const char* zc = "ZC";
  317.  
  318.    #ifdef MOD_MONITOR
  319.    addpath(conf.sos_labels_path, "sos.l");
  320.    #endif
  321.  
  322.    GetPrivateProfileString("*", "UNREAL", nil, line, sizeof line, ininame);
  323.    unsigned a,b,c;
  324.    sscanf(line, "%u.%u.%u", &a, &b, &c);
  325.    if ((((a << 8U) | b) != VER_HL) || (c != (VER_A & 0x7F)))
  326.        errexit("wrong ini-file version");
  327.  
  328.    GetPrivateProfileString(misc, "Help",  "help_eng.html", helpname, sizeof helpname, ininame);
  329.    addpath(helpname);
  330.  
  331.    if (GetPrivateProfileInt(misc, "HideConsole", 0, ininame))
  332.    {
  333.        FreeConsole();
  334.        nowait = 1;
  335.    }
  336.  
  337.    conf.ConfirmExit = u8(GetPrivateProfileInt(misc, "ConfirmExit", 0, ininame));
  338.  
  339.    conf.sleepidle = u8(GetPrivateProfileInt(misc, "ShareCPU", 0, ininame));
  340.    conf.highpriority = u8(GetPrivateProfileInt(misc, "HighPriority", 0, ininame));
  341.    GetPrivateProfileString(misc, "SyncMode", "SOUND", line, sizeof line, ininame);
  342.    conf.SyncMode = SM_SOUND;
  343.    if(!strnicmp(line, "SOUND", 5))
  344.        conf.SyncMode = SM_SOUND;
  345.    else if(!strnicmp(line, "VIDEO", 5))
  346.        conf.SyncMode = SM_VIDEO;
  347.    else if(!strnicmp(line, "TSC", 3))
  348.        conf.SyncMode = SM_TSC;
  349.    conf.HighResolutionTimer = GetPrivateProfileInt(misc, "HighResolutionTimer", 0, ininame);
  350.    conf.tape_traps = u8(GetPrivateProfileInt(misc, "TapeTraps", 1, ininame));
  351.    conf.tape_autostart = u8(GetPrivateProfileInt(misc, "TapeAutoStart", 1, ininame));
  352.    conf.EFF7_mask = u8(GetPrivateProfileInt(misc, "EFF7mask", 0, ininame));
  353.  
  354.    GetPrivateProfileString(rom, "ATM1", nil, conf.atm1_rom_path, sizeof conf.atm1_rom_path, ininame);
  355.    GetPrivateProfileString(rom, "ATM2", nil, conf.atm2_rom_path, sizeof conf.atm2_rom_path, ininame);
  356.    GetPrivateProfileString(rom, "ATM3", nil, conf.atm3_rom_path, sizeof conf.atm3_rom_path, ininame);
  357.    GetPrivateProfileString(rom, "SCORP", nil, conf.scorp_rom_path, sizeof conf.scorp_rom_path, ininame);
  358.    GetPrivateProfileString(rom, "PROFROM", nil, conf.prof_rom_path, sizeof conf.prof_rom_path, ininame);
  359.    GetPrivateProfileString(rom, "PROFI", nil, conf.profi_rom_path, sizeof conf.profi_rom_path, ininame);
  360. //[vv]   GetPrivateProfileString(rom, "KAY", nil, conf.kay_rom_path, sizeof conf.kay_rom_path, ininame);
  361.    GetPrivateProfileString(rom, "PLUS3", nil, conf.plus3_rom_path, sizeof conf.plus3_rom_path, ininame);
  362.    GetPrivateProfileString(rom, "QUORUM", nil, conf.quorum_rom_path, sizeof conf.quorum_rom_path, ininame);
  363.    #ifdef MOD_GSZ80
  364.    GetPrivateProfileString(rom, "GS", nil, conf.gs_rom_path, sizeof conf.gs_rom_path, ininame);
  365.    addpath(conf.gs_rom_path);
  366.    #endif
  367.    GetPrivateProfileString(rom, "MOONSOUND", nil, conf.moonsound_rom_path, sizeof conf.moonsound_rom_path, ininame);
  368.    addpath(conf.moonsound_rom_path);
  369.    addpath(conf.atm1_rom_path);
  370.    addpath(conf.atm2_rom_path);
  371.    addpath(conf.atm3_rom_path);
  372.    addpath(conf.scorp_rom_path);
  373.    addpath(conf.prof_rom_path);
  374.    addpath(conf.profi_rom_path);
  375.    addpath(conf.plus3_rom_path);
  376.    addpath(conf.quorum_rom_path);
  377. //[vv]   addpath(conf.kay_rom_path);
  378.  
  379.    GetPrivateProfileString(rom, "ROMSET", "default", line, sizeof line, ininame);
  380.    if(*line)
  381.    {
  382.        load_romset(&conf, line); conf.use_romset = 1;
  383.    }
  384.    else
  385.    {
  386.        conf.use_romset = 0;
  387.    }
  388.  
  389.    conf.smuc = u8(GetPrivateProfileInt(misc, "SMUC", 0, ininame));
  390.    GetPrivateProfileString(misc, "CMOS", nil, line, sizeof line, ininame);
  391.    conf.cmos = 0;
  392.    if (!strnicmp(line, "DALLAS", 6)) conf.cmos=1;
  393.    if (!strnicmp(line, "512Bu1", 6)) conf.cmos=2;
  394.    conf.cache = u8(GetPrivateProfileInt(misc, "Cache", 0, ininame));
  395.    if (conf.cache && conf.cache!=16 && conf.cache!=32) conf.cache = 0;
  396.    GetPrivateProfileString(misc, "HIMEM", nil, line, sizeof line, ininame);
  397.    conf.mem_model = MM_PENTAGON;
  398.    unsigned i; //Alone Coder 0.36.7
  399.    for (/*unsigned*/ i = 0; i < N_MM_MODELS; i++)
  400.       if (!strnicmp(line, mem_model[i].shortname, strlen(mem_model[i].shortname)))
  401.          conf.mem_model = mem_model[i].Model;
  402.    conf.ramsize = GetPrivateProfileInt(misc, "RamSize", 128, ininame);
  403.    conf.Sna128Lock = GetPrivateProfileInt(misc, "Sna128Lock", 1, ininame);
  404.  
  405.    GetPrivateProfileString(misc, "DIR", nil, conf.workdir, sizeof conf.workdir, ininame);
  406.  
  407.    GetCurrentDirectory(_countof(line), line);
  408.    SetCurrentDirectory(conf.workdir);
  409.    GetCurrentDirectory(_countof(temp.SnapDir), temp.SnapDir);
  410.    SetCurrentDirectory(line);
  411.    strcpy(temp.RomDir, temp.SnapDir);
  412.    strcpy(temp.HddDir, temp.SnapDir);
  413.    strcpy(temp.SdDir, temp.SnapDir);
  414.  
  415.    conf.reset_rom = RM_SOS;
  416.    GetPrivateProfileString(misc, "RESET", nil, line, sizeof line, ininame);
  417.    if (!strnicmp(line, "DOS", 3)) conf.reset_rom = RM_DOS;
  418.    if (!strnicmp(line, "MENU", 4)) conf.reset_rom = RM_128;
  419.    if (!strnicmp(line, "SYS", 3)) conf.reset_rom = RM_SYS;
  420.  
  421.    GetPrivateProfileString(misc, "Modem", nil, line, sizeof line, ininame);
  422.    conf.modem_port = 0;
  423.  
  424.    sscanf(line, "COM%d", &conf.modem_port);
  425.  
  426.    conf.paper = GetPrivateProfileInt(ula, "Paper", 17989, ininame);
  427.    conf.t_line = GetPrivateProfileInt(ula, "Line", 224, ininame);
  428.    conf.intfq = GetPrivateProfileInt(ula, "int", 50, ininame);
  429.    conf.intlen = GetPrivateProfileInt(ula, "intlen", 32, ininame);
  430.    /*conf.frame*/frametime/*Alone Coder*/ = GetPrivateProfileInt(ula, "Frame", 71680, ininame);
  431.    conf.border_4T = u8(GetPrivateProfileInt(ula, "4TBorder", 0, ininame));
  432.    conf.even_M1 = u8(GetPrivateProfileInt(ula, "EvenM1", 0, ininame));
  433.    conf.floatbus = u8(GetPrivateProfileInt(ula, "FloatBus", 0, ininame));
  434.    conf.floatdos = u8(GetPrivateProfileInt(ula, "FloatDOS", 0, ininame));
  435.    conf.portff = GetPrivateProfileInt(ula, "PortFF", 0, ininame) != 0;
  436.    conf.mcx_small = GetPrivateProfileInt(ula, "mcx_small", 320, ininame);
  437.    conf.mcy_small = GetPrivateProfileInt(ula, "mcy_small", 240, ininame);
  438.    conf.b_top_small = GetPrivateProfileInt(ula, "b_top_small", 24, ininame);
  439.    conf.b_left_small = GetPrivateProfileInt(ula, "b_left_small", 32, ininame);
  440.    conf.mcx_full = GetPrivateProfileInt(ula, "mcx_full", 384, ininame);
  441.    conf.mcy_full = GetPrivateProfileInt(ula, "mcy_full", 288, ininame);
  442.    conf.b_top_full = GetPrivateProfileInt(ula, "b_top_full", 48, ininame);
  443.    conf.b_left_full = GetPrivateProfileInt(ula, "b_left_full", 64, ininame);
  444.  
  445.    conf.ula_preset=u8(-1U);
  446.    add_presets(ula, "preset", &num_ula, ulapreset, &conf.ula_preset);
  447.  
  448.    load_ula_preset();
  449.  
  450.    conf.atm.mem_swap = u8(GetPrivateProfileInt(ula, "AtmMemSwap", 0, ininame));
  451.    conf.use_comp_pal = u8(GetPrivateProfileInt(ula, "UsePalette", 1, ininame));
  452.    conf.profi_monochrome = u8(GetPrivateProfileInt(ula, "ProfiMonochrome", 0, ininame));
  453.    conf.ula_plus = GetPrivateProfileInt(ula, "ULAPlus", 0, ininame) != 0;
  454.  
  455.    conf.flashcolor = u8(GetPrivateProfileInt(video, "FlashColor", 0, ininame));
  456.    conf.frameskip = u8(GetPrivateProfileInt(video, "SkipFrame", 0, ininame));
  457.    conf.flip = (conf.SyncMode == SM_VIDEO) ? 1 : u8(GetPrivateProfileInt(video, "VSync", 0, ininame));
  458.    conf.fullscr = u8(GetPrivateProfileInt(video, "FullScr", 1, ininame));
  459.    conf.refresh = GetPrivateProfileInt(video, "Refresh", 0, ininame);
  460.    conf.frameskipmax = u8(GetPrivateProfileInt(video, "SkipFrameMaxSpeed", 33, ininame));
  461.    conf.updateb = u8(GetPrivateProfileInt(video, "Update", 1, ininame));
  462.    conf.ch_size = u8(GetPrivateProfileInt(video, "ChunkSize", 0, ininame));
  463.    conf.noflic = u8(GetPrivateProfileInt(video, "NoFlic", 0, ininame));
  464.    conf.alt_nf = u8(GetPrivateProfileInt(video, "AltNoFlic", 0, ininame));
  465.    conf.scanbright = GetPrivateProfileInt(video, "ScanIntens", 66, ininame);
  466.    conf.pixelscroll = u8(GetPrivateProfileInt(video, "PixelScroll", 0, ininame));
  467.    conf.detect_video = u8(GetPrivateProfileInt(video, "DetectModel", 1, ininame));
  468.    conf.fontsize = 8;
  469.  
  470.    conf.videoscale = u8(GetPrivateProfileInt(video, "scale", 2, ininame));
  471.  
  472.    conf.rsm.mix_frames = u8(GetPrivateProfileInt(video, "rsm.frames", 8, ininame));
  473.    GetPrivateProfileString(video, "rsm.mode", nil, line, sizeof line, ininame);
  474.    conf.rsm.mode = RSM_FIR0;
  475.    if (!strnicmp(line, "FULL", 4)) conf.rsm.mode = RSM_FIR0;
  476.    if (!strnicmp(line, "2C", 2)) conf.rsm.mode = RSM_FIR1;
  477.    if (!strnicmp(line, "3C", 2)) conf.rsm.mode = RSM_FIR2;
  478.    if (!strnicmp(line, "SIMPLE", 6)) conf.rsm.mode = RSM_SIMPLE;
  479.  
  480.    GetPrivateProfileString(video, "AtariPreset", nil, conf.atariset, sizeof conf.atariset, ininame);
  481.  
  482.    GetPrivateProfileString(video, video, nil, line, sizeof line, ininame);
  483.    conf.render = 0;
  484.    for (i = 0; renders[i].func; i++)
  485.       if (!strnicmp(line, renders[i].nick, strlen(renders[i].nick)))
  486.          conf.render = i;
  487.  
  488.    GetPrivateProfileString(video, "driver", nil, line, sizeof line, ininame);
  489.    conf.driver = DRIVER_DDRAW;
  490.    for (i = 0; drivers[i].nick; i++)
  491.       if (!strnicmp(line, drivers[i].nick, strlen(drivers[i].nick)))
  492.          conf.driver = i;
  493.  
  494.    conf.fast_sl = u8(GetPrivateProfileInt(video, "fastlines", 0, ininame));
  495.  
  496.    GetPrivateProfileString(video, "Border", nil, line, sizeof line, ininame);
  497.    conf.bordersize = 1;
  498.    if (!strnicmp(line, "none", 4))
  499.        conf.bordersize = 0;
  500.    else if (!strnicmp(line, "small", 5))
  501.        conf.bordersize = 1;
  502.    else if (!strnicmp(line, "wide", 4))
  503.        conf.bordersize = 2;
  504.    conf.minres = GetPrivateProfileInt(video, "MinRes", 0, ininame);
  505.  
  506.    GetPrivateProfileString(video, "Hide", nil, line, sizeof line, ininame);
  507.    char *ptr = strchr(line, ';'); if (ptr) *ptr = 0;
  508.    for (ptr = line;;)
  509.    {
  510.       size_t max = renders_count - 1;
  511.       for (i = 0; renders[i].func; i++)
  512.       {
  513.          size_t sl = strlen(renders[i].nick);
  514.          if (!strnicmp(ptr, renders[i].nick, sl) && !isalnum(ptr[sl]))
  515.          {
  516.             ptr += sl;
  517.             memcpy(&renders[i], &renders[i+1], (sizeof *renders) * (max-i));
  518.             break;
  519.          }
  520.       }
  521.       if (!*ptr++)
  522.           break;
  523.    }
  524.  
  525.    GetPrivateProfileString(video, "ScrShotDir", ".", conf.scrshot_dir, sizeof(conf.scrshot_dir), ininame);
  526.  
  527.    GetPrivateProfileString(video, "ScrShot", nil, line, sizeof line, ininame);
  528.    conf.scrshot = 0;
  529.    if(!strnicmp(line, "scr", 3))
  530.        conf.scrshot = 0;
  531.    else if(!strnicmp(line, "bmp", 3))
  532.        conf.scrshot = 1;
  533.    else if(!strnicmp(line, "png", 3))
  534.        conf.scrshot = 2;
  535.  
  536.    GetPrivateProfileString(video, "ffmpeg.exec", "ffmpeg.exe", conf.ffmpeg.exec, sizeof conf.ffmpeg.exec, ininame);
  537.    GetPrivateProfileString(video, "ffmpeg.parm", nil, conf.ffmpeg.parm, sizeof conf.ffmpeg.parm, ininame);
  538.    GetPrivateProfileString(video, "ffmpeg.vout", "video#.avi", conf.ffmpeg.vout, sizeof conf.ffmpeg.vout, ininame);
  539.    conf.ffmpeg.newcons = i8(GetPrivateProfileInt(video, "ffmpeg.newconsole", 1, ininame));
  540.  
  541.    conf.trdos_present = u8(GetPrivateProfileInt(beta128, "beta128", 1, ininame));
  542.    conf.trdos_traps = u8(GetPrivateProfileInt(beta128, "Traps", 1, ininame));
  543.    conf.wd93_nodelay = u8(GetPrivateProfileInt(beta128, "Fast", 1, ininame));
  544.    conf.trdos_interleave = u8(GetPrivateProfileInt(beta128, "IL", 1, ininame)-1);
  545.    if (conf.trdos_interleave > 2) conf.trdos_interleave = 0;
  546.    conf.fdd_noise = u8(GetPrivateProfileInt(beta128, "Noise", 0, ininame));
  547.    GetPrivateProfileString(beta128, "BOOT", nil, conf.appendboot, sizeof conf.appendboot, ininame);
  548.    addpath(conf.appendboot);
  549.    conf.trdos_IORam=GetPrivateProfileInt(beta128, "RamPageFddIO", 0, ininame); //временный код, потом надо удалить
  550.    conf.wiznet=GetPrivateProfileInt(USBZXNET, "WizNet", 0, ininame);
  551.    GetPrivateProfileString(misc, "ColdRAM", "0000FFFF", conf.cold_ram_pat, sizeof conf.cold_ram_pat, ininame);
  552.    
  553.    conf.led.enabled = u8(GetPrivateProfileInt(leds, "leds", 1, ininame));
  554.    conf.led.flash_ay_kbd = u8(GetPrivateProfileInt(leds, "KBD_AY", 1, ininame));
  555.    conf.led.perf_t = u8(GetPrivateProfileInt(leds, "PerfShowT", 0, ininame));
  556.    conf.led.bandBpp = GetPrivateProfileInt(leds, "BandBpp", 512, ininame);
  557.    if (conf.led.bandBpp != 64 && conf.led.bandBpp != 128 && conf.led.bandBpp != 256 && conf.led.bandBpp != 512) conf.led.bandBpp = 512;
  558.  
  559.    static char nm[] = "AY\0Perf\0LOAD\0Input\0Time\0OSW\0MemBand\0Breakpoints\0";
  560.    char *n2 = nm;
  561.    for (i = 0; i < NUM_LEDS; i++) {
  562.       GetPrivateProfileString(leds, n2, nil, line, sizeof line, ininame);
  563.       int x, y;
  564.       unsigned z; unsigned r; n2 += strlen(n2) + 1;
  565.       if (sscanf(line, "%u:%d,%d", &z, &x, &y) != 3) r = 0;
  566.       else r = (x & 0xFFFF) + ((y << 16) & 0x7FFFFFFF) + z*0x80000000;
  567.       *(&conf.led.ay+i) = r;
  568.    }
  569.  
  570.    bkpts_ena = GetPrivateProfileInt(debug, "EnaBkpts", 1, ininame);
  571.  
  572.    conf.sound.do_sound = do_sound_none;
  573.    GetPrivateProfileString(sound, "SoundDrv", nil, line, sizeof line, ininame);
  574.    if (!strnicmp(line, "wave", 4)) {
  575.       conf.sound.do_sound = do_sound_wave;
  576.       conf.soundbuffer = GetPrivateProfileInt(sound, "SoundBuffer", 0, ininame);
  577.       if (!conf.soundbuffer) conf.soundbuffer = 6;
  578.       if (conf.soundbuffer >= MAXWQSIZE) conf.soundbuffer = MAXWQSIZE-1;
  579.    }
  580.    if (!strnicmp(line, "ds", 2)) {
  581.       conf.sound.do_sound = do_sound_ds;
  582. //      conf.soundbuffer = GetPrivateProfileInt(sound, "DSoundBuffer", 1000, ininame);
  583. //      conf.soundbuffer *= 4; // 16-bit, stereo
  584.    }
  585.  
  586.    conf.sound.enabled = u8(GetPrivateProfileInt(sound, "Enabled", 1, ininame));
  587.    #ifdef MOD_GS
  588.    conf.sound.gsreset = u8(GetPrivateProfileInt(sound, "GSReset", 0, ininame));
  589.    #endif
  590.    conf.sound.fq = GetPrivateProfileInt(sound, "Fq", 44100, ininame);
  591.    conf.sound.dsprimary = u8(GetPrivateProfileInt(sound, "DSPrimary", 0, ininame));
  592.  
  593.    conf.gs_type = 0;
  594. #ifdef MOD_GS
  595.    GetPrivateProfileString(sound, "GSTYPE", nil, line, sizeof line, ininame);
  596.    #ifdef MOD_GSZ80
  597.    if (!strnicmp(line, "Z80", 3)) conf.gs_type = 1;
  598.    #endif
  599.    #ifdef MOD_GSBASS
  600.    if (!strnicmp(line, "BASS", 4)) conf.gs_type = 2;
  601.    #endif
  602.    conf.gs_ramsize = GetPrivateProfileInt(ngs, "RamSize", 2048, ininame);
  603. #endif
  604.  
  605.    conf.soundfilter = u8(GetPrivateProfileInt(sound, "SoundFilter", 0, ininame)); //Alone Coder 0.36.4
  606.    conf.RejectDC = u8(GetPrivateProfileInt(sound, "RejectDC", 1, ininame));
  607.  
  608.    conf.sound.beeper_vol = int(GetPrivateProfileInt(sound, "BeeperVol", 4000, ininame));
  609.    conf.sound.micout_vol = int(GetPrivateProfileInt(sound, "MicOutVol", 1000, ininame));
  610.    conf.sound.micin_vol = int(GetPrivateProfileInt(sound, "MicInVol", 1000, ininame));
  611.    conf.sound.ay_vol = int(GetPrivateProfileInt(sound, "AYVol", 4000, ininame));
  612.    conf.sound.covoxFB = int(GetPrivateProfileInt(sound, "CovoxFB", 0, ininame));
  613.    conf.sound.covoxFB_vol = int(GetPrivateProfileInt(sound, "CovoxFBVol", 8192, ininame));
  614.    conf.sound.covoxDD = int(GetPrivateProfileInt(sound, "CovoxDD", 0, ininame));
  615.    conf.sound.covoxDD_vol = int(GetPrivateProfileInt(sound, "CovoxDDVol", 4000, ininame));
  616.    conf.sound.sd = int(GetPrivateProfileInt(sound, "SD", 0, ininame));
  617.    conf.sound.sd_vol = int(GetPrivateProfileInt(sound, "SDVol", 4000, ininame));
  618.    //conf.sound.saa1099 = GetPrivateProfileInt(sound, "Saa1099", 0, ininame);
  619.    conf.sound.saa1099 = SAA_NONE;
  620.    GetPrivateProfileString(sound, "Saa1099", 0, line, sizeof line, ininame);
  621.    if(!strnicmp(line, "ZXM", 3))
  622.        conf.sound.saa1099 = SAA_ZXM;
  623.    else if(!strnicmp(line, "TFMpro", 6))
  624.        conf.sound.saa1099 = SAA_TFM_PRO;
  625.    conf.sound.moonsound            = GetPrivateProfileInt(sound, "MoonSound", 0, ininame);
  626.    conf.sound.moonsound_dis_toc2c3 = GetPrivateProfileInt(sound, "MoonSound_dis_toc2c3", 0, ininame);
  627.    conf.sound.moonsound_vol        = GetPrivateProfileInt(sound, "MoonSoundVol", 4000, ininame);
  628.  
  629.    #ifdef MOD_GS
  630.    conf.sound.gs_vol = int(GetPrivateProfileInt(sound, "GSVol", 8000, ininame));
  631.    #endif
  632.  
  633.    #ifdef MOD_GSBASS
  634.    conf.sound.bass_vol = int(GetPrivateProfileInt(sound, "BASSVol", 8000, ininame));
  635.    #endif
  636.  
  637.    conf.sound.saa1099fq = GetPrivateProfileInt(saa1099, "Fq", 8000000, ininame);
  638.  
  639.    add_presets(ay, "VOLTAB", &num_ayvols, ayvols, &conf.sound.ay_vols);
  640.    add_presets(ay, "STEREO", &num_aystereo, aystereo, &conf.sound.ay_stereo);
  641.    conf.sound.ayfq = GetPrivateProfileInt(ay, "Fq", 1774400, ininame);
  642.  
  643.    GetPrivateProfileString(ay, "Chip", nil, line, sizeof line, ininame);
  644.    conf.sound.ay_chip = SNDCHIP::CHIP_YM;
  645.    if (!strnicmp(line, "AY", 2)) conf.sound.ay_chip = SNDCHIP::CHIP_AY;
  646.    if (!strnicmp(line, "YM2203", 6)) conf.sound.ay_chip = SNDCHIP::CHIP_YM2203;else //Dexus
  647.    if (!strnicmp(line, "YM", 2)) conf.sound.ay_chip = SNDCHIP::CHIP_YM;
  648.  
  649.    conf.sound.ay_samples = u8(GetPrivateProfileInt(ay, "UseSamples", 0, ininame));
  650.  
  651.    GetPrivateProfileString(ay, "Scheme", nil, line, sizeof line, ininame);
  652.    conf.sound.ay_scheme = AY_SCHEME_NONE;
  653.    if (!strnicmp(line, "default", 7)) conf.sound.ay_scheme = AY_SCHEME_SINGLE;
  654.    if(!strnicmp(line, "FULLER", 6)) conf.sound.ay_scheme = AY_SCHEME_FULLER;
  655.    if (!strnicmp(line, "PSEUDO", 6)) conf.sound.ay_scheme = AY_SCHEME_PSEUDO;
  656.    if (!strnicmp(line, "QUADRO", 6)) conf.sound.ay_scheme = AY_SCHEME_QUADRO;
  657.    if (!strnicmp(line, "POS", 3)) conf.sound.ay_scheme = AY_SCHEME_POS;
  658.    if (!strnicmp(line, "CHRV", 4)) conf.sound.ay_scheme = AY_SCHEME_CHRV;
  659.  
  660.    GetPrivateProfileString(input, "ZXKeyMap", "default", conf.zxkeymap, sizeof conf.zxkeymap, ininame);
  661.    for (i = 0; i < zxk_maps_count; i++)
  662.    {
  663.       if (!strnicmp(conf.zxkeymap, zxk_maps[i].name, strlen(zxk_maps[i].name)))
  664.       {
  665.           conf.input.active_zxk = &zxk_maps[i];
  666.           break;
  667.       }
  668.    }
  669.  
  670.    if(!conf.input.active_zxk)
  671.    {
  672.        errmsg("Invalid keyboard layout '%s' specified, default used", conf.zxkeymap);
  673.        conf.input.active_zxk = &zxk_maps[0]; // default
  674.    }
  675.  
  676.    GetPrivateProfileString(input, "KeybLayout", "default", line, sizeof(line), ininame);
  677.    ptr = strtok(line, " ;");
  678.    strcpy(conf.keyset, ptr ? ptr : line);
  679.  
  680.    GetPrivateProfileString(input, "Mouse", nil, line, sizeof line, ininame);
  681.    conf.input.mouse = 0;
  682.    if (!strnicmp(line, "KEMPSTON", 8)) conf.input.mouse = 1;
  683.    if (!strnicmp(line, "AY", 2)) conf.input.mouse = 2;
  684. //0.36.6 from 0.35b2
  685.    GetPrivateProfileString(input, "Wheel", nil, line, sizeof line, ininame);
  686.    conf.input.mousewheel = MOUSE_WHEEL_NONE;
  687.    if (!strnicmp(line, "KEMPSTON", 8)) conf.input.mousewheel = MOUSE_WHEEL_KEMPSTON;
  688.    if (!strnicmp(line, "KEYBOARD", 8)) conf.input.mousewheel = MOUSE_WHEEL_KEYBOARD;
  689. //~
  690.    conf.input.joymouse = u8(GetPrivateProfileInt(input, "JoyMouse", 0, ininame));
  691.    conf.input.mousescale = i8(GetPrivateProfileInt(input, "MouseScale", 0, ininame));
  692.    conf.input.mouseswap = u8(GetPrivateProfileInt(input, "SwapMouse", 0, ininame));
  693.    conf.input.kjoy = u8(GetPrivateProfileInt(input, "KJoystick", 1, ininame));
  694.    conf.input.fjoy = GetPrivateProfileInt(input, "FJoystick", 1, ininame) != 0;
  695.    conf.input.keymatrix = u8(GetPrivateProfileInt(input, "Matrix", 1, ininame));
  696.    conf.input.firedelay = u8(GetPrivateProfileInt(input, "FireRate", 1, ininame));
  697.    conf.input.altlock = u8(GetPrivateProfileInt(input, "AltLock", 1, ininame));
  698.    conf.input.paste_hold = u8(GetPrivateProfileInt(input, "HoldDelay", 2, ininame));
  699.    conf.input.paste_release = u8(GetPrivateProfileInt(input, "ReleaseDelay", 5, ininame));
  700.    conf.input.paste_newline = u8(GetPrivateProfileInt(input, "NewlineDelay", 20, ininame));
  701.    conf.input.keybpcmode = u8(GetPrivateProfileInt(input, "KeybPCMode", 0, ininame));
  702.    conf.atm.xt_kbd = u8(GetPrivateProfileInt(input, "ATMKBD", 0, ininame));
  703.    conf.input.JoyId = GetPrivateProfileInt(input, "Joy", 0, ininame);
  704.  
  705.    GetPrivateProfileString(input, "Fire", "0", line, sizeof line, ininame);
  706.    conf.input.firenum = 0; conf.input.fire = 0;
  707.    zxkeymap *active_zxk = conf.input.active_zxk;
  708.    for (i = 0; i < active_zxk->zxk_size; i++)
  709.       if (!stricmp(line, active_zxk->zxk[i].name))
  710.       {  conf.input.firenum = i; break; }
  711.  
  712.    char buff[0x7000];
  713.    GetPrivateProfileSection(colors, buff, sizeof buff, ininame);
  714.    GetPrivateProfileString(colors, "color", "default", line, sizeof line, ininame);
  715.    conf.pal = 0;
  716.  
  717.    for (i = 1, ptr = buff; i < _countof(pals); ptr += strlen(ptr)+1)
  718.    {
  719.       if (!*ptr)
  720.           break;
  721.       if (!isalnum(*ptr) || !strnicmp(ptr, "color=", 6))
  722.           continue;
  723.       char *ptr1 = strchr(ptr, '=');
  724.       if (!ptr1)
  725.           continue;
  726.       *ptr1 = 0; strcpy(pals[i].name, ptr); ptr = ptr1+1;
  727.       sscanf(ptr, "%02X,%02X,%02X,%02X,%02X,%02X:%X,%X,%X;%X,%X,%X;%X,%X,%X",
  728.          &pals[i].ZZ,  &pals[i].ZN,  &pals[i].NN,
  729.          &pals[i].NB,  &pals[i].BB,  &pals[i].ZB,
  730.          &pals[i].r11, &pals[i].r12, &pals[i].r13,
  731.          &pals[i].r21, &pals[i].r22, &pals[i].r23,
  732.          &pals[i].r31, &pals[i].r32, &pals[i].r33);
  733.  
  734.       pals[i].r11 = min(pals[i].r11, 256U);
  735.       pals[i].r12 = min(pals[i].r12, 256U);
  736.       pals[i].r13 = min(pals[i].r13, 256U);
  737.  
  738.       pals[i].r21 = min(pals[i].r21, 256U);
  739.       pals[i].r22 = min(pals[i].r22, 256U);
  740.       pals[i].r23 = min(pals[i].r23, 256U);
  741.  
  742.       pals[i].r31 = min(pals[i].r31, 256U);
  743.       pals[i].r32 = min(pals[i].r32, 256U);
  744.       pals[i].r33 = min(pals[i].r33, 256U);
  745.  
  746.       if (!strnicmp(line, pals[i].name, strlen(pals[i].name)))
  747.           conf.pal = i;
  748.       i++;
  749.    }
  750.    conf.num_pals = i;
  751.  
  752.    GetPrivateProfileString(hdd, "SCHEME", nil, line, sizeof line, ininame);
  753.    conf.ide_scheme = IDE_NONE;
  754.    if(!strnicmp(line, "ATM", 3))
  755.        conf.ide_scheme = IDE_ATM;
  756.    else if(!strnicmp(line, "NEMO-DIVIDE", 11))
  757.        conf.ide_scheme = IDE_NEMO_DIVIDE;
  758.    else if(!strnicmp(line, "NEMO-A8", 7))
  759.        conf.ide_scheme = IDE_NEMO_A8;
  760.    else if(!strnicmp(line, "NEMO", 4))
  761.        conf.ide_scheme = IDE_NEMO;
  762.    else if(!strnicmp(line, "SMUC", 4))
  763.        conf.ide_scheme = IDE_SMUC;
  764.    else if(!strnicmp(line, "PROFI", 5))
  765.        conf.ide_scheme = IDE_PROFI;
  766.    else if(!strnicmp(line, "DIVIDE", 6))
  767.        conf.ide_scheme = IDE_DIVIDE;
  768.  
  769.    conf.ide_skip_real = u8(GetPrivateProfileInt(hdd, "SkipReal", 0, ininame));
  770.    GetPrivateProfileString(hdd, "CDROM", "SPTI", line, sizeof line, ininame);
  771.    conf.cd_aspi = !strnicmp(line, "ASPI", 4) ? 1 : 0;
  772.  
  773.    for (int ide_device = 0; ide_device < 2; ide_device++)
  774.    {
  775.       char param[32];
  776.       sprintf(param, "LBA%d", ide_device);
  777.  
  778.       GetPrivateProfileString(hdd, param, "0", line, sizeof(line), ininame);
  779.       conf.ide[ide_device].lba = strtoull(line, nullptr, 10);
  780.       sprintf(param, "CHS%d", ide_device);
  781.       GetPrivateProfileString(hdd, param, "0/0/0", line, sizeof line, ininame);
  782.       unsigned c, h, s;
  783.  
  784.       sscanf(line, "%u/%u/%u", &c, &h, &s);
  785.       if(h > 16)
  786.       {
  787.           sprintf(line, "HDD%d heads count > 16 : %u\n", ide_device, h);
  788.           errexit(line);
  789.       }
  790.       if(s > 63)
  791.       {
  792.           sprintf(line, "error HDD%d sectors count > 63 : %u\n", ide_device, s);
  793.           errexit(line);
  794.       }
  795.       if(c > 16383)
  796.       {
  797.           sprintf(line, "error HDD%d cylinders count > 16383 : %u\n", ide_device, c);
  798.           errexit(line);
  799.       }
  800.  
  801.       conf.ide[ide_device].c = c;
  802.       conf.ide[ide_device].h = h;
  803.       conf.ide[ide_device].s = s;
  804.  
  805.       sprintf(param, "Image%d", ide_device);
  806.       GetPrivateProfileString(hdd, param, nil, conf.ide[ide_device].image, sizeof conf.ide[ide_device].image, ininame);
  807.  
  808.       if(conf.ide[ide_device].image[0] &&
  809.          conf.ide[ide_device].image[0] != '<')
  810.           addpath(conf.ide[ide_device].image);
  811.  
  812.       sprintf(param, "HD%dRO", ide_device);
  813.       conf.ide[ide_device].readonly = (BYTE)GetPrivateProfileInt(hdd, param, 0, ininame);
  814.       sprintf(param, "CD%d", ide_device);
  815.       conf.ide[ide_device].cd = (BYTE)GetPrivateProfileInt(hdd, param, 0, ininame);
  816.  
  817.       if(!conf.ide[ide_device].cd &&
  818.          conf.ide[ide_device].lba == 0 &&
  819.          conf.ide[ide_device].image[0] &&
  820.          conf.ide[ide_device].image[0] != '<')
  821.       {
  822.           int file = open(conf.ide[ide_device].image, O_RDONLY | O_BINARY, S_IREAD);
  823.           if(file >= 0)
  824.           {
  825.               __int64 sz = _filelengthi64(file);
  826.               close(file);
  827.               conf.ide[ide_device].lba = unsigned(sz / 512);
  828.           }
  829.       }
  830.    }
  831.  
  832.    addpath(line, "CMOS");
  833.    FILE *f0 = fopen(line, "rb");
  834.    if (f0)
  835.    {
  836.      fread(cmos, 1, sizeof cmos, f0);
  837.      fclose(f0);
  838.    }
  839.    else
  840.        cmos[0x11] = 0xAA;
  841.  
  842.    addpath(line, "NVRAM");
  843.    if ((f0 = fopen(line, "rb")))
  844.    {
  845.         fread(nvram, 1, sizeof nvram, f0);
  846.         fclose(f0);
  847.    }
  848.  
  849.    if(conf.gs_type == 1) // z80gs mode
  850.    {
  851.        GetPrivateProfileString(ngs, "SDCARD", nullptr, conf.ngs_sd_card_path, _countof(conf.ngs_sd_card_path), ininame);
  852.        addpath(conf.ngs_sd_card_path);
  853.        if(conf.ngs_sd_card_path[0])
  854.            printf("NGS SDCARD='%s'\n", conf.ngs_sd_card_path);
  855.    }
  856.  
  857.    conf.zc = u8(GetPrivateProfileInt(misc, "ZC", 0, ininame));
  858.    if(conf.zc)
  859.    {
  860.        GetPrivateProfileString(zc, "SDCARD", nullptr, conf.zc_sd_card_path, _countof(conf.zc_sd_card_path), ininame);
  861.        if ( strcmp(conf.zc_sd_card_path, "<CH341>") != 0 ) addpath(conf.zc_sd_card_path);
  862.        if(conf.zc_sd_card_path[0])
  863.            printf("ZC SDCARD='%s'\n", conf.zc_sd_card_path);
  864.        conf.sd_delay = GetPrivateProfileInt(zc, "SDDelay", 1000, ininame);
  865.    }
  866.  
  867.    GetPrivateProfileString("AUTOLOAD", "DefaultDrive", nil, line, sizeof(line), ininame);
  868.    if(!strnicmp(line, "Auto", 4))
  869.        DefaultDrive = -1U;
  870.    else if(!strnicmp(line, "A", 1))
  871.        DefaultDrive = 0;
  872.    else if(!strnicmp(line, "B", 1))
  873.        DefaultDrive = 1;
  874.    else if(!strnicmp(line, "C", 1))
  875.        DefaultDrive = 2;
  876.    else if(!strnicmp(line, "D", 1))
  877.        DefaultDrive = 3;
  878.  
  879.    load_arch(ininame);
  880.    loadkeys(ac_main);
  881. #ifdef MOD_MONITOR
  882.    loadkeys(ac_main_xt);
  883.    loadkeys(ac_regs);
  884.    loadkeys(ac_trace);
  885.    loadkeys(ac_mem);
  886. #endif
  887.    temp.scale = GetPrivateProfileInt(video, "winscale", 1, ininame);
  888. }
  889.  
  890. void autoload()
  891. {
  892.    static char autoload[] = "AUTOLOAD";
  893.    char line[512];
  894.  
  895.    for (unsigned disk = 0; disk < 4; disk++) {
  896.       char key[8]; sprintf(key, "disk%c", int('A'+disk));
  897.       GetPrivateProfileString(autoload, key, nil, line, sizeof line, ininame);
  898.       if (!*line) continue;
  899.       addpath(line);
  900.       trd_toload = disk;
  901.       if (!loadsnap(line)) errmsg("failed to autoload <%s>", line);
  902.    }
  903.  
  904.    GetPrivateProfileString(autoload, "snapshot", nil, line, sizeof line, ininame);
  905.    if (!*line) return;
  906.    addpath(line);
  907.    if (!loadsnap(line)) { color(CONSCLR_ERROR); printf("failed to start snapshot <%s>\n", line); }
  908. }
  909.  
  910. static void apply_memory()
  911. {
  912.    #ifdef MOD_GSZ80
  913.    if (conf.gs_type == 1)
  914.    {
  915.        if(load_rom(conf.gs_rom_path, ROM_GS_M, 32) != 512) // 512k rom
  916.        {
  917.            errmsg("invalid ROM size for NGS (need 512kb), NGS disabled\n");
  918.            conf.gs_type = 0;
  919.        }
  920.    }
  921.    #endif
  922.  
  923.    if (zxmmoonsound.load_rom(conf.moonsound_rom_path))
  924.    {
  925.        errmsg("failed to load MoonSound ROM, MoonSound disabled\n");
  926.        conf.sound.moonsound = 0;
  927.    }
  928.  
  929.    if (conf.ramsize != 128 && conf.ramsize != 256 && conf.ramsize != 512 && conf.ramsize != 1024 && conf.ramsize != 4096)
  930.       conf.ramsize = 0;
  931.    if (!(mem_model[conf.mem_model].availRAMs & conf.ramsize)) {
  932.       conf.ramsize = mem_model[conf.mem_model].defaultRAM;
  933.       color(CONSCLR_ERROR);
  934.       printf("invalid RAM size for %s, using default (%uK)\n",
  935.          mem_model[conf.mem_model].fullname, conf.ramsize);
  936.    }
  937.  
  938.    switch(conf.mem_model)
  939.    {
  940.    case MM_ATM710:
  941.    case MM_ATM3:
  942.       base_sos_rom = ROM_BASE_M + 0*PAGE;
  943.       base_dos_rom = ROM_BASE_M + 1*PAGE;
  944.       base_128_rom = ROM_BASE_M + 2*PAGE;
  945.       base_sys_rom = ROM_BASE_M + 3*PAGE;
  946.    break;
  947.  
  948.    case MM_ATM450:
  949.    case MM_PROFI:
  950.       base_sys_rom = ROM_BASE_M + 0*PAGE;
  951.       base_dos_rom = ROM_BASE_M + 1*PAGE;
  952.       base_128_rom = ROM_BASE_M + 2*PAGE;
  953.       base_sos_rom = ROM_BASE_M + 3*PAGE;
  954.    break;
  955.  
  956.    case MM_PLUS3:
  957.       base_128_rom = ROM_BASE_M + 0*PAGE;
  958.       base_sys_rom = ROM_BASE_M + 1*PAGE;
  959.       base_dos_rom = ROM_BASE_M + 2*PAGE;
  960.       base_sos_rom = ROM_BASE_M + 3*PAGE;
  961.    break;
  962.  
  963.    case MM_QUORUM:
  964.       base_sys_rom = ROM_BASE_M + 0*PAGE;
  965.       base_dos_rom = ROM_BASE_M + 1*PAGE;
  966.       base_128_rom = ROM_BASE_M + 2*PAGE;
  967.       base_sos_rom = ROM_BASE_M + 3*PAGE;
  968.    break;
  969.  
  970. /*
  971.    case MM_KAY:
  972.       base_128_rom = ROM_BASE_M + 0*PAGE;
  973.       base_sos_rom = ROM_BASE_M + 1*PAGE;
  974.       base_dos_rom = ROM_BASE_M + 2*PAGE;
  975.       base_sys_rom = ROM_BASE_M + 3*PAGE;
  976.    break;
  977. */
  978.  
  979.    default:
  980.       base_128_rom = ROM_BASE_M + 0*PAGE;
  981.       base_sos_rom = ROM_BASE_M + 1*PAGE;
  982.       base_sys_rom = ROM_BASE_M + 2*PAGE;
  983.       base_dos_rom = ROM_BASE_M + 3*PAGE;
  984.    }
  985.  
  986.    unsigned romsize;
  987.    if (conf.use_romset)
  988.    {
  989.       if (!load_rom(conf.sos_rom_path, base_sos_rom))
  990.           errexit("failed to load BASIC48 ROM");
  991.       if (!load_rom(conf.zx128_rom_path, base_128_rom) && conf.reset_rom == RM_128)
  992.           conf.reset_rom = RM_SOS;
  993.       if (!load_rom(conf.dos_rom_path, base_dos_rom))
  994.           conf.trdos_present = 0;
  995.       if (!load_rom(conf.sys_rom_path, base_sys_rom) && conf.reset_rom == RM_SYS)
  996.           conf.reset_rom = RM_SOS;
  997.       romsize = 64;
  998.    }
  999.    else
  1000.    {
  1001.       if (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)
  1002.       {
  1003.          romsize = load_rom(conf.mem_model == MM_ATM710 ? conf.atm2_rom_path : conf.atm3_rom_path, ROM_BASE_M, 64);
  1004.          if (romsize != 64 && romsize != 128 && romsize != 512 && romsize != 1024)
  1005.             errexit("invalid ROM size for ATM bios");
  1006.          unsigned char *lastpage = ROM_BASE_M + (romsize - 64) * 1024;
  1007.          base_sos_rom = lastpage + 0*PAGE;
  1008.          base_dos_rom = lastpage + 1*PAGE;
  1009.          base_128_rom = lastpage + 2*PAGE;
  1010.          base_sys_rom = lastpage + 3*PAGE;
  1011.       }
  1012.       else if (conf.mem_model == MM_PROFSCORP)
  1013.       {
  1014.          romsize = load_rom(conf.prof_rom_path, ROM_BASE_M, 16);
  1015.          if (romsize != 64 && romsize != 128 && romsize != 256)
  1016.             errexit("invalid PROF-ROM size");
  1017.       }
  1018.       else
  1019.       {
  1020.          const char *romname = nullptr;
  1021.          switch(conf.mem_model)
  1022.          {
  1023.          case MM_PROFI: romname = conf.profi_rom_path; break;
  1024.          case MM_SCORP: romname = conf.scorp_rom_path; break;
  1025. //[vv]         case MM_KAY: romname = conf.kay_rom_path; break;
  1026.          case MM_ATM450: romname = conf.atm1_rom_path; break;
  1027.          case MM_PLUS3: romname = conf.plus3_rom_path; break;
  1028.          case MM_QUORUM: romname = conf.quorum_rom_path; break;
  1029.  
  1030.          default:
  1031.              errexit("ROMSET should be defined for this memory model");
  1032.          }
  1033.  
  1034.          romsize = load_rom(romname, ROM_BASE_M, 64);
  1035.          if (romsize != 64)
  1036.              errexit("invalid ROM filesize");
  1037.       }
  1038.    }
  1039.  
  1040.    if (conf.mem_model == MM_PROFSCORP)
  1041.    {
  1042.       temp.profrom_mask = 0;
  1043.       if (romsize == 128)
  1044.           temp.profrom_mask = 1;
  1045.       if (romsize == 256)
  1046.           temp.profrom_mask = 3;
  1047.  
  1048.       comp.profrom_bank &= temp.profrom_mask;
  1049.       set_scorp_profrom(0);
  1050.    }
  1051.  
  1052. #ifdef MOD_MONITOR
  1053.    load_labels(conf.sos_labels_path, base_sos_rom, 0x4000);
  1054. #endif
  1055.  
  1056.    temp.gs_ram_mask = u8((conf.gs_ramsize-1) >> 4);
  1057.    temp.ram_mask = u8((conf.ramsize-1) >> 4);
  1058.    temp.rom_mask = u8((romsize-1) >> 4);
  1059.    set_banks();
  1060.  
  1061.    for(unsigned i = 0; i < CpuMgr.GetCount(); i++)
  1062.    {
  1063.        Z80 &cpu = CpuMgr.Cpu(i);
  1064.        cpu.dbgchk = isbrk(cpu);
  1065.    }
  1066. }
  1067.  
  1068.  
  1069. void applyconfig(bool Init)
  1070. {
  1071. #ifdef MOD_GS
  1072.     init_gs(Init);
  1073. #endif
  1074. //   printf("%s\n", __FUNCTION__);
  1075.  
  1076.    //[vv] disable turbo
  1077.    comp.pEFF7 |= EFF7_GIGASCREEN;
  1078.  
  1079. //Alone Coder 0.36.4
  1080.    conf.frame = frametime;
  1081.    cpu.SetTpi(conf.frame);
  1082. /*
  1083.    if ((conf.mem_model == MM_PENTAGON)&&(comp.pEFF7 & EFF7_GIGASCREEN))
  1084.        conf.frame = 71680;
  1085. */
  1086. //~Alone Coder
  1087.    temp.ticks_frame = (unsigned)(temp.cpufq / double(conf.intfq) + 1.0);
  1088.    loadzxkeys(&conf);
  1089.    apply_memory();
  1090.  
  1091.    temp.snd_frame_ticks = (conf.sound.fq << TICK_FF) / conf.intfq;
  1092.    temp.snd_frame_samples = temp.snd_frame_ticks >> TICK_FF;
  1093.    temp.frameskip = conf.sound.enabled? conf.frameskip : conf.frameskipmax;
  1094.  
  1095.    input.firedelay = 1; // if conf.input.fire changed
  1096.    input.clear_zx();
  1097.  
  1098.    modem.open(conf.modem_port);
  1099.  
  1100.    load_atariset();
  1101.    apply_video();
  1102.    apply_sound();
  1103.  
  1104.    hdd.dev[0].configure(conf.ide+0);
  1105.    hdd.dev[1].configure(conf.ide+1);
  1106.    if (conf.atm.xt_kbd) input.atm51.clear();
  1107.  
  1108.    if(conf.gs_type == 1)
  1109.    {
  1110.        SdCard.Close();
  1111.        SdCard.Open(conf.ngs_sd_card_path);
  1112.    }
  1113.  
  1114.    if(conf.zc)
  1115.    {
  1116.        Zc.Close();
  1117.        Zc.Open(conf.zc_sd_card_path);
  1118.    }
  1119.         if(conf.wiznet){
  1120.                 comp.wiznet.p83=0;
  1121.                 comp.wiznet.p82=0;
  1122.                 comp.wiznet.p81=0;
  1123.                 Wiz5300_Close();
  1124.                 Wiz5300_Init();
  1125.         }
  1126.  
  1127.    setpal(0);
  1128. }
  1129.  
  1130. void load_arch(const char *fname)
  1131. {
  1132.    GetPrivateProfileString("ARC", "SkipFiles", nil, skiparc, sizeof skiparc, fname);
  1133.    char *p; //Alone Coder 0.36.7
  1134.    for (/*char * */p = skiparc;;) {
  1135.       char *nxt = strchr(p, ';');
  1136.       if (!nxt) break;
  1137.       *nxt = 0; p = nxt+1;
  1138.    }
  1139.    p[strlen(p)+1] = 0;
  1140.  
  1141.    GetPrivateProfileSection("ARC", arcbuffer, sizeof arcbuffer, fname);
  1142.    for (char *x = arcbuffer; *x; ) {
  1143.       char *newx = x + strlen(x)+1;
  1144.       char *y = strchr(x, '=');
  1145.       if (!y) {
  1146. ignore_line:
  1147.          memcpy(x, newx, sizeof arcbuffer - size_t(newx-arcbuffer));
  1148.       } else {
  1149.          *y = 0; if (!stricmp(x, "SkipFiles")) goto ignore_line;
  1150.          x = newx;
  1151.       }
  1152.    }
  1153. }
  1154.  
  1155. void loadkeys(action *table)
  1156. {
  1157.    unsigned num[0x300], i = 0;
  1158.    unsigned j; //Alone Coder 0.36.7
  1159.    if (!table->name)
  1160.        return; // empty table (can't sort)
  1161.    for (action *p = table; p->name; p++, i++)
  1162.    {
  1163.       char line[0x400];
  1164.       GetPrivateProfileString("SYSTEM.KEYS", p->name, "`", line, sizeof line, ininame);
  1165.       if (*line == '`')
  1166.       {
  1167.          errmsg("keydef for %s not found", p->name);
  1168.          load_errors = 1;
  1169. bad_key:
  1170.          p->k1 = 0xFE;
  1171.          p->k2 = 0xFF;
  1172.          p->k3 = 0xFD;
  1173.          continue;
  1174.       }
  1175.       char *s = strchr(line, ';');
  1176.       if(s)
  1177.           *s = 0;
  1178.       p->k1 = p->k2 = p->k3 = p->k4 = 0; num[i] = 0;
  1179.       for (s = line;;)
  1180.       {
  1181.          while (*s == ' ') s++;
  1182.          if (!*s)
  1183.              break;
  1184.          char *s1 = s;
  1185.          while (isalnum(*s))
  1186.              s++;
  1187.          for (j = 0; j < pckeys_count; j++)
  1188.          {
  1189.             if ((int)strlen(pckeys[j].name)==s-s1 && !strnicmp(s1, pckeys[j].name, size_t(s-s1)))
  1190.             {
  1191.                switch (num[i])
  1192.                {
  1193.                   case 0: p->k1 = pckeys[j].virtkey; break;
  1194.                   case 1: p->k2 = pckeys[j].virtkey; break;
  1195.                   case 2: p->k3 = pckeys[j].virtkey; break;
  1196.                   case 3: p->k4 = pckeys[j].virtkey; break;
  1197.                   default:
  1198.                      color(CONSCLR_ERROR);
  1199.                      printf("warning: too many keys in %s=%s\n", p->name, line);
  1200.                      load_errors = 1;
  1201.                }
  1202.                num[i]++;
  1203.                break;
  1204.             }
  1205.          }
  1206.          if (j == pckeys_count)
  1207.          {
  1208.             color(CONSCLR_ERROR);
  1209.             char x = *s; *s = 0;
  1210.             printf("bad key: %s\n", s1); *s = x;
  1211.             load_errors = 1;
  1212.          }
  1213.       }
  1214.       if (!num[i])
  1215.           goto bad_key;
  1216.    }
  1217.  
  1218.    // sort keys
  1219.    for (unsigned k = 0; k < i-1; k++)
  1220.    {
  1221.       unsigned max = k;
  1222.       for (unsigned l = k+1; l < i; l++)
  1223.          if (num[l] > num[max])
  1224.              max = l;
  1225.  
  1226.       action tmp = table[k];
  1227.       table[k] = table[max];
  1228.       table[max] = tmp;
  1229.  
  1230.       unsigned tm = num[k];
  1231.       num[k] = num[max];
  1232.       num[max] = tm;
  1233.    }
  1234. }
  1235.  
  1236. void loadzxkeys(CONFIG *conf)
  1237. {
  1238.    char section[0x200];
  1239.    sprintf(section, "ZX.KEYS.%s", conf->keyset);
  1240.    char line[0x300];
  1241.    char *s; //Alone Coder 0.36.7
  1242.    unsigned k; //Alone Coder 0.36.7
  1243.    zxkeymap *active_zxk = conf->input.active_zxk;
  1244.  
  1245.    for (unsigned i = 0; i < VK_MAX; i++)
  1246.    {
  1247.       inports[i].port1 = inports[i].port2 = &input.kjoy;
  1248.       inports[i].mask1 = inports[i].mask2 = 0xFF;
  1249.       for (unsigned j = 0; j < pckeys_count; j++)
  1250.       {
  1251.          if (pckeys[j].virtkey == i)
  1252.          {
  1253.             GetPrivateProfileString(section, pckeys[j].name, "", line, sizeof line, ininame);
  1254.             s = strtok(line, " ;");
  1255.             if(s)
  1256.             {
  1257.                for(k = 0; k < active_zxk->zxk_size; k++)
  1258.                {
  1259.                   if (!stricmp(s, active_zxk->zxk[k].name))
  1260.                   {
  1261.                      inports[i].port1 = active_zxk->zxk[k].port;
  1262.                      inports[i].mask1 = active_zxk->zxk[k].mask;
  1263.                      switch(i)
  1264.                      {
  1265.                      case DIK_CONTROL:
  1266.                          inports[DIK_LCONTROL].port1 = active_zxk->zxk[k].port;
  1267.                          inports[DIK_LCONTROL].mask1 = active_zxk->zxk[k].mask;
  1268.                          inports[DIK_RCONTROL].port1 = active_zxk->zxk[k].port;
  1269.                          inports[DIK_RCONTROL].mask1 = active_zxk->zxk[k].mask;
  1270.                      break;
  1271.  
  1272.                      case DIK_SHIFT:
  1273.                          inports[DIK_LSHIFT].port1 = active_zxk->zxk[k].port;
  1274.                          inports[DIK_LSHIFT].mask1 = active_zxk->zxk[k].mask;
  1275.                          inports[DIK_RSHIFT].port1 = active_zxk->zxk[k].port;
  1276.                          inports[DIK_RSHIFT].mask1 = active_zxk->zxk[k].mask;
  1277.                      break;
  1278.  
  1279.                      case DIK_MENU:
  1280.                          inports[DIK_LMENU].port1 = active_zxk->zxk[k].port;
  1281.                          inports[DIK_LMENU].mask1 = active_zxk->zxk[k].mask;
  1282.                          inports[DIK_RMENU].port1 = active_zxk->zxk[k].port;
  1283.                          inports[DIK_RMENU].mask1 = active_zxk->zxk[k].mask;
  1284.                      break;
  1285.                      }
  1286.                      break;
  1287.                   }
  1288.                }
  1289.             }
  1290.             s = strtok(nullptr, " ;");
  1291.             if(s)
  1292.             {
  1293.                for (k = 0; k < active_zxk->zxk_size; k++)
  1294.                {
  1295.                   if (!stricmp(s, active_zxk->zxk[k].name))
  1296.                   {
  1297.                      inports[i].port2 = active_zxk->zxk[k].port;
  1298.                      inports[i].mask2 = active_zxk->zxk[k].mask;
  1299.  
  1300.                      switch(i)
  1301.                      {
  1302.                      case DIK_CONTROL:
  1303.                          inports[DIK_LCONTROL].port2 = active_zxk->zxk[k].port;
  1304.                          inports[DIK_LCONTROL].mask2 = active_zxk->zxk[k].mask;
  1305.                          inports[DIK_RCONTROL].port2 = active_zxk->zxk[k].port;
  1306.                          inports[DIK_RCONTROL].mask2 = active_zxk->zxk[k].mask;
  1307.                      break;
  1308.  
  1309.                      case DIK_SHIFT:
  1310.                          inports[DIK_LSHIFT].port2 = active_zxk->zxk[k].port;
  1311.                          inports[DIK_LSHIFT].mask2 = active_zxk->zxk[k].mask;
  1312.                          inports[DIK_RSHIFT].port2 = active_zxk->zxk[k].port;
  1313.                          inports[DIK_RSHIFT].mask2 = active_zxk->zxk[k].mask;
  1314.                      break;
  1315.  
  1316.                      case DIK_MENU:
  1317.                          inports[DIK_LMENU].port2 = active_zxk->zxk[k].port;
  1318.                          inports[DIK_LMENU].mask2 = active_zxk->zxk[k].mask;
  1319.                          inports[DIK_RMENU].port2 = active_zxk->zxk[k].port;
  1320.                          inports[DIK_RMENU].mask2 = active_zxk->zxk[k].mask;
  1321.                      break;
  1322.                      }
  1323.                      break;
  1324.                   }
  1325.                }
  1326.             }
  1327.             break;
  1328.          }
  1329.       }
  1330.    }
  1331. }
  1332.