Applied all relevant PCem commits;

Extensively cleaned up and changed the CD-ROM code;
Removed CD-ROM IOCTTL (it was causing performance and stability issues);
Turned a lot of things into device_t's;
Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem;
Numerous FDC fixes for the PS/1 Model 2121;
NVR changes ported from Varcem;
The PCap code no longer requires libpcap to be compiled;
Numerous fixes to various SCSI controllers;
Updated NukedOPL to 1.8;
Fixes to OpenAL initialization and closing, should give less Audio issues now;
Revorked parts of the common (S)VGA code (also based on code from QEMU);
Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there);
Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future);
In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit;
Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's);
Extensively reworked the IDE code and fixed quite a few bugs;
Fixes to XT MFM, AT MFM, and AT ESDI code;
Some changes to XTIDE and MCA ESDI code;
Some fixes to the CD-ROM image handler.
This commit is contained in:
OBattler
2018-04-25 23:51:13 +02:00
parent 2789adca0e
commit a412ceb4d9
151 changed files with 21026 additions and 21058 deletions

View File

@@ -8,7 +8,7 @@
*
* Handling of hard disk image files.
*
* Version: @(#)hdd_image.c 1.0.13 2018/03/19
* Version: @(#)hdd_image.c 1.0.14 2018/03/28
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -34,11 +34,11 @@
typedef struct
{
FILE *file;
uint32_t base;
uint32_t last_sector;
uint8_t type;
uint8_t loaded;
FILE *file;
uint32_t base;
uint32_t last_sector;
uint8_t type;
uint8_t loaded;
} hdd_image_t;
@@ -69,393 +69,442 @@ hdd_image_log(const char *fmt, ...)
}
int image_is_hdi(const wchar_t *s)
int
image_is_hdi(const wchar_t *s)
{
int len;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
char *ws = (char *) s;
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
return 0;
memcpy(ext, ws + ((len - 4) << 1), 8);
if (! wcscasecmp(ext, L".HDI"))
return 1;
else
return 0;
int len;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
char *ws = (char *) s;
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
return 0;
memcpy(ext, ws + ((len - 4) << 1), 8);
if (! wcscasecmp(ext, L".HDI"))
return 1;
else
return 0;
}
int
image_is_hdx(const wchar_t *s, int check_signature)
{
int len;
FILE *f;
uint64_t filelen;
uint64_t signature;
char *ws = (char *) s;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
return 0;
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcscasecmp(ext, L".HDX") == 0) {
if (check_signature) {
f = plat_fopen((wchar_t *)s, L"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 == 0xD778A82044445459ll)
return 1;
return 0;
}
return 1;
}
int len;
FILE *f;
uint64_t filelen;
uint64_t signature;
char *ws = (char *) s;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
return 0;
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcscasecmp(ext, L".HDX") == 0) {
if (check_signature) {
f = plat_fopen((wchar_t *)s, L"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 == 0xD778A82044445459ll)
return 1;
else
return 0;
} else
return 1;
} else
return 0;
}
int hdd_image_load(int id)
static int
prepare_new_hard_disk(uint8_t id, uint64_t full_size)
{
uint32_t sector_size = 512;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdd[id].fn;
int is_hdx[2] = { 0, 0 };
uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
memset(empty_sector, 0, sizeof(empty_sector));
uint32_t size;
uint32_t t, i;
hdd_images[id].base = 0;
t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */
size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */
if (hdd_images[id].loaded) {
if (hdd_images[id].file) {
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].loaded = 0;
empty_sector_1mb = (char *) malloc(1048576);
memset(empty_sector_1mb, 0, 1048576);
/* Temporarily switch off suppression of seen messages so that the
progress gets displayed. */
pclog_toggle_suppr();
pclog("Writing image sectors: [");
/* First, write all the 1 MB blocks. */
if (t > 0) {
for (i = 0; i < t; i++) {
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
pclog("#");
}
}
is_hdx[0] = image_is_hdx(fn, 0);
is_hdx[1] = image_is_hdx(fn, 1);
/* Then, write the remainder. */
fwrite(empty_sector_1mb, 1, size, hdd_images[id].file);
pclog("#]\n");
/* Switch the suppression of seen messages back on. */
pclog_toggle_suppr();
/* Try to open existing hard disk image */
if (fn[0] == '.') {
hdd_image_log("File name starts with .\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
free(empty_sector_1mb);
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
hdd_images[id].loaded = 1;
return 1;
}
void
hdd_image_init(void)
{
int i;
for (i = 0; i < HDD_NUM; i++)
memset(&hdd_images[i], 0, sizeof(hdd_image_t));
}
int
hdd_image_load(int id)
{
uint32_t sector_size = 512;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t s = 0;
wchar_t *fn = hdd[id].fn;
int is_hdx[2] = { 0, 0 };
memset(empty_sector, 0, sizeof(empty_sector));
hdd_images[id].base = 0;
if (hdd_images[id].loaded) {
if (hdd_images[id].file) {
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].file = plat_fopen(fn, L"rb+");
if (hdd_images[id].file == NULL) {
/* Failed to open existing hard disk image */
if (errno == ENOENT) {
/* Failed because it does not exist,
so try to create new file */
if (hdd[id].wp) {
hdd_image_log("A write-protected image must exist\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].loaded = 0;
}
hdd_images[id].file = plat_fopen(fn, L"wb+");
if (hdd_images[id].file == NULL) {
hdd_image_log("Unable to open image\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
} else {
if (image_is_hdi(fn)) {
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].base = 0x1000;
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fwrite(&full_size, 1, 4, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
for (c = 0; c < 0x3f8; c++)
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 1;
} else if (is_hdx[0]) {
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].base = 0x28;
fwrite(&signature, 1, 8, hdd_images[id].file);
fwrite(&full_size, 1, 8, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
}
else
hdd_images[id].type = 0;
hdd_images[id].last_sector = 0;
}
is_hdx[0] = image_is_hdx(fn, 0);
is_hdx[1] = image_is_hdx(fn, 1);
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
goto prepare_new_hard_disk;
} else {
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
/* Try to open existing hard disk image */
if (fn[0] == '.') {
hdd_image_log("File name starts with .\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].file = plat_fopen(fn, L"rb+");
if (hdd_images[id].file == NULL) {
/* Failed to open existing hard disk image */
if (errno == ENOENT) {
/* Failed because it does not exist,
so try to create new file */
if (hdd[id].wp) {
hdd_image_log("A write-protected image must exist\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
} else {
if (image_is_hdi(fn)) {
fseeko64(hdd_images[id].file, 0x8, SEEK_SET);
fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512) {
/* Sector size is not 512 */
hdd_image_log("HDI: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
hdd_image_log("HDI: Geometry mismatch\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
hdd_images[id].type = 1;
}
else if (is_hdx[1]) {
hdd_images[id].base = 0x28;
fseeko64(hdd_images[id].file, 8, SEEK_SET);
fread(&full_size, 1, 8, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512) {
/* Sector size is not 512 */
hdd_image_log("HDX: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
hdd_image_log("HDX: Geometry mismatch\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
hdd_images[id].file = plat_fopen(fn, L"wb+");
if (hdd_images[id].file == NULL) {
hdd_image_log("Unable to open image\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
} else {
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].type = 0;
}
}
fseeko64(hdd_images[id].file, 0, SEEK_END);
if (ftello64(hdd_images[id].file) < (full_size + hdd_images[id].base)) {
s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
prepare_new_hard_disk:
t = s >> 20; /* Amount of 1 MB blocks. */
s &= 0xfffff; /* 1 MB mask. */
empty_sector_1mb = (char *) malloc(1048576);
memset(empty_sector_1mb, 0, 1048576);
/* Temporarily switch off suppression of seen messages so that the
progress gets displayed. */
pclog_toggle_suppr();
pclog("Writing image sectors: [");
/* First, write all the 1 MB blocks. */
if (t > 0) {
for (i = 0; i < t; i++) {
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
pclog("#");
if (image_is_hdi(fn)) {
full_size = ((uint64_t) hdd[id].spt) *
((uint64_t) hdd[id].hpc) *
((uint64_t) hdd[id].tracks) << 9LL;
hdd_images[id].base = 0x1000;
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fwrite(&full_size, 1, 4, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
for (c = 0; c < 0x3f8; c++)
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 1;
} else if (is_hdx[0]) {
full_size = ((uint64_t) hdd[id].spt) *
((uint64_t) hdd[id].hpc) *
((uint64_t) hdd[id].tracks) << 9LL;
hdd_images[id].base = 0x28;
fwrite(&signature, 1, 8, hdd_images[id].file);
fwrite(&full_size, 1, 8, hdd_images[id].file);
fwrite(&sector_size, 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
}
else
hdd_images[id].type = 0;
hdd_images[id].last_sector = 0;
}
/* Then, write the remainder. */
fwrite(empty_sector_1mb, 1, s, hdd_images[id].file);
pclog("#]\n");
pclog_toggle_suppr();
s = full_size = ((uint64_t) hdd[id].spt) *
((uint64_t) hdd[id].hpc) *
((uint64_t) hdd[id].tracks) << 9LL;
free(empty_sector_1mb);
return prepare_new_hard_disk(id, full_size);
} else {
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
hdd_images[id].loaded = 1;
return 1;
}
void hdd_image_seek(uint8_t id, uint32_t sector)
{
off64_t addr = sector;
addr = (uint64_t)sector * 512;
fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET);
}
void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
fread(buffer, 1, count * 512, hdd_images[id].file);
}
uint32_t hdd_sectors(uint8_t id)
{
fseeko64(hdd_images[id].file, 0, SEEK_END);
return (uint32_t) (ftello64(hdd_images[id].file) >> 9);
}
int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
fread(buffer, 1, transfer_sectors * 512, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
fwrite(buffer, count * 512, 1, hdd_images[id].file);
}
int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
fwrite(buffer, transfer_sectors * 512, 1, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
{
int i = 0;
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
for (i = 0; i < count; i++)
fwrite(empty_sector, 512, 1, hdd_images[id].file);
}
int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
{
int i = 0;
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
for (i = 0; i < transfer_sectors; i++)
fwrite(empty_sector, 1, 512, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
uint32_t hdd_image_get_last_sector(uint8_t id)
{
return hdd_images[id].last_sector;
}
uint8_t hdd_image_get_type(uint8_t id)
{
return hdd_images[id].type;
}
void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
{
if (hdd_images[id].type == 2)
{
hdd[id].at_hpc = hpc;
hdd[id].at_spt = spt;
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
}
}
void hdd_image_unload(uint8_t id, int fn_preserve)
{
if (wcslen(hdd[id].fn) == 0)
return;
if (hdd_images[id].loaded) {
if (hdd_images[id].file != NULL) {
} else {
if (image_is_hdi(fn)) {
fseeko64(hdd_images[id].file, 0x8, SEEK_SET);
fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0xC, SEEK_SET);
full_size = 0LL;
fread(&full_size, 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512) {
/* Sector size is not 512 */
hdd_image_log("HDI: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].loaded = 0;
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
hdd_images[id].type = 1;
} else if (is_hdx[1]) {
hdd_images[id].base = 0x28;
fseeko64(hdd_images[id].file, 8, SEEK_SET);
fread(&full_size, 1, 8, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512) {
/* Sector size is not 512 */
hdd_image_log("HDX: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
fread(&spt, 1, 4, hdd_images[id].file);
fread(&hpc, 1, 4, hdd_images[id].file);
fread(&tracks, 1, 4, hdd_images[id].file);
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
} else {
full_size = ((uint64_t) hdd[id].spt) *
((uint64_t) hdd[id].hpc) *
((uint64_t) hdd[id].tracks) << 9LL;
hdd_images[id].type = 0;
}
}
hdd_images[id].last_sector = -1;
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
if (fn_preserve)
wcscpy(hdd[id].prev_fn, hdd[id].fn);
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
fseeko64(hdd_images[id].file, 0, SEEK_END);
s = ftello64(hdd_images[id].file);
if (s < (full_size + hdd_images[id].base))
return prepare_new_hard_disk(id, full_size);
else {
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
hdd_images[id].loaded = 1;
return 1;
}
}
void hdd_image_close(uint8_t id)
void
hdd_image_seek(uint8_t id, uint32_t sector)
{
off64_t addr = sector;
addr = (uint64_t)sector * 512;
fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET);
}
void
hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
fread(buffer, 1, count << 9, hdd_images[id].file);
}
uint32_t
hdd_sectors(uint8_t id)
{
fseeko64(hdd_images[id].file, 0, SEEK_END);
return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9);
}
int
hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
void
hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
fwrite(buffer, count << 9, 1, hdd_images[id].file);
}
int
hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
fwrite(buffer, transfer_sectors << 9, 1, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
void
hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
{
uint32_t i = 0;
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
for (i = 0; i < count; i++)
fwrite(empty_sector, 512, 1, hdd_images[id].file);
}
int
hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
{
uint32_t i = 0;
uint32_t transfer_sectors = count;
uint32_t sectors = hdd_sectors(id);
if ((sectors - sector) < transfer_sectors)
transfer_sectors = sectors - sector;
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
for (i = 0; i < transfer_sectors; i++)
fwrite(empty_sector, 1, 512, hdd_images[id].file);
if (count != transfer_sectors)
return 1;
return 0;
}
uint32_t
hdd_image_get_last_sector(uint8_t id)
{
return hdd_images[id].last_sector;
}
uint8_t
hdd_image_get_type(uint8_t id)
{
return hdd_images[id].type;
}
void
hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
{
if (hdd_images[id].type == 2) {
hdd[id].at_hpc = hpc;
hdd[id].at_spt = spt;
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
}
}
void
hdd_image_unload(uint8_t id, int fn_preserve)
{
if (wcslen(hdd[id].fn) == 0)
return;
if (hdd_images[id].loaded) {
if (hdd_images[id].file != NULL) {
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
hdd_images[id].loaded = 0;
}
hdd_images[id].last_sector = -1;
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
if (fn_preserve)
wcscpy(hdd[id].prev_fn, hdd[id].fn);
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
}
void
hdd_image_close(uint8_t id)
{
hdd_image_log("hdd_image_close(%i)\n", id);
if (!hdd_images[id].loaded)
return;
if (hdd_images[id].file != NULL) {
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
memset(&hdd_images[id], 0, sizeof(hdd_image_t));
hdd_images[id].loaded = 0;
}