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.
|
|
|
|
|
*
|
2020-03-25 00:46:02 +02:00
|
|
|
*
|
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
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdarg.h>
|
2017-06-16 03:18:59 +02:00
|
|
|
#include <stdint.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdio.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
2020-04-04 12:45:47 +02:00
|
|
|
#include <time.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <wchar.h>
|
|
|
|
|
#include <errno.h>
|
2017-12-10 02:53:10 -05:00
|
|
|
#define HAVE_STDARG_H
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/86box.h>
|
|
|
|
|
#include <86box/plat.h>
|
|
|
|
|
#include <86box/random.h>
|
|
|
|
|
#include <86box/hdd.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
|
2017-06-16 03:18:59 +02:00
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
FILE *file;
|
|
|
|
|
uint32_t base;
|
2018-05-21 19:04:05 +02:00
|
|
|
uint32_t pos, last_sector;
|
2018-04-25 23:51:13 +02:00
|
|
|
uint8_t type;
|
2018-05-21 19:04:05 +02:00
|
|
|
uint8_t loaded;
|
2017-06-16 03:18:59 +02:00
|
|
|
} 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
|
|
|
|
2018-07-15 01:41:53 +02:00
|
|
|
#define VHD_OFFSET_COOKIE 0
|
|
|
|
|
#define VHD_OFFSET_FEATURES 8
|
|
|
|
|
#define VHD_OFFSET_VERSION 12
|
|
|
|
|
#define VHD_OFFSET_DATA_OFFSET 16
|
|
|
|
|
#define VHD_OFFSET_TIMESTAMP 24
|
|
|
|
|
#define VHD_OFFSET_CREATOR 28
|
|
|
|
|
#define VHD_OFFSET_CREATOR_VERS 32
|
|
|
|
|
#define VHD_OFFSET_CREATOR_HOST 36
|
|
|
|
|
#define VHD_OFFSET_ORIG_SIZE 40
|
|
|
|
|
#define VHD_OFFSET_CURR_SIZE 48
|
|
|
|
|
#define VHD_OFFSET_GEOM_CYL 56
|
|
|
|
|
#define VHD_OFFSET_GEOM_HEAD 58
|
|
|
|
|
#define VHD_OFFSET_GEOM_SPT 59
|
|
|
|
|
#define VHD_OFFSET_TYPE 60
|
|
|
|
|
#define VHD_OFFSET_CHECKSUM 64
|
|
|
|
|
#define VHD_OFFSET_UUID 68
|
|
|
|
|
#define VHD_OFFSET_SAVED_STATE 84
|
|
|
|
|
#define VHD_OFFSET_RESERVED 85
|
|
|
|
|
|
|
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
#ifdef ENABLE_HDD_IMAGE_LOG
|
|
|
|
|
int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG;
|
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
|
|
|
{
|
2018-05-21 19:04:05 +02:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
if (hdd_image_do_log) {
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-10-19 00:39:32 +02:00
|
|
|
#else
|
|
|
|
|
#define hdd_image_log(fmt, ...)
|
|
|
|
|
#endif
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
int
|
|
|
|
|
image_is_hdi(const wchar_t *s)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
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;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2018-04-25 23:51:13 +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);
|
|
|
|
|
if (wcscasecmp(ext, L".HDX") == 0) {
|
|
|
|
|
if (check_signature) {
|
|
|
|
|
f = plat_fopen((wchar_t *)s, L"rb");
|
|
|
|
|
if (!f)
|
2018-02-07 19:01:39 +01:00
|
|
|
return 0;
|
2020-01-15 18:48:22 +01:00
|
|
|
if (fseeko64(f, 0, SEEK_END))
|
|
|
|
|
fatal("image_is_hdx(): Error while seeking");
|
2018-04-25 23:51:13 +02:00
|
|
|
filelen = ftello64(f);
|
2020-01-15 18:48:22 +01:00
|
|
|
if (fseeko64(f, 0, SEEK_SET))
|
|
|
|
|
fatal("image_is_hdx(): Error while seeking");
|
2020-01-14 23:08:13 +01:00
|
|
|
if (filelen < 44) {
|
|
|
|
|
if (f != NULL)
|
|
|
|
|
fclose(f);
|
2018-04-25 23:51:13 +02:00
|
|
|
return 0;
|
2020-01-14 23:08:13 +01:00
|
|
|
}
|
2020-01-15 04:58:28 +01:00
|
|
|
if (fread(&signature, 1, 8, f) != 8)
|
|
|
|
|
fatal("image_is_hdx(): Error reading signature\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
fclose(f);
|
|
|
|
|
if (signature == 0xD778A82044445459ll)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
} else
|
2018-02-07 19:01:39 +01:00
|
|
|
return 1;
|
2018-04-25 23:51:13 +02:00
|
|
|
} else
|
|
|
|
|
return 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2018-07-15 01:41:53 +02:00
|
|
|
int
|
|
|
|
|
image_is_vhd(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".VHD") == 0) {
|
|
|
|
|
if (check_signature) {
|
|
|
|
|
f = plat_fopen((wchar_t *)s, L"rb");
|
|
|
|
|
if (!f)
|
|
|
|
|
return 0;
|
|
|
|
|
fseeko64(f, 0, SEEK_END);
|
|
|
|
|
filelen = ftello64(f);
|
2020-01-15 03:04:59 +01:00
|
|
|
if (fseeko64(f, -512, SEEK_END) == -1) {
|
|
|
|
|
fclose(f);
|
|
|
|
|
fatal("image_is_vhd(): Error seeking\n");
|
|
|
|
|
}
|
2020-01-15 00:45:15 +01:00
|
|
|
if (filelen < 512) {
|
|
|
|
|
if (f != NULL)
|
|
|
|
|
fclose(f);
|
2018-07-15 01:41:53 +02:00
|
|
|
return 0;
|
2020-01-15 00:45:15 +01:00
|
|
|
}
|
2020-01-15 04:58:28 +01:00
|
|
|
if (fread(&signature, 1, 8, f) != 8)
|
|
|
|
|
fatal("image_is_vhd(): Error reading signature\n");
|
2018-07-15 01:41:53 +02:00
|
|
|
fclose(f);
|
|
|
|
|
if (signature == 0x78697463656E6F63ll)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
} else
|
|
|
|
|
return 1;
|
|
|
|
|
} else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint64_t
|
|
|
|
|
be_to_u64(uint8_t *bytes, int start)
|
|
|
|
|
{
|
2018-10-30 13:32:25 +01:00
|
|
|
uint64_t n = ((uint64_t) bytes[start + 7] << 0) |
|
|
|
|
|
((uint64_t) bytes[start + 6] << 8) |
|
|
|
|
|
((uint64_t) bytes[start + 5] << 16) |
|
|
|
|
|
((uint64_t) bytes[start + 4] << 24) |
|
|
|
|
|
((uint64_t) bytes[start + 3] << 32) |
|
|
|
|
|
((uint64_t) bytes[start + 2] << 40) |
|
|
|
|
|
((uint64_t) bytes[start + 1] << 48) |
|
|
|
|
|
((uint64_t) bytes[start ] << 56);
|
2018-07-15 01:41:53 +02:00
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
be_to_u32(uint8_t *bytes, int start)
|
|
|
|
|
{
|
2018-10-30 13:32:25 +01:00
|
|
|
uint32_t n = ((uint32_t) bytes[start + 3] << 0) |
|
|
|
|
|
((uint32_t) bytes[start + 2] << 8) |
|
|
|
|
|
((uint32_t) bytes[start + 1] << 16) |
|
|
|
|
|
((uint32_t) bytes[start ] << 24);
|
2018-07-15 01:41:53 +02:00
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint16_t
|
|
|
|
|
be_to_u16(uint8_t *bytes, int start)
|
|
|
|
|
{
|
2018-10-30 13:32:25 +01:00
|
|
|
uint16_t n = ((uint16_t) bytes[start + 1] << 0) |
|
|
|
|
|
((uint16_t) bytes[start ] << 8);
|
2018-07-15 01:41:53 +02:00
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint64_t
|
|
|
|
|
u64_to_be(uint64_t value, int is_be)
|
|
|
|
|
{
|
|
|
|
|
uint64_t res = 0;
|
|
|
|
|
if (is_be)
|
|
|
|
|
res = value;
|
|
|
|
|
else {
|
|
|
|
|
uint64_t mask = 0xff00000000000000;
|
2018-10-30 13:32:25 +01:00
|
|
|
res = ((value & (mask >> 0)) >> 56) |
|
|
|
|
|
((value & (mask >> 8)) >> 40) |
|
2018-07-15 01:41:53 +02:00
|
|
|
((value & (mask >> 16)) >> 24) |
|
2018-10-30 13:32:25 +01:00
|
|
|
((value & (mask >> 24)) >> 8) |
|
|
|
|
|
((value & (mask >> 32)) << 8) |
|
2018-07-15 01:41:53 +02:00
|
|
|
((value & (mask >> 40)) << 24) |
|
|
|
|
|
((value & (mask >> 48)) << 40) |
|
|
|
|
|
((value & (mask >> 56)) << 56);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
u32_to_be(uint32_t value, int is_be)
|
|
|
|
|
{
|
|
|
|
|
uint32_t res = 0;
|
|
|
|
|
if (is_be)
|
|
|
|
|
res = value;
|
|
|
|
|
else {
|
|
|
|
|
uint32_t mask = 0xff000000;
|
2018-10-30 13:32:25 +01:00
|
|
|
res = ((value & (mask >> 0)) >> 24) |
|
|
|
|
|
((value & (mask >> 8)) >> 8) |
|
|
|
|
|
((value & (mask >> 16)) << 8) |
|
2018-07-15 01:41:53 +02:00
|
|
|
((value & (mask >> 24)) << 24);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint16_t
|
|
|
|
|
u16_to_be(uint16_t value, int is_be)
|
|
|
|
|
{
|
|
|
|
|
uint16_t res = 0;
|
|
|
|
|
if (is_be)
|
|
|
|
|
res = value;
|
|
|
|
|
else
|
|
|
|
|
res = (value >> 8) | (value << 8);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mk_guid(uint8_t *guid)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < 16; n++)
|
|
|
|
|
guid[n] = random_generate();
|
|
|
|
|
|
|
|
|
|
guid[6] &= 0x0F;
|
|
|
|
|
guid[6] |= 0x40; /* Type 4 */
|
|
|
|
|
guid[8] &= 0x3F;
|
|
|
|
|
guid[8] |= 0x80; /* Variant 1 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
calc_vhd_timestamp()
|
|
|
|
|
{
|
|
|
|
|
time_t start_time;
|
|
|
|
|
time_t curr_time;
|
|
|
|
|
double vhd_time;
|
2018-10-30 13:32:25 +01:00
|
|
|
start_time = 946684800; /* 1 Jan 2000 00:00 */
|
2018-07-15 01:41:53 +02:00
|
|
|
curr_time = time(NULL);
|
|
|
|
|
vhd_time = difftime(curr_time, start_time);
|
|
|
|
|
|
|
|
|
|
return (uint32_t)vhd_time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes)
|
|
|
|
|
{
|
|
|
|
|
memcpy(vhd->cookie, bytes + VHD_OFFSET_COOKIE, sizeof(vhd->cookie));
|
|
|
|
|
vhd->features = be_to_u32(bytes, VHD_OFFSET_FEATURES);
|
|
|
|
|
vhd->version = be_to_u32(bytes, VHD_OFFSET_VERSION);
|
|
|
|
|
vhd->offset = be_to_u64(bytes, VHD_OFFSET_DATA_OFFSET);
|
|
|
|
|
vhd->timestamp = be_to_u32(bytes, VHD_OFFSET_TIMESTAMP);
|
|
|
|
|
memcpy(vhd->creator, bytes + VHD_OFFSET_CREATOR, sizeof(vhd->creator));
|
|
|
|
|
vhd->creator_vers = be_to_u32(bytes, VHD_OFFSET_CREATOR_VERS);
|
|
|
|
|
memcpy(vhd->creator_host_os, bytes + VHD_OFFSET_CREATOR_HOST, sizeof(vhd->creator_host_os));
|
|
|
|
|
vhd->orig_size = be_to_u64(bytes, VHD_OFFSET_ORIG_SIZE);
|
|
|
|
|
vhd->curr_size = be_to_u64(bytes, VHD_OFFSET_CURR_SIZE);
|
|
|
|
|
vhd->geom.cyl = be_to_u16(bytes, VHD_OFFSET_GEOM_CYL);
|
|
|
|
|
vhd->geom.heads = bytes[VHD_OFFSET_GEOM_HEAD];
|
|
|
|
|
vhd->geom.spt = bytes[VHD_OFFSET_GEOM_SPT];
|
|
|
|
|
vhd->type = be_to_u32(bytes, VHD_OFFSET_TYPE);
|
|
|
|
|
vhd->checksum = be_to_u32(bytes, VHD_OFFSET_CHECKSUM);
|
|
|
|
|
memcpy(vhd->uuid, bytes + VHD_OFFSET_UUID, sizeof(vhd->uuid)); /* TODO: handle UUID's properly */
|
|
|
|
|
vhd->saved_state = bytes[VHD_OFFSET_SAVED_STATE];
|
|
|
|
|
memcpy(vhd->reserved, bytes + VHD_OFFSET_RESERVED, sizeof(vhd->reserved));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd)
|
|
|
|
|
{
|
|
|
|
|
/* Quick endian check */
|
|
|
|
|
int is_be = 0;
|
|
|
|
|
uint8_t e = 1;
|
|
|
|
|
uint8_t *ep = &e;
|
|
|
|
|
uint16_t u16;
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
uint64_t u64;
|
|
|
|
|
|
|
|
|
|
if (ep[0] == 0)
|
|
|
|
|
is_be = 1;
|
|
|
|
|
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_COOKIE, vhd->cookie, sizeof(vhd->cookie));
|
|
|
|
|
u32 = u32_to_be(vhd->features, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_FEATURES, &u32, sizeof(vhd->features));
|
|
|
|
|
u32 = u32_to_be(vhd->version, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_VERSION, &u32, sizeof(vhd->version));
|
|
|
|
|
u64 = u64_to_be(vhd->offset, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_DATA_OFFSET, &u64, sizeof(vhd->offset));
|
|
|
|
|
u32 = u32_to_be(vhd->timestamp, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_TIMESTAMP, &u32, sizeof(vhd->timestamp));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_CREATOR, vhd->creator, sizeof(vhd->creator));
|
|
|
|
|
u32 = u32_to_be(vhd->creator_vers, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_CREATOR_VERS, &u32, sizeof(vhd->creator_vers));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_CREATOR_HOST, vhd->creator_host_os, sizeof(vhd->creator_host_os));
|
|
|
|
|
u64 = u64_to_be(vhd->orig_size, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_ORIG_SIZE, &u64, sizeof(vhd->orig_size));
|
|
|
|
|
u64 = u64_to_be(vhd->curr_size, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_CURR_SIZE, &u64, sizeof(vhd->curr_size));
|
|
|
|
|
u16 = u16_to_be(vhd->geom.cyl, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_GEOM_CYL, &u16, sizeof(vhd->geom.cyl));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_GEOM_HEAD, &(vhd->geom.heads), sizeof(vhd->geom.heads));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_GEOM_SPT, &(vhd->geom.spt), sizeof(vhd->geom.spt));
|
|
|
|
|
u32 = u32_to_be(vhd->type, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_TYPE, &u32, sizeof(vhd->type));
|
|
|
|
|
u32 = u32_to_be(vhd->checksum, is_be);
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_CHECKSUM, &u32, sizeof(vhd->checksum));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_UUID, vhd->uuid, sizeof(vhd->uuid));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_SAVED_STATE, &(vhd->saved_state), sizeof(vhd->saved_state));
|
|
|
|
|
memcpy(bytes + VHD_OFFSET_RESERVED, vhd->reserved, sizeof(vhd->reserved));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
new_vhd_footer(vhd_footer_t **vhd)
|
|
|
|
|
{
|
|
|
|
|
uint8_t cookie[8] = {'c', 'o', 'n', 'e', 'c', 't', 'i', 'x'};
|
|
|
|
|
uint8_t creator[4] = {'8', '6', 'b', 'x'};
|
|
|
|
|
uint8_t cr_host_os[4] = {'W', 'i', '2', 'k'};
|
|
|
|
|
|
|
|
|
|
if (*vhd == NULL)
|
|
|
|
|
*vhd = (vhd_footer_t *) malloc(sizeof(vhd_footer_t));
|
|
|
|
|
|
|
|
|
|
memcpy((*vhd)->cookie, cookie, 8);
|
|
|
|
|
(*vhd)->features = 0x00000002;
|
|
|
|
|
(*vhd)->version = 0x00010000;
|
|
|
|
|
(*vhd)->offset = 0xffffffffffffffff; /* fixed disk */
|
|
|
|
|
(*vhd)->timestamp = calc_vhd_timestamp();
|
|
|
|
|
memcpy((*vhd)->creator, creator, 4);
|
|
|
|
|
(*vhd)->creator_vers = 0x00010000;
|
|
|
|
|
memcpy((*vhd)->creator_host_os, cr_host_os, 4);
|
|
|
|
|
(*vhd)->type = 2; /* fixed disk */
|
|
|
|
|
mk_guid((*vhd)->uuid);
|
|
|
|
|
(*vhd)->saved_state = 0;
|
|
|
|
|
memset((*vhd)->reserved, 0, 427);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
generate_vhd_checksum(vhd_footer_t *vhd)
|
|
|
|
|
{
|
|
|
|
|
uint32_t chk = 0;
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < sizeof(vhd_footer_t); i++) {
|
|
|
|
|
/* We don't include the checksum field in the checksum */
|
|
|
|
|
if ((i < VHD_OFFSET_CHECKSUM) || (i >= VHD_OFFSET_UUID))
|
|
|
|
|
chk += ((uint8_t*)vhd)[i];
|
|
|
|
|
}
|
|
|
|
|
vhd->checksum = ~chk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size)
|
|
|
|
|
{
|
|
|
|
|
/* Calculate the geometry from size (in MB), using the algorithm provided in
|
|
|
|
|
"Virtual Hard Disk Image Format Specification, Appendix: CHS Calculation" */
|
|
|
|
|
uint64_t ts = ((uint64_t) size) << 11LL;
|
|
|
|
|
uint32_t spt, heads, cyl, cth;
|
|
|
|
|
if (ts > 65535 * 16 * 255)
|
|
|
|
|
ts = 65535 * 16 * 255;
|
|
|
|
|
|
|
|
|
|
if (ts >= 65535 * 16 * 63) {
|
|
|
|
|
spt = 255;
|
|
|
|
|
heads = 16;
|
2018-09-13 05:59:00 +02:00
|
|
|
cth = (uint32_t) (ts / spt);
|
2018-07-15 01:41:53 +02:00
|
|
|
} else {
|
|
|
|
|
spt = 17;
|
2018-09-13 05:59:00 +02:00
|
|
|
cth = (uint32_t) (ts / spt);
|
2018-07-15 01:41:53 +02:00
|
|
|
heads = (cth +1023) / 1024;
|
|
|
|
|
if (heads < 4)
|
|
|
|
|
heads = 4;
|
|
|
|
|
if ((cth >= (heads * 1024)) || (heads > 16)) {
|
|
|
|
|
spt = 31;
|
|
|
|
|
heads = 16;
|
2018-09-13 05:59:00 +02:00
|
|
|
cth = (uint32_t) (ts / spt);
|
2018-07-15 01:41:53 +02:00
|
|
|
}
|
|
|
|
|
if (cth >= (heads * 1024)) {
|
|
|
|
|
spt = 63;
|
|
|
|
|
heads = 16;
|
2018-09-13 05:59:00 +02:00
|
|
|
cth = (uint32_t) (ts / spt);
|
2018-07-15 01:41:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cyl = cth / heads;
|
|
|
|
|
*c = cyl;
|
|
|
|
|
*h = heads;
|
|
|
|
|
*s = spt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
static int
|
|
|
|
|
prepare_new_hard_disk(uint8_t id, uint64_t full_size)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t size;
|
|
|
|
|
uint32_t t, i;
|
2017-06-22 18:24:17 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */
|
|
|
|
|
size = (uint32_t) (target_size & 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++) {
|
2018-10-08 21:49:47 +02:00
|
|
|
fseek(hdd_images[id].file, 0, SEEK_END);
|
|
|
|
|
fwrite(empty_sector_1mb, 1, 1048576, hdd_images[id].file);
|
2018-04-25 23:51:13 +02:00
|
|
|
pclog("#");
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
/* Then, write the remainder. */
|
2018-10-08 21:49:47 +02:00
|
|
|
if (size > 0) {
|
|
|
|
|
fseek(hdd_images[id].file, 0, SEEK_END);
|
|
|
|
|
fwrite(empty_sector_1mb, 1, size, hdd_images[id].file);
|
|
|
|
|
pclog("#");
|
|
|
|
|
}
|
|
|
|
|
pclog("]\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
/* Switch the suppression of seen messages back on. */
|
|
|
|
|
pclog_toggle_suppr();
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
free(empty_sector_1mb);
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-10-30 13:32:25 +01:00
|
|
|
static void
|
|
|
|
|
hdd_image_gen_vft(int id, vhd_footer_t **vft, uint64_t full_size)
|
|
|
|
|
{
|
|
|
|
|
/* Generate new footer. */
|
|
|
|
|
new_vhd_footer(vft);
|
|
|
|
|
(*vft)->orig_size = (*vft)->curr_size = full_size;
|
|
|
|
|
(*vft)->geom.cyl = hdd[id].tracks;
|
|
|
|
|
(*vft)->geom.heads = hdd[id].hpc;
|
|
|
|
|
(*vft)->geom.spt = hdd[id].spt;
|
|
|
|
|
generate_vhd_checksum(*vft);
|
|
|
|
|
vhd_footer_to_bytes((uint8_t *) empty_sector, *vft);
|
|
|
|
|
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
|
|
|
|
fwrite(empty_sector, 1, 512, hdd_images[id].file);
|
|
|
|
|
free(*vft);
|
|
|
|
|
*vft = NULL;
|
|
|
|
|
hdd_images[id].type = 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-04-25 23:51:13 +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;
|
2018-07-15 01:41:53 +02:00
|
|
|
int c, ret;
|
2018-04-25 23:51:13 +02:00
|
|
|
uint64_t s = 0;
|
|
|
|
|
wchar_t *fn = hdd[id].fn;
|
|
|
|
|
int is_hdx[2] = { 0, 0 };
|
2018-07-15 01:41:53 +02:00
|
|
|
int is_vhd[2] = { 0, 0 };
|
|
|
|
|
vhd_footer_t *vft = NULL;
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
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].loaded = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is_hdx[0] = image_is_hdx(fn, 0);
|
|
|
|
|
is_hdx[1] = image_is_hdx(fn, 1);
|
|
|
|
|
|
2018-07-15 01:41:53 +02:00
|
|
|
is_vhd[0] = image_is_vhd(fn, 0);
|
|
|
|
|
is_vhd[1] = image_is_vhd(fn, 1);
|
|
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
hdd_images[id].pos = 0;
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
/* 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");
|
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-04-25 23:51:13 +02:00
|
|
|
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 = ((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(§or_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(§or_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;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
else
|
|
|
|
|
hdd_images[id].type = 0;
|
|
|
|
|
hdd_images[id].last_sector = 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-03-19 09:48:44 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
s = full_size = ((uint64_t) hdd[id].spt) *
|
|
|
|
|
((uint64_t) hdd[id].hpc) *
|
|
|
|
|
((uint64_t) hdd[id].tracks) << 9LL;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-07-15 01:41:53 +02:00
|
|
|
ret = prepare_new_hard_disk(id, full_size);
|
|
|
|
|
|
|
|
|
|
if (is_vhd[0]) {
|
|
|
|
|
/* VHD image. */
|
2018-10-30 13:32:25 +01:00
|
|
|
hdd_image_gen_vft(id, &vft, full_size);
|
2018-07-15 01:41:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2018-04-25 23:51:13 +02:00
|
|
|
} else {
|
|
|
|
|
/* Failed for another reason */
|
|
|
|
|
hdd_image_log("Failed for another reason\n");
|
|
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
|
|
|
|
return 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
} else {
|
|
|
|
|
if (image_is_hdi(fn)) {
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, 0x8, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error seeking to offset 0x8\n");
|
|
|
|
|
if (fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading base offset\n");
|
|
|
|
|
if (fseeko64(hdd_images[id].file, 0xC, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error seeking to offest 0xC\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
full_size = 0LL;
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fread(&full_size, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading full size\n");
|
|
|
|
|
if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error seeking to offset 0x10\n");
|
|
|
|
|
if (fread(§or_size, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading sector size\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fread(&spt, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading sectors per track\n");
|
|
|
|
|
if (fread(&hpc, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n");
|
|
|
|
|
if (fread(&tracks, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading number of tracks\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
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;
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, 8, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error seeking to offset 0x8\n");
|
|
|
|
|
if (fread(&full_size, 1, 8, hdd_images[id].file) != 8)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error reading full size\n");
|
|
|
|
|
if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error seeking to offset 0x10\n");
|
|
|
|
|
if (fread(§or_size, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error reading sector size\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fread(&spt, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading sectors per track\n");
|
|
|
|
|
if (fread(&hpc, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n");
|
|
|
|
|
if (fread(&tracks, 1, 4, hdd_images[id].file) != 4)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error reading number of tracks\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
hdd[id].spt = spt;
|
|
|
|
|
hdd[id].hpc = hpc;
|
|
|
|
|
hdd[id].tracks = tracks;
|
|
|
|
|
hdd_images[id].type = 2;
|
2018-07-15 01:41:53 +02:00
|
|
|
} else if (is_vhd[1]) {
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, -512, SEEK_END) == -1)
|
|
|
|
|
fatal("hdd_image_load(): VHD: Error seeking to 512 bytes before the end of file\n");
|
|
|
|
|
if (fread(empty_sector, 1, 512, hdd_images[id].file) != 512)
|
|
|
|
|
fatal("hdd_image_load(): HDX: Error reading the footer\n");
|
2018-07-15 01:41:53 +02:00
|
|
|
new_vhd_footer(&vft);
|
2018-10-30 13:32:25 +01:00
|
|
|
vhd_footer_from_bytes(vft, (uint8_t *) empty_sector);
|
2018-07-15 01:41:53 +02:00
|
|
|
if (vft->type != 2) {
|
|
|
|
|
/* VHD is not fixed size */
|
|
|
|
|
hdd_image_log("VHD: Image is not fixed size\n");
|
|
|
|
|
free(vft);
|
|
|
|
|
vft = NULL;
|
|
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
|
|
|
|
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
full_size = vft->orig_size;
|
|
|
|
|
hdd[id].tracks = vft->geom.cyl;
|
|
|
|
|
hdd[id].hpc = vft->geom.heads;
|
|
|
|
|
hdd[id].spt = vft->geom.spt;
|
|
|
|
|
free(vft);
|
|
|
|
|
vft = NULL;
|
|
|
|
|
hdd_images[id].type = 3;
|
|
|
|
|
/* If we're here, this means there is a valid VHD footer in the
|
|
|
|
|
image, which means that by definition, all valid sectors
|
|
|
|
|
are there. */
|
|
|
|
|
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
|
|
|
|
hdd_images[id].loaded = 1;
|
|
|
|
|
return 1;
|
2018-04-25 23:51:13 +02:00
|
|
|
} else {
|
|
|
|
|
full_size = ((uint64_t) hdd[id].spt) *
|
|
|
|
|
((uint64_t) hdd[id].hpc) *
|
|
|
|
|
((uint64_t) hdd[id].tracks) << 9LL;
|
|
|
|
|
hdd_images[id].type = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1)
|
|
|
|
|
fatal("hdd_image_load(): Error seeking to the end of file\n");
|
2018-04-25 23:51:13 +02:00
|
|
|
s = ftello64(hdd_images[id].file);
|
|
|
|
|
if (s < (full_size + hdd_images[id].base))
|
2018-10-08 21:49:47 +02:00
|
|
|
ret = prepare_new_hard_disk(id, full_size);
|
2018-04-25 23:51:13 +02:00
|
|
|
else {
|
2017-06-16 03:18:59 +02:00
|
|
|
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_images[id].loaded = 1;
|
2018-10-08 21:49:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_vhd[0]) {
|
2020-01-15 03:48:33 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1)
|
|
|
|
|
fatal("hdd_image_load(): VHD: Error seeking to the end of file\n");
|
2018-10-08 21:49:47 +02:00
|
|
|
s = ftello64(hdd_images[id].file);
|
|
|
|
|
if (s == (full_size + hdd_images[id].base)) {
|
|
|
|
|
/* VHD image. */
|
2018-10-30 13:32:25 +01:00
|
|
|
hdd_image_gen_vft(id, &vft, full_size);
|
2018-10-08 21:49:47 +02:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|
2018-10-08 21:49:47 +02:00
|
|
|
|
|
|
|
|
return ret;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_seek(uint8_t id, uint32_t sector)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
off64_t addr = sector;
|
2018-05-21 19:04:05 +02:00
|
|
|
addr = (uint64_t)sector << 9LL;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
hdd_images[id].pos = sector;
|
2020-01-15 04:58:28 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET) == -1)
|
|
|
|
|
fatal("hdd_image_seek(): Error seeking\n");
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
int i;
|
|
|
|
|
|
2020-01-14 20:55:13 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) {
|
2020-01-14 20:59:54 +01:00
|
|
|
fatal("Hard disk image %i: Read error during seek\n", id);
|
2020-01-14 20:55:13 +01:00
|
|
|
return;
|
|
|
|
|
}
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
if (feof(hdd_images[id].file))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
hdd_images[id].pos = sector + i;
|
|
|
|
|
fread(buffer + (i << 9), 1, 512, hdd_images[id].file);
|
|
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
|
hdd_sectors(uint8_t id)
|
2017-07-15 12:46:44 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
|
|
|
|
return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9);
|
2017-07-15 12:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
2017-07-15 12:46:44 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t transfer_sectors = count;
|
|
|
|
|
uint32_t sectors = hdd_sectors(id);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if ((sectors - sector) < transfer_sectors)
|
|
|
|
|
transfer_sectors = sectors - sector;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-10-30 13:32:25 +01:00
|
|
|
hdd_image_read(id, sector, transfer_sectors, buffer);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
2017-07-15 12:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
int i;
|
|
|
|
|
|
2020-01-14 20:59:54 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) {
|
|
|
|
|
fatal("Hard disk image %i: Write error during seek\n", id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
if (feof(hdd_images[id].file))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
hdd_images[id].pos = sector + i;
|
|
|
|
|
fwrite(buffer + (i << 9), 512, 1, hdd_images[id].file);
|
|
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
2017-07-15 12:46:44 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t transfer_sectors = count;
|
|
|
|
|
uint32_t sectors = hdd_sectors(id);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if ((sectors - sector) < transfer_sectors)
|
|
|
|
|
transfer_sectors = sectors - sector;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-10-30 13:32:25 +01:00
|
|
|
hdd_image_write(id, sector, transfer_sectors, buffer);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
2017-07-15 12:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t i = 0;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-10-30 13:32:25 +01:00
|
|
|
memset(empty_sector, 0, 512);
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
|
2020-01-14 21:00:45 +01:00
|
|
|
if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) {
|
|
|
|
|
fatal("Hard disk image %i: Zero error during seek\n", id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
if (feof(hdd_images[id].file))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
hdd_images[id].pos = sector + i;
|
2018-04-25 23:51:13 +02:00
|
|
|
fwrite(empty_sector, 512, 1, hdd_images[id].file);
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
|
2017-07-15 12:46:44 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t transfer_sectors = count;
|
|
|
|
|
uint32_t sectors = hdd_sectors(id);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if ((sectors - sector) < transfer_sectors)
|
|
|
|
|
transfer_sectors = sectors - sector;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-10-30 13:32:25 +01:00
|
|
|
hdd_image_zero(id, sector, transfer_sectors);
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (count != transfer_sectors)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
2017-07-15 12:46:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
|
hdd_image_get_last_sector(uint8_t id)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
return hdd_images[id].last_sector;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
uint32_t
|
|
|
|
|
hdd_image_get_pos(uint8_t id)
|
|
|
|
|
{
|
|
|
|
|
return hdd_images[id].pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
uint8_t
|
|
|
|
|
hdd_image_get_type(uint8_t id)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
return hdd_images[id].type;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_unload(uint8_t id, int fn_preserve)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
if (wcslen(hdd[id].fn) == 0)
|
|
|
|
|
return;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (hdd_images[id].loaded) {
|
|
|
|
|
if (hdd_images[id].file != NULL) {
|
|
|
|
|
fclose(hdd_images[id].file);
|
|
|
|
|
hdd_images[id].file = NULL;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
hdd_images[id].loaded = 0;
|
|
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
hdd_images[id].last_sector = -1;
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
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));
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
hdd_image_close(uint8_t id)
|
2017-06-16 03:18:59 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
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;
|
2017-06-16 03:18:59 +02:00
|
|
|
}
|