return ret;
}
-static int getfunc (struct devstruct *dev, uae_u8 *d, int *len)
+static int getfunc (struct s2devstruct *dev, uae_u8 *d, int *len)
{
int tlen;
return 1; // just allow everything
}
-static void gotfunc (struct devstruct *dev, const uae_u8 *data2, int len)
+static void gotfunc (struct s2devstruct *dev, const uae_u8 *data2, int len)
{
int i;
int size, insize, first;
STATIC_INLINE bool usehacks (void)
{
- return currprefs.cpu_model >= 68020 || currprefs.m68k_speed != -1;
+ return currprefs.cpu_model >= 68020 || currprefs.m68k_speed != 0;
}
#define SINC_QUEUE_MAX_AGE 2048
static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES];
static int openlist[MAX_TOTAL_SCSI_DEVICES];
+static int waspaused[MAX_TOTAL_SCSI_DEVICES];
/* convert minutes, seconds and frames -> logical sector number */
int msf2lsn (int msf)
int sys_command_open (int unitnum)
{
+ waspaused[unitnum] = 0;
return sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : NULL);
}
void sys_command_close (int unitnum)
{
+ waspaused[unitnum] = 0;
if (openlist[unitnum] <= 0)
write_log (L"BUG unit %d close: opencnt=%d!\n", unitnum, openlist[unitnum]);
if (device_func[unitnum]) {
return 1;
}
+void blkdev_entergui (void)
+{
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ waspaused[i] = 0;
+ struct device_info di;
+ if (sys_command_info (i, &di, 1)) {
+ if (sys_command_cd_pause (i, 1) == 0)
+ waspaused[i] = 1;
+ }
+ }
+}
+void blkdev_exitgui (void)
+{
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (waspaused[i]) {
+ struct device_info di;
+ if (sys_command_info (i, &di, 1)) {
+ sys_command_cd_pause (i, 0);
+ }
+ }
+ waspaused[i] = 0;
+ }
+}
+
+
+
static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256];
static int imagechangetime[MAX_TOTAL_SCSI_DEVICES];
static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES], wasopen[MAX_TOTAL_SCSI_DEVICES];
struct device_info *sys_command_info (int unitnum, struct device_info *di, int quick)
{
+ if (failunit (unitnum))
+ return NULL;
return device_func[unitnum]->info (unitnum, di, quick);
}
as->status = scsi_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen);
- as->cmdactual = as->status == 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */
+ as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */
if (as->status) {
io_error = 45; /* HFERR_BadStatus */
as->sense_len = senselen;
}
#endif
+
play_subchannel_callback cdda_subfunc;
int imagechange;
- int donotmountme;
TCHAR newfile[MAX_DPATH];
uae_sem_t sub_sem;
struct device_info di;
static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES];
static int bus_open;
+static volatile int cdimage_unpack_thread, cdimage_unpack_active;
+static smp_comm_pipe unpack_pipe;
+
static struct cdunit *unitisopen (int unitnum)
{
struct cdunit *cdu = &cdunits[unitnum];
}
static uae_u8 *flac_get_data (struct cdtoc *t)
{
- if (t->data)
- return t->data;
write_log (L"FLAC: unpacking '%s'..\n", zfile_getname (t->handle));
- t->data = xcalloc (uae_u8,t->filesize + 2352);
t->writeoffset = 0;
FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new ();
if (decoder) {
cdu->cdda_subfunc (d, 1);
}
+
+static void *cdda_unpack_func (void *v)
+{
+ cdimage_unpack_thread = 1;
+ mp3decoder *mp3dec = NULL;
+
+ for (;;) {
+ uae_u32 cduidx = read_comm_pipe_u32_blocking (&unpack_pipe);
+ if (cdimage_unpack_thread == 0)
+ break;
+ uae_u32 tocidx = read_comm_pipe_u32_blocking (&unpack_pipe);
+ struct cdunit *cdu = &cdunits[cduidx];
+ struct cdtoc *t = &cdu->toc[tocidx];
+ if (t->handle) {
+ // force unpack if handle points to delayed zipped file
+ uae_s64 pos = zfile_ftell (t->handle);
+ zfile_fseek (t->handle, -1, SEEK_END);
+ uae_u8 b;
+ zfile_fread (&b, 1, 1, t->handle);
+ zfile_fseek (t->handle, pos, SEEK_SET);
+ if (!t->data && (t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC)) {
+ t->data = xcalloc (uae_u8, t->filesize + 2352);
+ cdimage_unpack_active = 1;
+ if (t->data) {
+ if (t->enctype == AUDENC_MP3) {
+ if (!mp3dec) {
+ try {
+ mp3dec = new mp3decoder();
+ } catch (exception) { };
+ }
+ if (mp3dec)
+ t->data = mp3dec->get (t->handle, t->data, t->filesize);
+ } else if (t->enctype == AUDENC_FLAC) {
+ flac_get_data (t);
+ }
+ }
+ }
+ }
+ cdimage_unpack_active = 2;
+ }
+ delete mp3dec;
+ cdimage_unpack_thread = -1;
+ return 0;
+}
+
static void *cdda_play_func (void *v)
{
int cdda_pos;
MMRESULT mmr;
int volume[2], volume_main;
int oldplay;
- mp3decoder *mp3dec = NULL;
struct cdunit *cdu = (struct cdunit*)v;
int firstloops;
} else {
write_log (L"IMAGE CDDA: playing from %d to %d, track %d ('%s', offset %d, secoffset %d)\n",
cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector);
- if (!t->data) {
- if (t->enctype == AUDENC_MP3) {
- if (!mp3dec) {
- try {
- mp3dec = new mp3decoder();
- } catch (exception) { };
- }
- if (mp3dec)
- t->data = mp3dec->get (t->handle, t->filesize);
- } else if (t->enctype == AUDENC_FLAC) {
- flac_get_data (t);
- }
- }
+ // do this even if audio is not compressed, t->handle also could be
+ // compressed and we want to unpack it in background too
+ while (cdimage_unpack_active == 1)
+ Sleep (10);
+ cdimage_unpack_active = 0;
+ write_comm_pipe_u32 (&unpack_pipe, cdu - &cdunits[0], 0);
+ write_comm_pipe_u32 (&unpack_pipe, t - &cdu->toc[0], 1);
+ while (cdimage_unpack_active == 0)
+ Sleep (10);
}
- int millis;
- struct _timeb tb2;
- _ftime (&tb2);
- millis = (tb2.time - tb.time) * 1000;
- if (tb2.millitm >= tb.millitm)
- millis += tb2.millitm - tb.millitm;
- else
- millis += 1000 - tb.millitm + tb2.millitm;
- firstloops = 150 - millis * 75 / 1000;
+ firstloops = 150;
while (cdu->cdda_paused && cdu->cdda_play > 0) {
Sleep (10);
firstloops = -1;
int sector, cnt;
int dofinish = 0;
+ gui_flicker_led (LED_CD, cdu->di.unitnum - 1, LED_CD_AUDIO);
+
memset (px[bufnum], 0, num_sectors * 2352);
if (firstloops > 0) {
for (i = 0; i < 2; i++)
waveOutUnprepareHeader (cdda_wavehandle, &whdr[i], sizeof (WAVEHDR));
+ while (cdimage_unpack_active == 1)
+ Sleep (10);
+
cdda_closewav ();
xfree (p);
- delete mp3dec;
cdu->cdda_play = 0;
write_log (L"IMAGE CDDA: thread killed\n");
return NULL;
if (!t || t->handle == NULL)
return NULL;
cdda_stop (cdu);
- if (t->size == 2848) {
+ if (t->size == 2048) {
int offset = 0;
zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET);
zfile_fread (data, size, 2048, t->handle);
toc++;
memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head));
- gui_flicker_led (LED_CD, unitnum, 1);
return 1;
}
if (_tcsicmp (fnametype, L"BINARY") && _tcsicmp (fnametype, L"WAVE") && _tcsicmp (fnametype, L"MP3") && _tcsicmp (fnametype, L"FLAC")) {
write_log (L"CUE: unknown file type '%s' ('%s')\n", fnametype, fname);
}
- if (!_tcsicmp (fnametype, L"WAVE"))
- fnametypeid = AUDENC_PCM;
- else if (!_tcsicmp (fnametype, L"MP3"))
+ fnametypeid = AUDENC_PCM;
+ if (!_tcsicmp (fnametype, L"MP3"))
fnametypeid = AUDENC_MP3;
else if (!_tcsicmp (fnametype, L"FLAC"))
fnametypeid = AUDENC_FLAC;
}
newfile = 0;
- ztrack = zfile_fopen (fname, L"rb", ZFD_ARCHIVE);
+ ztrack = zfile_fopen (fname, L"rb", ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
if (!ztrack) {
TCHAR tmp[MAX_DPATH];
_tcscpy (tmp, fname);
p = tmp + _tcslen (tmp);
while (p > tmp) {
if (*p == '/' || *p == '\\') {
- ztrack = zfile_fopen (p + 1, L"rb", ZFD_ARCHIVE);
+ ztrack = zfile_fopen (p + 1, L"rb", ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
if (ztrack) {
xfree (fname);
fname = my_strdup (p + 1);
s2[0] = 0;
_tcscat (tmp, L"\\");
_tcscat (tmp, fname);
- ztrack = zfile_fopen (tmp, L"rb", ZFD_ARCHIVE);
+ ztrack = zfile_fopen (tmp, L"rb", ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
}
}
t->track = tracknum;
}
t->offset += zfile_ftell (zf);
t->filesize = size;
- t->enctype = fnametypeid;
}
+ t->enctype = fnametypeid;
} else if (fnametypeid == AUDENC_MP3 && t->handle) {
if (!mp3dec) {
try {
struct cdunit *cdu = &cdunits[unitnum];
memset (di, 0, sizeof (struct device_info));
if (!cdu->enabled)
- return 0;
+ return NULL;
di->open = cdu->open;
di->removable = 1;
di->bus = unitnum;
cdu->cdda_volume[0] = 0x7fff;
cdu->cdda_volume[1] = 0x7fff;
blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name);
+ if (cdimage_unpack_thread == 0) {
+ init_comm_pipe (&unpack_pipe, 10, 1);
+ uae_start_thread (L"cdimage_unpack", cdda_unpack_func, NULL, NULL);
+ while (cdimage_unpack_thread == 0)
+ Sleep (10);
+ }
return 1;
}
unload_image (cdu);
uae_sem_destroy (&cdu->sub_sem);
cdu->open = false;
- cdu->enabled = false;
blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name);
+ if (cdimage_unpack_thread) {
+ cdimage_unpack_thread = 0;
+ write_comm_pipe_u32 (&unpack_pipe, -1, 0);
+ write_comm_pipe_u32 (&unpack_pipe, -1, 1);
+ while (cdimage_unpack_thread == 0)
+ Sleep (10);
+ cdimage_unpack_thread = 0;
+ destroy_comm_pipe (&unpack_pipe);
+ }
}
static void close_bus (void)
write_log (L"IMAGE close_bus() when already closed!\n");
return;
}
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ struct cdunit *cdu = &cdunits[i];
+ if (cdu->open)
+ close_device (i);
+ cdu->enabled = false;
+ }
bus_open = 0;
write_log (L"IMAGE driver closed.\n");
}
}
}
+int disk_fifostatus (void)
+{
+ if (fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2])
+ return 1;
+ if (!fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2])
+ return -1;
+ return 0;
+}
+
static bool doreaddma (void)
{
if (dmaen (DMA_DISK) && bitoffset == 15 && dma_enable && dskdmaen == 2 && dsklength >= 0) {
}
DSKDAT (word);
dsklength--;
+ } else if (dsklength == 0 && disk_fifostatus () < 0) {
+ // zero length transfer wouldn't finish without this
+ disk_dmafinished ();
}
return true;
}
}
return v;
}
-int disk_fifostatus (void)
-{
- if (fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2])
- return 1;
- if (!fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2])
- return -1;
- return 0;
-}
uae_u16 disk_dmal (void)
{
extern int get_standard_cd_unit (enum cd_standard_unit csu);
extern void close_standard_cd_unit (int);
extern void blkdev_cd_change (int unitnum, const TCHAR *name);
+
+extern void blkdev_entergui (void);
+extern void blkdev_exitgui (void);
+
uae_u8 *data; // unpacked data
int dataseek; // use seek position even if real file
struct zfile *archiveparent; // set if parent is archive and this has not yet been unpacked (datasize < size)
+ int archiveid;
uae_s64 size; // real size
uae_s64 datasize; // available size (not yet unpacked completely?)
uae_s64 seek; // seek position
#define PEEK_BYTES 1024
#define FILE_PEEK 1
+#define FILE_DELAYEDOPEN 2
extern int zfile_is_ignore_ext (const TCHAR *name);
extern void archive_access_close (void *handle, unsigned int id);
extern struct zfile *archive_getzfile (struct znode *zn, unsigned int id, int flags);
+extern struct zfile *archive_unpackzfile (struct zfile *zf);
extern struct zfile *decompress_zfd (struct zfile*);
\ No newline at end of file
#define ZFD_CD 32 //cue/iso, cue has priority over iso
#define ZFD_DISKHISTORY 0x100 //allow diskhistory (if disk image)
#define ZFD_CHECKONLY 0x200 //file exists checkc
+#define ZFD_DELAYEDOPEN 0x400 //do not unpack, just get metadata
#define ZFD_NORMAL (ZFD_ARCHIVE|ZFD_UNPACK)
#define ZFD_ALL 0x0000ffff
cmd[4] = (uae_u8)(sector >> 8);
cmd[5] = (uae_u8)(sector >> 0);
if (unitnum >= 0)
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
int len = sizeof cmd;
return do_raw_scsi (ciw, unitnum, cmd, len, data, tlen);
}
if (!isaudiotrack (&ciw->di.toc, cdda_pos))
goto end; // data track?
+ gui_flicker_led (LED_CD, ciw->di.unitnum - 1, LED_CD_AUDIO);
+
uae_sem_wait (&ciw->sub_sem);
ciw->subcodevalid = false;
memset (ciw->subcode, 0, sizeof ciw->subcode);
if (log_scsi)
write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d\n", unitnum, sector, sectorsize);
cdda_stop (ciw);
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
if (sectorsize > 0) {
if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048 &&
sectorsize != 2336 + 96 && sectorsize != 2352 + 96 && sectorsize != 2048 + 96)
cdda_stop (ciw);
ciw->cd_last_pos = sector;
while (cnt-- > 0) {
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
seterrormode (ciw);
if (SetFilePointer (ciw->h, sector * ciw->di.bytespersector, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
reseterrormode (ciw);
break;
}
while (size-- > 0) {
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
seterrormode (ciw);
if (write) {
if (data) {
}
}
reseterrormode (ciw);
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
}
return 1;
}
if (!open_createfile (ciw, 0))
return 0;
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
while (cnt-- > 0) {
seterrormode (ciw);
if (!DeviceIoControl (ciw->h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) {
t->paddress = th->lastaddress;
t++;
- gui_flicker_led (LED_CD, unitnum, 1);
+ gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE);
memcpy (tocout, th, sizeof (struct cd_toc_head));
return 1;
}
}
}
-uae_u8 *mp3decoder::get (struct zfile *zf, int maxsize)
+uae_u8 *mp3decoder::get (struct zfile *zf, uae_u8 *outbuf, int maxsize)
{
MMRESULT mmr;
unsigned long rawbufsize = 0;
LPBYTE mp3buf;
LPBYTE rawbuf;
- uae_u8 *outbuf = NULL;
int outoffset = 0;
ACMSTREAMHEADER mp3streamHead;
HACMSTREAM h = (HACMSTREAM)g_mp3stream;
return NULL;
}
zfile_fseek(zf, 0, SEEK_SET);
- outbuf = xcalloc(uae_u8, maxsize + 2352);
for (;;) {
int count = zfile_fread(mp3buf, 1, MP3_BLOCK_SIZE, zf);
if (count != MP3_BLOCK_SIZE)
public:
mp3decoder();
~mp3decoder();
- uae_u8 *get(struct zfile *zf, int maxsize);
+ uae_u8 *get(struct zfile *zf, uae_u8 *, int maxsize);
uae_u32 mp3decoder::getsize(struct zfile *zf);
};
#include "cdtv.h"
#include "direct3d.h"
#include "clipboard_win32.h"
+#include "blkdev.h"
#ifdef RETROPLATFORM
#include "rp.h"
#endif
#ifdef CDTV
cdtv_exitgui ();
#endif
+ blkdev_exitgui ();
if (pausemouseactive)
setmouseactive (-1);
pausemouseactive = 0;
#ifdef CDTV
cdtv_entergui ();
#endif
+ blkdev_entergui ();
pausemouseactive = 1;
if (isfullscreen () <= 0) {
pausemouseactive = mouseactive;
#define WINUAEPUBLICBETA 1
#define LANG_DLL 1
-#define WINUAEBETA L"5"
-#define WINUAEDATE MAKEBD(2010, 7, 23)
+#define WINUAEBETA L"6"
+#define WINUAEDATE MAKEBD(2010, 7, 24)
#define WINUAEEXTRA L""
#define WINUAEREV L""
r = pcap_next_ex (sd->fp, &header, &pkt_data);
if (r == 1) {
uae_sem_wait (&sd->change_sem);
- sd->gotfunc ((struct devstruct*)sd->user, pkt_data, header->len);
+ sd->gotfunc ((struct s2devstruct*)sd->user, pkt_data, header->len);
uae_sem_post (&sd->change_sem);
}
if (r < 0) {
int donotwait = 0;
int towrite = sd->mtu;
uae_sem_wait (&sd->change_sem);
- if (sd->getfunc ((struct devstruct*)sd->user, sd->writebuffer, &towrite)) {
+ if (sd->getfunc ((struct s2devstruct*)sd->user, sd->writebuffer, &towrite)) {
pcap_sendpacket (sd->fp, sd->writebuffer, towrite);
donotwait = 1;
}
int active;
};
-typedef void (uaenet_gotfunc)(struct devstruct *dev, const uae_u8 *data, int len);
-typedef int (uaenet_getfunc)(struct devstruct *dev, uae_u8 *d, int *len);
+typedef void (uaenet_gotfunc)(struct s2devstruct *dev, const uae_u8 *data, int len);
+typedef int (uaenet_getfunc)(struct s2devstruct *dev, uae_u8 *d, int *len);
#define MAX_TOTAL_NET_DEVICES 10
extern int uaenet_getbytespending (void*);
extern int uaenet_open (void*, struct netdriverdata*, void*, uaenet_gotfunc*, uaenet_getfunc*, int);
extern void uaenet_close (void*);
-extern void uaenet_gotdata (struct devstruct *dev, const uae_u8 *data, int len);
-extern int uaenet_getdata (struct devstruct *dev, uae_u8 *d, int *len);
+extern void uaenet_gotdata (struct s2devstruct *dev, const uae_u8 *data, int len);
+extern int uaenet_getdata (struct s2devstruct *dev, uae_u8 *d, int *len);
extern void uaenet_trigger (void*);
idx2--;
if (p2) {
fname = my_strdup (p2 + 1);
- p2[0] = 0;
+ do {
+ *p2-- = 0;
+ } while (p2 > tmp2 && *p2 == ' ');
p2 = _tcschr (fname, '"');
if (p2)
*p2 = 0;
if (dynamic) {
if (!_stscanf (dostype, L"%x", &dt))
dt = 0;
+ if (_tcslen (init_path) > 4 && !_tcsicmp (init_path + _tcslen (init_path) - 4, L".hdf"))
+ _tcscpy (init_path + _tcslen (init_path) - 4, L".vhd");
result = vhd_create (init_path, hfsize, dt);
} else {
SetCursor (LoadCursor (NULL, IDC_WAIT));
{ 0, 0, 0 }
};
-static void harddiskdlg_button (HWND hDlg, WPARAM wParam)
+static int harddiskdlg_button (HWND hDlg, WPARAM wParam)
{
int button = LOWORD (wParam);
switch (button) {
archivehd = 0;
if (CustomDialogBox (IDD_FILESYS, hDlg, VolumeSettingsProc))
new_filesys (hDlg, -1);
- break;
+ return 1;
case IDC_NEW_FSARCH:
archivehd = 1;
current_fsvdlg = empty_fsvdlg;
if (CustomDialogBox (IDD_FILESYS, hDlg, VolumeSettingsProc))
new_filesys (hDlg, -1);
- break;
+ return 1;
case IDC_NEW_HF:
current_hfdlg = empty_hfdlg;
if (CustomDialogBox (IDD_HARDFILE, hDlg, HardfileSettingsProc))
new_hardfile (hDlg, -1);
- break;
+ return 1;
case IDC_NEW_HD:
memset (¤t_hfdlg, 0, sizeof (current_hfdlg));
if (CustomDialogBox (IDD_HARDDRIVE, hDlg, HarddriveSettingsProc))
new_harddrive (hDlg, -1);
}
- break;
+ return 1;
case IDC_EDIT:
harddisk_edit (hDlg);
- break;
+ return 1;
case IDC_REMOVE:
harddisk_remove (hDlg);
- break;
+ return 1;
case IDC_UP:
harddisk_move (hDlg, 1);
clicked_entry--;
- break;
+ return 1;
case IDC_DOWN:
harddisk_move (hDlg, 0);
clicked_entry++;
- break;
+ return 1;
case IDC_MAPDRIVES_AUTO:
workprefs.win32_automount_removable = ischecked (hDlg, IDC_MAPDRIVES_AUTO);
break;
}
+ return 0;
}
static void harddiskdlg_volume_notify (HWND hDlg, NM_LISTVIEW *nmlistview)
hilitehd ();
break;
default:
- harddiskdlg_button (hDlg, wParam);
- InitializeListView (hDlg);
- hilitehd ();
+ if (harddiskdlg_button (hDlg, wParam)) {
+ InitializeListView (hDlg);
+ hilitehd ();
+ }
break;
}
}
+- MP3/FLAC background decompression, no more delayed CDA startup if audio file
+ decompression takes more than 2 seconds
+- implemented "delayed decompression" zfile open flag, currently only zip backend supports it
+ and it is only enabled when using CD images. Most zipped CD images with big audio files
+ start almost instantly now
+- potential memory corruption crash in zfile_fclose() if file had parent file(s)
+- zero length disk DMA (used by some copy protections) never finished, broke in b1
+- fixed extra space characters in favorite menu items
+- pause uaescsi.device CDA when emulation is paused or GUI is open
+- uaescsi.device CDA lights green on screen CD led
+- cue/bin audio tracks were completely silent (cue/wav worked)
+- on the fly image switching didn't send uaescsi.device change interrupts correctly
+ if CDFS polling flag was disabled (empty drive without diskchange command)
+- new dynamic hardfiles have .vhd extension instead of .hdf
+
+Beta 5
+
+- version number bumped to 2.3
- few lines of non-filter scanlines was missing in bottom part of display
+- audio DMA start interrupt is now immediate after starting DMA in too fast CPU modes
+ (normally when audio state changes to 5), fixes EasyACDDA hang. Seems to be
+ yet another audio.device bug when CPU and memory is "too fast"..
+
+More CD related changes and updates:
+
+- unified CD32/CDTV CD unit allocation, also internal unit number is always zero =
+ GUI CD media change now work as expected
+- CDTV frontpanel Stop now quits frontpanel/CD+G mode correctly
+- added more obsolete SCSI commands: PLAY AUDIO TRACK RELATIVE (10) and (12) and
+ PLAY AUDIO (12) (10-byte version was added in b4)
+- CDTV subchannel hardware interrupt timing improved, CD+G works in cycle-exact mode now
+- cd configuration code cleanups
+- added mds/mdf image format (only v1 and first session, v2 appears to be scrambled..)
+- cdimage0 in configuration file now disables all following units (backwards compatiblity)
+ add 2 or more cdimage[0-7]= lines in increasing order if you want multiple units configured
+- cue/ccd/iso/mds detection in zipped cd images stopped working
+- moved 2048 to 2352 byte sector conversion code to generic image mounter code from CD32
+ emulation, CD32 FMV ROM now detects VideoCDs (and then it hangs)
- mp3 cd audio: detect audio length using ID3v2 TLEN tag if it exists, assume it is CBR MP3 if
- first 100 frames have same bit rate, fallback to original slow full file scan if no tags and VBR
-- remove mp3 decoding time from audio playback delay time, better av sync if decoding takes less
+ first 100 frames have equal bit rate, fallback to original slow full file scan if no tags and VBR
+- remove mp3 decoding time from audio playback delay time, keeps av sync if decoding takes less
than 2 seconds
+- FLAC CD audio tracks supported (cue/iso/flac), perhaps this will be useful in future..
+ (remember to redownload winuaeinclibs.zip if you want to recompile this or future versions)
+- note that currently both mp3 and flac decoding needs to finish before playback starts which
+ can take few seconds on slow machines
+- some XP-only CD access issues fixed, tested on VMware workstation (donated by Cloanto).
+ VirtualPC sucks too much.
+- when looking for cue/iso/ccd/mds inside archives: do not attempt to autodetect (unpack)
+ other files. CD image archives containing audio tracks should start faster now (all audio
+ tracks are still unpacked at startup but previously they were unpacked twice)
+
+Future todo: hardware IDE (ATAPI) and SCSI emulation to CD SCSI emulation connection, no big CD
+GUI updates until it has been designed. (won't be done in this beta series)
Beta 4:
Audio CD inserted), unit 0 changes are ignored until original drive becomes empty. This
needs to be more intelligent.
-Configuration file accepts cdimage0 to cdimage7. Full syntax:
-cdimagex=image path or device name,cd backend(:reserved for future)
-Cd backend not mandatory. Supported CD backend names are:
-image, ioctl, spti and aspi. (this is autoselected when using GUI)
-
Beta 3:
- most debugger options now accept .b, .w and .l size extension (+special .3 if 3-byte word),
int cnt;
};
-struct devstruct {
+struct s2devstruct {
int unit, opencnt, exclusive, promiscuous;
struct asyncreq *ar;
struct asyncreq *s2p;
#define FLUSH_TIMEOUT 20
-struct priv_devstruct {
+struct priv_s2devstruct {
int inuse;
int unit;
int flags; /* OpenDevice() */
};
static struct netdriverdata *td;
-static struct devstruct devst[MAX_TOTAL_NET_DEVICES];
-static struct priv_devstruct pdevst[MAX_OPEN_DEVICES];
+static struct s2devstruct devst[MAX_TOTAL_NET_DEVICES];
+static struct priv_s2devstruct pdevst[MAX_OPEN_DEVICES];
static uae_u32 nscmd_cmd;
static uae_sem_t change_sem, async_sem;
-static struct devstruct *getdevstruct (int unit)
+static struct s2devstruct *gets2devstruct (int unit)
{
if (unit >= MAX_TOTAL_NET_DEVICES || unit < 0)
return 0;
return &devst[unit];
}
-static struct priv_devstruct *getpdevstruct (uaecptr request)
+static struct priv_s2devstruct *getps2devstruct (uaecptr request)
{
int i = get_long (request + 24);
if (i < 0 || i >= MAX_OPEN_DEVICES || pdevst[i].inuse == 0) {
}
static void *dev_thread (void *devs);
-static int start_thread (struct devstruct *dev)
+static int start_thread (struct s2devstruct *dev)
{
if (dev->thread_running)
return 1;
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context)
{
uae_u32 request = m68k_areg (regs, 1);
- struct priv_devstruct *pdev = getpdevstruct (request);
- struct devstruct *dev;
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
+ struct s2devstruct *dev;
if (!pdev) {
write_log (L"%s close with unknown request %08X!?\n", SANA2NAME, request);
return 0;
}
- dev = getdevstruct (pdev->unit);
+ dev = gets2devstruct (pdev->unit);
if (!dev) {
write_log (L"%s:%d close with unknown request %08X!?\n", SANA2NAME, pdev->unit, request);
return 0;
uae_u32 unit = m68k_dreg (regs, 0);
uae_u32 flags = m68k_dreg (regs, 1);
uaecptr buffermgmt;
- struct devstruct *dev = getdevstruct (unit);
- struct priv_devstruct *pdev = 0;
+ struct s2devstruct *dev = gets2devstruct (unit);
+ struct priv_s2devstruct *pdev = 0;
int i;
uaecptr tagp, tagpnext;
xfree (s2p);
}
-static void add_async_packet (struct devstruct *dev, struct s2packet *s2p, uaecptr request)
+static void add_async_packet (struct s2devstruct *dev, struct s2packet *s2p, uaecptr request)
{
struct asyncreq *ar, *ar2;
ar->request = request;
}
-static void rem_async_packet (struct devstruct *dev, uaecptr request)
+static void rem_async_packet (struct s2devstruct *dev, uaecptr request)
{
struct asyncreq *ar, *prevar;
uae_sem_post (&async_sem);
}
-static struct asyncreq *get_async_request (struct devstruct *dev, uaecptr request, int ready)
+static struct asyncreq *get_async_request (struct s2devstruct *dev, uaecptr request, int ready)
{
struct asyncreq *ar;
int ret = 0;
return ar;
}
-static int add_async_request (struct devstruct *dev, uaecptr request)
+static int add_async_request (struct s2devstruct *dev, uaecptr request)
{
struct asyncreq *ar, *ar2;
return 1;
}
-static int release_async_request (struct devstruct *dev, uaecptr request)
+static int release_async_request (struct s2devstruct *dev, uaecptr request)
{
struct asyncreq *ar, *prevar;
return 0;
}
-static void do_abort_async (struct devstruct *dev, uaecptr request)
+static void do_abort_async (struct s2devstruct *dev, uaecptr request)
{
put_byte (request + 30, get_byte (request + 30) | 0x20);
put_byte (request + 31, IOERR_ABORTED);
write_comm_pipe_u32 (&dev->requests, request, 1);
}
-static void abort_async (struct devstruct *dev, uaecptr request)
+static void abort_async (struct s2devstruct *dev, uaecptr request)
{
struct asyncreq *ar = get_async_request (dev, request, 1);
if (!ar) {
do_abort_async (dev, request);
}
-static void signalasync (struct devstruct *dev, struct asyncreq *ar, int actual, int err)
+static void signalasync (struct s2devstruct *dev, struct asyncreq *ar, int actual, int err)
{
uaecptr request = ar->request;
int command = get_word (request + 28);
return addr;
}
-static void addmulticastaddresses (struct devstruct *dev, uae_u64 start, uae_u64 end)
+static void addmulticastaddresses (struct s2devstruct *dev, uae_u64 start, uae_u64 end)
{
struct mcast *mc, *mc2;
mc2->next = mc;
}
}
-static int delmulticastaddresses (struct devstruct *dev, uae_u64 start, uae_u64 end)
+static int delmulticastaddresses (struct s2devstruct *dev, uae_u64 start, uae_u64 end)
{
struct mcast *mc, *prevmc;
return 0;
}
-static struct s2packet *createreadpacket (struct devstruct *dev, const uae_u8 *d, int len)
+static struct s2packet *createreadpacket (struct s2devstruct *dev, const uae_u8 *d, int len)
{
struct s2packet *s2p = xcalloc (struct s2packet, 1);
s2p->data = xmalloc (uae_u8, dev->td->mtu + ETH_HEADER_SIZE + 2);
return s2p;
}
-static int handleread (TrapContext *ctx, struct priv_devstruct *pdev, uaecptr request, uae_u8 *d, int len, int cmd)
+static int handleread (TrapContext *ctx, struct priv_s2devstruct *pdev, uaecptr request, uae_u8 *d, int len, int cmd)
{
uae_u8 flags = get_byte (request + 30);
uaecptr data = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4);
return 1;
}
-void uaenet_gotdata (struct devstruct *dev, const uae_u8 *d, int len)
+void uaenet_gotdata (struct s2devstruct *dev, const uae_u8 *d, int len)
{
uae_u16 type;
struct mcast *mc;
uaecptr srcaddr = request + 32 + 4 + 4;
uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES;
uae_u16 packettype = get_long (request + 32 + 4);
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
struct s2packet *s2p;
if (!pdev)
return s2p;
}
-static int uaenet_getdata (struct devstruct *dev, uae_u8 *d, int *len)
+static int uaenet_getdata (struct s2devstruct *dev, uae_u8 *d, int *len)
{
int gotit;
struct asyncreq *ar;
int command = get_word (request + 28);
uae_u32 packettype = get_long (request + 32 + 4);
if (command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) {
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
struct asyncreq *ars2p = dev->s2p;
while (ars2p) {
if (ars2p->request == request) {
return gotit;
}
-void checkevents (struct devstruct *dev, int mask, int sem)
+void checkevents (struct s2devstruct *dev, int mask, int sem)
{
struct asyncreq *ar;
uae_sem_post (&async_sem);
}
-static int checksize (uaecptr request, struct devstruct *dev)
+static int checksize (uaecptr request, struct s2devstruct *dev)
{
uae_u32 datalength = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2);
return 1;
}
-static void flush (struct priv_devstruct *pdev)
+static void flush (struct priv_s2devstruct *pdev)
{
struct asyncreq *ar;
- struct devstruct *dev;
+ struct s2devstruct *dev;
- dev = getdevstruct (pdev->unit);
+ dev = gets2devstruct (pdev->unit);
ar = dev->ar;
while (ar) {
- if (!ar->ready && getpdevstruct (ar->request) == pdev) {
+ if (!ar->ready && getps2devstruct (ar->request) == pdev) {
ar->ready = 1;
do_abort_async (dev, ar->request);
}
}
}
-static int dev_do_io_2 (struct devstruct *dev, uaecptr request, int quick)
+static int dev_do_io_2 (struct s2devstruct *dev, uaecptr request, int quick)
{
uae_u8 flags = get_byte (request + 30);
uae_u32 command = get_word (request + 28);
uae_u32 wire_error = 0;
int i;
int async = 0;
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
if (log_net)
write_log (L"S2: C=%02d T=%04X S=%02X%02X%02X%02X%02X%02X D=%02X%02X%02X%02X%02X%02X L=%d D=%08X SD=%08X BM=%08X\n",
return async;
}
-static int dev_do_io (struct devstruct *dev, uaecptr request, int quick)
+static int dev_do_io (struct s2devstruct *dev, uaecptr request, int quick)
{
uae_u32 command = get_word (request + 28);
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
uaecptr data = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4);
put_byte (request + 31, 0);
return 0;
}
-static int dev_canquick (struct devstruct *dev, uaecptr request)
+static int dev_canquick (struct s2devstruct *dev, uaecptr request)
{
uae_u32 command = get_word (request + 28);
return dev_can_quick (command);
uae_u32 request = m68k_areg (regs, 1);
uae_u8 flags = get_byte (request + 30);
int command = get_word (request + 28);
- struct priv_devstruct *pdev = getpdevstruct (request);
- struct devstruct *dev;
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
+ struct s2devstruct *dev;
put_byte (request + 8, NT_MESSAGE);
if (!pdev) {
put_byte (request + 31, 32);
return get_byte (request + 31);
}
- dev = getdevstruct (pdev->unit);
+ dev = gets2devstruct (pdev->unit);
if (!dev) {
write_log (L"%s unknown iorequest (2) %08x\n", getdevname (), request);
put_byte (request + 31, 32);
static void *dev_thread (void *devs)
{
- struct devstruct *dev = (struct devstruct*)devs;
+ struct s2devstruct *dev = (struct s2devstruct*)devs;
uae_set_thread_priority (NULL, 1);
dev->thread_running = 1;
static uae_u32 REGPARAM2 dev_abortio (TrapContext *context)
{
uae_u32 request = m68k_areg (regs, 1);
- struct priv_devstruct *pdev = getpdevstruct (request);
- struct devstruct *dev;
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
+ struct s2devstruct *dev;
if (!pdev) {
write_log (L"%s abortio but no request %08x found!\n", getdevname(), request);
put_byte (request + 31, 32);
return get_byte (request + 31);
}
- dev = getdevstruct (pdev->unit);
+ dev = gets2devstruct (pdev->unit);
if (!dev) {
write_log (L"%s (%d) abortio but no request %08x found!\n", getdevname(), pdev->unit, request);
put_byte (request + 31, 32);
pdevst[i].tmp = 0;
for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) {
- struct devstruct *dev = &devst[i];
+ struct s2devstruct *dev = &devst[i];
struct s2packet *p;
if (dev->online) {
while (dev->readqueue) {
int command = get_word (request + 28);
uae_u32 packettype = get_long (request + 32 + 4);
if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) {
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
if (pdev && pdev->tmp == 0) {
if (handleread (ctx, pdev, request, p->data, p->len, command)) {
if (log_net)
uaecptr request = ar->request;
int command = get_word (request + 28);
if (command == S2_READORPHAN) {
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
if (pdev && pdev->tmp <= 0) {
if (log_net)
write_log (L"-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n", p, request, p->len);
uaecptr request = ar->request;
int command = get_word (request + 28);
if (command == S2_ONLINE) {
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
dev->packetsreceived = 0;
dev->packetssent = 0;
dev->baddata = 0;
write_comm_pipe_u32 (&dev->requests, request, 1);
uaenet_vsync_requested--;
} else {
- struct priv_devstruct *pdev = getpdevstruct (request);
+ struct priv_s2devstruct *pdev = getps2devstruct (request);
if (pdev) {
dev->flush_timeout--;
if (dev->flush_timeout <= 0) {
static void dev_reset (void)
{
int i;
- struct devstruct *dev;
+ struct s2devstruct *dev;
int unitnum = 0;
write_log (L"%s reset\n", getdevname());
}
while (dev->mc)
delmulticastaddresses (dev, dev->mc->start, dev->mc->end);
- memset (dev, 0, sizeof (struct devstruct));
+ memset (dev, 0, sizeof (struct s2devstruct));
}
for (i = 0; i < MAX_OPEN_DEVICES; i++)
- memset (&pdevst[i], 0, sizeof (struct priv_devstruct));
+ memset (&pdevst[i], 0, sizeof (struct priv_s2devstruct));
uaenet_vsync_requested = 0;
uaenet_int_requested = 0;
irq_init = 0;
zc->tm = time (NULL);
return zc;
}
-
+
+static void checkarchiveparent (struct zfile *z)
+{
+ // unpack completely if opened in PEEK mode
+ if (z->archiveparent)
+ archive_unpackzfile (z);
+}
+
static struct zfile *zfile_create (struct zfile *prev)
{
struct zfile *z;
void zfile_fclose (struct zfile *f)
{
- struct zfile *pl = NULL;
- struct zfile *l = zlist;
- struct zfile *nxt;
-
//write_log (L"%p\n", f);
if (!f)
return;
if (f->parent->opencnt <= 0)
zfile_fclose (f->parent);
}
+ if (f->archiveparent) {
+ zfile_fclose (f->archiveparent);
+ f->archiveparent = NULL;
+ }
+ struct zfile *pl = NULL;
+ struct zfile *nxt;
+ struct zfile *l = zlist;
while (l != f) {
if (l == 0) {
write_log (L"zfile: tried to free already freed or nonexisting filehandle!\n");
struct zfile *nzf;
if (!zf)
return NULL;
+ if (zf->archiveparent)
+ checkarchiveparent (zf);
if (zf->userdata)
return NULL;
if (!zf->data && zf->dataseek) {
memcpy (nzf->data, zf->data, zf->size);
nzf->size = zf->size;
nzf->datasize = zf->datasize;
- } else if (zf->zipname) {
- nzf = openzip (zf->name);
- return nzf;
- } else {
+ } else {
+ if (zf->zipname) {
+ nzf = openzip (zf->name);
+ if (nzf)
+ return nzf;
+ }
+ FILE *ff = _tfopen (zf->name, zf->mode);
+ if (!ff)
+ return NULL;
nzf = zfile_create (zf);
- nzf->f = _tfopen (zf->name, zf->mode);
+ nzf->f = ff;
}
zfile_fseek (nzf, zf->seek, SEEK_SET);
if (zf->name)
return z->zfileread (b, l1, l2, z);
if (z->data) {
if (z->datasize < z->size && z->seek + l1 * l2 > z->datasize) {
- write_log (L"zfile_fread(%s) attempted to read past PEEK_BYTES\n", z->name);
-
+ if (z->archiveparent) {
+ archive_unpackzfile (z);
+ return zfile_fread (b, l1, l2, z);
+ }
return 0;
}
if (z->seek + l1 * l2 > z->size) {
size_t zfile_fwrite (void *b, size_t l1, size_t l2, struct zfile *z)
{
+ if (z->archiveparent)
+ return 0;
if (z->zfilewrite)
return z->zfilewrite (b, l1, l2, z);
if (z->parent && z->useparent)
char *zfile_fgetsa (char *s, int size, struct zfile *z)
{
+ checkarchiveparent (z);
if (z->data) {
char *os = s;
int i;
TCHAR *zfile_fgets (TCHAR *s, int size, struct zfile *z)
{
+ checkarchiveparent (z);
if (z->data) {
char s2[MAX_DPATH];
char *p = s2;
int zfile_getc (struct zfile *z)
{
+ checkarchiveparent (z);
int out = -1;
if (z->data) {
if (z->seek < z->size) {
zfile_fseek (z, 0, SEEK_SET);
}
b = xmalloc (uae_u8, len);
- if (z->data) {
- memcpy (b, z->data + offset, len);
- } else {
- pos = zfile_ftell (z);
- zfile_fseek (z, offset, SEEK_SET);
- zfile_fread (b, len, 1, z);
- zfile_fseek (z, pos, SEEK_SET);
- }
+ pos = zfile_ftell (z);
+ zfile_fseek (z, offset, SEEK_SET);
+ zfile_fread (b, len, 1, z);
+ zfile_fseek (z, pos, SEEK_SET);
return b;
}
#include <zlib.h>
+#define unpack_log write_log
+
static time_t fromdostime (uae_u32 dd)
{
struct tm tm;
return zv;
}
-struct zfile *archive_getzfile (struct znode *zn, unsigned int id, int flags)
-{
- struct zfile *zf = NULL;
-
- switch (id)
- {
- case ArchiveFormatZIP:
- zf = archive_access_zip (zn, flags);
- break;
- case ArchiveFormat7Zip:
- zf = archive_access_7z (zn);
- break;
- case ArchiveFormatRAR:
- zf = archive_access_rar (zn);
- break;
- case ArchiveFormatLHA:
- zf = archive_access_lha (zn);
- break;
- case ArchiveFormatLZX:
- zf = archive_access_lzx (zn);
- break;
- case ArchiveFormatPLAIN:
- zf = archive_access_plain (zn);
- break;
- case ArchiveFormatADF:
- zf = archive_access_adf (zn);
- break;
- case ArchiveFormatRDB:
- zf = archive_access_rdb (zn);
- break;
- case ArchiveFormatFAT:
- zf = archive_access_fat (zn);
- break;
- case ArchiveFormatDIR:
- zf = archive_access_dir (zn);
- break;
- case ArchiveFormatTAR:
- zf = archive_access_tar (zn);
- break;
- }
- return zf;
-}
-
struct zfile *archive_access_select (struct znode *parent, struct zfile *zf, unsigned int id, int dodefault, int *retcode, int index)
{
struct zvolume *zv;
int diskimg;
int mask = zf->zfdmask;
int canhistory = (mask & ZFD_DISKHISTORY) && !(mask & ZFD_CHECKONLY);
+ int getflag = (mask & ZFD_DELAYEDOPEN) ? FILE_DELAYEDOPEN : 0;
if (retcode)
*retcode = 0;
ft = ZFILE_CDIMAGE;
}
} else {
- zt = archive_getzfile (zn, id, FILE_PEEK);
+ zt = archive_getzfile (zn, id, getflag);
ft = zfile_gettype (zt);
}
if ((select < 0 || ft) && whf > we_have_file) {
if (!zt)
- zt = archive_getzfile (zn, id, FILE_PEEK);
+ zt = archive_getzfile (zn, id, getflag);
we_have_file = whf;
if (z)
zfile_fclose (z);
static void archive_close_zip (void *handle)
{
- unzClose (handle);
}
struct zvolume *archive_directory_zip (struct zfile *z)
return 0;
if (unzGoToFirstFile (uz) != UNZ_OK)
return 0;
- zv = zvolume_alloc (z, ArchiveFormatZIP, uz, NULL);
+ zv = zvolume_alloc (z, ArchiveFormatZIP, NULL, NULL);
for (;;) {
char filename_inzip2[MAX_DPATH];
TCHAR c;
if (err != UNZ_OK)
break;
}
+ unzClose (uz);
zv->method = ArchiveFormatZIP;
return zv;
}
-struct zfile *archive_access_zip (struct znode *zn, int flags)
+static struct zfile *archive_do_zip (struct znode *zn, struct zfile *z, int flags)
{
- struct zfile *z = NULL;
- unzFile uz = zn->volume->handle;
- int i, err;
+ unzFile uz;
+ int i;
TCHAR tmp[MAX_DPATH];
+ TCHAR *name = z ? z->archiveparent->name : zn->volume->root.fullname;
char *s;
- _tcscpy (tmp, zn->fullname + _tcslen (zn->volume->root.fullname) + 1);
- if (unzGoToFirstFile (uz) != UNZ_OK)
+ uz = unzOpen (z ? z->archiveparent : zn->volume->archive);
+ if (!uz)
return 0;
+ if (z)
+ _tcscpy (tmp, z->archiveparent->name);
+ else
+ _tcscpy (tmp, zn->fullname + _tcslen (zn->volume->root.fullname) + 1);
+ if (unzGoToFirstFile (uz) != UNZ_OK)
+ goto error;
for (i = 0; tmp[i]; i++) {
if (tmp[i] == '\\')
tmp[i] = '/';
s = ua (tmp);
if (unzLocateFile (uz, s, 1) != UNZ_OK) {
xfree (s);
- return 0;
+ goto error;
}
}
xfree (s);
s = NULL;
if (unzOpenCurrentFile (uz) != UNZ_OK)
- return 0;
-// write_log (L"unpacking %s\n", zn->fullname);
- z = zfile_fopen_empty (NULL, zn->fullname, zn->size);
+ goto error;
+ if (!z)
+ z = zfile_fopen_empty (NULL, zn->fullname, zn->size);
if (z) {
-// if (flags & FILE_PEEK)
-// z->datasize = PEEK_BYTES;
- err = unzReadCurrentFile (uz, z->data, z->datasize);
+ int err = -1;
+ if (!(flags & FILE_DELAYEDOPEN) || z->size <= PEEK_BYTES) {
+ unpack_log (L"ZIP: unpacking %s, flags=%d\n", name, flags);
+ err = unzReadCurrentFile (uz, z->data, z->datasize);
+ unpack_log (L"ZIP: unpacked, code=%d\n", err);
+ } else {
+ z->archiveparent = zfile_dup (zn->volume->archive);
+ if (z->archiveparent) {
+ unpack_log (L"ZIP: delayed open '%s'\n", name);
+ xfree (z->archiveparent->name);
+ z->archiveparent->name = my_strdup (tmp);
+ z->datasize = PEEK_BYTES;
+ err = unzReadCurrentFile (uz, z->data, z->datasize);
+ unpack_log (L"ZIP: unpacked, code=%d\n", err);
+ } else {
+ unpack_log (L"ZIP: unpacking %s (failed DELAYEDOPEN)\n", name);
+ err = unzReadCurrentFile (uz, z->data, z->datasize);
+ unpack_log (L"ZIP: unpacked, code=%d\n", err);
+ }
+ }
}
unzCloseCurrentFile (uz);
+ unzClose (uz);
return z;
+error:
+ unzClose (uz);
+ return NULL;
+}
+
+static struct zfile *archive_access_zip (struct znode *zn, int flags)
+{
+ return archive_do_zip (zn, NULL, flags);
+}
+static struct zfile *archive_unpack_zip (struct zfile *zf)
+{
+ return archive_do_zip (NULL, zf, 0);
}
/* 7Z */
return zv;
}
-struct zfile *archive_access_7z (struct znode *zn)
+static struct zfile *archive_access_7z (struct znode *zn)
{
SRes res;
struct zvolume *zv = zn->volume;
return zv;
}
-struct zfile *archive_access_rar (struct znode *zn)
+static struct zfile *archive_access_rar (struct znode *zn)
{
struct RARContext *rc = (struct RARContext*)zn->volume->handle;
int i;
}
-struct zfile *archive_access_arcacc (struct znode *zn)
+static struct zfile *archive_access_arcacc (struct znode *zn)
{
struct zfile *zf;
struct zfile *z = zn->volume->archive;
}
return zv;
}
-struct zfile *archive_access_plain (struct znode *zn)
+static struct zfile *archive_access_plain (struct znode *zn)
{
struct zfile *z;
}
-struct zfile *archive_access_adf (struct znode *zn)
+static struct zfile *archive_access_adf (struct znode *zn)
{
struct zfile *z = NULL;
int root, ffs;
return zv;
}
-struct zfile *archive_access_rdb (struct znode *zn)
+static struct zfile *archive_access_rdb (struct znode *zn)
{
struct zfile *z = zn->volume->archive;
struct zfile *zf;
return zv;
}
-struct zfile *archive_access_fat (struct znode *zn)
+static struct zfile *archive_access_fat (struct znode *zn)
{
uae_u8 buf[512] = { 0 };
int fatbits = 12;
}
}
-struct zfile *archive_access_dir (struct znode *zn)
+static struct zfile *archive_access_dir (struct znode *zn)
{
return zfile_fopen (zn->fullname, L"rb", 0);
}
+
+struct zfile *archive_unpackzfile (struct zfile *zf)
+{
+ struct zfile *zout = NULL;
+ if (!zf->archiveparent)
+ return NULL;
+ unpack_log (L"delayed unpack '%s'\n", zf->name);
+ zf->datasize = zf->size;
+ switch (zf->archiveid)
+ {
+ case ArchiveFormatZIP:
+ zout = archive_unpack_zip (zf);
+ break;
+ }
+ zfile_fclose (zf->archiveparent);
+ zf->archiveparent = NULL;
+ zf->archiveid = 0;
+ return NULL;
+}
+
+struct zfile *archive_getzfile (struct znode *zn, unsigned int id, int flags)
+{
+ struct zfile *zf = NULL;
+
+ switch (id)
+ {
+ case ArchiveFormatZIP:
+ zf = archive_access_zip (zn, flags);
+ break;
+ case ArchiveFormat7Zip:
+ zf = archive_access_7z (zn);
+ break;
+ case ArchiveFormatRAR:
+ zf = archive_access_rar (zn);
+ break;
+ case ArchiveFormatLHA:
+ zf = archive_access_lha (zn);
+ break;
+ case ArchiveFormatLZX:
+ zf = archive_access_lzx (zn);
+ break;
+ case ArchiveFormatPLAIN:
+ zf = archive_access_plain (zn);
+ break;
+ case ArchiveFormatADF:
+ zf = archive_access_adf (zn);
+ break;
+ case ArchiveFormatRDB:
+ zf = archive_access_rdb (zn);
+ break;
+ case ArchiveFormatFAT:
+ zf = archive_access_fat (zn);
+ break;
+ case ArchiveFormatDIR:
+ zf = archive_access_dir (zn);
+ break;
+ case ArchiveFormatTAR:
+ zf = archive_access_tar (zn);
+ break;
+ }
+ if (zf)
+ zf->archiveid = id;
+ return zf;
+}