2017-10-01 16:29:15 -04:00
|
|
|
/*
|
|
|
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
|
|
|
* running old operating systems and software designed for IBM
|
|
|
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
|
|
|
* system designs based on the PCI bus.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the 86Box distribution.
|
|
|
|
|
*
|
|
|
|
|
* Handling of hard disk image files.
|
|
|
|
|
*
|
2018-03-19 09:48:44 +01:00
|
|
|
* Version: @(#)hdd_image.c 1.0.13 2018/03/19
|
2017-10-01 16:29:15 -04:00
|
|
|
*
|
2018-01-24 20:58:39 +01:00
|
|
|
* Authors: Miran Grca, <mgrca8@gmail.com>
|
2017-10-01 16:29:15 -04:00
|
|
|
* Fred N. van Kempen, <decwiz@yahoo.com>
|
2017-10-12 14:25:17 -04:00
|
|
|
*
|
2018-01-24 20:58:39 +01:00
|
|
|
* Copyright 2016-2018 Miran Grca.
|
|
|
|
|
* Copyright 2017,2018 Fred N. van Kempen.
|
2017-10-01 16:29:15 -04:00
|
|
|
*/
|
2017-06-16 03:18:59 +02:00
|
|
|
#define _LARGEFILE_SOURCE
|
|
|
|
|
#define _LARGEFILE64_SOURCE
|
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdint.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <wchar.h>
|
|
|
|
|
#include <errno.h>
|
2017-12-10 02:53:10 -05:00
|
|
|
#define HAVE_STDARG_H
|
2017-10-17 01:59:09 -04:00
|
|
|
#include "../86box.h"
|
2017-10-12 14:25:17 -04:00
|
|
|
#include "../plat.h"
|
2017-09-30 16:56:38 -04:00
|
|
|
#include "hdd.h"
|
2017-09-25 04:31:20 -04:00
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
FILE *file;
|
|
|
|
|
uint32_t base;
|
|
|
|
|
uint32_t last_sector;
|
|
|
|
|
uint8_t type;
|
|
|
|
|
uint8_t loaded;
|
|
|
|
|
} hdd_image_t;
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
|
|
|
|
hdd_image_t hdd_images[HDD_NUM];
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
static char empty_sector[512];
|
|
|
|
|
static char *empty_sector_1mb;
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2017-10-19 21:08:34 -04:00
|
|
|
#ifdef ENABLE_HDD_LOG
|
|
|
|
|
int hdd_image_do_log = ENABLE_HDD_LOG;
|
|
|
|
|
#endif
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
|
|
|
|
static void
|
2017-12-10 02:53:10 -05:00
|
|
|
hdd_image_log(const char *fmt, ...)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2017-10-19 21:08:34 -04:00
|
|
|
#ifdef ENABLE_HDD_LOG
|
2017-12-05 23:35:35 +01:00
|
|
|
va_list ap;
|
|
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
if (hdd_image_do_log)
|
|
|
|
|
{
|
2017-12-10 02:53:10 -05:00
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
2017-06-16 03:18:59 +02:00
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
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);
|
2017-10-12 14:25:17 -04:00
|
|
|
if (! wcscasecmp(ext, L".HDI"))
|
2017-06-16 03:18:59 +02:00
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
image_is_hdx(const wchar_t *s, int check_signature)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
|
|
|
|
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);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (wcscasecmp(ext, L".HDX") == 0) {
|
|
|
|
|
if (check_signature) {
|
2017-10-12 14:25:17 -04:00
|
|
|
f = plat_fopen((wchar_t *)s, L"rb");
|
2017-06-16 03:18:59 +02:00
|
|
|
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;
|
2018-02-07 19:01:39 +01:00
|
|
|
return 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-02-07 19:01:39 +01:00
|
|
|
return 1;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-02-07 19:01:39 +01:00
|
|
|
return 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
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 i = 0, s = 0, t = 0;
|
2017-09-30 16:56:38 -04:00
|
|
|
wchar_t *fn = hdd[id].fn;
|
2017-06-22 18:24:17 +02:00
|
|
|
int is_hdx[2] = { 0, 0 };
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
memset(empty_sector, 0, sizeof(empty_sector));
|
|
|
|
|
|
|
|
|
|
hdd_images[id].base = 0;
|
|
|
|
|
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd_images[id].loaded) {
|
|
|
|
|
if (hdd_images[id].file) {
|
2017-10-01 20:55:41 +02:00
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
|
|
|
|
}
|
2017-06-22 18:24:17 +02:00
|
|
|
hdd_images[id].loaded = 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-22 18:24:17 +02:00
|
|
|
is_hdx[0] = image_is_hdx(fn, 0);
|
|
|
|
|
is_hdx[1] = image_is_hdx(fn, 1);
|
|
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
/* Try to open existing hard disk image */
|
2018-02-07 19:01:39 +01:00
|
|
|
if (fn[0] == '.') {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_image_log("File name starts with .\n");
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
2017-10-12 14:25:17 -04:00
|
|
|
hdd_images[id].file = plat_fopen(fn, L"rb+");
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd_images[id].file == NULL) {
|
2017-06-16 03:18:59 +02:00
|
|
|
/* Failed to open existing hard disk image */
|
2018-02-07 19:01:39 +01:00
|
|
|
if (errno == ENOENT) {
|
2017-06-16 03:18:59 +02:00
|
|
|
/* Failed because it does not exist,
|
|
|
|
|
so try to create new file */
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd[id].wp) {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_image_log("A write-protected image must exist\n");
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-12 14:25:17 -04:00
|
|
|
hdd_images[id].file = plat_fopen(fn, L"wb+");
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd_images[id].file == NULL) {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_image_log("Unable to open image\n");
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
2018-02-07 19:01:39 +01:00
|
|
|
} else {
|
|
|
|
|
if (image_is_hdi(fn)) {
|
2017-09-30 16:56:38 -04:00
|
|
|
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
2017-06-16 03:18:59 +02:00
|
|
|
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(§or_size, 1, 4, hdd_images[id].file);
|
2017-09-30 16:56:38 -04:00
|
|
|
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);
|
2017-06-16 03:18:59 +02:00
|
|
|
for (c = 0; c < 0x3f8; c++)
|
|
|
|
|
fwrite(&zero, 1, 4, hdd_images[id].file);
|
|
|
|
|
hdd_images[id].type = 1;
|
2018-02-07 19:01:39 +01:00
|
|
|
} else if (is_hdx[0]) {
|
2017-09-30 16:56:38 -04:00
|
|
|
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_images[id].base = 0x28;
|
|
|
|
|
fwrite(&signature, 1, 8, hdd_images[id].file);
|
|
|
|
|
fwrite(&full_size, 1, 8, hdd_images[id].file);
|
|
|
|
|
fwrite(§or_size, 1, 4, hdd_images[id].file);
|
2017-09-30 16:56:38 -04:00
|
|
|
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);
|
2017-06-16 03:18:59 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
goto prepare_new_hard_disk;
|
2018-02-07 19:01:39 +01:00
|
|
|
} else {
|
2017-06-16 03:18:59 +02:00
|
|
|
/* Failed for another reason */
|
|
|
|
|
hdd_image_log("Failed for another reason\n");
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
2018-02-07 19:01:39 +01:00
|
|
|
} else {
|
|
|
|
|
if (image_is_hdi(fn)) {
|
2017-06-16 03:18:59 +02:00
|
|
|
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(§or_size, 1, 4, hdd_images[id].file);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (sector_size != 512) {
|
2017-06-16 03:18:59 +02:00
|
|
|
/* 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;
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
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);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
|
|
|
|
|
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_image_log("HDI: Geometry mismatch\n");
|
|
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd[id].spt = spt;
|
|
|
|
|
hdd[id].hpc = hpc;
|
|
|
|
|
hdd[id].tracks = tracks;
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_images[id].type = 1;
|
|
|
|
|
}
|
2018-02-07 19:01:39 +01:00
|
|
|
else if (is_hdx[1]) {
|
2017-06-16 03:18:59 +02:00
|
|
|
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(§or_size, 1, 4, hdd_images[id].file);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (sector_size != 512) {
|
2017-06-16 03:18:59 +02:00
|
|
|
/* 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;
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
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);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
|
|
|
|
|
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_image_log("HDX: Geometry mismatch\n");
|
|
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
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);
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_images[id].type = 2;
|
2018-02-07 19:01:39 +01:00
|
|
|
} else {
|
2017-09-30 16:56:38 -04:00
|
|
|
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_images[id].type = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
2018-02-07 19:01:39 +01:00
|
|
|
if (ftello64(hdd_images[id].file) < (full_size + hdd_images[id].base)) {
|
2017-06-16 03:18:59 +02:00
|
|
|
s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
|
|
|
|
|
prepare_new_hard_disk:
|
2018-03-19 09:48:44 +01:00
|
|
|
t = s >> 20; /* Amount of 1 MB blocks. */
|
|
|
|
|
s &= 0xfffff; /* 1 MB mask. */
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
empty_sector_1mb = (char *) malloc(1048576);
|
|
|
|
|
memset(empty_sector_1mb, 0, 1048576);
|
|
|
|
|
|
2018-03-19 09:48:44 +01:00
|
|
|
/* Temporarily switch off suppression of seen messages so that the
|
|
|
|
|
progress gets displayed. */
|
|
|
|
|
pclog_toggle_suppr();
|
2018-01-24 20:58:39 +01:00
|
|
|
pclog("Writing image sectors: [");
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-03-19 09:48:44 +01:00
|
|
|
/* First, write all the 1 MB blocks. */
|
2018-02-07 19:01:39 +01:00
|
|
|
if (t > 0) {
|
|
|
|
|
for (i = 0; i < t; i++) {
|
2017-06-16 03:18:59 +02:00
|
|
|
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
|
2018-03-19 09:48:44 +01:00
|
|
|
pclog("#");
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-03-19 09:48:44 +01:00
|
|
|
|
|
|
|
|
/* Then, write the remainder. */
|
|
|
|
|
fwrite(empty_sector_1mb, 1, s, hdd_images[id].file);
|
|
|
|
|
pclog("#]\n");
|
|
|
|
|
pclog_toggle_suppr();
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
free(empty_sector_1mb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_images[id].loaded = 1;
|
2017-10-01 16:29:15 -04:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
return 1;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hdd_image_seek(uint8_t id, uint32_t sector)
|
|
|
|
|
{
|
2018-02-07 19:01:39 +01:00
|
|
|
off64_t addr = sector;
|
|
|
|
|
addr = (uint64_t)sector * 512;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-02-07 19:01:39 +01:00
|
|
|
fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET);
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
|
|
|
|
{
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2018-02-07 19:01:39 +01:00
|
|
|
fread(buffer, 1, count * 512, hdd_images[id].file);
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-07-15 12:46:44 +02:00
|
|
|
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;
|
|
|
|
|
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2018-02-07 19:01:39 +01:00
|
|
|
fread(buffer, 1, transfer_sectors * 512, hdd_images[id].file);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
|
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
|
|
|
|
{
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2018-02-07 19:01:39 +01:00
|
|
|
fwrite(buffer, count * 512, 1, hdd_images[id].file);
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-07-15 12:46:44 +02:00
|
|
|
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;
|
|
|
|
|
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2018-02-07 19:01:39 +01:00
|
|
|
fwrite(buffer, transfer_sectors * 512, 1, hdd_images[id].file);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
|
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2017-06-16 03:18:59 +02:00
|
|
|
for (i = 0; i < count; i++)
|
2018-02-07 19:01:39 +01:00
|
|
|
fwrite(empty_sector, 512, 1, hdd_images[id].file);
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-07-15 12:46:44 +02:00
|
|
|
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;
|
|
|
|
|
|
2018-02-11 20:51:42 +01:00
|
|
|
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
2017-07-15 12:46:44 +02:00
|
|
|
for (i = 0; i < transfer_sectors; i++)
|
2018-02-07 19:01:39 +01:00
|
|
|
fwrite(empty_sector, 1, 512, hdd_images[id].file);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
|
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
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)
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd[id].at_hpc = hpc;
|
|
|
|
|
hdd[id].at_spt = spt;
|
2017-06-16 03:18:59 +02:00
|
|
|
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
|
2017-09-30 16:56:38 -04:00
|
|
|
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
|
|
|
|
|
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hdd_image_unload(uint8_t id, int fn_preserve)
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
if (wcslen(hdd[id].fn) == 0)
|
2017-06-16 03:18:59 +02:00
|
|
|
return;
|
|
|
|
|
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd_images[id].loaded) {
|
|
|
|
|
if (hdd_images[id].file != NULL) {
|
2017-06-16 03:18:59 +02:00
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
|
|
|
|
}
|
2017-10-01 16:29:15 -04:00
|
|
|
hdd_images[id].loaded = 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hdd_images[id].last_sector = -1;
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
if (fn_preserve)
|
2017-09-30 16:56:38 -04:00
|
|
|
wcscpy(hdd[id].prev_fn, hdd[id].fn);
|
|
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hdd_image_close(uint8_t id)
|
|
|
|
|
{
|
2018-02-07 19:01:39 +01:00
|
|
|
if (hdd_images[id].file != NULL) {
|
2017-06-16 03:18:59 +02:00
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
|
|
|
|
}
|
2017-10-01 16:29:15 -04:00
|
|
|
hdd_images[id].loaded = 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|