Code improvements for hardfile handling
This commit is contained in:
parent
c85ae3f98a
commit
dcd0525cc4
2 changed files with 357 additions and 194 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue