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

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()