Code improvements for hardfile handling

This commit is contained in:
Dimitris Panokostas 2017-02-25 01:37:31 +01:00
parent c85ae3f98a
commit dcd0525cc4
2 changed files with 357 additions and 194 deletions

View file

@ -1,4 +1,4 @@
/*
/*
* UAE - The Un*x Amiga Emulator
*
* Unix file system handler for AmigaDOS
@ -9,51 +9,85 @@
#ifndef FILESYS_H
#define FILESYS_H
struct hardfiledata {
uae_u64 virtsize; // virtual size
uae_u64 physsize; // physical size (dynamic disk)
uae_u64 offset;
struct uaedev_config_info ci;
struct hardfilehandle *handle;
int handle_valid;
int dangerous;
int flags;
uae_u8 *cache;
int cache_valid;
uae_u64 cache_offset;
TCHAR vendor_id[8 + 1];
TCHAR product_id[16 + 1];
TCHAR product_rev[4 + 1];
TCHAR device_name[256];
/* geometry from possible RDSK block */
int rdbcylinders;
int rdbsectors;
int rdbheads;
uae_u8 *virtual_rdb;
uae_u64 virtual_size;
int unitnum;
int byteswap;
int adide;
int hfd_type;
struct hardfilehandle;
int drive_empty;
TCHAR *emptyname;
#define MAX_HDF_CACHE_BLOCKS 128
#define MAX_SCSI_SENSE 36
struct hdf_cache
{
bool valid;
uae_u8 *data;
uae_u64 block;
bool dirty;
int readcount;
int writecount;
time_t lastaccess;
};
struct hardfiledata
{
uae_u64 virtsize; // virtual size
uae_u64 physsize; // physical size (dynamic disk)
uae_u64 offset;
struct uaedev_config_info ci;
struct hardfilehandle *handle;
int handle_valid;
int dangerous;
int flags;
uae_u8 *cache;
int cache_valid;
uae_u64 cache_offset;
TCHAR vendor_id[8 + 1];
TCHAR product_id[16 + 1];
TCHAR product_rev[4 + 1];
TCHAR device_name[256];
/* geometry from possible RDSK block */
int rdbcylinders;
int rdbsectors;
int rdbheads;
uae_u8 *virtual_rdb;
uae_u64 virtual_size;
int unitnum;
int byteswap;
int adide;
int hfd_type;
uae_u8 *vhd_header;
uae_u32 vhd_bamoffset;
uae_u32 vhd_bamsize;
uae_u32 vhd_blocksize;
uae_u8 *vhd_sectormap;
uae_u64 vhd_sectormapblock;
uae_u32 vhd_bitmapsize;
uae_u64 vhd_footerblock;
void *chd_handle;
int drive_empty;
TCHAR* emptyname;
struct hdf_cache bcache[MAX_HDF_CACHE_BLOCKS];
uae_u8 scsi_sense[MAX_SCSI_SENSE];
struct uaedev_config_info delayedci;
int reinsertdelay;
bool isreinsert;
};
struct hd_hardfiledata {
struct hardfiledata hfd;
uae_u64 size;
int cyls;
int heads;
int secspertrack;
int cyls_def;
int secspertrack_def;
int heads_def;
int ansi_version;
#define HFD_FLAGS_REALDRIVE 1
#define HFD_FLAGS_REALDRIVEPARTITION 2
struct hd_hardfiledata
{
struct hardfiledata hfd;
uae_u64 size;
int cyls;
int heads;
int secspertrack;
int cyls_def;
int secspertrack_def;
int heads_def;
int ansi_version;
};
#define HD_CONTROLLER_UAE 0
@ -83,28 +117,33 @@ struct hd_hardfiledata {
struct uaedev_mount_info;
extern struct uaedev_mount_info options_mountinfo;
extern struct hardfiledata *get_hardfile_data (int nr);
extern struct hardfiledata* get_hardfile_data(int nr);
#define FILESYS_MAX_BLOCKSIZE 2048
extern int hdf_open (struct hardfiledata *hfd);
extern int hdf_open (struct hardfiledata *hfd, const TCHAR *altname);
extern void hdf_close (struct hardfiledata *hfd);
extern int hdf_read_rdb (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int hdf_read (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int get_native_path(uae_u32 lock, TCHAR *out);
extern void hardfile_do_disk_change (struct uaedev_config_data *uci, bool insert);
extern void hardfile_send_disk_change (struct hardfiledata *hfd, bool insert);
extern int hardfile_media_change (struct hardfiledata *hfd, struct uaedev_config_info *ci, bool inserted, bool timer);
extern int hdf_open(struct hardfiledata* hfd);
extern int hdf_open(struct hardfiledata* hfd, const TCHAR* altname);
extern void hdf_close(struct hardfiledata* hfd);
extern int hdf_read_rdb(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len);
extern int hdf_read(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len);
extern int hdf_write(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len);
extern int get_native_path(uae_u32 lock, TCHAR* out);
extern void hardfile_do_disk_change(struct uaedev_config_data* uci, bool insert);
extern void hardfile_send_disk_change(struct hardfiledata* hfd, bool insert);
extern int hardfile_media_change(struct hardfiledata* hfd, struct uaedev_config_info* ci, bool inserted, bool timer);
void hdf_hd_close(struct hd_hardfiledata *hfd);
int hdf_hd_open(struct hd_hardfiledata *hfd);
void hdf_hd_close(struct hd_hardfiledata* hfd);
int hdf_hd_open(struct hd_hardfiledata* hfd);
extern int hdf_open_target (struct hardfiledata *hfd, const TCHAR *name);
extern void hdf_close_target (struct hardfiledata *hfd);
extern int hdf_read_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int hdf_write_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern void getchsgeometry (uae_u64 size, int *pcyl, int *phead, int *psectorspertrack);
extern void getchsgeometry_hdf (struct hardfiledata *hfd, uae_u64 size, int *pcyl, int *phead, int *psectorspertrack);
extern void getchspgeometry (uae_u64 total, int *pcyl, int *phead, int *psectorspertrack, bool idegeometry);
extern int vhd_create(const TCHAR *name, uae_u64 size, uae_u32);
extern int hdf_init_target();
extern int hdf_open_target(struct hardfiledata *hfd, const TCHAR *name);
extern int hdf_dup_target(struct hardfiledata *dhfd, const struct hardfiledata *shfd);
extern void hdf_close_target(struct hardfiledata *hfd);
extern int hdf_read_target(struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int hdf_write_target(struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
extern int hdf_resize_target(struct hardfiledata *hfd, uae_u64 newsize);
extern void getchsgeometry(uae_u64 size, int *pcyl, int *phead, int *psectorspertrack);
extern void getchsgeometry_hdf(struct hardfiledata *hfd, uae_u64 size, int *pcyl, int *phead, int *psectorspertrack);
extern void getchspgeometry(uae_u64 total, int *pcyl, int *phead, int *psectorspertrack, bool idegeometry);
#endif /* MEMORY_H */

View file

@ -6,28 +6,39 @@
#include "filesys.h"
#include "zfile.h"
#define hfd_log write_log
#define hdf_log2
static int usefloppydrives = 0;
static int num_drives;
static bool drives_enumerated;
struct hardfilehandle
{
int zfile;
struct zfile *zf;
FILE *f;
struct zfile* zf;
FILE* f;
BOOL firstwrite;
};
struct uae_driveinfo {
struct uae_driveinfo
{
TCHAR vendor_id[128];
TCHAR product_id[128];
TCHAR product_rev[128];
TCHAR product_serial[128];
TCHAR device_name[2048];
TCHAR device_path[2048];
TCHAR device_full_path[2048];
uae_u64 size;
uae_u64 offset;
int bytespersector;
int removablemedia;
int nomedia;
int dangerous;
bool partitiondrive;
int readonly;
int cylinders, sectors, heads;
};
#define HDF_HANDLE_FILE 1
@ -37,225 +48,303 @@ struct uae_driveinfo {
#define CACHE_SIZE 16384
#define CACHE_FLUSH_TIME 5
static TCHAR *hdz[] = { _T("hdz"), _T("zip"), NULL };
static TCHAR *hdz[] = { _T("hdz"), _T("zip"), _T("rar"), _T("7z"), NULL };
int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
/* safety check: only accept drives that:
* - contain RDSK in block 0
* - block 0 is zeroed
*/
int harddrive_dangerous; // = 0x1234dead; // test only!
int do_rdbdump;
static struct uae_driveinfo uae_drives[MAX_FILESYSTEM_UNITS];
static void rdbdump(FILE* h, uae_u64 offset, uae_u8 *buf, int blocksize)
{
FILE *f = 0;
int i;
TCHAR *name = my_strdup (pname);
TCHAR *ext;
int zmode = 0;
static int cnt = 1;
int i, blocks;
TCHAR name[100];
FILE *f;
bool needfree = false;
write_log(_T("creating rdb dump.. offset=%I64X blocksize=%d\n"), offset, blocksize);
if (buf) {
blocks = (buf[132] << 24) | (buf[133] << 16) | (buf[134] << 8) | (buf[135] << 0);
if (blocks < 0 || blocks > 100000)
return;
}
else {
blocks = 16383;
buf = static_cast<uae_u8*>(malloc(CACHE_SIZE));
needfree = true;
}
_stprintf(name, _T("rdb_dump_%d.rdb"), cnt);
f = _tfopen(name, _T("wb"));
if (!f) {
write_log(_T("failed to create file '%s'\n"), name);
return;
}
for (i = 0; i <= blocks; i++) {
unsigned long outlen;
if (fseek(h, static_cast<unsigned long>(offset), SEEK_SET) != 0)
break;
outlen = fread(buf, 1, blocksize, h);
fwrite(buf, 1, blocksize, f);
offset += blocksize;
}
fclose(f);
if (needfree)
free(buf);
write_log(_T("'%s' saved\n"), name);
cnt++;
}
int hdf_open_target(struct hardfiledata* hfd, const TCHAR* pname)
{
FILE* f = nullptr;
unsigned long flags;
int i;
struct uae_driveinfo *udi = nullptr, tmpudi;
TCHAR* name = my_strdup(pname);
hfd->flags = 0;
hfd->drive_empty = 0;
hdf_close (hfd);
hfd->cache = (uae_u8*)malloc (CACHE_SIZE);
hdf_close(hfd);
hfd->cache = static_cast<uae_u8*>(malloc(CACHE_SIZE));
hfd->cache_valid = 0;
hfd->virtual_size = 0;
hfd->virtual_rdb = NULL;
if (!hfd->cache) {
hfd->virtual_rdb = nullptr;
if (!hfd->cache)
{
write_log (_T("malloc(%d) failed in hdf_open_target\n"), CACHE_SIZE);
goto end;
}
hfd->handle = xcalloc (struct hardfilehandle, 1);
hfd->handle->f = 0;
write_log (_T("hfd attempting to open: '%s'\n"), name);
hfd->handle->f = nullptr;
hfd_log(_T("hfd attempting to open: '%s'\n"), name);
ext = _tcsrchr (name, '.');
if (ext != NULL) {
int zmode = 0;
TCHAR* ext = _tcsrchr (name, '.');
if (ext != nullptr)
{
ext++;
for (i = 0; hdz[i]; i++) {
for (i = 0; hdz[i]; i++)
{
if (!_tcsicmp (ext, hdz[i]))
zmode = 1;
}
}
f = fopen(name, (hfd->ci.readonly ? "rb" : "r+b"));
if (f == NULL && !hfd->ci.readonly) {
f = fopen(name, "rb");
if(f != NULL)
hfd->ci.readonly = true;
}
if (f == nullptr && !hfd->ci.readonly)
{
f = fopen(name, "rb");
if (f != nullptr)
hfd->ci.readonly = true;
}
hfd->handle->f = f;
i = _tcslen (name) - 1;
while (i >= 0) {
if ((i > 0 && (name[i - 1] == '/' || name[i - 1] == '\\')) || i == 0) {
while (i >= 0)
{
if ((i > 0 && (name[i - 1] == '/' || name[i - 1] == '\\')) || i == 0)
{
_tcsncpy (hfd->product_id, name + i, 15);
break;
}
i--;
}
_tcscpy (hfd->vendor_id, _T("UAE"));
_tcscpy (hfd->product_rev, _T("0.4"));
if (f != NULL) {
uae_s64 pos = ftell(f);
fseek(f, 0, SEEK_END);
uae_s64 size = ftell(f);
fseek(f, pos, SEEK_SET);
_tcscpy (hfd->vendor_id, _T("UAE"));
_tcscpy (hfd->product_rev, _T("0.4"));
if (f != nullptr)
{
uae_s64 pos = ftell(f);
fseek(f, 0, SEEK_END);
uae_s64 size = ftell(f);
fseek(f, pos, SEEK_SET);
size &= ~(hfd->ci.blocksize - 1);
hfd->physsize = hfd->virtsize = size;
if (hfd->physsize < hfd->ci.blocksize || hfd->physsize == 0) {
if (hfd->physsize < hfd->ci.blocksize || hfd->physsize == 0)
{
write_log (_T("HDF '%s' is too small\n"), name);
goto end;
}
hfd->handle_valid = HDF_HANDLE_FILE;
if (hfd->physsize < 64 * 1024 * 1024 && zmode) {
if (hfd->physsize < 64 * 1024 * 1024 && zmode)
{
write_log (_T("HDF '%s' re-opened in zfile-mode\n"), name);
fclose (f);
hfd->handle->f = 0;
hfd->handle->zf = zfile_fopen (name, _T("rb"), ZFD_NORMAL);
fclose(f);
hfd->handle->f = nullptr;
hfd->handle->zf = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
hfd->handle->zfile = 1;
if (!hfd->handle->zf)
goto end;
zfile_fseek (hfd->handle->zf, 0, SEEK_END);
hfd->physsize = hfd->virtsize = zfile_ftell (hfd->handle->zf);
zfile_fseek (hfd->handle->zf, 0, SEEK_SET);
zfile_fseek(hfd->handle->zf, 0, SEEK_END);
hfd->physsize = hfd->virtsize = zfile_ftell(hfd->handle->zf);
zfile_fseek(hfd->handle->zf, 0, SEEK_SET);
hfd->handle_valid = HDF_HANDLE_ZFILE;
}
} else {
}
else
{
write_log (_T("HDF '%s' failed to open.\n"), name);
}
if (hfd->handle_valid || hfd->drive_empty) {
if (hfd->handle_valid || hfd->drive_empty)
{
write_log (_T("HDF '%s' %p opened, size=%dK mode=%d empty=%d\n"),
name, hfd, hfd->physsize / 1024, hfd->handle_valid, hfd->drive_empty);
return 1;
}
end:
hdf_close (hfd);
hdf_close(hfd);
xfree (name);
return 0;
}
static void freehandle (struct hardfilehandle *h)
static void freehandle(struct hardfilehandle* h)
{
if (!h)
return;
if (!h->zfile && h->f != 0)
fclose (h->f);
if (!h->zfile && h->f != nullptr)
fclose(h->f);
if (h->zfile && h->zf)
zfile_fclose (h->zf);
h->zf = NULL;
h->f = 0;
zfile_fclose(h->zf);
h->zf = nullptr;
h->f = nullptr;
h->zfile = 0;
}
void hdf_close_target (struct hardfiledata *hfd)
void hdf_close_target(struct hardfiledata* hfd)
{
freehandle (hfd->handle);
freehandle(hfd->handle);
xfree (hfd->handle);
xfree (hfd->emptyname);
hfd->emptyname = NULL;
hfd->handle = NULL;
hfd->emptyname = nullptr;
hfd->handle = nullptr;
hfd->handle_valid = 0;
if (hfd->cache)
free (hfd->cache);
free(hfd->cache);
xfree(hfd->virtual_rdb);
hfd->virtual_rdb = 0;
hfd->virtual_rdb = nullptr;
hfd->virtual_size = 0;
hfd->cache = 0;
hfd->cache = nullptr;
hfd->cache_valid = 0;
hfd->drive_empty = 0;
hfd->dangerous = 0;
}
static int hdf_seek (struct hardfiledata *hfd, uae_u64 offset)
static int hdf_seek(struct hardfiledata* hfd, uae_u64 offset)
{
int ret;
if (hfd->handle_valid == 0) {
gui_message (_T("hd: hdf handle is not valid. bug."));
if (hfd->handle_valid == 0)
{
gui_message(_T("hd: hdf handle is not valid. bug."));
abort();
}
if (offset >= hfd->physsize - hfd->virtual_size) {
gui_message (_T("hd: tried to seek out of bounds! (%I64X >= %I64X - %I64X)\n"), offset, hfd->physsize, hfd->virtual_size);
if (offset >= hfd->physsize - hfd->virtual_size)
{
gui_message(_T("hd: tried to seek out of bounds! (%I64X >= %I64X - %I64X)\n"), offset, hfd->physsize, hfd->virtual_size);
abort ();
}
offset += hfd->offset;
if (offset & (hfd->ci.blocksize - 1)) {
gui_message (_T("hd: poscheck failed, offset=%I64X not aligned to blocksize=%d! (%I64X & %04X = %04X)\n"),
offset, hfd->ci.blocksize, offset, hfd->ci.blocksize, offset & (hfd->ci.blocksize - 1));
if (offset & (hfd->ci.blocksize - 1))
{
gui_message(_T("hd: poscheck failed, offset=%I64X not aligned to blocksize=%d! (%I64X & %04X = %04X)\n"),
offset, hfd->ci.blocksize, offset, hfd->ci.blocksize, offset & (hfd->ci.blocksize - 1));
abort ();
}
if (hfd->handle_valid == HDF_HANDLE_FILE) {
ret = fseek (hfd->handle->f, offset, SEEK_SET);
if (hfd->handle_valid == HDF_HANDLE_FILE)
{
ret = fseek(hfd->handle->f, static_cast<unsigned long>(offset), SEEK_SET);
if (ret != 0)
return -1;
} else if (hfd->handle_valid == HDF_HANDLE_ZFILE) {
zfile_fseek (hfd->handle->zf, (long)offset, SEEK_SET);
}
else if (hfd->handle_valid == HDF_HANDLE_ZFILE)
{
zfile_fseek(hfd->handle->zf, long(offset), SEEK_SET);
}
return 0;
}
static void poscheck (struct hardfiledata *hfd, int len)
static void poscheck(struct hardfiledata* hfd, int len)
{
uae_u64 pos;
if (hfd->handle_valid == HDF_HANDLE_FILE) {
pos = ftell (hfd->handle->f);
if (pos == -1) {
gui_message (_T("hd: poscheck failed. seek failure"));
if (hfd->handle_valid == HDF_HANDLE_FILE)
{
pos = ftell(hfd->handle->f);
if (pos == -1)
{
gui_message(_T("hd: poscheck failed. seek failure"));
abort ();
}
} else if (hfd->handle_valid == HDF_HANDLE_ZFILE) {
pos = zfile_ftell (hfd->handle->zf);
}
if (len < 0) {
gui_message (_T("hd: poscheck failed, negative length! (%d)"), len);
else if (hfd->handle_valid == HDF_HANDLE_ZFILE)
{
pos = zfile_ftell(hfd->handle->zf);
}
if (len < 0)
{
gui_message(_T("hd: poscheck failed, negative length! (%d)"), len);
abort ();
}
if (pos < hfd->offset) {
gui_message (_T("hd: poscheck failed, offset out of bounds! (%I64d < %I64d)"), pos, hfd->offset);
if (pos < hfd->offset)
{
gui_message(_T("hd: poscheck failed, offset out of bounds! (%I64d < %I64d)"), pos, hfd->offset);
abort ();
}
if (pos >= hfd->offset + hfd->physsize - hfd->virtual_size || pos >= hfd->offset + hfd->physsize + len - hfd->virtual_size) {
gui_message (_T("hd: poscheck failed, offset out of bounds! (%I64d >= %I64d, LEN=%d)"), pos, hfd->offset + hfd->physsize, len);
if (pos >= hfd->offset + hfd->physsize - hfd->virtual_size || pos >= hfd->offset + hfd->physsize + len - hfd->virtual_size)
{
gui_message(_T("hd: poscheck failed, offset out of bounds! (%I64d >= %I64d, LEN=%d)"), pos, hfd->offset + hfd->physsize, len);
abort ();
}
if (pos & (hfd->ci.blocksize - 1)) {
gui_message (_T("hd: poscheck failed, offset not aligned to blocksize! (%I64X & %04X = %04X\n"), pos, hfd->ci.blocksize, pos & hfd->ci.blocksize);
if (pos & (hfd->ci.blocksize - 1))
{
gui_message(_T("hd: poscheck failed, offset not aligned to blocksize! (%I64X & %04X = %04X\n"), pos, hfd->ci.blocksize, pos & hfd->ci.blocksize);
abort ();
}
}
static int isincache (struct hardfiledata *hfd, uae_u64 offset, int len)
static int isincache(struct hardfiledata* hfd, uae_u64 offset, int len)
{
if (!hfd->cache_valid)
return -1;
if (offset >= hfd->cache_offset && offset + len <= hfd->cache_offset + CACHE_SIZE)
return (int)(offset - hfd->cache_offset);
return int(offset - hfd->cache_offset);
return -1;
}
static int hdf_read_2 (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
static int hdf_read_2(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len)
{
int outlen = 0;
int coffset;
if (offset == 0)
hfd->cache_valid = 0;
coffset = isincache (hfd, offset, len);
if (coffset >= 0) {
memcpy (buffer, hfd->cache + coffset, len);
coffset = isincache(hfd, offset, len);
if (coffset >= 0)
{
memcpy(buffer, hfd->cache + coffset, len);
return len;
}
hfd->cache_offset = offset;
if (offset + CACHE_SIZE > hfd->offset + (hfd->physsize - hfd->virtual_size))
hfd->cache_offset = hfd->offset + (hfd->physsize - hfd->virtual_size) - CACHE_SIZE;
hdf_seek (hfd, hfd->cache_offset);
poscheck (hfd, CACHE_SIZE);
hdf_seek(hfd, hfd->cache_offset);
poscheck(hfd, CACHE_SIZE);
if (hfd->handle_valid == HDF_HANDLE_FILE)
outlen = fread(hfd->cache, 1, CACHE_SIZE, hfd->handle->f);
else if (hfd->handle_valid == HDF_HANDLE_ZFILE)
outlen = zfile_fread (hfd->cache, 1, CACHE_SIZE, hfd->handle->zf);
outlen = zfile_fread(hfd->cache, 1, CACHE_SIZE, hfd->handle->zf);
hfd->cache_valid = 0;
if (outlen != CACHE_SIZE)
return 0;
hfd->cache_valid = 1;
coffset = isincache (hfd, offset, len);
if (coffset >= 0) {
memcpy (buffer, hfd->cache + coffset, len);
coffset = isincache(hfd, offset, len);
if (coffset >= 0)
{
memcpy(buffer, hfd->cache + coffset, len);
return len;
}
write_log (_T("hdf_read: cache bug! offset=%I64d len=%d\n"), offset, len);
@ -263,38 +352,46 @@ static int hdf_read_2 (struct hardfiledata *hfd, void *buffer, uae_u64 offset, i
return 0;
}
int hdf_read_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
int hdf_read_target(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len)
{
int got = 0;
uae_u8 *p = (uae_u8*)buffer;
uae_u8* p = static_cast<uae_u8*>(buffer);
if (hfd->drive_empty)
return 0;
if (offset < hfd->virtual_size) {
if (offset < hfd->virtual_size)
{
uae_u64 len2 = offset + len <= hfd->virtual_size ? len : hfd->virtual_size - offset;
if (!hfd->virtual_rdb)
return 0;
memcpy (buffer, hfd->virtual_rdb + offset, len2);
memcpy(buffer, hfd->virtual_rdb + offset, len2);
return len2;
}
offset -= hfd->virtual_size;
while (len > 0) {
while (len > 0)
{
int maxlen;
int ret;
if (hfd->physsize < CACHE_SIZE) {
if (hfd->physsize < CACHE_SIZE)
{
hfd->cache_valid = 0;
hdf_seek (hfd, offset);
poscheck (hfd, len);
if (hfd->handle_valid == HDF_HANDLE_FILE) {
ret = fread (hfd->cache, 1, len, hfd->handle->f);
memcpy (buffer, hfd->cache, ret);
} else if (hfd->handle_valid == HDF_HANDLE_ZFILE) {
ret = zfile_fread (buffer, 1, len, hfd->handle->zf);
hdf_seek(hfd, offset);
poscheck(hfd, len);
if (hfd->handle_valid == HDF_HANDLE_FILE)
{
ret = fread(hfd->cache, 1, len, hfd->handle->f);
memcpy(buffer, hfd->cache, ret);
}
else if (hfd->handle_valid == HDF_HANDLE_ZFILE)
{
ret = zfile_fread(buffer, 1, len, hfd->handle->zf);
}
maxlen = len;
} else {
}
else
{
maxlen = len > CACHE_SIZE ? CACHE_SIZE : len;
ret = hdf_read_2 (hfd, p, offset, maxlen);
ret = hdf_read_2(hfd, p, offset, maxlen);
}
got += ret;
if (ret != maxlen)
@ -306,7 +403,7 @@ int hdf_read_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int
return got;
}
static int hdf_write_2 (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
static int hdf_write_2(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len)
{
int outlen = 0;
@ -315,45 +412,62 @@ static int hdf_write_2 (struct hardfiledata *hfd, void *buffer, uae_u64 offset,
if (hfd->dangerous)
return 0;
hfd->cache_valid = 0;
hdf_seek (hfd, offset);
poscheck (hfd, len);
memcpy (hfd->cache, buffer, len);
if (hfd->handle_valid == HDF_HANDLE_FILE) {
TCHAR *name = hfd->emptyname == NULL ? (char *) _T("<unknown>") : hfd->emptyname;
outlen = fwrite (hfd->cache, 1, len, hfd->handle->f);
hdf_seek(hfd, offset);
poscheck(hfd, len);
memcpy(hfd->cache, buffer, len);
if (hfd->handle_valid == HDF_HANDLE_FILE)
{
const TCHAR* name = hfd->emptyname == nullptr ? _T("<unknown>") : hfd->emptyname;
if (offset == 0) {
int outlen2;
uae_u8 *tmp;
int tmplen = 512;
tmp = (uae_u8*)malloc (tmplen);
if (tmp) {
memset (tmp, 0xa1, tmplen);
hdf_seek (hfd, offset);
outlen2 = fread (tmp, 1, tmplen, hfd->handle->f);
if (memcmp (hfd->cache, tmp, tmplen) != 0 || outlen != len)
gui_message (_T("\"%s\"\n\nblock zero write failed!"), name);
free (tmp);
if (!hfd->handle->firstwrite && (hfd->flags & HFD_FLAGS_REALDRIVE) && !(hfd->flags & HFD_FLAGS_REALDRIVEPARTITION)) {
hfd->handle->firstwrite = true;
//TODO: implement ismounted()
/*if (ismounted(hfd->device_name, hfd->handle->f)) {
gui_message(_T("\"%s\"\n\nBlock zero write attempt but drive has one or more mounted partitions. Erase the drive or unmount all partitions first."), name);
hfd->ci.readonly = true;
return 0;
}*/
}
}
} else if (hfd->handle_valid == HDF_HANDLE_ZFILE) {
outlen = zfile_fwrite (hfd->cache, 1, len, hfd->handle->zf);
outlen = fwrite(hfd->cache, 1, len, hfd->handle->f);
if (offset == 0)
{
int outlen2;
uae_u8* tmp;
int tmplen = 512;
tmp = static_cast<uae_u8*>(malloc(tmplen));
if (tmp)
{
memset(tmp, 0xa1, tmplen);
hdf_seek(hfd, offset);
outlen2 = fread(tmp, 1, tmplen, hfd->handle->f);
if (memcmp(hfd->cache, tmp, tmplen) != 0 || outlen != len)
gui_message(_T("\"%s\"\n\nblock zero write failed!"), name);
free(tmp);
}
}
}
else if (hfd->handle_valid == HDF_HANDLE_ZFILE)
{
outlen = zfile_fwrite(hfd->cache, 1, len, hfd->handle->zf);
}
return outlen;
}
int hdf_write_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
int hdf_write_target(struct hardfiledata* hfd, void* buffer, uae_u64 offset, int len)
{
int got = 0;
uae_u8 *p = (uae_u8*)buffer;
uae_u8* p = static_cast<uae_u8*>(buffer);
if (hfd->drive_empty)
return 0;
if (offset < hfd->virtual_size)
return len;
offset -= hfd->virtual_size;
while (len > 0) {
while (len > 0)
{
int maxlen = len > CACHE_SIZE ? CACHE_SIZE : len;
int ret = hdf_write_2 (hfd, p, offset, maxlen);
int ret = hdf_write_2(hfd, p, offset, maxlen);
if (ret < 0)
return ret;
got += ret;
@ -365,3 +479,13 @@ int hdf_write_target (struct hardfiledata *hfd, void *buffer, uae_u64 offset, in
}
return got;
}
static void generatestorageproperty(struct uae_driveinfo *udi, int ignoreduplicates)
{
_tcscpy(udi->vendor_id, _T("UAE"));
_tcscpy(udi->product_id, _T("DISK"));
_tcscpy(udi->product_rev, _T("1.2"));
_stprintf(udi->device_name, _T("%s"), udi->device_path);
udi->removablemedia = 1;
}