Added the 3Com 3C503 Network card;
Several bug fixes; Preliminar addition of the SDL 2 renderer (does not yet work correctly in full screen mode); SCSI devices no longer have configurable LUN's (this matches the configurability of real SCSI devices); SCSI LUN's are now handed by the device's handler; Removed all unused strings; Removed some unused code files; Significantly rewrote the bus mouse emulation.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdc_ide.c 1.0.46 2018/05/02
|
||||
* Version: @(#)hdc_ide.c 1.0.47 2018/06/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -844,7 +844,7 @@ ide_set_signature(ide_t *ide)
|
||||
ide->head=0;
|
||||
|
||||
if (ide_drive_is_zip(ide)) {
|
||||
zip_set_signature(zip_id);
|
||||
zip_set_signature(zip[zip_id]);
|
||||
ide->secount = zip[zip_id]->phase;
|
||||
ide->cylinder = zip[zip_id]->request_length;
|
||||
} else if (ide_drive_is_cdrom(ide)) {
|
||||
@@ -2058,7 +2058,7 @@ ide_callback(void *priv)
|
||||
if (ide_drive_is_zip(ide)) {
|
||||
zip[zip_id]->status = DRDY_STAT | DSC_STAT;
|
||||
zip[zip_id]->error = 1;
|
||||
zip_reset(zip_id);
|
||||
zip_reset(zip[zip_id]);
|
||||
} else if (ide_drive_is_cdrom(ide)) {
|
||||
cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT;
|
||||
cdrom[cdrom_id]->error = 1;
|
||||
@@ -2451,7 +2451,7 @@ ide_callback(void *priv)
|
||||
goto abort_cmd;
|
||||
|
||||
if (ide_drive_is_zip(ide))
|
||||
zip_phase_callback(atapi_zip_drives[ch]);
|
||||
zip_phase_callback(zip[atapi_zip_drives[ch]]);
|
||||
else
|
||||
cdrom_phase_callback(cdrom[atapi_cdrom_drives[ch]]);
|
||||
return;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Common code to handle all sorts of hard disk images.
|
||||
*
|
||||
* Version: @(#)hdd.c 1.0.8 2018/04/24
|
||||
* Version: @(#)hdd.c 1.0.9 2018/05/25
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -48,7 +48,7 @@ hdd_string_to_bus(char *str, int cdrom)
|
||||
if (! strcmp(str, "mfm")) {
|
||||
if (cdrom) {
|
||||
no_cdrom:
|
||||
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4114);
|
||||
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4099);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the hard disk image handler.
|
||||
*
|
||||
* Version: @(#)hdd.h 1.0.5 2018/04/30
|
||||
* Version: @(#)hdd.h 1.0.6 2018/06/09
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -84,7 +84,6 @@ typedef struct {
|
||||
uint8_t xta_channel;
|
||||
uint8_t ide_channel;
|
||||
uint8_t scsi_id;
|
||||
uint8_t scsi_lun;
|
||||
|
||||
uint32_t base,
|
||||
spt,
|
||||
@@ -104,6 +103,31 @@ extern hard_disk_t hdd[HDD_NUM];
|
||||
extern unsigned int hdd_table[128][3];
|
||||
|
||||
|
||||
typedef struct vhd_footer_t
|
||||
{
|
||||
uint8_t cookie[8];
|
||||
uint32_t features;
|
||||
uint32_t version;
|
||||
uint64_t offset;
|
||||
uint32_t timestamp;
|
||||
uint8_t creator[4];
|
||||
uint32_t creator_vers;
|
||||
uint8_t creator_host_os[4];
|
||||
uint64_t orig_size;
|
||||
uint64_t curr_size;
|
||||
struct {
|
||||
uint16_t cyl;
|
||||
uint8_t heads;
|
||||
uint8_t spt;
|
||||
} geom;
|
||||
uint32_t type;
|
||||
uint32_t checksum;
|
||||
uint8_t uuid[16];
|
||||
uint8_t saved_state;
|
||||
uint8_t reserved[427];
|
||||
} vhd_footer_t;
|
||||
|
||||
|
||||
extern int hdd_init(void);
|
||||
extern int hdd_string_to_bus(char *str, int cdrom);
|
||||
extern char *hdd_bus_to_string(int bus, int cdrom);
|
||||
@@ -124,9 +148,16 @@ extern uint8_t hdd_image_get_type(uint8_t id);
|
||||
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
|
||||
extern void hdd_image_unload(uint8_t id, int fn_preserve);
|
||||
extern void hdd_image_close(uint8_t id);
|
||||
extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size);
|
||||
|
||||
extern void vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes);
|
||||
extern void vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd);
|
||||
extern void new_vhd_footer(vhd_footer_t **vhd);
|
||||
extern void generate_vhd_checksum(vhd_footer_t *vhd);
|
||||
|
||||
extern int image_is_hdi(const wchar_t *s);
|
||||
extern int image_is_hdx(const wchar_t *s, int check_signature);
|
||||
extern int image_is_vhd(const wchar_t *s, int check_signature);
|
||||
|
||||
|
||||
#endif /*EMU_HDD_H*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of hard disk image files.
|
||||
*
|
||||
* Version: @(#)hdd_image.c 1.0.15 2018/04/29
|
||||
* Version: @(#)hdd_image.c 1.0.16 2018/06/09
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -24,11 +24,13 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../plat.h"
|
||||
#include "../random.h"
|
||||
#include "hdd.h"
|
||||
|
||||
|
||||
@@ -48,6 +50,26 @@ static char empty_sector[512];
|
||||
static char *empty_sector_1mb;
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
||||
#ifdef ENABLE_HDD_IMAGE_LOG
|
||||
int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG;
|
||||
#endif
|
||||
@@ -121,6 +143,303 @@ image_is_hdx(const wchar_t *s, int check_signature)
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
fseeko64(f, -512, SEEK_END);
|
||||
if (filelen < 512)
|
||||
return 0;
|
||||
fread(&signature, 1, 8, f);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
be_to_u32(uint8_t *bytes, int start)
|
||||
{
|
||||
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);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
be_to_u16(uint8_t *bytes, int start)
|
||||
{
|
||||
uint16_t n = ((uint16_t)bytes[start+1] << 0) |
|
||||
((uint16_t)bytes[start] <<8);
|
||||
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;
|
||||
res = ((value & (mask >> 0)) >> 56) |
|
||||
((value & (mask >> 8)) >> 40) |
|
||||
((value & (mask >> 16)) >> 24) |
|
||||
((value & (mask >> 24)) >> 8) |
|
||||
((value & (mask >> 32)) << 8) |
|
||||
((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;
|
||||
res = ((value & (mask >> 0)) >> 24) |
|
||||
((value & (mask >> 8)) >> 8) |
|
||||
((value & (mask >> 16)) << 8) |
|
||||
((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;
|
||||
start_time = 946684800; /* 1 Jan 2000 00: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;
|
||||
cth = ts / spt;
|
||||
} else {
|
||||
spt = 17;
|
||||
cth = ts / spt;
|
||||
heads = (cth +1023) / 1024;
|
||||
if (heads < 4)
|
||||
heads = 4;
|
||||
if ((cth >= (heads * 1024)) || (heads > 16)) {
|
||||
spt = 31;
|
||||
heads = 16;
|
||||
cth = ts / spt;
|
||||
}
|
||||
if (cth >= (heads * 1024)) {
|
||||
spt = 63;
|
||||
heads = 16;
|
||||
cth = ts / spt;
|
||||
}
|
||||
}
|
||||
cyl = cth / heads;
|
||||
*c = cyl;
|
||||
*h = heads;
|
||||
*s = spt;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
prepare_new_hard_disk(uint8_t id, uint64_t full_size)
|
||||
{
|
||||
@@ -182,10 +501,12 @@ hdd_image_load(int id)
|
||||
uint64_t signature = 0xD778A82044445459ll;
|
||||
uint64_t full_size = 0;
|
||||
uint64_t spt = 0, hpc = 0, tracks = 0;
|
||||
int c;
|
||||
int c, ret;
|
||||
uint64_t s = 0;
|
||||
wchar_t *fn = hdd[id].fn;
|
||||
int is_hdx[2] = { 0, 0 };
|
||||
int is_vhd[2] = { 0, 0 };
|
||||
vhd_footer_t *vft = NULL;
|
||||
|
||||
memset(empty_sector, 0, sizeof(empty_sector));
|
||||
|
||||
@@ -202,6 +523,9 @@ hdd_image_load(int id)
|
||||
is_hdx[0] = image_is_hdx(fn, 0);
|
||||
is_hdx[1] = image_is_hdx(fn, 1);
|
||||
|
||||
is_vhd[0] = image_is_vhd(fn, 0);
|
||||
is_vhd[1] = image_is_vhd(fn, 1);
|
||||
|
||||
hdd_images[id].pos = 0;
|
||||
|
||||
/* Try to open existing hard disk image */
|
||||
@@ -268,7 +592,29 @@ hdd_image_load(int id)
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
((uint64_t) hdd[id].tracks) << 9LL;
|
||||
|
||||
return prepare_new_hard_disk(id, full_size);
|
||||
ret = prepare_new_hard_disk(id, full_size);
|
||||
|
||||
if (is_vhd[0]) {
|
||||
/* VHD image. */
|
||||
/* Generate new footer. */
|
||||
empty_sector_1mb = (char *) malloc(512);
|
||||
new_vhd_footer(&vft);
|
||||
vft->orig_size = vft->curr_size = full_size;
|
||||
vft->geom.cyl = tracks;
|
||||
vft->geom.heads = hpc;
|
||||
vft->geom.spt = spt;
|
||||
generate_vhd_checksum(vft);
|
||||
memset(empty_sector_1mb, 0, 512);
|
||||
vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft);
|
||||
fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file);
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = NULL;
|
||||
hdd_images[id].type = 3;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
/* Failed for another reason */
|
||||
hdd_image_log("Failed for another reason\n");
|
||||
@@ -322,6 +668,40 @@ hdd_image_load(int id)
|
||||
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 if (is_vhd[1]) {
|
||||
empty_sector_1mb = (char *) malloc(512);
|
||||
memset(empty_sector_1mb, 0, 512);
|
||||
fseeko64(hdd_images[id].file, -512, SEEK_END);
|
||||
fread(empty_sector_1mb, 1, 512, hdd_images[id].file);
|
||||
new_vhd_footer(&vft);
|
||||
vhd_footer_from_bytes(vft, (uint8_t *) empty_sector_1mb);
|
||||
if (vft->type != 2) {
|
||||
/* VHD is not fixed size */
|
||||
hdd_image_log("VHD: Image is not fixed size\n");
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = 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;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = 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;
|
||||
} else {
|
||||
full_size = ((uint64_t) hdd[id].spt) *
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
|
||||
1186
src/disk/zip.c
1186
src/disk/zip.c
File diff suppressed because it is too large
Load Diff
@@ -48,9 +48,32 @@ enum {
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t previous_command, error,
|
||||
features, status,
|
||||
phase, *buffer,
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t ide_channel,
|
||||
bus_mode; /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
|
||||
unsigned int scsi_device_id, is_250;
|
||||
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
int read_only, ui_writeprot;
|
||||
|
||||
uint32_t medium_size, base;
|
||||
|
||||
FILE *f;
|
||||
} zip_drive_t;
|
||||
|
||||
typedef struct {
|
||||
mode_sense_pages_t ms_pages_saved;
|
||||
|
||||
zip_drive_t *drv;
|
||||
|
||||
uint8_t previous_command,
|
||||
error, features,
|
||||
status, phase,
|
||||
id, *buffer,
|
||||
atapi_cdb[16],
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
@@ -77,35 +100,16 @@ typedef struct {
|
||||
uint64_t current_page_code;
|
||||
} zip_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t ide_channel,
|
||||
bus_mode; /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
|
||||
unsigned int scsi_device_id, scsi_device_lun,
|
||||
is_250;
|
||||
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
int read_only, ui_writeprot;
|
||||
|
||||
uint32_t medium_size, base;
|
||||
|
||||
FILE *f;
|
||||
} zip_drive_t;
|
||||
|
||||
|
||||
extern zip_t *zip[ZIP_NUM];
|
||||
extern zip_drive_t zip_drives[ZIP_NUM];
|
||||
extern uint8_t atapi_zip_drives[8];
|
||||
extern uint8_t scsi_zip_drives[16][8];
|
||||
extern uint8_t scsi_zip_drives[16];
|
||||
|
||||
#define zip_sense_error zip[id]->sense[0]
|
||||
#define zip_sense_key zip[id]->sense[2]
|
||||
#define zip_asc zip[id]->sense[12]
|
||||
#define zip_ascq zip[id]->sense[13]
|
||||
#define zip_sense_error dev->sense[0]
|
||||
#define zip_sense_key dev->sense[2]
|
||||
#define zip_asc dev->sense[12]
|
||||
#define zip_ascq dev->sense[13]
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -116,37 +120,32 @@ extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_lengt
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
|
||||
extern void *ide_bus_master_priv[2];
|
||||
extern void ioctl_close(uint8_t id);
|
||||
|
||||
extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel);
|
||||
extern uint32_t zip_mode_sense_get_volume(uint8_t id, int channel);
|
||||
extern void build_atapi_zip_map(void);
|
||||
extern void build_scsi_zip_map(void);
|
||||
extern int zip_ZIP_PHASE_to_scsi(uint8_t id);
|
||||
extern int zip_atapi_phase_to_scsi(uint8_t id);
|
||||
extern void zip_command(uint8_t id, uint8_t *cdb);
|
||||
extern void zip_phase_callback(uint8_t id);
|
||||
extern int zip_ZIP_PHASE_to_scsi(zip_t *dev);
|
||||
extern int zip_atapi_phase_to_scsi(zip_t *dev);
|
||||
extern void zip_command(zip_t *dev, uint8_t *cdb);
|
||||
extern void zip_phase_callback(zip_t *dev);
|
||||
extern uint32_t zip_read(uint8_t channel, int length);
|
||||
extern void zip_write(uint8_t channel, uint32_t val, int length);
|
||||
|
||||
extern void zip_close(uint8_t id);
|
||||
extern void zip_disk_reload(uint8_t id);
|
||||
extern void zip_reset(uint8_t id);
|
||||
extern void zip_set_signature(int id);
|
||||
extern void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void zip_disk_close(zip_t *dev);
|
||||
extern void zip_disk_reload(zip_t *dev);
|
||||
extern void zip_reset(zip_t *dev);
|
||||
extern void zip_set_signature(zip_t *dev);
|
||||
extern void zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
|
||||
extern void zip_insert(uint8_t id);
|
||||
extern void zip_insert(zip_t *dev);
|
||||
|
||||
extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
extern int find_zip_for_scsi_id(uint8_t scsi_id);
|
||||
extern int zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
|
||||
extern void zip_global_init(void);
|
||||
extern void zip_hard_reset(void);
|
||||
|
||||
extern int zip_load(uint8_t id, wchar_t *fn);
|
||||
|
||||
extern void zip_destroy_drives(void);
|
||||
extern void zip_close(uint8_t id);
|
||||
extern int zip_load(zip_t *dev, wchar_t *fn);
|
||||
extern void zip_close();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user