diff --git a/menu.cpp b/menu.cpp index 426fb58..2f576c2 100644 --- a/menu.cpp +++ b/menu.cpp @@ -84,6 +84,8 @@ enum MENU MENU_HARDFILE_SELECT1, MENU_HARDFILE_SELECT2, MENU_HARDFILE_SELECTED, + MENU_HARDFILE_SELECTED2, + MENU_HARDFILE_SELECTED3, MENU_LOADCONFIG_1, MENU_LOADCONFIG_2, MENU_SAVECONFIG_1, @@ -641,7 +643,8 @@ void HandleUI(void) // No UI in unknown cores. return; } - + + struct RigidDiskBlock *rdb; char *p; char s[40]; @@ -2049,7 +2052,7 @@ void HandleUI(void) OsdWrite(5, s, menusub == 4, 0); OsdWrite(6, "", 0, 0); - OsdWrite(7, " Hard disk", menusub == 5, 0); + OsdWrite(7, " Hard disks", menusub == 5, 0); OsdWrite(8, " Chipset", menusub == 6, 0); OsdWrite(9, " Memory", menusub == 7, 0); OsdWrite(10, " Audio & Video", menusub == 8, 0); @@ -2764,6 +2767,56 @@ void HandleUI(void) if (len > sizeof(config.hardfile[num].filename) - 1) len = sizeof(config.hardfile[num].filename) - 1; if(len) memcpy(config.hardfile[num].filename, SelectedPath, len); config.hardfile[num].filename[len] = 0; + menustate = checkHDF(config.hardfile[num].filename, &rdb) ? MENU_SETTINGS_HARDFILE1 : MENU_HARDFILE_SELECTED2; + } + break; + + case MENU_HARDFILE_SELECTED2: + m = 0; + menumask = 0x1; + if (!rdb) + { + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " Cannot open the file", 0, 0); + } + else + { + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " !! DANGEROUS !!", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " RDB has illegal CHS values:", 0, 0); + sprintf(s, " Cylinders: %d", rdb->rdb_Cylinders); + OsdWrite(m++, s, 0, 0); + sprintf(s, " Heads: %d", rdb->rdb_Heads); + OsdWrite(m++, s, 0, 0); + sprintf(s, " Sectors: %d", rdb->rdb_Sectors); + OsdWrite(m++, s, 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " Max legal values:", 0, 0); + OsdWrite(m++, " C:65536, H:16, S:255", 0, 0); + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " Some functions won't work", 0, 0); + OsdWrite(m++, " correctly and may corrupt", 0, 0); + OsdWrite(m++, " the data!", 0, 0); + } + OsdWrite(m++, "", 0, 0); + OsdWrite(m++, " OK", 1, 0); + while (m < OsdGetSize()) OsdWrite(m++, "", 0, 0); + + menusub_last = menusub; + menusub = 0; + menustate = MENU_HARDFILE_SELECTED3; + break; + + case MENU_HARDFILE_SELECTED3: + if (select || menu) + { + menusub = menusub_last; + parentstate = menustate; menustate = MENU_SETTINGS_HARDFILE1; } break; diff --git a/minimig_hdd.cpp b/minimig_hdd.cpp index d88b179..51e375f 100644 --- a/minimig_hdd.cpp +++ b/minimig_hdd.cpp @@ -24,7 +24,6 @@ along with this program. If not, see . #include "hardware.h" #include "file_io.h" #include "minimig_hdd.h" -#include "minimig_hdd_internal.h" #include "menu.h" #include "minimig_config.h" #include "debug.h" @@ -63,7 +62,7 @@ typedef struct { int enabled; fileTYPE file; - unsigned short cylinders; + unsigned long cylinders; unsigned short heads; unsigned short sectors; unsigned short sectors_per_block; @@ -493,32 +492,46 @@ static void GetRDBGeometry(hdfTYPE *pHDF) pHDF->heads = SWAP(rdb->rdb_Heads); pHDF->sectors = SWAP(rdb->rdb_Sectors); pHDF->cylinders = SWAP(rdb->rdb_Cylinders); - if (pHDF->sectors > 255) + if (pHDF->sectors > 255 || pHDF->heads > 16) { - printf("ATTN: Too many sectors per track %d.", pHDF->sectors); - if (pHDF->sectors & 1) + printf("ATTN: Illegal CHS value(s)."); + if (!(pHDF->sectors & 1) && (pHDF->sectors < 512) && (pHDF->heads <= 8)) { - printf(" Odd number of sectors, Cannot translate. Give up! 8-E\n"); + printf(" Translate: sectors %d->%d, heads %d->%d.\n", pHDF->sectors, pHDF->sectors / 2, pHDF->heads, pHDF->heads * 2); + pHDF->sectors /= 2; + pHDF->heads *= 2; return; } - if (pHDF->sectors > 511) - { - printf(" Really, too many! Give up! 8-E\n"); - return; - } + printf(" DANGEROUS: Cannot translate to legal CHS values. Re-calculate the CHS.\n"); - if (pHDF->heads > 8) - { - printf(" Too many heads (%d). Cannot translate. Give up! 8-E\n", pHDF->heads); - return; - } - - printf(" Translate: sectors %d->%d, heads %d->%d.\n", pHDF->sectors, pHDF->sectors / 2, pHDF->heads, pHDF->heads * 2); - - pHDF->sectors /= 2; - pHDF->heads *= 2; - } + uint32_t head, cyl, spt; + uint32_t sptt[] = { 63, 127, 255, 0 }; + uint32_t total = pHDF->file.size / 512; + for (int i = 0; sptt[i] != 0; i++) + { + spt = sptt[i]; + for (head = 4; head <= 16; head++) + { + cyl = total / (head * spt); + if (total <= 1024 * 1024) + { + if (cyl <= 1023) break; + } + else + { + if (cyl < 16383) break; + if (cyl < 32767 && head >= 5) break; + if (cyl <= 65536) break; + } + } + if (head <= 16) break; + } + + pHDF->cylinders = cyl; + pHDF->heads = (unsigned short)head; + pHDF->sectors = (unsigned short)spt; + } } static void write_sector(int unit, uint32_t lba) @@ -752,12 +765,12 @@ static void SetHardfileGeometry(hdfTYPE *pHDF, int isHDF) { if (cyl < 16383) break; if (cyl < 32767 && head >= 5) break; - if (cyl <= 65535) break; // Should there some head constraint here? + if (cyl <= 65536) break; // Should there some head constraint here? } } if (head <= 16) break; } - pHDF->cylinders = (unsigned short)cyl; + pHDF->cylinders = cyl; pHDF->heads = (unsigned short)head; pHDF->sectors = (unsigned short)spt; @@ -806,3 +819,30 @@ unsigned char OpenHardfile(unsigned char unit) FileClose(&hdf[unit].file); return 0; } + +int checkHDF(const char* name, struct RigidDiskBlock **rdb) +{ + fileTYPE file = { 0 }; + + *rdb = NULL; + if (FileOpenEx(&file, name, O_RDONLY)) + { + *rdb = (struct RigidDiskBlock *)sector_buffer; + for (int i = 0; i<16; ++i) + { + if (!FileReadSec(&file, sector_buffer)) break; + if ((*rdb)->rdb_ID == 0x4B534452) + { + FileClose(&file); + (*rdb)->rdb_Heads = SWAP((*rdb)->rdb_Heads); + (*rdb)->rdb_Sectors = SWAP((*rdb)->rdb_Sectors); + (*rdb)->rdb_Cylinders = SWAP((*rdb)->rdb_Cylinders); + return ((*rdb)->rdb_Heads <= 16 && (*rdb)->rdb_Sectors <= 255 && (*rdb)->rdb_Cylinders <= 65536); + } + } + + FileClose(&file); + return 1; // non-HDF file + } + return 0; +} diff --git a/minimig_hdd.h b/minimig_hdd.h index 57869a3..3df900f 100644 --- a/minimig_hdd.h +++ b/minimig_hdd.h @@ -3,8 +3,11 @@ #ifndef __MINIMIG_HDD_H__ #define __MINIMIG_HDD_H__ +#include "minimig_hdd_internal.h" + // functions void HandleHDD(unsigned char c1, unsigned char c2); unsigned char OpenHardfile(unsigned char unit); +int checkHDF(const char* name, struct RigidDiskBlock **rdb); #endif // __HDD_H__