From 419b0b0c58305083c22e85a0f76538333e3b3dfd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 15 Feb 2017 18:19:00 +0100 Subject: [PATCH] Added support for custom HDX hard disk image format that is less size-limited than HDI and supports storing translation parameters; Commented out excess EGA logging. --- src/disc.c | 4 +- src/ibm.h | 11 +-- src/ide.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++- src/ide.h | 3 +- src/vid_ega.c | 14 ++-- src/vid_svga.c | 3 + src/win-hdconf.c | 36 +++++++-- 7 files changed, 232 insertions(+), 26 deletions(-) diff --git a/src/disc.c b/src/disc.c index 8a273f463..ed3d7d1d2 100644 --- a/src/disc.c +++ b/src/disc.c @@ -197,7 +197,7 @@ double disc_real_period(int drive) /* This is a giant hack but until the timings become even more correct, this is needed to make floppies work right on that BIOS. */ if (romset == ROM_MRTHOR) { - return (ddbp * dusec) / 2.0; + return (ddbp * dusec) / 4.0; } else { @@ -209,7 +209,7 @@ void disc_poll(int drive) { if (drive >= FDD_NUM) { - disc_poll_time[drive] += (int) (((romset == ROM_MRTHOR) ? 16.0 : 32.0) * TIMER_USEC); + disc_poll_time[drive] += (int) (((romset == ROM_MRTHOR) ? 8.0 : 32.0) * TIMER_USEC); return; } diff --git a/src/ibm.h b/src/ibm.h index 78570ecc5..5626ea263 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -517,13 +517,14 @@ char pcempath[512]; /*Hard disc*/ -typedef struct +typedef struct __attribute__((__packed__)) { - FILE *f; - uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/ - uint64_t tracks; + FILE *f; + uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/ + uint64_t tracks; int is_hdi; - uint32_t base; + uint32_t base; + uint64_t at_spt,at_hpc; /*[Translation] Sectors per track, heads per cylinder*/ } hard_disk_t; #define IDE_NUM 8 diff --git a/src/ide.c b/src/ide.c index 001a915a4..db88e534d 100644 --- a/src/ide.c +++ b/src/ide.c @@ -199,6 +199,61 @@ int image_is_hdi(const char *s) } } +int image_is_hdx(const char *s, int check_signature) +{ + int i, len; + FILE *f; + uint64_t filelen; + uint64_t signature; + char ext[5] = { 0, 0, 0, 0, 0 }; + len = strlen(s); + if ((len < 4) || (s[0] == '.')) + { + return 0; + } + memcpy(ext, s + len - 4, 4); + for (i = 0; i < 4; i++) + { + ext[i] = toupper(ext[i]); + } + if (strcmp(ext, ".HDX") == 0) + { + if (check_signature) + { + f = fopen(s, "rb"); + if (!f) + { + return 0; + } + fseeko64(f, 0, SEEK_END); + filelen = ftello64(f); + fseeko64(f, 0, SEEK_SET); + if (filelen < 44) + { + return 0; + } + fread(&signature, 1, 8, f); + fclose(f); + if (signature == 0xD778A82044445459) + { + return 1; + } + else + { + return 0; + } + } + else + { + return 1; + } + } + else + { + return 0; + } +} + int ide_enable[4] = { 1, 1, 0, 0 }; int ide_irq[4] = { 14, 15, 10, 11 }; @@ -334,6 +389,7 @@ static void ide_identify(IDE *ide) { int c, h, s; uint8_t device_identify[8] = { '8', '6', 'B', '_', 'H', 'D', '0', 0 }; + uint64_t full_size = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt); device_identify[6] = ide->channel + 0x30; ide_log("IDE Identify: %s\n", device_identify); @@ -347,7 +403,14 @@ static void ide_identify(IDE *ide) s = hdc[cur_ide[ide->board]].spt; /* Sectors */ // ide->buffer[0] = 0x40; /* Fixed disk */ - ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ + if (hdc[cur_ide[ide->board]].tracks <= 16383) + { + ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ + } + else + { + ide->buffer[1] = 16383; /* Cylinders */ + } ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */ ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */ ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ @@ -372,9 +435,26 @@ static void ide_identify(IDE *ide) ide->buffer[50] = 0x4000; /* Capabilities */ ide->buffer[51] = 2 << 8; /*PIO timing mode*/ ide->buffer[52] = 2 << 8; /*DMA timing mode*/ + ide->buffer[53] = ide->specify_success ? 1 : 0; + ide->buffer[55] = ide->hpc; + ide->buffer[56] = ide->spt; + if (((full_size / ide->hpc) / ide->spt) <= 16383) + { + ide->buffer[54] = (full_size / ide->hpc) / ide->spt; + } + else + { + ide->buffer[54] = 16383; + } + full_size = ((uint64_t) ide->hpc) * ((uint64_t) ide->spt) * ((uint64_t) ide->buffer[54]); + ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[61] = full_size >> 16; ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; - ide->buffer[60] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[61] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >> 16; + if (ide->buffer[49] & (1 << 9)) + { + ide->buffer[60] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[61] = ((hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >> 16) & 0x0FFF; + } ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ // ide->buffer[63] = 7; /*Multiword DMA*/ if (ide->board < 2) @@ -471,7 +551,8 @@ static void loadhd(IDE *ide, int d, const char *fn) { uint32_t sector_size = 512; uint32_t zero = 0; - uint32_t full_size = 0; + uint64_t signature = 0xD778A82044445459; + uint64_t full_size = 0; int c; ide->base = 0; ide->hdi = 0; @@ -517,6 +598,20 @@ static void loadhd(IDE *ide, int d, const char *fn) fwrite(&zero, 1, 4, ide->hdfile); } } + else if (image_is_hdx(fn, 0)) + { + full_size = hdc[d].spt * hdc[d].hpc * hdc[d].tracks * 512; + ide->base = 0x28; + ide->hdi = 2; + fwrite(&signature, 1, 8, ide->hdfile); + fwrite(&full_size, 1, 8, ide->hdfile); + fwrite(§or_size, 1, 4, ide->hdfile); + fwrite(&(hdc[d].spt), 1, 4, ide->hdfile); + fwrite(&(hdc[d].hpc), 1, 4, ide->hdfile); + fwrite(&(hdc[d].tracks), 1, 4, ide->hdfile); + fwrite(&zero, 1, 4, ide->hdfile); + fwrite(&zero, 1, 4, ide->hdfile); + } ide->hdc_num = d; } } @@ -547,6 +642,25 @@ static void loadhd(IDE *ide, int d, const char *fn) fread(&(hdc[d].tracks), 1, 4, ide->hdfile); ide->hdi = 1; } + else if (image_is_hdx(fn, 1)) + { + ide->base = 0x28; + fseeko64(ide->hdfile, 0x10, SEEK_SET); + fread(§or_size, 1, 4, ide->hdfile); + if (sector_size != 512) + { + /* Sector size is not 512 */ + fclose(ide->hdfile); + ide->type = IDE_NONE; + return; + } + fread(&(hdc[d].spt), 1, 4, ide->hdfile); + fread(&(hdc[d].hpc), 1, 4, ide->hdfile); + fread(&(hdc[d].tracks), 1, 4, ide->hdfile); + fread(&(hdc[d].at_spt), 1, 4, ide->hdfile); + fread(&(hdc[d].at_hpc), 1, 4, ide->hdfile); + ide->hdi = 2; + } } } @@ -1567,6 +1681,7 @@ void callbackide(int ide_board) ext_ide = ide; int64_t snum; int cdrom_id; + uint64_t full_size = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt); if (ide_drive_is_cdrom(ide)) { @@ -1690,6 +1805,10 @@ void callbackide(int ide_board) ide_set_signature(ide); goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); @@ -1707,6 +1826,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; fseeko64(ide->hdfile, addr, SEEK_SET); fread(ide->buffer, 512, 1, ide->hdfile); @@ -1751,6 +1874,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); @@ -1777,6 +1904,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); fwrite(ide->buffer, 512, 1, ide->hdfile); @@ -1801,6 +1932,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } if (ide_bus_master_write) { @@ -1839,6 +1974,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); fwrite(ide->buffer, 512, 1, ide->hdfile); @@ -1869,6 +2008,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } ide->pos=0; ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); @@ -1880,6 +2023,10 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (!ide->specify_success) + { + goto id_not_found; + } addr = ide_get_sector(ide) * 512; // ide_log("Format cyl %i head %i offset %08X %08X %08X secount %i\n",ide.cylinder,ide.head,addr,addr>>32,addr,ide.secount); fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); @@ -1917,6 +2064,32 @@ void callbackide(int ide_board) { goto abort_cmd; } + if (((hdc[cur_ide[ide->board]].at_hpc == 0) && (hdc[cur_ide[ide->board]].at_spt == 0)) || (ide->hdi != 2)) + { + full_size /= (ide->head+1); + full_size /= ide->secount; + ide->specify_success = 1; + if (ide->hdi == 2) + { + hdc[cur_ide[ide->board]].at_hpc = ide->head+1; + hdc[cur_ide[ide->board]].at_spt = ide->secount; + fseeko64(ide->hdfile, 0x20, SEEK_SET); + fwrite(&(hdc[cur_ide[ide->board]].at_spt), 1, 4, ide->hdfile); + fwrite(&(hdc[cur_ide[ide->board]].at_hpc), 1, 4, ide->hdfile); + } + } + else + { + if ((hdc[cur_ide[ide->board]].at_hpc == (ide->head + 1)) && (hdc[cur_ide[ide->board]].at_spt == ide->secount)) + { + ide->specify_success = 1; + } + else + { + ide_log("WIN_SPECIFY error (%04X, %04X)\n", ide->head + 1, ide->secount); + ide->specify_success = 0; + } + } ide->spt=ide->secount; ide->hpc=ide->head+1; ide->atastat = READY_STAT | DSC_STAT; @@ -2028,6 +2201,12 @@ abort_cmd: ide->pos = 0; } ide_irq_raise(ide); + return; +id_not_found: + ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; + ide->error = ABRT_ERR | 0x10; + ide->pos = 0; + ide_irq_raise(ide); } void ide_callback_pri() diff --git a/src/ide.h b/src/ide.h index 87dc9081c..970bc557b 100644 --- a/src/ide.h +++ b/src/ide.h @@ -4,7 +4,7 @@ #ifndef __IDE__ #define __IDE__ -typedef struct IDE +typedef struct __attribute__((__packed__)) IDE { int type; int board; @@ -32,6 +32,7 @@ typedef struct IDE uint16_t dma_identify_data[3]; int hdi,base; int hdc_num; + uint8_t specify_success; } IDE; extern void writeide(int ide_board, uint16_t addr, uint8_t val); diff --git a/src/vid_ega.c b/src/vid_ega.c index 6a377efe3..dc8ec33a8 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -128,12 +128,12 @@ void ega_out(uint16_t addr, uint8_t val, void *p) break; case 0x3d0: case 0x3d4: - pclog("Write 3d4 %02X %04X:%04X\n", val, CS, cpu_state.pc); + // pclog("Write 3d4 %02X %04X:%04X\n", val, CS, cpu_state.pc); ega->crtcreg = val & 31; return; case 0x3d1: case 0x3d5: - pclog("Write 3d5 %02X %02X %02X\n", ega->crtcreg, val, ega->crtc[0x11]); + // pclog("Write 3d5 %02X %02X %02X\n", ega->crtcreg, val, ega->crtc[0x11]); // if (ega->crtcreg == 1 && val == 0x14) // fatal("Here\n"); if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return; @@ -178,7 +178,7 @@ uint8_t ega_in(uint16_t addr, void *p) ega_t *ega = (ega_t *)p; if (addr != 0x3da && addr != 0x3ba) - pclog("ega_in %04X\n", addr); + // pclog("ega_in %04X\n", addr); if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -250,7 +250,7 @@ void ega_recalctimings(ega_t *ega) ega->rowoffset = ega->crtc[0x13]; - printf("Recalc! %i %i %i %i %i %02X\n", ega->vtotal, ega->dispend, ega->vsyncstart, ega->split, ega->hdisp, ega->attrregs[0x16]); + // printf("Recalc! %i %i %i %i %i %02X\n", ega->vtotal, ega->dispend, ega->vsyncstart, ega->split, ega->hdisp, ega->attrregs[0x16]); if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); @@ -258,7 +258,7 @@ void ega_recalctimings(ega_t *ega) disptime = ega->crtc[0] + 2; _dispontime = ega->crtc[1] + 1; - printf("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, ega->crtc[1] * 8); + // printf("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, ega->crtc[1] * 8); if (ega->seqregs[1] & 8) { disptime*=2; @@ -270,8 +270,8 @@ void ega_recalctimings(ega_t *ega) ega->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); - pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime / (1 << TIMER_SHIFT), - ega->dispofftime, (float)ega->dispofftime / (1 << TIMER_SHIFT)); + /* pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime / (1 << TIMER_SHIFT), + ega->dispofftime, (float)ega->dispofftime / (1 << TIMER_SHIFT)); */ // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]); diff --git a/src/vid_svga.c b/src/vid_svga.c index 77300bbe9..ad6a5411c 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -1710,7 +1710,10 @@ uint32_t svga_readl(uint32_t addr, void *p) if (!svga->enablevram) return 0xffffffff; if (!svga->fast) + { + if (addr == 0xBF0000) pclog ("%08X\n", svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24)); return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24); + } egareads += 4; diff --git a/src/win-hdconf.c b/src/win-hdconf.c index d42bd8e80..a5f241a3d 100644 --- a/src/win-hdconf.c +++ b/src/win-hdconf.c @@ -143,9 +143,9 @@ int hdconf_idok_common(HWND hdlg) MessageBox(ghwnd, "Drive has too many heads (maximum is 16)", "86Box error", MB_OK); return 1; } - if (hd_new_cyl > 16383) + if (hd_new_cyl > 266305) { - MessageBox(ghwnd, "Drive has too many cylinders (maximum is 16383)", "86Box error", MB_OK); + MessageBox(ghwnd, "Drive has too many cylinders (maximum is 266305)", "86Box error", MB_OK); return 1; } @@ -245,7 +245,9 @@ BOOL CALLBACK hdconf_common_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR FILE *f; uint8_t buf[512]; int is_hdi; + int is_hdx; uint64_t size; + uint64_t signature = 0xD778A82044445459; uint32_t zero = 0; uint32_t sector_size = 512; uint32_t base = 0x1000; @@ -307,7 +309,7 @@ BOOL CALLBACK hdconf_common_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR fwrite(&zero, 1, 4, f); /* 00000000: Zero/unknown */ fwrite(&zero, 1, 4, f); /* 00000004: Zero/unknown */ fwrite(&base, 1, 4, f); /* 00000008: Offset at which data starts */ - fwrite(&full_size_bytes, 1, 4, f); /* 0000000C: Full size of the data (32-bit) */ + fwrite(&full_size_bytes, 1, 8, f); /* 0000000C: Full size of the data (32-bit) */ fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ fwrite(&hd_new_spt, 1, 4, f); /* 00000014: Sectors per cylinder */ fwrite(&hd_new_hpc, 1, 4, f); /* 00000018: Heads per cylinder */ @@ -318,6 +320,26 @@ BOOL CALLBACK hdconf_common_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR fwrite(&zero, 1, 4, f); } } + else if (image_is_hdx(hd_new_name, 0)) + { + if (full_size_bytes > 0xffffffffffffffff) + { + MessageBox(ghwnd, "Drive is HDX and way too big (size filed in HDX header is 64-bit)", "86Box error", MB_OK); + fclose(f); + return TRUE; + } + + hd_new_hdi = 1; + + fwrite(&signature, 1, 8, f); /* 00000000: Signature */ + fwrite(&full_size_bytes, 1, 8, f); /* 00000008: Full size of the data (64-bit) */ + fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ + fwrite(&hd_new_spt, 1, 4, f); /* 00000014: Sectors per cylinder */ + fwrite(&hd_new_hpc, 1, 4, f); /* 00000018: Heads per cylinder */ + fwrite(&hd_new_cyl, 1, 4, f); /* 0000001C: Cylinders */ + fwrite(&zero, 1, 4, f); /* 00000020: [Translation] Sectors per cylinder */ + fwrite(&zero, 1, 4, f); /* 00000004: [Translation] Heads per cylinder */ + } memset(buf, 0, 512); for (c = 0; c < full_size; c++) fwrite(buf, 512, 1, f); @@ -336,7 +358,7 @@ BOOL CALLBACK hdconf_common_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR case IDC_CFILE: if (!type) { - if (!getsfile(hdlg, "Hard disc image (*.HDI;*.IMA;*.IMG)\0*.HDI;*.IMA;*.IMG\0All files (*.*)\0*.*\0", "")) + if (!getsfile(hdlg, "Hard disc image (*.HDI;*.HDX;*.IMA;*.IMG)\0*.HDI;*.HDX;*.IMA;*.IMG\0All files (*.*)\0*.*\0", "")) { h = GetDlgItem(hdlg, IDC_EDITC); SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); @@ -429,7 +451,7 @@ static void hdconf_file(HWND hdlg, int drive_num) uint32_t base = 0x1000; int ret; - if (!getfile(hdlg, "Hard disc image (*.HDI;*.IMA;*.IMG;*.VHD)\0*.HDI;*.IMA;*.IMG;*.VHD\0All files (*.*)\0*.*\0", "")) + if (!getfile(hdlg, "Hard disc image (*.HDI;*.HDX;*.IMA;*.IMG;*.VHD)\0*.HDI;*.HDX;*.IMA;*.IMG;*.VHD\0All files (*.*)\0*.*\0", "")) { f = fopen64(openfilestring, "rb"); if (!f) @@ -438,13 +460,13 @@ static void hdconf_file(HWND hdlg, int drive_num) return; } - if (image_is_hdi(openfilestring)) + if (image_is_hdi(openfilestring) || image_is_hdx(openfilestring, 1)) { fseeko64(f, 0x10, SEEK_SET); fread(§or_size, 1, 4, f); if (sector_size != 512) { - MessageBox(ghwnd,"HDI image with a sector size that is not 512","86Box error",MB_OK); + MessageBox(ghwnd,"HDI or HDX image with a sector size that is not 512","86Box error",MB_OK); fclose(f); return; }