]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
HDF/HD low level metadata support. (ATA Identity, SCSI Inquiry etc..)
authorToni Wilen <twilen@winuae.net>
Sun, 16 Jul 2017 17:57:02 +0000 (20:57 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 16 Jul 2017 17:57:02 +0000 (20:57 +0300)
cfgfile.cpp
filesys.cpp
hardfile.cpp
ide.cpp
include/disk.h
include/filesys.h
include/ide.h
include/options.h
od-win32/hardfile_win32.cpp
od-win32/win32gui.cpp

index 8c0f9f6d4dc7a60cab1f006b0f2a7b1370ba9249..771f2f04a02443f034391c6160773cb2d5eef870 100644 (file)
@@ -38,6 +38,7 @@
 #include "luascript.h"
 #include "ethernet.h"
 #include "native2amiga_api.h"
+#include "ini.h"
 
 #define cfgfile_warning write_log
 #define cfgfile_warning_obsolete write_log
@@ -946,7 +947,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                        else
                                _tcscpy(hdcs, _T("scide"));
                } else if (ct == HD_CONTROLLER_TYPE_UAE) {
-                       _tcscpy(hdcs, _T("uae"));
+                       _stprintf(hdcs, _T("uae%d"), ci->controller_unit);
                }
                if (romtype) {
                        for (int j = 0; hdcontrollers[j].label; j++) {
@@ -973,25 +974,33 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                        zfile_fputs (f, tmp2);
 #endif
                } else if (ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD || ci->type == UAEDEV_TAPE) {
+                       TCHAR *sfilesys = cfgfile_escape_min(ci->filesys);
+                       TCHAR *sgeometry = cfgfile_escape_min(ci->geometry);
                        _stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"),
                                ci->readonly ? _T("ro") : _T("rw"),
                                ci->devname ? ci->devname : _T(""), str1c,
                                ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
-                               bp, ci->filesys ? ci->filesys : _T(""), hdcs);
+                               bp, ci->filesys[0] ? sfilesys : _T(""), hdcs);
                        _stprintf (tmp3, _T("%s,%s:%s%s%s,%d,%d,%d,%d,%d,%s,%s"),
                                ci->readonly ? _T("ro") : _T("rw"),
                                ci->devname ? ci->devname : _T(""), str1b, str2b[0] ? _T(":") : _T(""), str2b,
                                ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
-                               bp, ci->filesys ? ci->filesys : _T(""), hdcs);
-                       if (ci->highcyl || ci->physical_geometry) {
+                               bp, ci->filesys[0] ? sfilesys : _T(""), hdcs);
+                       if (ci->highcyl || ci->physical_geometry || ci->geometry[0]) {
                                TCHAR *s = tmp + _tcslen (tmp);
                                TCHAR *s2 = s;
                                _stprintf (s2, _T(",%d"), ci->highcyl);
-                               if (ci->physical_geometry && ci->pheads && ci->psecs) {
-                                       TCHAR *s = tmp + _tcslen (tmp);
+                               if ((ci->physical_geometry && ci->pheads && ci->psecs) || ci->geometry[0]) {
+                                       s = tmp + _tcslen (tmp);
                                        _stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs);
+                                       if (ci->geometry[0]) {
+                                               s = tmp + _tcslen (tmp);
+                                               _stprintf (s, _T(",%s"), sgeometry);
+                                       }
                                }
                                _tcscat (tmp3, s2);
+                               xfree(sfilesys);
+                               xfree(sgeometry);
                        }
                        if (ci->controller_media_type) {
                                _tcscat(tmp, _T(",CF"));
@@ -1242,9 +1251,14 @@ static void cfgfile_write_rom_settings(const struct expansionboardsettings *ebs,
        }
 }
 
+static bool is_custom_romboard(struct boardromconfig *br)
+{
+       return ((br->device_type & ROMTYPE_MASK) == ROMTYPE_UAEBOARDZ2 || (br->device_type & ROMTYPE_MASK) == ROMTYPE_UAEBOARDZ3);
+}
+
 static void cfgfile_write_board_rom(struct uae_prefs *prefs, struct zfile *f, struct multipath *mp, struct boardromconfig *br)
 {
-       TCHAR buf[256];
+       TCHAR buf[MAX_DPATH];
        TCHAR name[256];
        const struct expansionromtype *ert;
        
@@ -1265,7 +1279,7 @@ static void cfgfile_write_board_rom(struct uae_prefs *prefs, struct zfile *f, st
                                _stprintf(buf, _T("%s%s_rom"), name, i ? _T("_ext") : _T(""));
                                cfgfile_dwrite_str (f, buf, br->roms[i].romident);
                        }
-                       if (br->roms[i].autoboot_disabled || ert->subtypes || ert->settings || ert->id_jumper || br->device_order > 0) {
+                       if (br->roms[i].autoboot_disabled || ert->subtypes || ert->settings || ert->id_jumper || br->device_order > 0 || is_custom_romboard(br)) {
                                TCHAR buf2[256], *p;
                                buf2[0] = 0;
                                p = buf2;
@@ -1300,6 +1314,23 @@ static void cfgfile_write_board_rom(struct uae_prefs *prefs, struct zfile *f, st
                                if (br->roms[i].device_settings && ert->settings) {
                                        cfgfile_write_rom_settings(ert->settings, buf2, br->roms[i].device_settings, br->roms[i].configtext);
                                }
+                               if (is_custom_romboard(br)) {
+                                       if (br->roms[i].manufacturer) {
+                                               if (buf2[0])
+                                                       _tcscat(buf2, _T(","));
+                                               TCHAR *p2 = buf2 + _tcslen(buf2);
+                                               _stprintf(p2, _T("mid=%u,pid=%u"), br->roms[i].manufacturer, br->roms[i].product);
+                                       }
+                                       if (br->roms[i].autoconfig[0]) {
+                                               uae_u8 *ac = br->roms[i].autoconfig;
+                                               if (buf2[0])
+                                                       _tcscat(buf2, _T(","));
+                                               TCHAR *p2 = buf2 + _tcslen(buf2);
+                                               _stprintf(p2, _T("data=%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x"),
+                                                       ac[0], ac[1], ac[2], ac[3], ac[4], ac[5], ac[6], ac[7],
+                                                       ac[8], ac[9], ac[10], ac[11], ac[12], ac[13], ac[14], ac[15]);
+                                       }
+                               }
                                if (buf2[0])
                                        cfgfile_dwrite_str (f, buf, buf2);
                        }
@@ -2183,8 +2214,12 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_write (f, _T("cpu_model"), _T("%d"), p->cpu_model);
        if (p->fpu_model)
                cfgfile_write (f, _T("fpu_model"), _T("%d"), p->fpu_model);
-       if (p->mmu_model)
-               cfgfile_write (f, _T("mmu_model"), _T("%d"), p->mmu_model);
+       if (p->mmu_model) {
+               if (p->mmu_ec)
+                       cfgfile_write (f, _T("mmu_model"), _T("68ec0%d"), p->mmu_model % 100);
+               else
+                       cfgfile_write (f, _T("mmu_model"), _T("%d"), p->mmu_model);
+       }
        if (p->ppc_mode) {
                cfgfile_write_str(f, _T("ppc_model"), p->ppc_model[0] ? p->ppc_model : (p->ppc_mode == 1 ? _T("automatic") : _T("manual")));
                cfgfile_write_str(f, _T("ppc_cpu_idle"), ppc_cpu_idle[p->ppc_cpu_idle]);
@@ -3414,11 +3449,17 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
                return 1;
        }
        if (_tcscmp (option, _T("joyport0")) == 0 || _tcscmp (option, _T("joyport1")) == 0) {
-               inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyport0")) == 0 ? 0 : 1, -1, 0);
+               int port = _tcscmp (option, _T("joyport0")) == 0 ? 0 : 1;
+               inputdevice_joyport_config_store(p, _T(""), port, -1, 1);
+               inputdevice_joyport_config_store(p, _T(""), port, -1, 2);
+               inputdevice_joyport_config_store(p, value, port, -1, 0);
                return 1;
        }
        if (_tcscmp (option, _T("joyport2")) == 0 || _tcscmp (option, _T("joyport3")) == 0) {
-               inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyport2")) == 0 ? 2 : 3, -1, 0);
+               int port = _tcscmp (option, _T("joyport0")) == 0 ? 2 : 3;
+               inputdevice_joyport_config_store(p, _T(""), port, -1, 1);
+               inputdevice_joyport_config_store(p, _T(""), port, -1, 2);
+               inputdevice_joyport_config_store(p, value, port, -1, 0);
                return 1;
        }
        if (cfgfile_strval (option, value, _T("joyport0mode"), &p->jports[0].mode, joyportmodes, 0))
@@ -3901,6 +3942,23 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s
                                        break;
                                }
                        }
+               } else if (ci->controller_type == HD_CONTROLLER_TYPE_UAE) {
+                       int ctrl = ci->controller_type;
+                       int ctrlunit = ci->controller_type_unit;
+                       int cunit = ci->controller_unit;
+                       for (;;) {
+                               for (i = 0; i < p->mountitems; i++) {
+                                       if (p->mountconfig[i].ci.controller_type == ctrl && p->mountconfig[i].ci.controller_type_unit == ctrlunit && p->mountconfig[i].ci.controller_unit == cunit) {
+                                               cunit++;
+                                               if (cunit >= MAX_FILESYSTEM_UNITS)
+                                                       return NULL;
+                                       }
+                               }
+                               if (i == p->mountitems) {
+                                       ci->controller_unit = cunit;
+                                       break;
+                               }
+                       }
                }
                if (ci->type == UAEDEV_CD) {
                        for (i = 0; i < p->mountitems; i++) {
@@ -3980,7 +4038,11 @@ static void get_filesys_controller (const TCHAR *hdc, int *type, int *typenum, i
                if (hdunit < 0 || hdunit >= 8 + 2)
                        hdunit = 0;
        }
-       if (hdcv > HD_CONTROLLER_TYPE_UAE) {
+       if (hdcv == HD_CONTROLLER_TYPE_UAE) {
+               hdunit = _tstol(hdc + 3);
+               if (hdunit >= MAX_FILESYSTEM_UNITS)
+                       hdunit = 0;
+       } else if (hdcv > HD_CONTROLLER_TYPE_UAE) {
                bool found = false;
                const TCHAR *ext = _tcsrchr (hdc, '_');
                if (ext) {
@@ -4039,6 +4101,8 @@ static void get_filesys_controller (const TCHAR *hdc, int *type, int *typenum, i
        }
        if (idx >= MAX_DUPLICATE_EXPANSION_BOARDS)
                idx = MAX_DUPLICATE_EXPANSION_BOARDS - 1;
+       if (hdunit < 0)
+               hdunit = 0;
        *type = hdcv;
        *typenum = idx;
        *num = hdunit;
@@ -4046,139 +4110,168 @@ static void get_filesys_controller (const TCHAR *hdc, int *type, int *typenum, i
 
 static bool parse_geo (const TCHAR *tname, struct uaedev_config_info *uci, struct hardfiledata *hfd, bool empty)
 {
-       struct zfile *f;
-       int found;
-       TCHAR buf[200];
-       
-       f = zfile_fopen (tname, _T("r"));
-       if (!f)
-               return false;
-       found = hfd == NULL && !empty ? 2 : 0;
-       if (found)
-               write_log (_T("Geometry file '%s' detected\n"), tname);
-       while (zfile_fgets (buf, sizeof buf / sizeof (TCHAR), f)) {
-               int v;
-               TCHAR *sep;
-               
-               my_trim (buf);
-               if (_tcslen (buf) == 0)
-                       continue;
-               if (buf[0] == '[' && buf[_tcslen (buf) - 1] == ']') {
-                       if (found > 1) {
-                               zfile_fclose (f);
-                               return true;
-                       }
-                       found = 0;
-                       buf[_tcslen (buf) - 1] = 0;
-                       my_trim (buf + 1);
-                       if (!_tcsicmp (buf + 1, _T("empty"))) {
-                               if (empty)
-                                       found = 1;
-                       } else if (!_tcsicmp (buf + 1, _T("default"))) {
-                               if (!empty)
-                                       found = 1;
-                       } else if (hfd) {
-                               uae_u64 size = _tstoi64 (buf + 1);
-                               if (size == hfd->virtsize)
-                                       found = 2;
-                       }
-                       if (found)
-                               write_log (_T("Geometry file '%s', entry '%s' detected\n"), tname, buf + 1);
-                       continue;
+       int found = 0;
+       TCHAR section[200];
+       struct ini_data *ini;
+       bool ret = false;
+
+       ini = ini_load(tname);
+       if (!ini)
+               return ret;
+
+       _tcscpy(section, _T("empty"));
+       if (empty && ini_getstring(ini, section, NULL, NULL)) {
+               found = 1;
+       }
+       _tcscpy(section, _T("default"));
+       if (!empty && ini_getstring(ini, section, NULL, NULL)) {
+               found = 1;
+       }
+       _tcscpy(section, _T("geometry"));
+       if (ini_getstring(ini, section, NULL, NULL)) {
+               found = 1;
+       }
+       if (hfd) {
+               _stprintf(section, _T("%llu"), hfd->virtsize);
+               if (ini_getstring(ini, section, NULL, NULL)) {
+                       found = 1;
                }
-               if (!found)
-                       continue;
+       }
 
-               sep =  _tcschr (buf, '=');
-               if (!sep)
-                       continue;
-               sep[0] = 0;
+       if (found) {
+               ret = true;
+               write_log(_T("Geometry file '%s' section '%s' found\n"), tname, section);
+               _tcscpy(uci->geometry, tname);
 
-               TCHAR *key = my_strdup_trim (buf);
-               TCHAR *val = my_strdup_trim (sep + 1);
-               if (val[0] == '0' && _totupper (val[1]) == 'X') {
-                       TCHAR *endptr;
-                       v = _tcstol (val, &endptr, 16);
-               } else {
-                       v = _tstol (val);
-               }
-               if (!_tcsicmp (key, _T("surfaces")))
-                       uci->surfaces = v;
-               if (!_tcsicmp (key, _T("sectorspertrack")) || !_tcsicmp (key, _T("blockspertrack")))
-                       uci->sectors = v;
-               if (!_tcsicmp (key, _T("sectorsperblock")))
-                       uci->sectorsperblock = v;
-               if (!_tcsicmp (key, _T("reserved")))
-                       uci->reserved = v;
-               if (!_tcsicmp (key, _T("lowcyl")))
-                       uci->lowcyl = v;
-               if (!_tcsicmp (key, _T("highcyl")) || !_tcsicmp (key, _T("cyl")))
-                       uci->highcyl = v;
-               if (!_tcsicmp (key, _T("blocksize")) || !_tcsicmp (key, _T("sectorsize")))
-                       uci->blocksize = v;
-               if (!_tcsicmp (key, _T("buffers")))
-                       uci->buffers = v;
-               if (!_tcsicmp (key, _T("maxtransfer")))
-                       uci->maxtransfer = v;
-               if (!_tcsicmp (key, _T("interleave")))
-                       uci->interleave = v;
-               if (!_tcsicmp (key, _T("dostype")))
-                       uci->dostype = v;
-               if (!_tcsicmp (key, _T("bufmemtype")))
-                       uci->bufmemtype = v;
-               if (!_tcsicmp (key, _T("stacksize")))
-                       uci->stacksize = v;
-               if (!_tcsicmp (key, _T("mask")))
-                       uci->mask = v;
-               if (!_tcsicmp (key, _T("unit")))
-                       uci->unit = v;
-               if (!_tcsicmp (key, _T("controller")))
-                       get_filesys_controller (val, &uci->controller_type, &uci->controller_type_unit, &uci->controller_unit);
-               if (!_tcsicmp (key, _T("flags")))
-                       uci->flags = v;
-               if (!_tcsicmp (key, _T("priority")))
-                       uci->priority = v;
-               if (!_tcsicmp (key, _T("forceload")))
-                       uci->forceload = v;
-               if (!_tcsicmp (key, _T("bootpri"))) {
-                       if (v < -129)
-                               v = -129;
-                       if (v > 127)
-                               v = 127;
-                       uci->bootpri = v;
-               }
-               if (!_tcsicmp (key, _T("filesystem")))
-                       _tcscpy (uci->filesys, val);
-               if (!_tcsicmp (key, _T("device")))
-                       _tcscpy (uci->devname, val);
-               if (!_tcsicmp(key, _T("badblocks"))) {
-                       TCHAR *p = val;
-                       while (p && *p && uci->badblock_num < MAX_UAEDEV_BADBLOCKS) {
-                               struct uaedev_badblock *bb = &uci->badblocks[uci->badblock_num];
-                               if (!_istdigit(*p))
-                                       break;
-                               bb->first = _tstol(p);
-                               bb->last = bb->first;
-                               TCHAR *p1 = _tcschr(p, ',');
-                               TCHAR *p2 = NULL;
-                               if (p1) {
-                                       p2 = p1 + 1;
-                                       *p1 = 0;
-                               }
-                               p1 = _tcschr(p, '-');
-                               if (p1) {
-                                       bb->last = _tstol(p1 + 1);
+               int idx = 0;
+               for (;;) {
+                       TCHAR *key = NULL, *val = NULL;
+                       int v;
+                       if (!ini_getsectionstring(ini, section, idx, &key, &val))
+                               break;
+                       if (val[0] == '0' && _totupper (val[1]) == 'X') {
+                               TCHAR *endptr;
+                               v = _tcstol (val, &endptr, 16);
+                       } else {
+                               v = _tstol (val);
+                       }
+                       if (!_tcsicmp (key, _T("surfaces")))
+                               uci->surfaces = v;
+                       if (!_tcsicmp (key, _T("sectorspertrack")) || !_tcsicmp (key, _T("blockspertrack")))
+                               uci->sectors = v;
+                       if (!_tcsicmp (key, _T("sectorsperblock")))
+                               uci->sectorsperblock = v;
+                       if (!_tcsicmp (key, _T("reserved")))
+                               uci->reserved = v;
+                       if (!_tcsicmp (key, _T("lowcyl")))
+                               uci->lowcyl = v;
+                       if (!_tcsicmp (key, _T("highcyl")) || !_tcsicmp (key, _T("cyl")))
+                               uci->highcyl = v;
+                       if (!_tcsicmp (key, _T("blocksize")) || !_tcsicmp (key, _T("sectorsize")))
+                               uci->blocksize = v;
+                       if (!_tcsicmp (key, _T("buffers")))
+                               uci->buffers = v;
+                       if (!_tcsicmp (key, _T("maxtransfer")))
+                               uci->maxtransfer = v;
+                       if (!_tcsicmp (key, _T("interleave")))
+                               uci->interleave = v;
+                       if (!_tcsicmp (key, _T("dostype")))
+                               uci->dostype = v;
+                       if (!_tcsicmp (key, _T("bufmemtype")))
+                               uci->bufmemtype = v;
+                       if (!_tcsicmp (key, _T("stacksize")))
+                               uci->stacksize = v;
+                       if (!_tcsicmp (key, _T("mask")))
+                               uci->mask = v;
+                       if (!_tcsicmp (key, _T("unit")))
+                               uci->unit = v;
+                       if (!_tcsicmp (key, _T("controller")))
+                               get_filesys_controller (val, &uci->controller_type, &uci->controller_type_unit, &uci->controller_unit);
+                       if (!_tcsicmp (key, _T("flags")))
+                               uci->flags = v;
+                       if (!_tcsicmp (key, _T("priority")))
+                               uci->priority = v;
+                       if (!_tcsicmp (key, _T("forceload")))
+                               uci->forceload = v;
+                       if (!_tcsicmp (key, _T("bootpri"))) {
+                               if (v < -129)
+                                       v = -129;
+                               if (v > 127)
+                                       v = 127;
+                               uci->bootpri = v;
+                       }
+                       if (!_tcsicmp (key, _T("filesystem")))
+                               _tcscpy (uci->filesys, val);
+                       if (!_tcsicmp (key, _T("device")))
+                               _tcscpy (uci->devname, val);
+                       if (!_tcsicmp(key, _T("badblocks"))) {
+                               TCHAR *p = val;
+                               while (p && *p && uci->badblock_num < MAX_UAEDEV_BADBLOCKS) {
+                                       struct uaedev_badblock *bb = &uci->badblocks[uci->badblock_num];
+                                       if (!_istdigit(*p))
+                                               break;
+                                       bb->first = _tstol(p);
+                                       bb->last = bb->first;
+                                       TCHAR *p1 = _tcschr(p, ',');
+                                       TCHAR *p2 = NULL;
+                                       if (p1) {
+                                               p2 = p1 + 1;
+                                               *p1 = 0;
+                                       }
+                                       p1 = _tcschr(p, '-');
+                                       if (p1) {
+                                               bb->last = _tstol(p1 + 1);
+                                       }
+                                       uci->badblock_num++;
+                                       p = p2;
                                }
-                               uci->badblock_num++;
-                               p = p2;
                        }
+                       xfree (val);
+                       xfree (key);
+                       idx++;
                }
-               xfree (val);
-               xfree (key);
        }
-       zfile_fclose (f);
-       return false;
+
+       uae_u8 *out;
+       int outsize;
+
+       if (ini_getdata(ini, _T("MODE SENSE"), _T("03"), &out, &outsize) && outsize >= 16) {
+               uci->psecs = (out[10] << 8) | (out[11] << 0);
+               uci->blocksize = (out[12] << 8) | (out[13] << 0);
+               xfree(out);
+               ret = true;
+       }
+
+       if (ini_getdata(ini, _T("MODE SENSE"), _T("04"), &out, &outsize) && outsize >= 20) {
+               uci->pheads = out[5];
+               uci->pcyls = (out[2] << 16) | (out[3] << 8) | (out[4] << 0);
+               xfree(out);
+               ret = true;
+       }
+
+       if (ini_getdata(ini, _T("READ CAPACITY"), _T("DATA"), &out, &outsize) && outsize >= 8) {
+               uci->blocksize = (out[4] << 24) | (out[5] << 16) | (out[6] << 8) | (out[7] << 0);
+               uci->max_lba = ((out[0] << 24) | (out[1] << 16) | (out[2] << 8) | (out[3] << 0)) + 1;
+               xfree(out);
+               ret = true;
+       }
+
+       void ata_parse_identity(uae_u8 *out, struct uaedev_config_info *uci, bool *lba48, int *max_multiple);
+       bool ata_get_identity(struct ini_data *ini, uae_u8 *out, bool overwrite);
+
+       uae_u8 ident[512];
+       if (ata_get_identity(ini, ident, true)) {
+               bool lba48;
+               int max_multiple;
+               ata_parse_identity(ident, uci, &lba48, &max_multiple);
+               ret = true;
+       }
+       xfree(out);
+
+       ini_free(ini);
+       return ret;
 }
+
 bool get_hd_geometry (struct uaedev_config_info *uci)
 {
        TCHAR tname[MAX_DPATH];
@@ -4197,7 +4290,9 @@ bool get_hd_geometry (struct uaedev_config_info *uci)
                        parse_geo (tname, uci, NULL, true);
                }
        }
-       if (uci->rootdir[0]) {
+       if (uci->geometry[0]) {
+               return parse_geo (uci->geometry, uci, NULL, false);
+       } else if (uci->rootdir[0]) {
                _tcscpy (tname, uci->rootdir);
                _tcscat (tname, _T(".geo"));
                return parse_geo (tname, uci, NULL, false);
@@ -4332,61 +4427,81 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHA
                        || ! getintval (&tmpp, &uci.blocksize, ','))
                        goto invalid_fs;
                if (getintval2 (&tmpp, &uci.bootpri, ',', false)) {
+                       const TCHAR *end;
+                       TCHAR *n;
                        tmpp2 = tmpp;
-                       tmpp = _tcschr (tmpp, ',');
-                       if (tmpp != 0) {
+                       // quoted special case
+                       if (tmpp2[0] == '\"') {
+                               const TCHAR *end;
+                               TCHAR *n = cfgfile_unescape (tmpp2, &end, 0);
+                               if (!n)
+                                       goto invalid_fs;
+                               _tcscpy (uci.filesys, n);
+                               xfree(n);
+                               tmpp = (TCHAR*)end;
+                               *tmpp++ = 0;
+                       } else {
+                               tmpp = _tcschr (tmpp, ',');
+                               if (tmpp == 0)
+                                       goto empty_fs;
                                *tmpp++ = 0;
                                _tcscpy (uci.filesys, tmpp2);
-                               TCHAR *tmpp2 = _tcschr (tmpp, ',');
-                               if (tmpp2)
-                                       *tmpp2++ = 0;
-                               get_filesys_controller (tmpp, &uci.controller_type, &uci.controller_type_unit, &uci.controller_unit);
-                               if (tmpp2) {
-                                       if (getintval2 (&tmpp2, &uci.highcyl, ',', false)) {
-                                               getintval (&tmpp2, &uci.pcyls, '/');
-                                               getintval (&tmpp2, &uci.pheads, '/');
-                                               getintval2 (&tmpp2, &uci.psecs, '/', true);
-                                               if (uci.pheads && uci.psecs) {
-                                                       uci.physical_geometry = true;
-                                               } else {
-                                                       uci.pheads = uci.psecs = uci.pcyls = 0;
-                                                       uci.physical_geometry = false;
-                                               }
+                       }
+                       get_filesys_controller (tmpp, &uci.controller_type, &uci.controller_type_unit, &uci.controller_unit);
+                       tmpp2 = _tcschr (tmpp, ',');
+                       if (tmpp2) {
+                               tmpp2++;
+                               if (getintval2 (&tmpp2, &uci.highcyl, ',', false)) {
+                                       getintval (&tmpp2, &uci.pcyls, '/');
+                                       getintval (&tmpp2, &uci.pheads, '/');
+                                       getintval2 (&tmpp2, &uci.psecs, '/', true);
+                                       if (uci.pheads && uci.psecs) {
+                                               uci.physical_geometry = true;
+                                       } else {
+                                               uci.pheads = uci.psecs = uci.pcyls = 0;
+                                               uci.physical_geometry = false;
+                                       }
+                                       if (tmpp2[0]) {
+                                               n = cfgfile_unescape (tmpp2, &end, 0);
+                                               if (!n)
+                                                       goto invalid_fs;
+                                               _tcscpy(uci.geometry, n);
+                                               xfree(n);
                                        }
                                }
-                               uci.controller_media_type = 0;
-                               uci.unit_feature_level = 1;
+                       }
+                       uci.controller_media_type = 0;
+                       uci.unit_feature_level = 1;
 
-                               if (cfgfile_option_find(tmpp2, _T("CF")))
-                                       uci.controller_media_type = 1;
-                               else if (cfgfile_option_find(tmpp2, _T("HD")))
-                                       uci.controller_media_type = 0;
+                       if (cfgfile_option_find(tmpp2, _T("CF")))
+                               uci.controller_media_type = 1;
+                       else if (cfgfile_option_find(tmpp2, _T("HD")))
+                               uci.controller_media_type = 0;
 
-                               TCHAR *pflags;
-                               if ((pflags = cfgfile_option_get(tmpp2, _T("flags")))) {
-                                       getintval(&pflags, &uci.unit_special_flags, 0);
-                               }
+                       TCHAR *pflags;
+                       if ((pflags = cfgfile_option_get(tmpp2, _T("flags")))) {
+                               getintval(&pflags, &uci.unit_special_flags, 0);
+                       }
 
-                               if (cfgfile_option_find(tmpp2, _T("lock")))
-                                       uci.lock = true;
+                       if (cfgfile_option_find(tmpp2, _T("lock")))
+                               uci.lock = true;
                                        
-                               if (cfgfile_option_find(tmpp2, _T("SCSI2")))
-                                       uci.unit_feature_level = HD_LEVEL_SCSI_2;
-                               else if (cfgfile_option_find(tmpp2, _T("SCSI1")))
-                                       uci.unit_feature_level = HD_LEVEL_SCSI_1;
-                               else if (cfgfile_option_find(tmpp2, _T("SASIE")))
-                                       uci.unit_feature_level = HD_LEVEL_SASI_ENHANCED;
-                               else if (cfgfile_option_find(tmpp2, _T("SASI")))
-                                       uci.unit_feature_level = HD_LEVEL_SASI;
-                               else if (cfgfile_option_find(tmpp2, _T("SASI_CHS")))
-                                       uci.unit_feature_level = HD_LEVEL_SASI_CHS;
-                               else if (cfgfile_option_find(tmpp2, _T("ATA2+S")))
-                                       uci.unit_feature_level = HD_LEVEL_ATA_2S;
-                               else if (cfgfile_option_find(tmpp2, _T("ATA2+")))
-                                       uci.unit_feature_level = HD_LEVEL_ATA_2;
-                               else if (cfgfile_option_find(tmpp2, _T("ATA1")))
-                                       uci.unit_feature_level = HD_LEVEL_ATA_1;
-                       }
+                       if (cfgfile_option_find(tmpp2, _T("SCSI2")))
+                               uci.unit_feature_level = HD_LEVEL_SCSI_2;
+                       else if (cfgfile_option_find(tmpp2, _T("SCSI1")))
+                               uci.unit_feature_level = HD_LEVEL_SCSI_1;
+                       else if (cfgfile_option_find(tmpp2, _T("SASIE")))
+                               uci.unit_feature_level = HD_LEVEL_SASI_ENHANCED;
+                       else if (cfgfile_option_find(tmpp2, _T("SASI")))
+                               uci.unit_feature_level = HD_LEVEL_SASI;
+                       else if (cfgfile_option_find(tmpp2, _T("SASI_CHS")))
+                               uci.unit_feature_level = HD_LEVEL_SASI_CHS;
+                       else if (cfgfile_option_find(tmpp2, _T("ATA2+S")))
+                               uci.unit_feature_level = HD_LEVEL_ATA_2S;
+                       else if (cfgfile_option_find(tmpp2, _T("ATA2+")))
+                               uci.unit_feature_level = HD_LEVEL_ATA_2;
+                       else if (cfgfile_option_find(tmpp2, _T("ATA1")))
+                               uci.unit_feature_level = HD_LEVEL_ATA_1;
                }
                if (type == 2) {
                        uci.device_emu_unit = unit;
@@ -4412,6 +4527,9 @@ empty_fs:
                str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, false);
                _tcscpy (uci.rootdir, str);
        }
+       if (uci.geometry[0]) {
+               parse_geo(uci.geometry, &uci, NULL, false);
+       }
 #ifdef FILESYS
        add_filesys_config (p, nr, &uci);
 #endif
@@ -4430,7 +4548,7 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
        for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
                TCHAR tmp[100];
                _stprintf (tmp, _T("uaehf%d"), i);
-               if (_tcscmp (option, tmp) == 0) {
+               if (!_tcscmp (option, tmp)) {
                        for (;;) {
                                int type = -1;
                                int unit = -1;
@@ -4481,6 +4599,8 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                                        _tcscpy (uci->rootdir, value);
                                } else if (!_tcscmp (s, _T("filesys"))) {
                                        _tcscpy (uci->filesys, value);
+                               } else if (!_tcscmp (s, _T("geometry"))) {
+                                       _tcscpy (uci->geometry, value);
                                } else if (!_tcscmp (s, _T("controller"))) {
                                        get_filesys_controller (value, &uci->controller_type, &uci->controller_type_unit, &uci->controller_unit);
                                }
@@ -4535,6 +4655,8 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                        _tcscpy (uci.rootdir, value);
                }
                str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, true);
+               if (uci.geometry[0])
+                       parse_geo(uci.geometry, &uci, NULL, false);
 #ifdef FILESYS
                uci.type = hdf ? UAEDEV_HDF : UAEDEV_DIR;
                add_filesys_config (p, -1, &uci);
@@ -4686,6 +4808,25 @@ static bool cfgfile_read_board_rom(struct uae_prefs *p, const TCHAR *option, con
                                                if (v >= 0)
                                                        brc->roms[idx].subtype = v;
                                        }
+                                       p = cfgfile_option_get(buf2, _T("mid"));
+                                       if (p) {
+                                               brc->roms[idx].manufacturer = _tstol(p);
+                                       }
+                                       p = cfgfile_option_get(buf2, _T("pid"));
+                                       if (p) {
+                                               brc->roms[idx].product = _tstol(p);
+                                       }
+                                       p = cfgfile_option_get(buf2, _T("data"));
+                                       if (p && _tcslen(p) >= 3 * 16 - 1) {
+                                               for (int i = 0; i < sizeof brc->roms[idx].autoconfig; i++) {
+                                                       TCHAR *s2 = &p[i * 3];
+                                                       if (i + 1 < sizeof brc->roms[idx].autoconfig && s2[2] != '.')
+                                                               break;
+                                                       TCHAR *endptr;
+                                                       p[2] = 0;
+                                                       brc->roms[idx].autoconfig[i] = (uae_u8)_tcstol(s2, &endptr, 16);
+                                               }
+                                       }
                                }
                                return true;
                        }
@@ -5138,7 +5279,14 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
        }
 
        if (cfgfile_string (option, value, _T("mmu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
-               p->mmu_model = _tstol (tmpbuf);
+               TCHAR *s =_tcsstr(tmpbuf, _T("ec"));
+               if (s) {
+                       p->mmu_ec = true;
+                       p->mmu_model = 68000 + _tstol(s + 2);
+               } else {
+                       p->mmu_ec = false;
+                       p->mmu_model = _tstol(tmpbuf);
+               }
                return 1;
        }
 
@@ -5318,7 +5466,7 @@ void cfgfile_compatibility_rtg(struct uae_prefs *p)
        int vga = -1;
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtgboardconfig *rbc = &p->rtgboards[i];
-               if (rbc->rtgmem_type == GFXBOARD_A2410) {
+               if (rbc->rtgmem_type == GFXBOARD_A2410  || rbc->rtgmem_type == GFXBOARD_RESOLVER) {
                        if (a2410 >= 0) {
                                rbc->rtgmem_size = 0;
                                rbc->rtgmem_type = 0;
index 4e53678751121d4a0b98f12d3973406652db7769..00d5398a4ee69b3d5f5786b856f864876d49a519 100644 (file)
@@ -8049,8 +8049,13 @@ static int pt_babe(TrapContext *ctx, uae_u8 *bufrdb, UnitInfo *uip, int unit_no,
        struct uaedev_config_info *ci = &uip[unit_no].hf.ci;
        uae_u32 bad;
        
-       // blocksize != 128?
-       if (bufrdb[0x20] != 0 || bufrdb[0x21] != 0 || bufrdb[0x22] != 0 || bufrdb[0x23] != 0x80)
+       uae_u32 bs = (bufrdb[0x20] << 24) | (bufrdb[0x21] << 16) | (bufrdb[0x22] << 8) | (bufrdb[0x23] << 0);
+       int bscnt;
+       for (bscnt = 512; bscnt <= 32768; bscnt <<= 1) {
+               if (bs == (bscnt >> 2))
+                       break;
+       }
+       if (bscnt > 32768)
                return 0;
 
        bad = rl(bufrdb + 4);
index 52ad814ca2a5af6f60a62c3634c6a8bcc439578f..2ef31a234f74ff54e0944e25ae9bd189872f7b11 100644 (file)
@@ -29,6 +29,7 @@
 #include "zfile.h"
 #include "ide.h"
 #include "debug.h"
+#include "ini.h"
 
 #ifdef WITH_CHD
 #include "archivers/chd/chdtypes.h"
@@ -589,7 +590,12 @@ end:
 }
 int hdf_open (struct hardfiledata *hfd)
 {
-       return hdf_open (hfd, NULL);
+       int v = hdf_open (hfd, NULL);
+       if (!v)
+               return v;
+       get_hd_geometry(&hfd->ci);
+       hfd->geometry = ini_load(hfd->ci.geometry);
+       return v;
 }
 
 void hdf_close (struct hardfiledata *hfd)
@@ -608,6 +614,8 @@ void hdf_close (struct hardfiledata *hfd)
                cf->close();
                delete cf;
        }
+       ini_free(hfd->geometry);
+       hfd->geometry = NULL;
        hfd->chd_handle = NULL;
 #endif
        hfd->hfd_type = 0;
@@ -1146,6 +1154,15 @@ static int checkbounds (struct hardfiledata *hfd, uae_u64 offset, uae_u64 len, i
                        (uae_u32)(max >> 32),(uae_u32)max);
                return -1;
        }
+       if (hfd->ci.max_lba) {
+               max = hfd->ci.max_lba * hfd->ci.blocksize;
+               if (offset >= max) {
+                       write_log (_T("UAEHF SCSI: forced last lba out of bounds, %08X-%08X + %08X-%08X > %08X-%08X\n"),
+                               (uae_u32)(offset >> 32),(uae_u32)offset,(uae_u32)(len >> 32),(uae_u32)len,
+                               (uae_u32)(max >> 32),(uae_u32)max);
+                       return -1;
+               }
+       }
        if ((mode == 1 || mode == 2) && hfd->ci.badblock_num) {
                offset /= hfd->ci.blocksize;
                len /= hfd->ci.blocksize;
@@ -1368,16 +1385,12 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                                r[0] = 0x7f;
                        } else {
                                r[0] = 0;
-                               if (hfd->drive_empty) {
-                                       r[1] |= 0x80; // removable..
-                                       r[0] |= 0x20; // not present
-                               }
                        }
                        r[2] = 2; /* supports SCSI-2 */
                        r[3] = 2; /* response data format */
                        r[4] = 32; /* additional length */
                        r[7] = 0;
-                       scsi_len = lr = alen < 36 ? alen : 36;
+                       lr = alen < 36 ? alen : 36;
                        if (hdhfd) {
                                r[2] = hdhfd->ansi_version;
                                r[3] = hdhfd->ansi_version >= 2 ? 2 : 0;
@@ -1385,6 +1398,18 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        setdrivestring(hfd->vendor_id, r, 8, 8);
                        setdrivestring(hfd->product_id, r, 16, 16);
                        setdrivestring(hfd->product_rev, r, 32, 4);
+                       uae_u8 *rr;
+                       if (ini_getdata(hfd->geometry, _T("INQUIRY"), _T("00"), &rr, &lr)) {
+                               if (lr > alen)
+                                       lr = alen;
+                               memcpy(r, rr, lr);
+                               xfree(rr);
+                       }
+                       if (lun == 0 && hfd->drive_empty) {
+                               r[0] |= 0x20; // not present
+                               r[1] |= 0x80; // removable..
+                       }
+                       scsi_len = lr;
                }
                goto scsi_done;
        case 0x1b: /* START/STOP UNIT */
@@ -1725,6 +1750,8 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        if (nodisk (hfd))
                                goto nodisk;
                        blocks = (uae_u32)(hfd->virtsize / hfd->ci.blocksize);
+                       if (hfd->ci.max_lba)
+                               blocks = hfd->ci.max_lba;
                        if (hdhfd) {
                                cyl = hdhfd->cyls;
                                head = hdhfd->heads;
diff --git a/ide.cpp b/ide.cpp
index 8aaae7831cfb6b5bb296050e4a1fbc3d6c1bf3e0..8d0c8f7d0fc9a85f5ec1aa1fe6e49e2a9b5c5c64 100644 (file)
--- a/ide.cpp
+++ b/ide.cpp
@@ -23,6 +23,7 @@
 #include "savestate.h"
 #include "scsi.h"
 #include "ide.h"
+#include "ini.h"
 
 /* STATUS bits */
 #define IDE_STATUS_ERR 0x01            // 0
 #define ATAPI_CD 0x01
 
 #define ATAPI_MAX_TRANSFER 32768
-#define MAX_IDE_MULTIPLE_SECTORS 128
+
+void ata_parse_identity(uae_u8 *out, struct uaedev_config_info *uci, bool *lba48, int *max_multiple)
+{
+       *lba48 = false;
+       *max_multiple = 0;
+       struct uaedev_config_info uci2;
+
+       uae_u16 v;
+
+       memcpy(&uci2, uci, sizeof(struct uaedev_config_info));
+
+       uci->blocksize = 512;
+
+       uci->pcyls = (out[1 * 2 + 0] << 8) | (out[1 * 2 + 1] << 0);
+       uci->pheads = (out[3 * 2 + 0] << 8) | (out[3 * 2 + 1] << 0);
+       uci->psecs = (out[6 * 2 + 0] << 8) | (out[6 * 2 + 1] << 0);
+       
+       if (!uci->pcyls || !uci->pheads || !uci->psecs) {
+               uci->pcyls = uci2.pcyls;
+               uci->pheads = uci2.pheads;
+               uci->psecs = uci2.psecs;
+       }
+
+       v = (out[59 * 2 + 0] << 8) | (out[59 * 2 + 1] << 0);
+       if (v & 1) { // multiple mode?
+               *max_multiple = (out[47 * 2 + 0] << 8) | (out[47 * 2 + 1] << 0);
+       }
+
+       v = (out[53 * 2 + 0] << 8) | (out[53 * 2 + 1] << 0);
+       if (v & 1) { // 54-58 valid?
+               uci->pcyls = (out[54 * 2 + 0] << 8) | (out[54 * 2 + 1] << 0);
+               uci->pheads = (out[55 * 2 + 0] << 8) | (out[55 * 2 + 1] << 0);
+               uci->psecs = (out[56 * 2 + 0] << 8) | (out[56 * 2 + 1] << 0);
+               uci->max_lba = (out[57 * 2 + 0] << 24) | (out[57 * 2 + 1] << 16) | (out[58 * 2 + 0] << 8) | (out[58 * 2 + 1] << 0);
+       }
+       v = (out[49 * 2 + 0] << 8) | (out[49 * 2 + 1] << 0);
+       if (v & (1 << 9)) { // LBA supported?
+               uci->max_lba = (out[60 * 2 + 0] << 24) | (out[60 * 2 + 1] << 16) | (out[61 * 2 + 0] << 8) | (out[61 * 2 + 1] << 0);
+       }
+       v = (out[83 * 2 + 0] << 8) | (out[83 * 2 + 1] << 0);
+       if ((v & 0xc000) == 0x4000 && (v & (1 << 10))) { // LBA48 supported?
+               *lba48 = true;
+               uci->max_lba = (out[100 * 2 + 0] << 24) | (out[100 * 2 + 1] << 16) | (out[101 * 2 + 0] << 8) | (out[101 * 2 + 1] << 0);
+               uci->max_lba <<= 32;
+               uci->max_lba |= (out[102 * 2 + 0] << 24) | (out[102 * 2 + 1] << 16) | (out[103 * 2 + 0] << 8) | (out[103 * 2 + 1] << 0);        
+       }
+}
+
+bool ata_get_identity(struct ini_data *ini, uae_u8 *out, bool overwrite)
+{
+       if (!out)
+               return false;
+       if (overwrite) {
+               uae_u8 *out2;
+               int len;
+               if (!ini_getdata(ini, _T("IDENTITY"), _T("DATA"), &out2, &len))
+                       return false;
+               if (len == 512) {
+                       memcpy(out, out2, 512);
+               }
+               xfree(out2);
+       }
+       int v;
+       if (ini_getval(ini, _T("IDENTITY"), _T("multiple_mode"), &v)) {
+               if (v) {
+                       out[59 * 2 + 1] |= 1;
+                       out[47 * 2 + 0] = 0;
+                       out[47 * 2 + 1] = v;
+               } else {
+                       out[59 * 2 + 1] &= ~1;
+               }
+       }
+
+       return true;
+}
 
 
 uae_u16 adide_decode_word(uae_u16 w)
@@ -157,6 +232,46 @@ static void ide_grow_buffer(struct ide_hdf *ide, int newsize)
        xfree(oldbuf);
 }
 
+static void sl(uae_u8 *d, int o)
+{
+       o *= 2;
+       uae_u16 t = (d[o + 0] << 8) | d[o + 1];
+       d[o + 0] = d[o + 2];
+       d[o + 1] = d[o + 3];
+       d[o + 2] = t >> 8;
+       d[o + 3] = t;
+}
+static void ql(uae_u8 *d, int o)
+{
+       sl(d, o + 1);
+       o *= 2;
+       uae_u16 t = (d[o + 0] << 8) | d[o + 1];
+       d[o + 0] = d[o + 6];
+       d[o + 1] = d[o + 7];
+       d[o + 6] = t >> 8;
+       d[o + 7] = t;
+}
+
+void ata_byteswapidentity(uae_u8 *d)
+{
+       for (int i = 0; i < 512; i += 2)
+       {
+               uae_u8 t = d[i + 0];
+               d[i + 0] = d[i + 1];
+               d[i + 1] = t;
+       }
+       sl(d, 7);
+       sl(d, 57);
+       sl(d, 60);
+       sl(d, 98);
+       sl(d, 117);
+       sl(d, 210);
+       sl(d, 212);
+       sl(d, 215);
+       ql(d, 100);
+       ql(d, 230);
+}
+
 static void pw (struct ide_hdf *ide, int offset, uae_u16 w)
 {
        if (ide->byteswap) {
@@ -168,6 +283,28 @@ static void pw (struct ide_hdf *ide, int offset, uae_u16 w)
        ide->secbuf[offset * 2 + 1] = w >> 8;
 }
 
+static void pwand (struct ide_hdf *ide, int offset, uae_u16 w)
+{
+       if (ide->byteswap) {
+               w = (w >> 8) | (w << 8);
+       }
+       if (ide->adide)
+               w = adide_decode_word(w);
+       ide->secbuf[offset * 2 + 0] &= ~((uae_u8)w);
+       ide->secbuf[offset * 2 + 1] &= ~(w >> 8);
+}
+
+static void pwor (struct ide_hdf *ide, int offset, uae_u16 w)
+{
+       if (ide->byteswap) {
+               w = (w >> 8) | (w << 8);
+       }
+       if (ide->adide)
+               w = adide_decode_word(w);
+       ide->secbuf[offset * 2 + 0] |= (uae_u8)w;
+       ide->secbuf[offset * 2 + 1] |= w >> 8;
+}
+
 static void ps (struct ide_hdf *ide, int offset, const TCHAR *src, int max)
 {
        int i, len;
@@ -315,87 +452,106 @@ static void ide_recalibrate (struct ide_hdf *ide)
        ide_interrupt (ide);
 }
 
-static void ide_identify_drive (struct ide_hdf *ide)
+static void ide_identity_buffer(struct ide_hdf *ide)
 {
-       uae_u64 totalsecs;
-       int v;
-       uae_u8 *buf = ide->secbuf;
        TCHAR tmp[100];
        bool atapi = ide->atapi;
        bool cf = ide->media_type > 0;
+       int v;
+
+       memset(ide->secbuf, 0, 512);
+
+       if (ata_get_identity(ide->hdhfd.hfd.geometry, ide->secbuf, true)) {
+
+               if (ide->byteswap)
+                       ata_byteswapidentity(ide->secbuf);
+
+       } else {
+
+               pw (ide, 0, atapi ? 0x85c0 : (cf ? 0x848a : (1 << 6)));
+               pw (ide, 1, ide->hdhfd.cyls_def);
+               pw (ide, 2, 0xc837);
+               pw (ide, 3, ide->hdhfd.heads_def);
+               pw (ide, 4, ide->blocksize * ide->hdhfd.secspertrack_def);
+               pw (ide, 5, ide->blocksize);
+               pw (ide, 6, ide->hdhfd.secspertrack_def);
+               ps (ide, 10, _T("68000"), 20); /* serial */
+               pw (ide, 20, 3);
+               pw (ide, 21, ide->blocksize);
+               pw (ide, 22, 4);
+               ps (ide, 23, _T("0.7"), 8); /* firmware revision */
+               if (ide->atapi)
+                       _tcscpy (tmp, _T("UAE-ATAPI"));
+               else
+                       _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id);
+               ps (ide, 27, tmp, 40); /* model */
+               pw (ide, 47, ide->max_multiple_mode >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */
+               pw (ide, 48, 1);
+               pw (ide, 49, (1 << 9) | (1 << 8)); /* LBA and DMA supported */
+               pw (ide, 51, 0x200); /* PIO cycles */
+               pw (ide, 52, 0x200); /* DMA cycles */
+               pw (ide, 53, 1 | 2 | 4);
+               pw (ide, 54, ide->hdhfd.cyls);
+               pw (ide, 55, ide->hdhfd.heads);
+               pw (ide, 56, ide->hdhfd.secspertrack);
+               uae_u64 totalsecs = ide->hdhfd.cyls * ide->hdhfd.heads * ide->hdhfd.secspertrack;
+               pw (ide, 57, (uae_u16)totalsecs);
+               pw (ide, 58, (uae_u16)(totalsecs >> 16));
+               pw (ide, 59, 1); /* Multiple mode supported */
+               totalsecs = ide->blocksize ? ide->hdhfd.size / ide->blocksize : 0;
+               if (totalsecs > 0x0fffffff)
+                       totalsecs = 0x0fffffff;
+               pw (ide, 60, (uae_u16)totalsecs);
+               pw (ide, 61, (uae_u16)(totalsecs >> 16));
+               pw (ide, 62, 0x0f);
+               pw (ide, 63, 0x0f);
+               if (ide->ata_level) {
+                       pw (ide, 64, ide->ata_level ? 0x03 : 0x00); /* PIO3 and PIO4 */
+                       pw (ide, 65, 120); /* MDMA2 supported */
+                       pw (ide, 66, 120);
+                       pw (ide, 67, 120);
+                       pw (ide, 68, 120);
+                       pw (ide, 80, (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)); /* ATA-1 to ATA-6 */
+                       pw (ide, 81, 0x1c); /* ATA revision */
+                       pw (ide, 82, (1 << 14) | (atapi ? 0x10 | 4 : 0)); /* NOP, ATAPI: PACKET and Removable media features supported */
+                       pw (ide, 83, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 supported */
+                       pw (ide, 84, 1 << 14);
+                       pw (ide, 85, 1 << 14);
+                       pw (ide, 86, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 enabled */
+                       pw (ide, 87, 1 << 14);
+                       pw (ide, 88, (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); /* UDMA modes */
+                       pw (ide, 93, (1 << 14) | (1 << 13) | (1 << 0));
+                       if (ide->lba48) {
+                               totalsecs = ide->hdhfd.size / ide->blocksize;
+                               pw (ide, 100, (uae_u16)(totalsecs >> 0));
+                               pw (ide, 101, (uae_u16)(totalsecs >> 16));
+                               pw (ide, 102, (uae_u16)(totalsecs >> 32));
+                               pw (ide, 103, (uae_u16)(totalsecs >> 48));
+                       }
+               }
+               ata_get_identity(ide->hdhfd.hfd.geometry, ide->secbuf, false);
+       }
 
+       v = ide->multiple_mode;
+       pwor(ide, 59, v > 0 ? 0x100 : 0);
+       if (!atapi && cf) {
+               pw(ide, 0, 0x848a);
+       } else if (!atapi && !cf) {
+               pwand(ide, 0, 0x8000);
+       }
+}
+
+static void ide_identify_drive (struct ide_hdf *ide)
+{
        if (!ide_isdrive (ide)) {
                ide_fail (ide);
                return;
        }
-       memset (buf, 0, ide->blocksize);
-       ide->byteswapped_buffer = 1;
        if (IDE_LOG > 0)
                write_log (_T("IDE%d identify drive\n"), ide->num);
        ide_data_ready (ide);
        ide->direction = 0;
-       pw (ide, 0, atapi ? 0x85c0 : (cf ? 0x848a : (1 << 6)));
-       pw (ide, 1, ide->hdhfd.cyls_def);
-       pw (ide, 2, 0xc837);
-       pw (ide, 3, ide->hdhfd.heads_def);
-       pw (ide, 4, ide->blocksize * ide->hdhfd.secspertrack_def);
-       pw (ide, 5, ide->blocksize);
-       pw (ide, 6, ide->hdhfd.secspertrack_def);
-       ps (ide, 10, _T("68000"), 20); /* serial */
-       pw (ide, 20, 3);
-       pw (ide, 21, ide->blocksize);
-       pw (ide, 22, 4);
-       ps (ide, 23, _T("0.7"), 8); /* firmware revision */
-       if (ide->atapi)
-               _tcscpy (tmp, _T("UAE-ATAPI"));
-       else
-               _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id);
-       ps (ide, 27, tmp, 40); /* model */
-       pw (ide, 47, MAX_IDE_MULTIPLE_SECTORS >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */
-       pw (ide, 48, 1);
-       pw (ide, 49, (1 << 9) | (1 << 8)); /* LBA and DMA supported */
-       pw (ide, 51, 0x200); /* PIO cycles */
-       pw (ide, 52, 0x200); /* DMA cycles */
-       pw (ide, 53, 1 | 2 | 4);
-       pw (ide, 54, ide->hdhfd.cyls);
-       pw (ide, 55, ide->hdhfd.heads);
-       pw (ide, 56, ide->hdhfd.secspertrack);
-       totalsecs = ide->hdhfd.cyls * ide->hdhfd.heads * ide->hdhfd.secspertrack;
-       pw (ide, 57, (uae_u16)totalsecs);
-       pw (ide, 58, (uae_u16)(totalsecs >> 16));
-       v = ide->multiple_mode;
-       pw (ide, 59, (v > 0 ? 0x100 : 0) | v);
-       totalsecs = ide->blocksize ? ide->hdhfd.size / ide->blocksize : 0;
-       if (totalsecs > 0x0fffffff)
-               totalsecs = 0x0fffffff;
-       pw (ide, 60, (uae_u16)totalsecs);
-       pw (ide, 61, (uae_u16)(totalsecs >> 16));
-       pw (ide, 62, 0x0f);
-       pw (ide, 63, 0x0f);
-       if (ide->ata_level) {
-               pw (ide, 64, ide->ata_level ? 0x03 : 0x00); /* PIO3 and PIO4 */
-               pw (ide, 65, 120); /* MDMA2 supported */
-               pw (ide, 66, 120);
-               pw (ide, 67, 120);
-               pw (ide, 68, 120);
-               pw (ide, 80, (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)); /* ATA-1 to ATA-6 */
-               pw (ide, 81, 0x1c); /* ATA revision */
-               pw (ide, 82, (1 << 14) | (atapi ? 0x10 | 4 : 0)); /* NOP, ATAPI: PACKET and Removable media features supported */
-               pw (ide, 83, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 supported */
-               pw (ide, 84, 1 << 14);
-               pw (ide, 85, 1 << 14);
-               pw (ide, 86, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 enabled */
-               pw (ide, 87, 1 << 14);
-               pw (ide, 88, (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); /* UDMA modes */
-               pw (ide, 93, (1 << 14) | (1 << 13) | (1 << 0));
-               if (ide->lba48) {
-                       totalsecs = ide->hdhfd.size / ide->blocksize;
-                       pw (ide, 100, (uae_u16)(totalsecs >> 0));
-                       pw (ide, 101, (uae_u16)(totalsecs >> 16));
-                       pw (ide, 102, (uae_u16)(totalsecs >> 32));
-                       pw (ide, 103, (uae_u16)(totalsecs >> 48));
-               }
-       }
+       ide_identity_buffer(ide);
 }
 
 static void set_signature (struct ide_hdf *ide)
@@ -468,8 +624,12 @@ static void ide_initialize_drive_parameters (struct ide_hdf *ide)
 static void ide_set_multiple_mode (struct ide_hdf *ide)
 {
        write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs.ide_nsector);
-       ide->multiple_mode = ide->regs.ide_nsector;
-       ide_interrupt (ide);
+       if (ide->regs.ide_nsector > (ide->max_multiple_mode >> (ide->blocksize / 512 - 1))) {
+               ide_fail(ide);
+       } else {
+               ide->multiple_mode = ide->regs.ide_nsector;
+       }
+       ide_interrupt(ide);
 }
 
 static void ide_set_features (struct ide_hdf *ide)
@@ -755,8 +915,8 @@ static void do_process_rw_command (struct ide_hdf *ide)
        get_lbachs (ide, &lba, &cyl, &head, &sec);
        if (IDE_LOG > 1)
                write_log (_T("IDE%d off=%d, nsec=%d (%d) lba48=%d\n"), ide->num, (uae_u32)lba, nsec, ide->multiple_mode, ide->lba48 + ide->lba48cmd);
-       if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize) {
-               nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize;
+       if (nsec > ide->max_lba - lba) {
+               nsec = ide->max_lba - lba;
                if (IDE_LOG > 1)
                        write_log (_T("IDE%d nsec changed to %d\n"), ide->num, nsec);
        }
@@ -832,7 +992,7 @@ static void ide_read_sectors (struct ide_hdf *ide, int flags)
        gui_flicker_led (LED_HD, ide->num, 1);
        nsec = get_nsec (ide);
        get_lbachs (ide, &lba, &cyl, &head, &sec);
-       if (lba * ide->blocksize >= ide->hdhfd.size) {
+       if (lba >= ide->max_lba) {
                ide_data_ready (ide);
                ide_fail_err (ide, IDE_ERR_IDNF);
                return;
@@ -870,15 +1030,15 @@ static void ide_write_sectors (struct ide_hdf *ide, int flags)
        gui_flicker_led (LED_HD, ide->num, 2);
        nsec = get_nsec (ide);
        get_lbachs (ide, &lba, &cyl, &head, &sec);
-       if (lba * ide->blocksize >= ide->hdhfd.size) {
+       if (lba >= ide->max_lba) {
                ide_data_ready (ide);
                ide_fail_err (ide, IDE_ERR_IDNF);
                return;
        }
        if (IDE_LOG > 0)
                write_log (_T("IDE%d write off=%d, sec=%d (%d) lba48=%d\n"), ide->num, (uae_u32)lba, nsec, ide->multiple_mode, ide->lba48 + ide->lba48cmd);
-       if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize)
-               nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize;
+       if (nsec > ide->max_lba - lba)
+               nsec = ide->max_lba - lba;
        if (nsec <= 0) {
                ide_data_ready (ide);
                ide_fail_err (ide, IDE_ERR_IDNF);
@@ -904,7 +1064,6 @@ static void ide_do_command (struct ide_hdf *ide, uae_u8 cmd)
        ide->regs.ide_error = 0;
        ide->intdrq = false;
        ide->lba48cmd = false;
-       ide->byteswapped_buffer = 0;
 
        if (ide->atapi) {
 
@@ -1390,12 +1549,15 @@ struct ide_hdf *add_ide_unit (struct ide_hdf **idetable, int max, int ch, struct
        if (ci)
                memcpy (&ide->hdhfd.hfd.ci, ci, sizeof (struct uaedev_config_info));
        if (ci->type == UAEDEV_CD && ci->device_emu_unit >= 0) {
+
                device_func_init (0);
                ide->scsi = scsi_alloc_cd (ch, ci->device_emu_unit, true);
                if (!ide->scsi) {
                        write_log (_T("IDE: CD EMU unit %d failed to open\n"), ide->cd_unit_num);
                        return NULL;
                }
+
+               ide_identity_buffer(ide);
                ide->cd_unit_num = ci->device_emu_unit;
                ide->atapi = true;
                ide->blocksize = 512;
@@ -1404,9 +1566,13 @@ struct ide_hdf *add_ide_unit (struct ide_hdf **idetable, int max, int ch, struct
                write_log (_T("IDE%d CD %d\n"), ch, ide->cd_unit_num);
 
        } else if (ci->type == UAEDEV_HDF) {
+
                if (!hdf_hd_open (&ide->hdhfd))
                        return NULL;
+
+               ide->max_multiple_mode = 128;
                ide->blocksize = ide->hdhfd.hfd.ci.blocksize;
+               ide->max_lba = ide->hdhfd.size / ide->blocksize;
                ide->lba48 = (ide->hdhfd.hfd.ci.unit_special_flags & 1) || ide->hdhfd.size >= 128 * (uae_u64)0x40000000 ? 1 : 0;
                gui_flicker_led (LED_HD, ch, -1);
                ide->cd_unit_num = -1;
@@ -1414,12 +1580,25 @@ struct ide_hdf *add_ide_unit (struct ide_hdf **idetable, int max, int ch, struct
                ide->ata_level = ci->unit_feature_level;
                if (!ide->ata_level && (ide->hdhfd.size >= 4 * (uae_u64)0x40000000 || ide->media_type))
                        ide->ata_level = 1;
+               ide_identity_buffer(ide);
+
+               if (!ide->byteswap)
+                       ata_byteswapidentity(ide->secbuf);
+               struct uaedev_config_info ci = { 0 };
+               ata_parse_identity(ide->secbuf, &ci, &ide->lba48, &ide->max_multiple_mode);
+               ide->hdhfd.cyls = ide->hdhfd.cyls_def = ci.pcyls;
+               ide->hdhfd.heads = ide->hdhfd.heads_def = ci.pheads;
+               ide->hdhfd.secspertrack = ide->hdhfd.secspertrack_def = ci.psecs;
+               if (ci.max_lba)
+                       ide->max_lba = ci.max_lba;
+               if (ide->lba48 && !ide->ata_level)
+                       ide->ata_level = 1;
 
-               write_log (_T("IDE%d HD '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. LBA48=%d\n"),
+               write_log (_T("IDE%d HD '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. MM=%d LBA48=%d\n"),
                        ch, ide->hdhfd.hfd.ci.rootdir,
                        ide->hdhfd.cyls, ide->hdhfd.heads, ide->hdhfd.secspertrack,
                        ide->hdhfd.hfd.ci.pcyls, ide->hdhfd.hfd.ci.pheads, ide->hdhfd.hfd.ci.psecs,
-                       (int)(ide->hdhfd.size / (1024 * 1024)), ide->lba48);
+                       (int)(ide->hdhfd.size / (1024 * 1024)), ide->max_multiple_mode, ide->lba48);
 
        }
        ide->regs.ide_status = 0;
index 348b81c50918e7a5aa2c7665308cb40e7853a11f..ab46ea1ffa2a996d4beb2a5f8ec32831fdfc434e 100644 (file)
@@ -21,7 +21,8 @@ typedef enum { DRV_NONE = -1, DRV_35_DD = 0, DRV_35_HD, DRV_525_SD, DRV_35_DD_ES
 #define HISTORY_TAPE 5
 #define HISTORY_GENLOCK_IMAGE 6
 #define HISTORY_GENLOCK_VIDEO 7
-#define HISTORY_MAX 8
+#define HISTORY_GEO 8
+#define HISTORY_MAX 9
 
 struct diskinfo
 {
index 70612b238a8c6b4062ca3212b8e5edea8fc61325..8bcef2b79383bbb9f9b19c6ae4241d93c27c1241 100644 (file)
@@ -74,6 +74,8 @@ struct hardfiledata {
        int reinsertdelay;
        bool isreinsert;
        bool unit_stopped;
+
+       struct ini_data *geometry;
 };
 
 #define HFD_FLAGS_REALDRIVE 1
index 4773b810e96f68a326ab6fed6377374effeb4c20..0413d2fdca1015e813e632237f48aa4d21c2a71d 100644 (file)
@@ -71,7 +71,6 @@ struct ide_hdf
        struct ide_hdf *pair; // master<>slave
        struct ide_thread_state *its;
        bool byteswap;
-       int byteswapped_buffer;
        bool adide;
 
        uae_u8 *secbuf;
@@ -85,7 +84,9 @@ struct ide_hdf
        bool lba48;
        bool lba48cmd;
        uae_u64 start_lba;
+       uae_u64 max_lba;
        int start_nsec;
+       int max_multiple_mode;
        uae_u8 multiple_mode;
        int irq_delay;
        int irq;
@@ -133,6 +134,10 @@ void remove_ide_unit(struct ide_hdf **idetable, int ch);
 void alloc_ide_mem (struct ide_hdf **ide, int max, struct ide_thread_state *its);
 void ide_reset_device(struct ide_hdf *ide);
 
+void ata_byteswapidentity(uae_u8 *d);
+void ata_parse_identity(uae_u8 *out, struct uaedev_config_info *uci, bool *lba48, int *max_multiple);
+bool ata_get_identity(struct ini_data *ini, uae_u8 *out, bool overwrite);
+
 void start_ide_thread(struct ide_thread_state *its);
 void stop_ide_thread(struct ide_thread_state *its);
 
index ddc8e54a387fbcedc77e30e29c4edde1c0ac7320..03bd015532aaa9ac2d3c72cf1ecd45c8d173ac3c 100644 (file)
@@ -16,7 +16,7 @@
 
 #define UAEMAJOR 3
 #define UAEMINOR 5
-#define UAESUBREV 0
+#define UAESUBREV 1
 
 typedef enum { KBD_LANG_US, KBD_LANG_DK, KBD_LANG_DE, KBD_LANG_SE, KBD_LANG_FR, KBD_LANG_IT, KBD_LANG_ES } KbdLang;
 
@@ -192,6 +192,7 @@ struct uaedev_config_info {
        bool lock;
        int bootpri;
        TCHAR filesys[MAX_DPATH];
+       TCHAR geometry[MAX_DPATH];
        int lowcyl;
        int highcyl; // zero if detected from size
        int cyls; // calculated/corrected highcyl
@@ -199,6 +200,7 @@ struct uaedev_config_info {
        int sectors;
        int reserved;
        int blocksize;
+       uae_u64 max_lba;
        int controller_type;
        int controller_type_unit;
        int controller_unit;
@@ -361,6 +363,9 @@ struct romconfig
        int subtype;
        void *unitdata;
        TCHAR configtext[256];
+       uae_u16 manufacturer;
+       uae_u8 product;
+       uae_u8 autoconfig[16];
        struct boardromconfig *back;
 };
 #define MAX_BOARD_ROMS 2
@@ -643,6 +648,7 @@ struct uae_prefs {
        double x86_speed_throttle;
        int cpu_model;
        int mmu_model;
+       bool mmu_ec;
        int cpu060_revision;
        int fpu_model;
        int fpu_revision;
index d33f7802dd2ff3f22b514f8bf89bb62b1b1a33e1..5c37a7a150aa4aec1c46405a790e2a8f0a536a12 100644 (file)
@@ -15,6 +15,7 @@
 #include "registry.h"
 #include "win32gui.h"
 #include "zfile.h"
+#include "ini.h"
 
 #define hfd_log write_log
 #define hdf_log2
@@ -65,6 +66,8 @@ struct uae_driveinfo {
        bool partitiondrive;
        int readonly;
        int cylinders, sectors, heads;
+       int BusType;
+
 };
 
 #define HDF_HANDLE_WIN32 1
@@ -376,6 +379,107 @@ int isharddrive (const TCHAR *name)
 
 static TCHAR *hdz[] = { _T("hdz"), _T("zip"), _T("rar"), _T("7z"), NULL };
 
+static int progressdialogreturn;
+static int progressdialogactive;
+
+static INT_PTR CALLBACK ProgressDialogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+       switch(msg)
+       {
+       case WM_DESTROY:
+               PostQuitMessage (0);
+               progressdialogactive = 0;
+               return TRUE;
+       case WM_CLOSE:
+               if (progressdialogreturn < 0)
+                       progressdialogreturn = 0;
+               return TRUE;
+       case WM_INITDIALOG:
+               return TRUE;
+       case WM_COMMAND:
+               switch (LOWORD(wParam))
+               {
+               case IDCANCEL:
+                       progressdialogreturn = 0;
+                       return TRUE;
+               }
+               break;
+       }
+       return FALSE;
+}
+
+typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER {
+       SCSI_PASS_THROUGH_DIRECT spt;
+       ULONG Filler;
+       UCHAR SenseBuf[32];
+} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
+
+static bool do_scsi_in(HANDLE h, const uae_u8 *cdb, int cdblen, uae_u8 *in, int insize)
+{
+       SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
+       DWORD status, returned;
+
+       memset(&swb, 0, sizeof swb);
+       swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
+       swb.spt.CdbLength = cdblen;
+       swb.spt.DataIn = insize > 0 ? SCSI_IOCTL_DATA_IN : 0;
+       swb.spt.DataTransferLength = insize;
+       swb.spt.DataBuffer = in;
+       swb.spt.TimeOutValue = 2 * 60;
+       swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
+       swb.spt.SenseInfoLength = 32;
+       memcpy(swb.spt.Cdb, cdb, cdblen);
+       status = DeviceIoControl (h, IOCTL_SCSI_PASS_THROUGH_DIRECT,
+               &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
+               &swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
+               &returned, NULL);
+       if (!status) {
+               DWORD err = GetLastError();
+               write_log(_T("IOCTL_SCSI_PASS_THROUGH_DIRECT: "));
+               for (int i = 0; i < cdblen; i++) {
+                       write_log(_T("%02X."), cdb[i]);
+               }
+               write_log(_T(" failed %08x\n"), err);
+               return false;
+       } else if (swb.spt.ScsiStatus) {
+               write_log(_T("IOCTL_SCSI_PASS_THROUGH_DIRECT: "));
+               for (int i = 0; i < cdblen; i++) {
+                       write_log(_T("%02X."), cdb[i]);
+               }
+               write_log(_T("\n"));
+               write_log(_T("SENSE: "));
+               for (int i = 0; i < swb.spt.SenseInfoLength; i++) {
+                       write_log(_T("%02X."), swb.SenseBuf[i]);
+               }
+               write_log(_T("\n"));
+               return false;
+       }
+       return true;
+}
+
+#if 0
+static const uae_u8 inquiry[] = { 0x12, 0x01, 0x81, 0, 0xf0, 0 };
+static const uae_u8 modesense[] = { 0x1a, 0x00, 0x3f, 0, 0xf0, 0 };
+
+static void scsidirect(HANDLE h)
+{
+       uae_u8 *inbuf;
+
+       inbuf = (uae_u8*)VirtualAlloc (NULL, 65536, MEM_COMMIT, PAGE_READWRITE);
+
+       do_scsi_in(h, modesense, 6, inbuf, 0xf0);
+       do_scsi_in(h, inquiry, 6, inbuf, 0xf0);
+       do_scsi_in(h, realtek_read, 6, inbuf, 0xff00);
+
+       FILE *f = fopen("c:\\temp\\identity.bin", "wb");
+       fwrite(inbuf, 1, 512, f);
+       fclose(f);
+
+       VirtualFree(inbuf, 65536, MEM_RELEASE);
+}
+
+#endif
+
 #if 0
 static void getserial (HANDLE h)
 {
@@ -383,12 +487,8 @@ static void getserial (HANDLE h)
        DISK_GEOMETRY_EX *out;
        VOLUME_DISK_EXTENTS *vde;
 
-       DWORD serial, mcl, fsflags;
-       if (GetVolumeInformationByHandleW (h, NULL, 0, &serial, &mcl, &fsflags, NULL, 0)) {
-       }
-
        outsize = sizeof (DISK_GEOMETRY_EX) + 10 * (sizeof (DISK_DETECTION_INFO) + sizeof (DISK_PARTITION_INFO));
-       out = xmalloc (outsize);
+       out = (DISK_GEOMETRY_EX*)xmalloc(uae_u8, outsize);
        if (DeviceIoControl (h, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, out, outsize, &written, NULL)) {
                DISK_DETECTION_INFO *ddi = DiskGeometryGetDetect (out);
                DISK_PARTITION_INFO *dpi = DiskGeometryGetPartition (out);
@@ -398,7 +498,7 @@ static void getserial (HANDLE h)
 
 
        outsize = sizeof (VOLUME_DISK_EXTENTS) + sizeof (DISK_EXTENT) * 10;
-       vde = xmalloc (outsize);
+       vde = (VOLUME_DISK_EXTENTS*)xmalloc(uae_u8, outsize);
        if (DeviceIoControl (h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, vde, outsize, &written, NULL)) {
                if (vde->NumberOfDiskExtents > 0)
                        write_log(_T("%d\n"), vde->Extents[0].DiskNumber);
@@ -408,7 +508,7 @@ static void getserial (HANDLE h)
 #endif
 
 #if 0
-static void queryidentifydevice (struct hardfiledata *hfd)
+static void queryataidentity(HANDLE h)
 {
        DWORD r, size;
        uae_u8 *b;
@@ -417,22 +517,579 @@ static void queryidentifydevice (struct hardfiledata *hfd)
        size = sizeof (ATA_PASS_THROUGH_EX) + 512;
        b = xcalloc (uae_u8, size);
        ata = (ATA_PASS_THROUGH_EX*)b;
+       uae_u8 *data = b + sizeof(ATA_PASS_THROUGH_EX);
 
-       ata->Length = sizeof ata;
+       ata->Length = sizeof(ATA_PASS_THROUGH_EX);
        ata->DataTransferLength = 512;
        ata->TimeOutValue = 10;
        ata->AtaFlags = ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN;
-       ata->CurrentTaskFile[6] = 0xec;
-       ata->DataBufferOffset = ata->Length;
+       IDEREGS* ir = (IDEREGS*)ata->CurrentTaskFile;
+       ir->bCommandReg = ID_CMD;
+       ata->DataBufferOffset = data - b;
        
-       if (!DeviceIoControl (hfd->handle->h, IOCTL_ATA_PASS_THROUGH, b, size, b, size, &r, NULL)) {
+       if (!DeviceIoControl (h, IOCTL_ATA_PASS_THROUGH, b, size, b, size, &r, NULL)) {
                write_log (_T("IOCTL_ATA_PASS_THROUGH_DIRECT Identify Device failed %d\n"), GetLastError ());
        }
+
+       xfree(b);
 }
 #endif
 
 static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_driveinfo *udi, int ignoreduplicates);
 
+#if 0
+typedef enum _STORAGE_PROTOCOL_TYPE { 
+  ProtocolTypeUnknown      = 0x00,
+  ProtocolTypeScsi,
+  ProtocolTypeAta,
+  ProtocolTypeNvme,
+  ProtocolTypeSd,
+  ProtocolTypeProprietary  = 0x7E,
+  ProtocolTypeMaxReserved  = 0x7F
+} STORAGE_PROTOCOL_TYPE, *PSTORAGE_PROTOCOL_TYPE;
+
+typedef struct _STORAGE_PROTOCOL_SPECIFIC_DATA {
+  STORAGE_PROTOCOL_TYPE ProtocolType;
+  DWORD                 DataType;
+  DWORD                 ProtocolDataRequestValue;
+  DWORD                 ProtocolDataRequestSubValue;
+  DWORD                 ProtocolDataOffset;
+  DWORD                 ProtocolDataLength;
+  DWORD                 FixedProtocolReturnData;
+  DWORD                 Reserved[3];
+} STORAGE_PROTOCOL_SPECIFIC_DATA, *PSTORAGE_PROTOCOL_SPECIFIC_DATA;
+
+typedef enum _STORAGE_PROTOCOL_ATA_DATA_TYPE { 
+  AtaDataTypeUnknown   = 0,
+  AtaDataTypeIdentify,
+  AtaDataTypeLogPage
+} STORAGE_PROTOCOL_ATA_DATA_TYPE, *PSTORAGE_PROTOCOL_ATA_DATA_TYPE;
+
+static void getstorageproperty_ataidentity(HANDLE hDevice)
+{
+       DWORD returnedLength;
+       DWORD bufferLength = FIELD_OFFSET(STORAGE_PROPERTY_QUERY, AdditionalParameters) + sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) + 512;
+       uae_u8 *buffer = xcalloc(uae_u8, bufferLength);
+       PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)buffer;
+       PSTORAGE_PROTOCOL_SPECIFIC_DATA protocolData = (PSTORAGE_PROTOCOL_SPECIFIC_DATA)query->AdditionalParameters;
+
+       query->PropertyId = (STORAGE_PROPERTY_ID)50;
+       query->QueryType = PropertyStandardQuery;
+
+       protocolData->ProtocolType = ProtocolTypeAta;
+       protocolData->DataType = AtaDataTypeIdentify;
+       protocolData->ProtocolDataOffset = sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA);
+    protocolData->ProtocolDataLength = 512;
+
+       DWORD status = DeviceIoControl(
+               hDevice,
+               IOCTL_STORAGE_QUERY_PROPERTY,
+               query,
+               bufferLength,
+               query,
+               bufferLength,
+               &returnedLength,
+               NULL);
+
+       DWORD spqerr = GetLastError();
+
+       xfree(buffer);
+}
+#endif
+
+static void bintotextpart(TCHAR *out, uae_u8 *data, int size)
+{
+       for (int i = 0; i < size; i++) {
+               uae_u8 b = data[i];
+               if (b >= 32 && b < 127)
+                       out[i] = (TCHAR)b;
+               else
+                       out[i] = '.';
+       }
+       out[size] = 0;
+}
+
+static void bintotextline(TCHAR *out, uae_u8 *data, int size)
+{
+       TCHAR tmp2[MAX_DPATH];
+       int w = 32;
+       for (int i = 0; i < size; i += w) {
+               for (int j = 0; j < w + 1 + w / 2; j++) {
+                       tmp2[j * 2 + 0] = ' ';
+                       tmp2[j * 2 + 1] = ' ';
+               }
+               for (int j = 0; j < w && j + i < size; j++) {
+                       uae_u8 b = data[i + j];
+                       _stprintf (tmp2 + j * 2, _T("%02X"), b);
+                       tmp2[j * 2 + 2] = ' ';
+                       if (b >= 32 && b < 127)
+                               tmp2[w * 2 + 1 + j] = (TCHAR)b;
+                       else
+                               tmp2[w * 2 + 1 + j] = '.';
+               }
+               tmp2[w * 2] = ' ';
+               tmp2[w * 2 + 1 + w] = 0;
+               _tcscat (out, tmp2);
+               _tcscat (out, _T("\r\n"));
+       }
+}
+
+void gui_infotextbox(HWND hDlg, const TCHAR *text);
+
+static bool hd_get_meta_ata(HWND hDlg, HANDLE h, uae_u8 *datap)
+{
+       DWORD r, size;
+       uae_u8 *b;
+       ATA_PASS_THROUGH_EX *ata;
+
+       size = sizeof (ATA_PASS_THROUGH_EX) + 512;
+       b = xcalloc (uae_u8, size);
+       ata = (ATA_PASS_THROUGH_EX*)b;
+       uae_u8 *data = b + sizeof(ATA_PASS_THROUGH_EX);
+       ata->Length = sizeof(ATA_PASS_THROUGH_EX);
+       ata->DataTransferLength = 512;
+       ata->TimeOutValue = 10;
+       ata->AtaFlags = ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN;
+       IDEREGS* ir = (IDEREGS*)ata->CurrentTaskFile;
+       ir->bCommandReg = ID_CMD;
+       ata->DataBufferOffset = data - b;
+               if (!DeviceIoControl (h, IOCTL_ATA_PASS_THROUGH, b, size, b, size, &r, NULL)) {
+               write_log (_T("IOCTL_ATA_PASS_THROUGH_DIRECT ID_CMD failed %08x\n"), GetLastError());
+               return false;
+       }
+       memcpy(datap, data, 512);
+       xfree(b);
+       return true;
+}
+
+#define INQUIRY_LEN 240
+
+static const uae_u8 realtek_inquiry_0x83[] = { 0x12, 0x01, 0x83, 0, 0xf0, 0 };
+static const uae_u8 realtek_read[] = { 0xf0, 0x0d, 0xfa, 0x00, 0x02, 0x00 };
+
+static bool hd_get_meta_hack(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 *inq)
+{
+       uae_u8 cmd[16];
+
+       memset(data, 0, 512);
+       memcpy(cmd, realtek_inquiry_0x83, sizeof(realtek_inquiry_0x83));
+       if (!do_scsi_in(h, cmd, 6, data, 0xf0))
+               return false;
+       if (memcmp(data + 20, "realtek\0", 8)) {
+               memset(data, 0, 512);
+               return false;
+       }
+
+       memset(data, 0, 512);
+       memcpy(cmd, realtek_read, sizeof(realtek_read));
+       if (!do_scsi_in(h, cmd, 6, data, 512)) {
+               memset(data, 0, 512);
+               return false;
+       }
+
+       int state = 0;
+
+       memset(cmd, 0, 6); // TEST UNIT READY
+       TCHAR *infotxt;
+       if (!do_scsi_in(h, cmd, 6, data, 0)) {
+               state = 1;
+               infotxt = _T("Realtek hack, insert card.");
+       } else {
+               infotxt = _T("Realtek hack, remove and insert the card.");
+       }
+
+       progressdialogreturn = -1;
+       progressdialogactive = 1;
+       HWND hwnd = CustomCreateDialog(IDD_PROGRESSBAR, hDlg, ProgressDialogProc);
+       if (hwnd == NULL)
+               return false;
+       HWND hwndprogress = GetDlgItem (hwnd, IDC_PROGRESSBAR);
+       ShowWindow(hwndprogress, SW_HIDE);
+       HWND hwndprogresstxt = GetDlgItem (hwnd, IDC_PROGRESSBAR_TEXT);
+       ShowWindow(hwnd, SW_SHOW);
+
+       int tcnt = 0;
+       for (;;) {
+               if (progressdialogreturn >= 0)
+                       break;
+               MSG msg;
+               SendMessage (hwndprogresstxt, WM_SETTEXT, 0, (LPARAM)infotxt);
+               while (PeekMessage (&msg, hwnd, 0, 0, PM_REMOVE)) {
+                       if (!IsDialogMessage (hwnd, &msg)) {
+                               TranslateMessage (&msg);
+                               DispatchMessage (&msg);
+                       }
+               }
+               Sleep(100);
+               tcnt++;
+               if (tcnt >= 10) {
+                       memset(cmd, 0, 6);
+                       if (do_scsi_in(h, cmd, 6, data, 0)) {
+                               if (state != 0) {
+                                       break;
+                               }
+                       } else {
+                               if (state == 0) {
+                                       state++;
+                                       infotxt = _T("Removed. Re-insert the card.");
+                               }
+                       }
+                       tcnt = 0;
+               }
+       }
+
+       if (progressdialogactive) {
+               DestroyWindow (hwnd);
+               MSG msg;
+               while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
+                       TranslateMessage (&msg);
+                       DispatchMessage (&msg);
+               }
+       }
+
+       memset(data, 0, 512);
+       memcpy(cmd, realtek_read, sizeof(realtek_read));
+       if (do_scsi_in(h, cmd, 6, data, 512))
+               return true;
+
+       return false;
+}
+
+static bool hd_get_meta_satl(HWND hDlg, HANDLE h, uae_u8 *data, TCHAR *text, struct ini_data *ini)
+{
+       uae_u8 cmd[16];
+       TCHAR cline[256];
+
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0x12; // inquiry
+       cmd[4] = INQUIRY_LEN;
+       if (!do_scsi_in(h, cmd, 6, data, INQUIRY_LEN)) {
+               write_log(_T("SAT: INQUIRY failed\n"));
+               return false;
+       }
+
+       int type = data[0] & 0x3f;
+
+       _tcscat (text, _T("INQUIRY:\r\n"));
+       int len = INQUIRY_LEN;
+       while (len > 0) {
+               len--;
+               if (data[len] != 0)
+                       break;
+       }
+       len += 3;
+       len &= ~3;
+       bintotextline(text, data, len);
+       _tcscat (text, _T("\r\n"));
+       bintotextpart(cline, data + 8, 44 - 8);
+       ini_addnewcomment(ini, _T("INQUIRY"), cline);
+       ini_addnewdata(ini, _T("INQUIRY"), _T("00"), data, len);
+
+       memset(data, 0, 512);
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0x25;
+       if (do_scsi_in(h, cmd, 10, data, 8)) {
+               _tcscat (text, _T("READ CAPACITY:\r\n"));
+               bintotextline(text, data, 8);
+               _tcscat (text, _T("\r\n"));
+               ini_addnewdata(ini, _T("READ CAPACITY"), _T("DATA"), data, 8);
+       }
+
+       // get supported evpd pages
+       memset(data, 0, 512);
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0x12; // inquiry
+       cmd[1] = 1;
+       cmd[4] = INQUIRY_LEN;
+       if (do_scsi_in(h, cmd, 6, data, INQUIRY_LEN)) {
+               uae_u8 evpd[256];
+               int cnt = 0;
+               uae_u8 pl = data[3];
+               uae_u8 *p = &data[4];
+               while (pl != 0) {
+                       if (*p) {
+                               evpd[cnt++] = *p;
+                       }
+                       p++;
+                       pl--;
+               }
+               for (int i = 0; i < cnt; i++) {
+                       for (int j = i + 1; j < cnt; j++) {
+                               if (evpd[i] > evpd[j]) {
+                                       uae_u8 t = evpd[i];
+                                       evpd[i] = evpd[j];
+                                       evpd[j] = t;
+                               }
+                       }
+               }
+               for (int i = 0; i < cnt; i++) {
+                       cmd[2] = evpd[i];
+                       memset(data, 0, 512);
+                       if (do_scsi_in(h, cmd, 6, data, INQUIRY_LEN)) {
+                               TCHAR tmp[256];
+                               _stprintf(tmp, _T("INQUIRY %02X:\r\n"), evpd[i]);
+                               _tcscat (text, tmp);
+                               int len = INQUIRY_LEN;
+                               while (len > 0) {
+                                       len--;
+                                       if (data[len] != 0)
+                                               break;
+                               }
+                               len += 3;
+                               len &= ~3;
+                               bintotextline(text, data, len);
+                               _tcscat (text, _T("\r\n"));
+                               _stprintf(tmp, _T("%02X"), evpd[i]);
+                               ini_addnewdata(ini, _T("INQUIRY"),tmp, data, len);
+                       }
+               }
+       }
+
+       // get mode sense pages
+       memset(data, 0, 512);
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0x5a;
+       cmd[2] = 0x80 | 0x3f;
+       cmd[7] = 0xff;
+       cmd[8] = 0;
+       if (do_scsi_in(h, cmd, 10, data, 0xff00)) {
+               TCHAR tmp[256];
+               int l = (data[0] << 8) | data[1];
+               _tcscat (text, _T("MODE SENSE:\r\n"));
+               bintotextline(text, data + 2, 4);
+               _tcscat (text, _T("\r\n"));
+               ini_addnewdata(ini, _T("MODE SENSE"),_T("PARAMETER LIST"), data + 2, 4);
+               uae_u16 dbd = (data[6] << 8) | data[7];
+               if (dbd) {
+                       _tcscat (text, _T("MODE SENSE BLOCK DESCRIPTOR DATA:\r\n"));
+                       bintotextline(text, data + 8, dbd);
+                       _tcscat (text, _T("\r\n"));
+                       ini_addnewdata(ini, _T("MODE SENSE"), _T("BLOCK DESCRIPTOR DATA"), data + 8, dbd);
+               }
+               l -= 8 + dbd;
+               uae_u8 *p = &data[8 + dbd];
+               while (l >= 2) {
+                       uae_u8 page = p[0];
+                       uae_u8 pl = p[1];
+                       _stprintf(tmp, _T("MODE SENSE %02X:\r\n"), page);
+                       _tcscat (text, tmp);
+                       bintotextline(text, p, pl + 2);
+                       _tcscat (text, _T("\r\n"));
+                       _stprintf(tmp, _T("%02X"), page);
+                       ini_addnewdata(ini, _T("MODE SENSE"), tmp, p, pl + 2);
+                       p += 2 + pl;
+                       l -= 2 + pl;
+               }
+       }
+
+       if (type != 0 && type != 05) {
+               write_log(_T("SAT: Not Direct access or CD device\n"));
+               return false;
+       }
+
+       if (type == 5) {
+
+               memset(cmd, 0, sizeof(cmd));
+               memset(data, 0, 512);
+               cmd[0] = 0x85; // SAT ATA PASSTHROUGH (16)
+               cmd[1] = 4 << 1; // PIO data-in
+               cmd[2] = 0x08 | 0x04 | 0x02; // dir = from device, 512 byte block, sector count = block cnt
+               cmd[6] = 1; // block count
+               cmd[14] = 0xa1; // identity packet device
+               if (do_scsi_in(h, cmd, 16, data, 512))
+                       return true;
+               write_log(_T("SAT: ATA PASSTHROUGH(16) failed\n"));
+
+       } else {
+
+               memset(cmd, 0, sizeof(cmd));
+               memset(data, 0, 512);
+               cmd[0] = 0xa1; // SAT ATA PASSTHROUGH (12)
+               cmd[1] = 4 << 1; // PIO data-in
+               cmd[2] = 0x08 | 0x04 | 0x02; // dir = from device, 512 byte block, sector count = block cnt
+               cmd[4] = 1; // block count
+               cmd[9] = 0xec; // identity
+               if (do_scsi_in(h, cmd, 12, data, 512))
+                       return true;
+               write_log(_T("SAT: ATA PASSTHROUGH(12) failed\n"));
+       }
+
+       return false;
+}
+
+static int stringboxdialogactive;
+static TCHAR geometry_file[MAX_DPATH];
+static struct ini_data *hdini;
+static INT_PTR CALLBACK StringBoxDialogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+       switch(msg)
+       {
+       case WM_DESTROY:
+               PostQuitMessage (0);
+               return TRUE;
+       case WM_CLOSE:
+               stringboxdialogactive = 0;
+               DestroyWindow (hDlg);
+               return TRUE;
+       case WM_INITDIALOG:
+               geometry_file[0] = 0;
+               ShowWindow(GetDlgItem (hDlg, IDC_SAVEBOOTBLOCK), SW_SHOW);
+               SetWindowText(hDlg, _T("Harddrive information"));
+               return TRUE;
+       case WM_COMMAND:
+               switch (LOWORD (wParam))
+               {
+               case IDC_SAVEBOOTBLOCK:
+                       if (DiskSelection(hDlg, 0, 24, &workprefs, geometry_file)) {
+                               ini_save(hdini, geometry_file);
+                       }
+                       break;
+               case IDOK:
+                       stringboxdialogactive = -1;
+                       DestroyWindow (hDlg);
+                       return TRUE;
+               case IDCANCEL:
+                       stringboxdialogactive = 0;
+                       DestroyWindow (hDlg);
+                       return TRUE;
+               }
+               break;
+       }
+       return FALSE;
+}
+
+void ata_byteswapidentity(uae_u8 *d);
+
+void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
+{
+       struct uae_driveinfo *udi = &uae_drives[idx];
+       bool satl = false;
+       uae_u8 *data = NULL;
+       uae_u8 inq[INQUIRY_LEN + 4] = { 0 };
+       TCHAR *text;
+       struct ini_data *ini = NULL;
+
+       geometryfile[0] = 0;
+       text = xcalloc(TCHAR, 10000);
+
+       HANDLE h = CreateFile(udi->device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+       if (h == INVALID_HANDLE_VALUE) {
+               write_log(_T("CreateFile('%s') failed, err=%08x\n"), udi->device_path, GetLastError());
+               goto end;
+       }
+
+       ini = ini_new();
+       ini_addstring(ini, _T("GEOMETRY"), NULL, NULL);
+       data = (uae_u8*)VirtualAlloc (NULL, 65536, MEM_COMMIT, PAGE_READWRITE);
+       inq[0] = 0xff;
+
+       if (udi->BusType == BusTypeAta || udi->BusType == BusTypeSata) {
+               if (!_tcscmp(udi->vendor_id, _T("ATA     "))) {
+                       satl = true;
+               }
+       }
+
+       _stprintf(text, _T("BusType: 0x%02x\r\nVendor: '%s'\r\nProduct: '%s'\r\nRevision: '%s'\r\nSerial: '%s'\r\nSize: %llu\r\n\r\n"),
+                udi->BusType, udi->vendor_id, udi->product_id, udi->product_rev, udi->product_serial, udi->size);
+
+       if (satl || udi->BusType == BusTypeScsi || udi->BusType == BusTypeUsb || udi->BusType == BusTypeRAID) {
+               if (!hd_get_meta_satl(hDlg, h, data, text, ini)) {
+                       write_log(_T("SAT Passthrough failed\n"));
+                       memset(data, 0, 512);
+                       if (udi->BusType == BusTypeUsb) {
+                               hd_get_meta_hack(hDlg, h, data, inq);
+                       }
+                       if (text[0] == 0) {
+                               _tcscpy(text, _T("SCSI ATA Passthrough error!"));
+                               goto doout;
+                       }
+               }
+       } else if (udi->BusType == BusTypeAta || udi->BusType == BusTypeSata) {
+               if (!hd_get_meta_ata(hDlg, h, data)) {
+                       write_log(_T("ATA Passthrough failed\n"));
+                       _tcscpy(text, _T("ATA Passthrough error!"));
+                       goto doout;
+               }
+       } else {
+               _stprintf(text, _T("Unsupported bus type %02x\n"), udi->BusType);
+               goto doout;
+       }
+
+       bool empty = true;
+       for (int i = 0; i < 512; i++) {
+               if (data[i] != 0)
+                       empty = false;
+       }
+
+       if (empty) {
+               write_log(_T("Nothing returned!\n"));
+               if (text[0] == 0) {
+                       _tcscpy(text, _T("Nothing returned!"));
+                       goto doout;
+               }
+       }
+
+       ata_byteswapidentity(data);
+
+       if (!empty) {
+               TCHAR cline[256];
+               _tcscat (text, _T("IDENTITY:\r\n"));
+               bintotextline(text, data, 512);
+
+               bintotextpart(cline, data + 27 * 2, 40);
+               ini_addnewcomment(ini, _T("IDENTITY"), cline);
+               bintotextpart(cline, data + 23 * 2, 8);
+               ini_addnewcomment(ini, _T("IDENTITY"), cline);
+               bintotextpart(cline, data + 10 * 2, 20);
+               ini_addnewcomment(ini, _T("IDENTITY"), cline);
+
+               ini_addnewdata(ini, _T("IDENTITY"), _T("DATA"), data, 512);
+       }
+
+doout:
+       stringboxdialogactive = 1;
+       hdini = ini;
+       HWND hwnd = CustomCreateDialog (IDD_DISKINFO, hDlg, StringBoxDialogProc);
+       if (hwnd != NULL) {
+               HFONT font = CreateFont (12, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T("Lucida Console"));
+               if (font)
+                       SendMessage (GetDlgItem (hwnd, IDC_DISKINFOBOX), WM_SETFONT, WPARAM(font), FALSE);
+               SendMessage (GetDlgItem (hwnd, IDC_DISKINFOBOX), WM_SETTEXT, 0, (LPARAM)text);
+               while (stringboxdialogactive == 1) {
+                       MSG msg;
+                       int ret;
+                       WaitMessage ();
+                       while ((ret = GetMessage (&msg, NULL, 0, 0))) {
+                               if (ret == -1)
+                                       break;
+                               if (!IsWindow (hwnd) || !IsDialogMessage (hwnd, &msg)) {
+                                       TranslateMessage (&msg);
+                                       DispatchMessage (&msg);
+                               }
+                       }
+                       if (stringboxdialogactive == -1)
+                               break;
+               }
+               DeleteObject (font);
+       }
+
+end:
+       if (ini)
+               ini_free(ini);
+
+       if (data)
+               VirtualFree(data, 65536, MEM_RELEASE);
+
+       if (h != INVALID_HANDLE_VALUE)
+               CloseHandle(h);
+
+       _tcscpy(geometryfile, geometry_file);
+
+       xfree(text);
+}
+
 static bool getdeviceinfo (HANDLE hDevice, struct uae_driveinfo *udi)
 {
        DISK_GEOMETRY dg;
@@ -470,6 +1127,8 @@ static bool getdeviceinfo (HANDLE hDevice, struct uae_driveinfo *udi)
                }
        }
 
+       //queryidentifydevice(hDevice);
+
        udi->device_name[0] = 0;
        memset (outBuf, 0, sizeof outBuf);
        query.PropertyId = StorageDeviceProperty;
@@ -729,6 +1388,9 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
                                if (udi->readonly)
                                        hfd->ci.readonly = 1;
                        }
+
+                       //hfd->ci.readonly = false;
+
                        flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS;
                        h = CreateFile (udi->device_path,
                                GENERIC_READ | (hfd->ci.readonly ? 0 : GENERIC_WRITE),
@@ -756,7 +1418,6 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
                                goto end;
                        }
 
-                       //queryidentifydevice (hfd);
                        _tcsncpy (hfd->vendor_id, udi->vendor_id, 8);
                        _tcsncpy (hfd->product_id, udi->product_id, 16);
                        _tcsncpy (hfd->product_rev, udi->product_rev, 4);
@@ -800,11 +1461,15 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
                                hfd->warned = -1;
 #endif
                        }
+
                        lock_drive(hfd, name, h);
 
                        hfd->handle_valid = HDF_HANDLE_WIN32;
                        hfd->emptyname = my_strdup (name);
 
+                       //getstorageproperty_ataidentity(h);
+                       //queryataidentity(h);
+                       //scsidirect(h);
                        //fixdrive (hfd);
 
                } else {
@@ -827,7 +1492,7 @@ emptyreal:
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
                if (h == INVALID_HANDLE_VALUE && !hfd->ci.readonly) {
                        DWORD err = GetLastError ();
-                       if (err == ERROR_WRITE_PROTECT || err == ERROR_SHARING_VIOLATION) {
+                       if (err == ERROR_WRITE_PROTECT || err == ERROR_ACCESS_DENIED || err == ERROR_SHARING_VIOLATION) {
                                h = CreateFile (name, GENERIC_READ, FILE_SHARE_READ, NULL,
                                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
                                if (h != INVALID_HANDLE_VALUE)
@@ -1380,6 +2045,12 @@ static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_dri
                for (i = devDesc->SerialNumberOffset; p[i] != (UCHAR) NULL && i < returnedLength; i++)
                        udi->product_serial[j++] = p[i];
        }
+
+       my_trim(udi->vendor_id);
+       my_trim(udi->product_id);
+       my_trim(udi->product_rev);
+       my_trim(udi->product_serial);
+
        if (udi->vendor_id[0])
                _tcscat (udi->device_name, udi->vendor_id);
        if (udi->product_id[0]) {
@@ -1409,6 +2080,7 @@ static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_dri
                        udi->device_name[i] = '_';
        }
        write_log (_T("device id string: '%s'\n"), udi->device_name);
+       udi->BusType = devDesc->BusType;
        if (ignoreduplicates) {
                if (!udi->removablemedia) {
                        write_log (_T("drive letter not removable, ignored\n"));
@@ -2110,35 +2782,6 @@ int win32_hardfile_media_change (const TCHAR *drvname, int inserted)
        return gotinsert;
 }
 
-static int progressdialogreturn;
-static int progressdialogactive;
-
-static INT_PTR CALLBACK ProgressDialogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-       switch(msg)
-       {
-       case WM_DESTROY:
-               PostQuitMessage (0);
-               progressdialogactive = 0;
-               return TRUE;
-       case WM_CLOSE:
-               if (progressdialogreturn < 0)
-                       progressdialogreturn = 0;
-               return TRUE;
-       case WM_INITDIALOG:
-               return TRUE;
-       case WM_COMMAND:
-               switch (LOWORD(wParam))
-               {
-               case IDCANCEL:
-                       progressdialogreturn = 0;
-                       return TRUE;
-               }
-               break;
-       }
-       return FALSE;
-}
-
 extern HMODULE hUIDLL;
 extern HINSTANCE hInst;
 
index 56bf8519fb316b4e6ed5ad5bf19af211024162de..fff9c94248b17cbf262ef41f179f4f03de430843 100644 (file)
@@ -96,6 +96,7 @@
 #ifdef RETROPLATFORM
 #include "rp.h"
 #endif
+#include "ini.h"
 
 #define GUI_SCALE_DEFAULT 100
 #define MIN_GUI_INTERNAL_WIDTH 512
 #define HDF_FORMAT_STRING _T("(*.hdf;*.vhd;*.rdf;*.hdz;*.rdz;*.chd)\0*.hdf;*.vhd;*.rdf;*.hdz;*.rdz;*.chd\0")
 #define INP_FORMAT_STRING _T("(*.inp)\0*.inp\0")
 #define  CD_FORMAT_STRING _T("(*.cue;*.ccd;*.mds;*.iso;*.chd;*.nrg)\0*.cue;*.ccd;*.mds;*.iso;*.chd;*.nrg;") ARCHIVE_STRING _T("\0")
+#define GEO_FORMAT_STRING _T("(*.geo)\0*.geo\0")
 #define CONFIG_HOST _T("Host")
 #define CONFIG_HARDWARE _T("Hardware")
 
@@ -650,7 +652,8 @@ static const TCHAR *historytypes[] =
        _T("FileSysMRUList"),
        _T("TapeImageMRUList"),
        _T("GenlockImageMRUList"),
-       _T("GenlockVideoMRUList")
+       _T("GenlockVideoMRUList"),
+       _T("GeometryMRUList")
 };
 static int regread;
 
@@ -692,6 +695,7 @@ void write_disk_history (void)
        write_disk_history2(HISTORY_TAPE);
        write_disk_history2(HISTORY_GENLOCK_IMAGE);
        write_disk_history2(HISTORY_GENLOCK_VIDEO);
+       write_disk_history2(HISTORY_GEO);
 }
 
 void reset_disk_history (void)
@@ -707,6 +711,7 @@ void reset_disk_history (void)
                DISK_history_add(NULL, i, HISTORY_TAPE, 0);
                DISK_history_add(NULL, i, HISTORY_GENLOCK_IMAGE, 0);
                DISK_history_add(NULL, i, HISTORY_GENLOCK_VIDEO, 0);
+               DISK_history_add(NULL, i, HISTORY_GEO, 0);
        }
        rrold = regread;
        regread = (1 << HISTORY_MAX) - 1;
@@ -2262,7 +2267,7 @@ void gui_display (int shortcut)
                inputdevice_acquire (TRUE);
                setmouseactive (1);
 #ifdef AVIOUTPUT
-               AVIOutput_Begin ();
+               AVIOutput_Begin (true);
 #endif
        }
        flipgui(false);
@@ -2397,6 +2402,35 @@ static void eject_cd (void)
        }
 }
 
+void gui_infotextbox(HWND hDlg, const TCHAR *text)
+{
+       stringboxdialogactive = 1;
+       HWND hwnd = CustomCreateDialog (IDD_DISKINFO, hDlg ? hDlg : hGUIWnd, StringBoxDialogProc);
+       if (hwnd == NULL)
+               return;
+
+       HFONT font = CreateFont (12, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T("Lucida Console"));
+       if (font)
+               SendMessage (GetDlgItem (hwnd, IDC_DISKINFOBOX), WM_SETFONT, WPARAM(font), FALSE);
+       SendMessage (GetDlgItem (hwnd, IDC_DISKINFOBOX), WM_SETTEXT, 0, (LPARAM)text);
+       while (stringboxdialogactive == 1) {
+               MSG msg;
+               int ret;
+               WaitMessage ();
+               while ((ret = GetMessage (&msg, NULL, 0, 0))) {
+                       if (ret == -1)
+                               break;
+                       if (!IsWindow (hwnd) || !IsDialogMessage (hwnd, &msg)) {
+                               TranslateMessage (&msg);
+                               DispatchMessage (&msg);
+                       }
+               }
+               if (stringboxdialogactive == -1)
+                       break;
+       }
+       DeleteObject (font);
+}
+
 static void infofloppy (HWND hDlg, int n)
 {
        struct diskinfo di;
@@ -2566,6 +2600,8 @@ static void setdpath (const TCHAR *name, const TCHAR *path)
 // flag = 20 for genlock image
 // flag = 21 for genlock video
 // flag = 22 for floppy replacement (missing statefile)
+// fags = 23 for hdf geometry (load)
+// fags = 24 for hdf geometry (save)
 
 int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs, TCHAR *path_out, int *multi)
 {
@@ -2606,6 +2642,8 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs
                        break;
                case 2:
                case 3:
+               case 23:
+               case 24:
                        getfilter (flag, _T("hdfPath"), previousfilter, filtername);
                        fetch_path (_T("hdfPath"), init_path, sizeof (init_path) / sizeof (TCHAR));
                        guid = &diskselectionguids[1];
@@ -2819,6 +2857,14 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs
        case 21:
                _tcscpy(szTitle, _T("Select genlock video"));
                break;
+       case 23:
+       case 24:
+               _tcscpy(szTitle, _T("Select geometry file"));
+               _stprintf (szFilter, _T("%s "), _T("Geometry files"));
+               memcpy (szFilter + _tcslen (szFilter),  GEO_FORMAT_STRING, sizeof (GEO_FORMAT_STRING) + sizeof (TCHAR));
+               defext = _T("geo");
+               break;
+               break;
        }
        if (all) {
                p = szFilter;
@@ -2850,7 +2896,7 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs
 
        if (multi)
                openFileName.Flags |= OFN_ALLOWMULTISELECT;
-       if (flag == 1 || flag == 3 || flag == 5 || flag == 9 || flag == 16) {
+       if (flag == 1 || flag == 3 || flag == 5 || flag == 9 || flag == 16 || flag == 24) {
                openFileName.Flags &= ~OFN_FILEMUSTEXIST;
                if (!(result = GetSaveFileName_2 (hDlg, &openFileName, guid)))
                        write_log (_T("GetSaveFileNameX() failed, err=%d.\n"), GetLastError ());
@@ -2906,6 +2952,9 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs
                case IDC_GENLOCKFILESELECT:
                        selectgenlock(prefs, hDlg, IDC_GENLOCKFILE, full_path);
                        break;
+               case IDC_PATH_GEOMETRY:
+                       SetDlgItemText (hDlg, wParam, full_path);
+                       break;
                case IDC_CD_SELECT:
                        selectcd (prefs, hDlg, 0, IDC_CD_TEXT, full_path);
                        break;
@@ -3030,7 +3079,7 @@ int DiskSelection_2 (HWND hDlg, WPARAM wParam, int flag, struct uae_prefs *prefs
                                        *amiga_path = 0;
                                        setdpath (_T("FloppyPath"), openFileName.lpstrFile);
                                }
-                       } else if (flag == 2 || flag == 3) {
+                       } else if (flag == 2 || flag == 3 || flag == 23) {
                                amiga_path = _tcsstr (openFileName.lpstrFile, openFileName.lpstrFileTitle);
                                if (amiga_path && amiga_path != openFileName.lpstrFile) {
                                        *amiga_path = 0;
@@ -4808,7 +4857,7 @@ void InitializeListView (HWND hDlg)
                                _stprintf (bootpri_str, _T("%d"), ci->bootpri);
                        } else if (type == FILESYS_HARDFILE_RDB || type == FILESYS_HARDDRIVE || ci->controller_type != HD_CONTROLLER_TYPE_UAE) {
                                _stprintf (blocksize_str, _T("%d"), ci->blocksize);
-                               _tcscpy (devname_str, _T("UAE"));
+                               _stprintf (devname_str, _T("UAE:%d"), ci->controller_unit);
                                _tcscpy (volname_str, _T("n/a"));
                                _tcscpy (bootpri_str, _T("n/a"));
                        } else if (type == FILESYS_TAPE) {
@@ -9163,10 +9212,19 @@ static void init_expansion2(HWND hDlg, bool init)
        SendDlgItemMessage(hDlg, IDC_SCSIROMSELECTNUM, CB_SETCURSEL, scsiromselectednum, 0);
 
        SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_RESETCONTENT, 0, 0);
-       for (int i = 0; i < 8; i++) {
-               TCHAR tmp[10];
-               _stprintf(tmp, _T("%d"), i);
-               SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_ADDSTRING, 0, (LPARAM)tmp);
+       int index;
+       struct boardromconfig *brc = get_device_rom(&workprefs, expansionroms[scsiromselected].romtype, scsiromselectednum, &index);
+       const struct expansionromtype *ert = &expansionroms[scsiromselected];
+       if (brc && ert && ert->id_jumper) {
+               for (int i = 0; i < 8; i++) {
+                       TCHAR tmp[10];
+                       _stprintf(tmp, _T("%d"), i);
+                       SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_ADDSTRING, 0, (LPARAM)tmp);
+               }
+       } else {
+               SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_ADDSTRING, 0, (LPARAM)_T("-"));
+               SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_SETCURSEL, 0, 0);
+               ew(hDlg, IDC_SCSIROMID, 0);
        }
 }
 
@@ -9189,8 +9247,7 @@ static void values_to_expansion2dlg_sub(HWND hDlg)
        if (brc) {
                SendDlgItemMessage(hDlg, IDC_SCSIROMSUBSELECT, CB_SETCURSEL, brc->roms[index].subtype, 0);
                SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_SETCURSEL, brc->roms[index].device_id, 0);
-       }
-       else if (srt) {
+       } else if (srt) {
                SendDlgItemMessage(hDlg, IDC_SCSIROMSUBSELECT, CB_SETCURSEL, 0, 0);
                SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_SETCURSEL, 0, 0);
        }
@@ -9207,11 +9264,14 @@ static void values_from_expansion2dlg(HWND hDlg)
        struct boardromconfig *brc;
        TCHAR tmp[MAX_DPATH];
        bool changed = false;
+       bool isnew = false;
 
        int checked = ischecked(hDlg, IDC_SCSIROMSELECTED);
        getromfile(hDlg, IDC_SCSIROMFILE, tmp, MAX_DPATH / sizeof(TCHAR));
        if (tmp[0] || checked) {
                const struct expansionromtype *ert = &expansionroms[scsiromselected];
+               if (!get_device_rom(&workprefs, expansionroms[scsiromselected].romtype, scsiromselectednum, &index))
+                       isnew = true;
                brc = get_device_rom_new(&workprefs, expansionroms[scsiromselected].romtype, scsiromselectednum, &index);
                if (checked) {
                        if (!brc->roms[index].romfile[0])
@@ -9224,10 +9284,9 @@ static void values_from_expansion2dlg(HWND hDlg)
                brc->roms[index].autoboot_disabled = ischecked(hDlg, IDC_SCSIROMFILEAUTOBOOT);
 
                int v = SendDlgItemMessage(hDlg, IDC_SCSIROMID, CB_GETCURSEL, 0, 0L);
-               if (v != CB_ERR)
+               if (v != CB_ERR && !isnew)
                        brc->roms[index].device_id = v;
 
-
                const struct expansionboardsettings *cbs = ert->settings;
                if (cbs) {
                        brc->roms[index].device_settings = expansion_gui_item.expansionrom_gui_settings;
@@ -11383,6 +11442,7 @@ static void enable_for_cpudlg (HWND hDlg)
        ew (hDlg, IDC_FPU1, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
        ew (hDlg, IDC_FPU2, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
        ew (hDlg, IDC_FPU3, workprefs.cpu_model >= 68040);
+       ew (hDlg, IDC_MMUENABLEEC, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
        ew (hDlg, IDC_MMUENABLE, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
        ew (hDlg, IDC_CPU_PPC, workprefs.cpu_model >= 68040 && (workprefs.ppc_mode == 1 || (workprefs.ppc_mode == 0 && !is_ppc_cpu(&workprefs))));
 
@@ -11452,11 +11512,11 @@ static void values_to_cpudlg (HWND hDlg)
        CheckDlgButton (hDlg, IDC_HARDFLUSH, workprefs.comp_hardflush);
        CheckDlgButton (hDlg, IDC_CONSTJUMP, workprefs.comp_constjump);
        CheckDlgButton (hDlg, IDC_JITENABLE, workprefs.cachesize > 0);
-       CheckDlgButton (hDlg, IDC_MMUENABLE,
-               ((workprefs.cpu_model == 68060 && workprefs.mmu_model == 68060) ||
+       bool mmu = ((workprefs.cpu_model == 68060 && workprefs.mmu_model == 68060) ||
                (workprefs.cpu_model == 68040 && workprefs.mmu_model == 68040) ||
                (workprefs.cpu_model == 68030 && workprefs.mmu_model == 68030)) &&
-               workprefs.cachesize == 0);
+               workprefs.cachesize == 0;
+       CheckRadioButton (hDlg, IDC_MMUENABLEOFF, IDC_MMUENABLE, mmu == 0 ? IDC_MMUENABLEOFF : (mmu && workprefs.mmu_ec) ? IDC_MMUENABLEEC : IDC_MMUENABLE);
        CheckDlgButton(hDlg, IDC_CPU_PPC, workprefs.ppc_mode || is_ppc_cpu(&workprefs));
 
        if (workprefs.cpu_cycle_exact) {
@@ -11505,6 +11565,7 @@ static void values_from_cpudlg (HWND hDlg)
                newfpu = 0;
        workprefs.cpu_model = newcpu;
        workprefs.mmu_model = 0;
+       workprefs.mmu_ec = false;
        switch(newcpu)
        {
        case 68000:
@@ -11522,19 +11583,22 @@ static void values_from_cpudlg (HWND hDlg)
                if (newcpu != oldcpu)
                        workprefs.address_space_24 = 0;
                workprefs.fpu_model = newfpu == 0 ? 0 : (newfpu == 2 ? 68882 : 68881);
-               workprefs.mmu_model = ischecked (hDlg, IDC_MMUENABLE) ? 68030 : 0;
+               workprefs.mmu_ec = ischecked(hDlg, IDC_MMUENABLEEC);
+               workprefs.mmu_model = workprefs.mmu_ec || ischecked (hDlg, IDC_MMUENABLE) ? 68030 : 0;
                break;
        case 68040:
                workprefs.fpu_model = newfpu ? 68040 : 0;
                workprefs.address_space_24 = 0;
                if (workprefs.fpu_model)
                        workprefs.fpu_model = 68040;
-               workprefs.mmu_model = ischecked (hDlg, IDC_MMUENABLE) ? 68040 : 0;
+               workprefs.mmu_ec = ischecked(hDlg, IDC_MMUENABLEEC);
+               workprefs.mmu_model = workprefs.mmu_ec || ischecked (hDlg, IDC_MMUENABLE) ? 68040 : 0;
                break;
        case 68060:
                workprefs.fpu_model = newfpu ? 68060 : 0;
                workprefs.address_space_24 = 0;
-               workprefs.mmu_model = ischecked (hDlg, IDC_MMUENABLE) ? 68060 : 0;
+               workprefs.mmu_ec = ischecked(hDlg, IDC_MMUENABLEEC);
+               workprefs.mmu_model = workprefs.mmu_ec || ischecked (hDlg, IDC_MMUENABLE) ? 68060 : 0;
                break;
        }
 
@@ -12300,9 +12364,13 @@ static void hardfile_testrdb (struct hfdlg_vals *hdf)
                                hdf->ci.controller_type_unit = 0;
                                break;
                        }
-                       if (!memcmp (id, "RDSK\0\0\0", 7) || !memcmp (id, "CDSK\0\0\0", 7) || !memcmp (id, "DRKS\0\0", 6) || (id[0] == 0x53 && id[1] == 0x10 && id[2] == 0x9b && id[3] == 0x13 && id[4] == 0 && id[5] == 0)) {
+                       bool babe = id[0] == 0xBA && id[1] == 0xBE; // A2090
+                       if (!memcmp (id, "RDSK\0\0\0", 7) || !memcmp (id, "CDSK\0\0\0", 7) || !memcmp (id, "DRKS\0\0", 6) ||
+                               (id[0] == 0x53 && id[1] == 0x10 && id[2] == 0x9b && id[3] == 0x13 && id[4] == 0 && id[5] == 0) || babe) {
                                // RDSK or ADIDE "encoded" RDSK
-                               int blocksize = (id[16] << 24)  | (id[17] << 16) | (id[18] << 8) | (id[19] << 0);
+                               int blocksize = 512;
+                               if (!babe)
+                                       blocksize = (id[16] << 24)  | (id[17] << 16) | (id[18] << 8) | (id[19] << 0);
                                hdf->ci.cyls = hdf->ci.highcyl = hdf->forcedcylinders = 0;
                                hdf->ci.sectors = 0;
                                hdf->ci.surfaces = 0;
@@ -12521,6 +12589,16 @@ STATIC_INLINE bool is_hdf_rdb (void)
 
 static int hdmenutable[256];
 
+static void sethardfilegeo(HWND hDlg)
+{
+       if (current_hfdlg.ci.geometry[0]) {
+               current_hfdlg.ci.physical_geometry = true;
+               setchecked(hDlg, IDC_HDF_PHYSGEOMETRY, TRUE);
+               ew (hDlg, IDC_HDF_PHYSGEOMETRY, FALSE);
+               get_hd_geometry(&current_hfdlg.ci);
+       }
+}
+
 static void sethardfiletypes(HWND hDlg)
 {
        bool ide = current_hfdlg.ci.controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && current_hfdlg.ci.controller_type <= HD_CONTROLLER_TYPE_IDE_LAST;
@@ -12536,16 +12614,12 @@ static void sethardfiletypes(HWND hDlg)
        SendDlgItemMessage(hDlg, IDC_HDF_FEATURE_LEVEL, CB_SETCURSEL, current_hfdlg.ci.unit_feature_level, 0);
 }
 
-static void sethardfile (HWND hDlg)
+static void sethd(HWND hDlg)
 {
-       bool ide = current_hfdlg.ci.controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && current_hfdlg.ci.controller_type <= HD_CONTROLLER_TYPE_IDE_LAST;
-       bool scsi = current_hfdlg.ci.controller_type >= HD_CONTROLLER_TYPE_SCSI_FIRST && current_hfdlg.ci.controller_type <= HD_CONTROLLER_TYPE_SCSI_LAST;
        bool rdb = is_hdf_rdb ();
        bool physgeo = rdb && ischecked(hDlg, IDC_HDF_PHYSGEOMETRY);
-       bool enablegeo = !rdb || physgeo;
-       bool disables = !rdb || (rdb && current_hfdlg.ci.controller_type == HD_CONTROLLER_TYPE_UAE);
+       bool enablegeo = !rdb || (physgeo && current_hfdlg.ci.geometry[0] == 0);
        const struct expansionromtype *ert = get_unit_expansion_rom(current_hfdlg.ci.controller_type);
-
        if (ert && current_hfdlg.ci.controller_unit >= 8) {
                if (!_tcscmp(ert->name, _T("a2091"))) {
                        current_hfdlg.ci.unit_feature_level = HD_LEVEL_SASI_CHS;
@@ -12553,11 +12627,39 @@ static void sethardfile (HWND hDlg)
                        current_hfdlg.ci.unit_feature_level = HD_LEVEL_SCSI_1;
                }
        }
+       if (!physgeo)
+               current_hfdlg.ci.physical_geometry = false;
+       ew(hDlg, IDC_SECTORS, enablegeo);
+       ew(hDlg, IDC_HEADS, enablegeo);
+       ew(hDlg, IDC_RESERVED, enablegeo);
+       ew(hDlg, IDC_BLOCKSIZE, enablegeo);
+}
 
+static void setharddrive(HWND hDlg)
+{
+       sethardfilegeo(hDlg);
+       sethd(hDlg);
+       ew(hDlg,IDC_BLOCKSIZE, FALSE);
+       SetDlgItemInt (hDlg, IDC_SECTORS, current_hfdlg.ci.psecs, FALSE);
+       SetDlgItemInt (hDlg, IDC_HEADS, current_hfdlg.ci.pheads, FALSE);
+       SetDlgItemInt (hDlg, IDC_RESERVED, current_hfdlg.ci.pcyls, FALSE);
+       SetDlgItemInt (hDlg, IDC_BLOCKSIZE, current_hfdlg.ci.blocksize, FALSE);
+       sethardfiletypes(hDlg);
+}
+
+static void sethardfile (HWND hDlg)
+{
+       sethardfilegeo(hDlg);
+
+       bool ide = current_hfdlg.ci.controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && current_hfdlg.ci.controller_type <= HD_CONTROLLER_TYPE_IDE_LAST;
+       bool scsi = current_hfdlg.ci.controller_type >= HD_CONTROLLER_TYPE_SCSI_FIRST && current_hfdlg.ci.controller_type <= HD_CONTROLLER_TYPE_SCSI_LAST;
+       bool rdb = is_hdf_rdb ();
+       bool physgeo = rdb && ischecked(hDlg, IDC_HDF_PHYSGEOMETRY);
+       bool disables = !rdb || (rdb && current_hfdlg.ci.controller_type == HD_CONTROLLER_TYPE_UAE);
+
+       sethd(hDlg);
        if (!disables)
                current_hfdlg.ci.bootpri = 0;
-       if (!physgeo)
-               current_hfdlg.ci.physical_geometry = false;
        SetDlgItemText (hDlg, IDC_PATH_NAME, current_hfdlg.ci.rootdir);
        SetDlgItemText (hDlg, IDC_PATH_FILESYS, current_hfdlg.ci.filesys);
        SetDlgItemText (hDlg, IDC_HARDFILE_DEVICE, current_hfdlg.ci.devname);
@@ -12577,10 +12679,6 @@ static void sethardfile (HWND hDlg)
        hide (hDlg, IDC_HARDFILE_BOOTPRI, !disables);
        hide (hDlg, IDC_HARDFILE_BOOTPRI_TEXT, !disables);
        hide (hDlg, IDC_HDF_PHYSGEOMETRY, !rdb);
-       ew(hDlg, IDC_SECTORS, enablegeo);
-       ew(hDlg, IDC_HEADS, enablegeo);
-       ew(hDlg, IDC_RESERVED, enablegeo);
-       ew(hDlg, IDC_BLOCKSIZE, enablegeo);
        hide(hDlg, IDC_RESERVED_TEXT, rdb);
        hide(hDlg, IDC_CYLINDERS_TEXT, !rdb);
        gui_set_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER, current_hfdlg.ci.controller_type +  current_hfdlg.ci.controller_type_unit * HD_CONTROLLER_NEXT_UNIT);
@@ -12617,7 +12715,7 @@ static void addhdcontroller(HWND hDlg, const struct expansionromtype *erc, int *
        }
 }
 
-static void inithdcontroller (HWND hDlg, int ctype, int ctype_unit, int devtype)
+static void inithdcontroller (HWND hDlg, int ctype, int ctype_unit, int devtype, bool media)
 {
        hdmenutable[0] = -1;
        
@@ -12667,7 +12765,8 @@ static void inithdcontroller (HWND hDlg, int ctype, int ctype_unit, int devtype)
                        _stprintf(tmp, _T("%d"), i + 1);
                        SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)tmp);
                }
-               ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
+               if (media)
+                       ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
        } else if (ctype >= HD_CONTROLLER_TYPE_SCSI_FIRST && ctype <= HD_CONTROLLER_TYPE_SCSI_LAST) {
                const struct expansionromtype *ert = get_unit_expansion_rom(ctype);
                SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)_T("0"));
@@ -12686,11 +12785,20 @@ static void inithdcontroller (HWND hDlg, int ctype, int ctype_unit, int devtype)
                                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)_T("ST-506 #2"));
                        }
                }
-               ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
+               if (media)
+                       ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
        } else if (ctype == HD_CONTROLLER_TYPE_PCMCIA) {
                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)_T("SRAM"));
                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)_T("IDE"));
                ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
+       } else if (ctype == HD_CONTROLLER_TYPE_UAE) {
+               for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
+                       TCHAR tmp[100];
+                       _stprintf(tmp, _T("%d"), i);
+                       SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_ADDSTRING, 0, (LPARAM)tmp);
+               }
+               if (media)
+                       ew(hDlg, IDC_HDF_CONTROLLER_UNIT, TRUE);
        } else {
                ew(hDlg, IDC_HDF_CONTROLLER_UNIT, FALSE);
        }
@@ -12715,13 +12823,13 @@ static void inithdcontroller (HWND hDlg, int ctype, int ctype_unit, int devtype)
        }
 }
 
-static void inithardfile (HWND hDlg)
+static void inithardfile (HWND hDlg, bool media)
 {
        TCHAR tmp[MAX_DPATH];
 
        ew (hDlg, IDC_HF_DOSTYPE, FALSE);
        ew (hDlg, IDC_HF_CREATE, FALSE);
-       inithdcontroller (hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF);
+       inithdcontroller (hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, media);
        SendDlgItemMessage (hDlg, IDC_HF_TYPE, CB_RESETCONTENT, 0, 0);
        WIN32GUI_LoadUIString (IDS_HF_FS_CUSTOM, tmp, sizeof (tmp) / sizeof (TCHAR));
        SendDlgItemMessage (hDlg, IDC_HF_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("RDB/OFS/FFS"));
@@ -12818,6 +12926,9 @@ static void updatehdfinfo (HWND hDlg, bool force, bool defaults)
        blocks = cyls * (secs * heads);
        if (!blocks && current_hfdlg.ci.blocksize)
                blocks = bsize / current_hfdlg.ci.blocksize;
+       if (current_hfdlg.ci.max_lba)
+               blocks = current_hfdlg.ci.max_lba;
+
        for (i = 0; i < sizeof (idtmp) / sizeof (TCHAR) - 1; i++) {
                TCHAR c = id[i];
                if (c < 32 || c > 126)
@@ -12868,7 +12979,7 @@ static void hardfileselecthdf (HWND hDlg, TCHAR *newpath, bool ask, bool newhd)
                        current_hfdlg.ci.sectors = current_hfdlg.ci.reserved = current_hfdlg.ci.surfaces = 0;
                }
        }
-       inithardfile (hDlg);
+       inithardfile (hDlg, true);
        hardfile_testrdb (&current_hfdlg);
        updatehdfinfo (hDlg, true, true);
        get_hd_geometry (&current_hfdlg.ci);
@@ -12907,7 +13018,7 @@ static INT_PTR CALLBACK TapeDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                recursive++;
                if (current_tapedlg.ci.controller_type < HD_CONTROLLER_TYPE_SCSI_AUTO)
                        current_tapedlg.ci.controller_type = HD_CONTROLLER_TYPE_SCSI_AUTO;
-               inithdcontroller(hDlg, current_tapedlg.ci.controller_type, current_tapedlg.ci.controller_type_unit, UAEDEV_TAPE);
+               inithdcontroller(hDlg, current_tapedlg.ci.controller_type, current_tapedlg.ci.controller_type_unit, UAEDEV_TAPE, current_tapedlg.ci.rootdir[0] != 0);
                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_tapedlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_tapedlg.ci.controller_unit : current_tapedlg.ci.controller_type_unit, 0);
                setautocomplete (hDlg, IDC_PATH_NAME);
                addhistorymenu(hDlg, current_tapedlg.ci.rootdir, IDC_PATH_NAME, HISTORY_TAPE, false);
@@ -12940,7 +13051,7 @@ static INT_PTR CALLBACK TapeDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                        current_tapedlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
                                        if (current_tapedlg.ci.controller_type == HD_CONTROLLER_TYPE_PCMCIA)
                                                current_tapedlg.ci.controller_type_unit = 1;
-                                       inithdcontroller(hDlg, current_tapedlg.ci.controller_type, current_tapedlg.ci.controller_type_unit, UAEDEV_TAPE);
+                                       inithdcontroller(hDlg, current_tapedlg.ci.controller_type, current_tapedlg.ci.controller_type_unit, UAEDEV_TAPE, current_tapedlg.ci.rootdir);
                                        SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_tapedlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_tapedlg.ci.controller_unit : current_tapedlg.ci.controller_type_unit, 0);
                                }
                                break;
@@ -13023,7 +13134,7 @@ static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam,
                                is_board_enabled(&workprefs, ROMTYPE_GVPS2, 0) || is_board_enabled(&workprefs, ROMTYPE_A4091, 0) ||
                        workprefs.cs_cdtvscsi ||
                        (workprefs.cs_mbdmac & 3)) ? HD_CONTROLLER_TYPE_SCSI_AUTO : HD_CONTROLLER_TYPE_IDE_AUTO;
-               inithdcontroller(hDlg, current_cddlg.ci.controller_type, current_cddlg.ci.controller_type_unit, UAEDEV_CD);
+               inithdcontroller(hDlg, current_cddlg.ci.controller_type, current_cddlg.ci.controller_type_unit, UAEDEV_CD, current_cddlg.ci.rootdir[0] != 0);
                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_cddlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_cddlg.ci.controller_unit : current_cddlg.ci.controller_type_unit, 0);
                InitializeListView (hDlg);
                recursive--;
@@ -13056,7 +13167,7 @@ static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam,
                                current_cddlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
                                if (current_cddlg.ci.controller_type == HD_CONTROLLER_TYPE_PCMCIA)
                                        current_cddlg.ci.controller_type_unit = 1;
-                               inithdcontroller(hDlg, current_cddlg.ci.controller_type, current_cddlg.ci.controller_type_unit, UAEDEV_CD);
+                               inithdcontroller(hDlg, current_cddlg.ci.controller_type, current_cddlg.ci.controller_type_unit, UAEDEV_CD, current_cddlg.ci.rootdir[0] != 0);
                                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_cddlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_cddlg.ci.controller_unit : current_cddlg.ci.controller_type_unit, 0);
                        }
                        break;
@@ -13124,7 +13235,9 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam
                setchecked(hDlg, IDC_HDF_PHYSGEOMETRY, current_hfdlg.ci.physical_geometry);
                setautocomplete (hDlg, IDC_PATH_NAME);
                setautocomplete (hDlg, IDC_PATH_FILESYS);
-               inithardfile (hDlg);
+               setautocomplete (hDlg, IDC_PATH_GEOMETRY);
+               addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false);
+               inithardfile (hDlg, current_hfdlg.ci.rootdir[0] != 0);
                addhistorymenu(hDlg, current_hfdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_HDF, false);
                addhistorymenu(hDlg, current_hfdlg.ci.filesys, IDC_PATH_FILESYS, HISTORY_FS, false);
                updatehdfinfo (hDlg, true, false);
@@ -13197,7 +13310,7 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam
                                        current_hfdlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
                                        if (current_hfdlg.ci.controller_type == HD_CONTROLLER_TYPE_PCMCIA)
                                                current_hfdlg.ci.controller_type_unit = 1;
-                                       inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF);
+                                       inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0);
                                        sethardfile(hDlg);
                                }
                                break;
@@ -13232,6 +13345,13 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam
                                }
                                break;
                        }
+                       case IDC_PATH_GEOMETRY:
+                               getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof  current_hfdlg.ci.geometry / sizeof(TCHAR));
+                               if (HIWORD (wParam) == CBN_KILLFOCUS) {
+                                       addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false);
+                                       sethardfile(hDlg);
+                               }
+                               break;
                }
 
                switch (LOWORD (wParam)) {
@@ -13307,6 +13427,12 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam
                        current_hfdlg.ci.bootpri = 0;
                        sethardfile (hDlg);
                        break;
+               case IDC_PATH_GEOMETRY_SELECTOR:
+                       DiskSelection (hDlg, IDC_PATH_GEOMETRY, 23, &workprefs, 0);
+                       getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof  current_hfdlg.ci.geometry / sizeof(TCHAR));
+                       DISK_history_add(current_hfdlg.ci.geometry, -1, HISTORY_GEO, 1);
+                       sethardfile(hDlg);
+                       break;
                case IDC_SECTORS:
                        p = ischecked(hDlg, IDC_HDF_PHYSGEOMETRY) ? &current_hfdlg.ci.psecs : &current_hfdlg.ci.sectors;
                        v = *p;
@@ -13367,7 +13493,8 @@ extern int harddrive_to_hdf (HWND, struct uae_prefs*, int);
 static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 {
        static int recursive = 0;
-       int i;
+       int v, i;
+       int *p;
        LRESULT posn;
        static int oposn;
 
@@ -13378,14 +13505,15 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                        oposn = -1;
                        hdf_init_target ();
                        recursive++;
-                       sethardfiletypes(hDlg);
-                       inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF);
+                       setautocomplete (hDlg, IDC_PATH_GEOMETRY);
+                       addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false);
+                       setchecked(hDlg, IDC_HDF_PHYSGEOMETRY, current_hfdlg.ci.physical_geometry);
+                       setharddrive(hDlg);
+                       inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0);
                        CheckDlgButton (hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
                        CheckDlgButton (hDlg, IDC_HDF_LOCK, current_hfdlg.ci.lock);
                        SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_RESETCONTENT, 0, 0);
                        ew (hDlg, IDC_HARDDRIVE_IMAGE, FALSE);
-                       ew (hDlg, IDOK, FALSE);
-                       ew (hDlg, IDC_HDF_RW, FALSE);
                        index = -1;
                        for (i = 0; i < hdf_getnumharddrives (); i++) {
                                SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_ADDSTRING, 0, (LPARAM)hdf_getnameharddrive (i, 1, NULL, NULL));
@@ -13409,6 +13537,19 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                if (recursive)
                        break;
                recursive++;
+               if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_KILLFOCUS) {
+                       switch (LOWORD(wParam)) {
+                               case IDC_PATH_GEOMETRY:
+                                       getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof  current_hfdlg.ci.geometry / sizeof(TCHAR));
+                                       if (HIWORD (wParam) == CBN_KILLFOCUS) {
+                                               addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false);
+                                               setharddrive(hDlg);
+                                               updatehdfinfo (hDlg, true, false);
+                                       }
+                                       break;
+                       }
+               }
+
                if (HIWORD (wParam) == BN_CLICKED) {
                        switch (LOWORD (wParam)) {
                        case IDOK:
@@ -13417,6 +13558,18 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                        case IDCANCEL:
                                EndDialog (hDlg, 0);
                                break;
+                       case IDC_HDF_PHYSGEOMETRY:
+                               current_hfdlg.ci.physical_geometry = ischecked(hDlg, IDC_HDF_PHYSGEOMETRY);
+                               updatehdfinfo(hDlg, true, false);
+                               setharddrive(hDlg);
+                               break;
+                       case IDC_HARDDRIVE_ID:
+                               if (oposn >= 0) {
+                                       void hd_get_meta(HWND hDlg, int idx, TCHAR*);
+                                       hd_get_meta(hDlg, oposn, current_hfdlg.ci.geometry);
+                                       setharddrive(hDlg);
+                               }
+                               break;
                        case IDC_HARDDRIVE_IMAGE:
                                posn = SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
                                if (posn != CB_ERR)
@@ -13440,66 +13593,121 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                break;
                        }
                }
-               if (LOWORD (wParam) == IDC_HARDDRIVE) {
-                       posn = SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
-                       if (oposn != posn && posn != CB_ERR) {
-                               oposn = posn;
-                               if (posn >= 0) {
-                                       BOOL ena;
-                                       int dang = 1;
-                                       hdf_getnameharddrive (posn, 1, NULL, &dang);
-                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 4, NULL, &dang));
-                                       ena = dang >= 0;
-                                       ew (hDlg, IDC_HARDDRIVE_IMAGE, ena);
-                                       ew (hDlg, IDOK, ena);
-                                       ew (hDlg, IDC_HDF_RW, !dang);
-                                       if (dang)
-                                               current_hfdlg.ci.readonly = true;
-                                       current_hfdlg.ci.blocksize = 512;
+               switch(LOWORD(wParam))
+               {
+                       case IDC_HARDDRIVE:
+                               posn = SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
+                               if (oposn != posn && posn != CB_ERR) {
+                                       oposn = posn;
+                                       if (posn >= 0) {
+                                               BOOL ena;
+                                               int dang = 1;
+                                               hdf_getnameharddrive (posn, 1, NULL, &dang);
+                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 4, NULL, &dang));
+                                               ena = dang >= 0;
+                                               ew (hDlg, IDC_HARDDRIVE_IMAGE, ena);
+                                               ew (hDlg, IDC_HARDDRIVE_ID, ena);
+                                               ew (hDlg, IDC_HDF_LOCK, ena);
+                                               ew (hDlg, IDOK, ena);
+                                               ew (hDlg, IDC_HDF_RW, !dang);
+                                               ew (hDlg, IDC_HDF_FEATURE_LEVEL, ena);
+                                               ew (hDlg, IDC_HDF_CONTROLLER, ena);
+                                               ew (hDlg, IDC_HDF_CONTROLLER_UNIT, ena);
+                                               ew (hDlg, IDC_HDF_CONTROLLER_TYPE, ena);
+                                               ew (hDlg, IDC_PATH_GEOMETRY, ena);
+                                               ew (hDlg, IDC_PATH_GEOMETRY_SELECTOR, ena);
+                                               ew (hDlg, IDC_HDF_PHYSGEOMETRY, ena && current_hfdlg.ci.geometry[0] == 0);
+                                               if (dang)
+                                                       current_hfdlg.ci.readonly = true;
+                                               current_hfdlg.ci.blocksize = 512;
+                                               current_hfdlg.forcedcylinders = 0;
+                                               current_hfdlg.ci.cyls = current_hfdlg.ci.highcyl = current_hfdlg.ci.sectors = current_hfdlg.ci.surfaces = 0;
+                                               SetDlgItemText (hDlg, IDC_HDFINFO, _T(""));
+                                               SetDlgItemText (hDlg, IDC_HDFINFO2, _T(""));
+                                               updatehdfinfo (hDlg, true, current_hfdlg.ci.geometry[0] ? false : true);
+                                               gui_set_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER, current_hfdlg.ci.controller_type + current_hfdlg.ci.controller_type_unit * MAX_DUPLICATE_EXPANSION_BOARDS);
+                                               SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_hfdlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_hfdlg.ci.controller_unit : current_hfdlg.ci.controller_type_unit, 0);
+                                               CheckDlgButton(hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
+                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, &current_hfdlg.ci.blocksize, NULL));
+                                               setharddrive(hDlg);
+                                       }
+                               }
+                               break;
+                       case IDC_HDF_CONTROLLER:
+                               posn = gui_get_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER);
+                               if (posn != CB_ERR && current_hfdlg.ci.controller_type != posn) {
+                                       current_hfdlg.ci.controller_type = posn % HD_CONTROLLER_NEXT_UNIT;
+                                       current_hfdlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
                                        current_hfdlg.forcedcylinders = 0;
                                        current_hfdlg.ci.cyls = current_hfdlg.ci.highcyl = current_hfdlg.ci.sectors = current_hfdlg.ci.surfaces = 0;
                                        SetDlgItemText (hDlg, IDC_HDFINFO, _T(""));
                                        SetDlgItemText (hDlg, IDC_HDFINFO2, _T(""));
                                        updatehdfinfo (hDlg, true, true);
-                                       gui_set_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER, current_hfdlg.ci.controller_type + current_hfdlg.ci.controller_type_unit * MAX_DUPLICATE_EXPANSION_BOARDS);
+                                       inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0);
                                        SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_hfdlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_hfdlg.ci.controller_unit : current_hfdlg.ci.controller_type_unit, 0);
-                                       CheckDlgButton(hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
-                                       _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, &current_hfdlg.ci.blocksize, NULL));
                                        sethardfiletypes(hDlg);
                                }
-                       }
-               } else if (LOWORD (wParam) == IDC_HDF_CONTROLLER) {
-                       posn = gui_get_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER);
-                       if (posn != CB_ERR && current_hfdlg.ci.controller_type != posn) {
-                               current_hfdlg.ci.controller_type = posn % HD_CONTROLLER_NEXT_UNIT;
-                               current_hfdlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
-                               current_hfdlg.forcedcylinders = 0;
-                               current_hfdlg.ci.cyls = current_hfdlg.ci.highcyl = current_hfdlg.ci.sectors = current_hfdlg.ci.surfaces = 0;
-                               SetDlgItemText (hDlg, IDC_HDFINFO, _T(""));
-                               SetDlgItemText (hDlg, IDC_HDFINFO2, _T(""));
-                               updatehdfinfo (hDlg, true, true);
-                               inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF);
-                               SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_hfdlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_hfdlg.ci.controller_unit : current_hfdlg.ci.controller_type_unit, 0);
-                               sethardfiletypes(hDlg);
-                       }
-               } else if (LOWORD(wParam) == IDC_HDF_CONTROLLER_UNIT) {
-                       posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER_UNIT, CB_GETCURSEL, 0, 0);
-                       if (posn != CB_ERR) {
-                               if (current_hfdlg.ci.controller_type == HD_CONTROLLER_TYPE_PCMCIA)
-                                       current_hfdlg.ci.controller_type_unit = posn;
-                               else
-                                       current_hfdlg.ci.controller_unit = posn;
-                       }
-               } else if (LOWORD(wParam) == IDC_HDF_CONTROLLER_TYPE) {
-                       posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER_TYPE, CB_GETCURSEL, 0, 0);
-                       if (posn != CB_ERR) {
-                               current_hfdlg.ci.controller_media_type = posn;
-                       }
-               } else if (LOWORD(wParam) == IDC_HDF_FEATURE_LEVEL) {
-                       posn = SendDlgItemMessage(hDlg, IDC_HDF_FEATURE_LEVEL, CB_GETCURSEL, 0, 0);
-                       if (posn != CB_ERR) {
-                               current_hfdlg.ci.unit_feature_level = posn;
-                       }
+                               break;
+                       case IDC_HDF_CONTROLLER_UNIT:
+                               posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER_UNIT, CB_GETCURSEL, 0, 0);
+                               if (posn != CB_ERR) {
+                                       if (current_hfdlg.ci.controller_type == HD_CONTROLLER_TYPE_PCMCIA)
+                                               current_hfdlg.ci.controller_type_unit = posn;
+                                       else
+                                               current_hfdlg.ci.controller_unit = posn;
+                               }
+                               break;
+                       case IDC_HDF_CONTROLLER_TYPE:
+                               posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER_TYPE, CB_GETCURSEL, 0, 0);
+                               if (posn != CB_ERR) {
+                                       current_hfdlg.ci.controller_media_type = posn;
+                               }
+                               break;
+                       case IDC_HDF_FEATURE_LEVEL:
+                               posn = SendDlgItemMessage(hDlg, IDC_HDF_FEATURE_LEVEL, CB_GETCURSEL, 0, 0);
+                               if (posn != CB_ERR) {
+                                       current_hfdlg.ci.unit_feature_level = posn;
+                               }
+                       break;
+                       case IDC_PATH_GEOMETRY_SELECTOR:
+                               DiskSelection (hDlg, IDC_PATH_GEOMETRY, 23, &workprefs, 0);
+                               getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof  current_hfdlg.ci.geometry / sizeof(TCHAR));
+                               DISK_history_add(current_hfdlg.ci.geometry, -1, HISTORY_GEO, 1);
+                               setharddrive(hDlg);
+                               updatehdfinfo (hDlg, true, false);
+                               break;
+                       case IDC_SECTORS:
+                               p = &current_hfdlg.ci.psecs;
+                               v = *p;
+                               *p = GetDlgItemInt (hDlg, IDC_SECTORS, NULL, FALSE);
+                               if (v != *p) {
+                                       set_phys_cyls(hDlg);
+                                       updatehdfinfo (hDlg, true, false);
+                                       ew (hDlg, IDC_HDF_RDB, !is_hdf_rdb ());
+                               }
+                               break;
+                       case IDC_RESERVED:
+                               p = &current_hfdlg.ci.pcyls;
+                               v = *p;
+                               *p = GetDlgItemInt (hDlg, IDC_RESERVED, NULL, FALSE);
+                               if (v != *p) {
+                                       if (ischecked(hDlg, IDC_HDF_PHYSGEOMETRY)) {
+                                               current_hfdlg.ci.physical_geometry = true;
+                                       }
+                                       updatehdfinfo (hDlg, true, false);
+                                       ew (hDlg, IDC_HDF_RDB, !is_hdf_rdb ());
+                               }
+                               break;
+                       case IDC_HEADS:
+                               p = &current_hfdlg.ci.pheads;
+                               v = *p;
+                               *p = GetDlgItemInt (hDlg, IDC_HEADS, NULL, FALSE);
+                               if (v != *p) {
+                                       set_phys_cyls(hDlg);
+                                       updatehdfinfo (hDlg, true, false);
+                                       ew (hDlg, IDC_HDF_RDB, !is_hdf_rdb ());
+                               }
+                               break;
                }
                recursive--;
                break;
@@ -20396,7 +20604,7 @@ int gui_init (void)
        }
        if (ret > 0) {
 #ifdef AVIOUTPUT
-               AVIOutput_Begin ();
+               AVIOutput_Begin (true);
 #endif
        }
        return ret;