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.
This commit is contained in:
OBattler
2017-02-15 18:19:00 +01:00
parent de6f785029
commit 419b0b0c58
7 changed files with 232 additions and 26 deletions

View File

@@ -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;
}

View File

@@ -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

187
src/ide.c
View File

@@ -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(&sector_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(&sector_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()

View File

@@ -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);

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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(&sector_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(&sector_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(&sector_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;
}