diff --git a/Makefile b/Makefile
index d2093029..8f441b0d 100644
--- a/Makefile
+++ b/Makefile
@@ -289,6 +289,8 @@ OBJS = \
src/cd32_fmv.o \
src/cd32_fmv_genlock.o \
src/cdrom.o \
+ src/cdtv.o \
+ src/cdtvcr.o \
src/cfgfile.o \
src/cia.o \
src/crc32.o \
@@ -315,6 +317,7 @@ OBJS = \
src/hrtmon.rom.o \
src/ide.o \
src/inputdevice.o \
+ src/isofs.o \
src/keybuf.o \
src/main.o \
src/memory.o \
@@ -324,6 +327,7 @@ OBJS = \
src/savestate.o \
src/scp.o \
src/scsi.o \
+ src/scsiemul.o \
src/statusline.o \
src/traps.o \
src/uaelib.o \
diff --git a/VisualGDB/Amiberry/Amiberry.vcxproj b/VisualGDB/Amiberry/Amiberry.vcxproj
index 51eb0a71..dcbcd0a3 100644
--- a/VisualGDB/Amiberry/Amiberry.vcxproj
+++ b/VisualGDB/Amiberry/Amiberry.vcxproj
@@ -200,6 +200,8 @@
+
+
@@ -233,6 +235,7 @@
+
@@ -296,6 +299,7 @@
+
@@ -367,6 +371,8 @@
+
+
@@ -394,6 +400,8 @@
+
+
@@ -409,6 +417,7 @@
+
diff --git a/VisualGDB/Amiberry/Amiberry.vcxproj.filters b/VisualGDB/Amiberry/Amiberry.vcxproj.filters
index 0ceaae7e..20a3736c 100644
--- a/VisualGDB/Amiberry/Amiberry.vcxproj.filters
+++ b/VisualGDB/Amiberry/Amiberry.vcxproj.filters
@@ -595,6 +595,18 @@
Source files
+
+ Source files
+
+
+ Source files
+
+
+ Source files
+
+
+ Source files
+
@@ -975,5 +987,20 @@
Source files\include
+
+ Source files\include
+
+
+ Source files\include
+
+
+ Source files\include
+
+
+ Source files\include
+
+
+ Source files\include
+
\ No newline at end of file
diff --git a/src/ar.cpp b/src/ar.cpp
index d1dd9f2d..dde6c8c4 100644
--- a/src/ar.cpp
+++ b/src/ar.cpp
@@ -1698,9 +1698,9 @@ int hrtmon_load (void)
cart_type = CART_AR;
hrtmem_start = 0xa10000;
if(!_tcscmp(currprefs.cartfile, _T(":HRTMon")))
- rd = getromdatabyid(63);
+ rd = getromdatabyid(63);
else
- rd = getromdatabypath(currprefs.cartfile);
+ rd = getromdatabypath(currprefs.cartfile);
if (rd) {
if (rd->id == 63)
isinternal = 1;
diff --git a/src/autoconf.cpp b/src/autoconf.cpp
index 0a6562bf..a7bcd0f4 100644
--- a/src/autoconf.cpp
+++ b/src/autoconf.cpp
@@ -44,7 +44,7 @@ addrbank rtarea_bank = {
rtarea_lput, rtarea_wput, rtarea_bput,
rtarea_xlate, rtarea_check, NULL, _T("rtarea"), _T("UAE Boot ROM"),
rtarea_wget,
- ABFLAG_ROMIN, S_READ, S_WRITE
+ ABFLAG_ROMIN | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
};
#define MAX_ABSOLUTE_ROM_ADDRESS 1024
@@ -96,6 +96,7 @@ static void rethink_traps(void)
rethink_traps2();
}
+
#define RTAREA_WRITEOFFSET 0xfff0
static bool rtarea_trap_data(uaecptr addr)
@@ -123,7 +124,7 @@ static bool rtarea_trap_status_extra(uaecptr addr)
return false;
}
-static uae_u8 *REGPARAM2 rtarea_xlate(uaecptr addr)
+static uae_u8 *REGPARAM2 rtarea_xlate (uaecptr addr)
{
addr &= 0xFFFF;
return rtarea_bank.baseaddr + addr;
@@ -334,8 +335,8 @@ void rtarea_reset(void)
}
/* some quick & dirty code to fill in the rt area and save me a lot of
- * scratch paper
- */
+* scratch paper
+*/
static int rt_addr;
static int rt_straddr;
@@ -370,7 +371,7 @@ void df(uae_u8 b, int len)
rt_addr += len;
}
-uae_u8 dbg(uaecptr addr)
+uae_u8 dbg (uaecptr addr)
{
addr &= 0xffff;
return rtarea_bank.baseaddr[addr];
@@ -407,17 +408,17 @@ uae_u32 dsf(uae_u8 b, int len)
return addr(rt_straddr);
}
-uae_u32 ds_bstr_ansi(const uae_char *str)
+uae_u32 ds_bstr_ansi (const uae_char *str)
{
int len;
-
- len = strlen(str) + 2;
+
+ len = strlen (str) + 2;
rt_straddr -= len;
while (rt_straddr & 3)
rt_straddr--;
rtarea_bank.baseaddr[rt_straddr] = len - 2;
- strcpy((uae_char*)rtarea_bank.baseaddr + rt_straddr + 1, str);
- return addr(rt_straddr) >> 2;
+ strcpy ((uae_char*)rtarea_bank.baseaddr + rt_straddr + 1, str);
+ return addr (rt_straddr) >> 2;
}
void save_rom_absolute(uaecptr addr)
@@ -511,26 +512,26 @@ void calltrap (uae_u32 n)
}
}
-void org(uae_u32 a)
+void org (uae_u32 a)
{
- if (((a & 0xffff0000) != 0x00f00000) && ((a & 0xffff0000) != rtarea_base))
- write_log(_T("ORG: corrupt address! %08X"), a);
+ if ( ((a & 0xffff0000) != 0x00f00000) && ((a & 0xffff0000) != rtarea_base) )
+ write_log (_T("ORG: corrupt address! %08X"), a);
rt_addr = a & 0xffff;
}
-uae_u32 here(void)
+uae_u32 here (void)
{
- return addr(rt_addr);
+ return addr (rt_addr);
}
-void align(int b)
+void align (int b)
{
rt_addr = (rt_addr + b - 1) & ~(b - 1);
}
-static uae_u32 REGPARAM2 nullfunc(TrapContext *ctx)
+static uae_u32 REGPARAM2 nullfunc (TrapContext *ctx)
{
- write_log(_T("Null function called\n"));
+ write_log (_T("Null function called\n"));
return 0;
}
@@ -544,19 +545,19 @@ static uae_u32 REGPARAM2 getchipmemsize (TrapContext *ctx)
static uae_u32 REGPARAM2 uae_puts (TrapContext *ctx)
{
uae_char buf[MAX_DPATH];
- trap_get_string(ctx, buf, trap_get_areg(ctx, 0), sizeof (uae_char));
+ trap_get_string(ctx, buf, trap_get_areg(ctx, 0), sizeof(uae_char));
TCHAR *s = au(buf);
write_log(_T("%s"), s);
xfree(s);
return 0;
}
-static void rtarea_init_mem (void)
+void rtarea_init_mem (void)
{
rtarea_bank.reserved_size = RTAREA_SIZE;
rtarea_bank.start = rtarea_base;
- if (!mapped_malloc(&rtarea_bank)) {
- write_log(_T("virtual memory exhausted (rtarea)!\n"));
+ if (!mapped_malloc (&rtarea_bank)) {
+ write_log (_T("virtual memory exhausted (rtarea)!\n"));
abort ();
}
}
@@ -578,21 +579,21 @@ void rtarea_init(void)
trap_entry = 0;
absolute_rom_address = 0;
rombase_new = 0;
-
- init_traps();
- rtarea_init_mem();
- memset(rtarea_bank.baseaddr, 0, RTAREA_SIZE);
+ init_traps ();
- _stprintf(uaever, _T("uae-%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV);
+ rtarea_init_mem ();
+ memset (rtarea_bank.baseaddr, 0, RTAREA_SIZE);
+
+ _stprintf (uaever, _T("uae-%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV);
EXPANSION_uaeversion = ds (uaever);
EXPANSION_explibname = ds (_T("expansion.library"));
EXPANSION_doslibname = ds (_T("dos.library"));
EXPANSION_uaedevname = ds (_T("uae.device"));
- dw(0);
- dw(0);
+ dw (0);
+ dw (0);
#ifdef FILESYS
filesys_install_code();
@@ -604,38 +605,38 @@ void rtarea_init(void)
uae_sem_init(&hardware_trap_event[i], 0, 0);
uae_sem_init(&hardware_trap_event2[i], 0, 0);
}
-
+
#endif
deftrap(NULL); /* Generic emulator trap */
- a = here();
+ a = here ();
/* Dummy trap - removing this breaks the filesys emulation. */
- org(rtarea_base + 0xFF00);
- calltrap(deftrap2(nullfunc, TRAPFLAG_NO_RETVAL, _T("")));
+ org (rtarea_base + 0xFF00);
+ calltrap (deftrap2 (nullfunc, TRAPFLAG_NO_RETVAL, _T("")));
- org(rtarea_base + 0xFF80);
- calltrap(deftrapres(getchipmemsize, TRAPFLAG_DORET, _T("getchipmemsize")));
+ org (rtarea_base + 0xFF80);
+ calltrap (deftrapres (getchipmemsize, TRAPFLAG_DORET, _T("getchipmemsize")));
dw(RTS);
org (rtarea_base + 0xFF10);
calltrap (deftrapres (uae_puts, TRAPFLAG_NO_RETVAL, _T("uae_puts")));
dw (RTS);
-
- org(a);
- uae_boot_rom_size = here() - rtarea_base;
+ org (a);
+
+ uae_boot_rom_size = here () - rtarea_base;
if (uae_boot_rom_size >= RTAREA_TRAPS) {
- write_log(_T("RTAREA_TRAPS needs to be increased!"));
+ write_log (_T("RTAREA_TRAPS needs to be increased!"));
abort ();
}
#ifdef PICASSO96
- uaegfx_install_code(rtarea_base + RTAREA_RTG);
+ uaegfx_install_code (rtarea_base + RTAREA_RTG);
#endif
- org(RTAREA_TRAPS | rtarea_base);
- init_extended_traps();
+ org (RTAREA_TRAPS | rtarea_base);
+ init_extended_traps ();
if (currprefs.uaeboard >= 2) {
device_add_rethink(rethink_traps);
@@ -644,11 +645,11 @@ void rtarea_init(void)
volatile uae_atomic uae_int_requested = 0;
-void rtarea_setup(void)
+void rtarea_setup (void)
{
- uaecptr base = need_uae_boot_rom(&currprefs);
+ uaecptr base = need_uae_boot_rom (&currprefs);
if (base) {
- write_log(_T("RTAREA located at %08X\n"), base);
+ write_log (_T("RTAREA located at %08X\n"), base);
rtarea_base = base;
}
}
@@ -681,3 +682,4 @@ uaecptr makedatatable (uaecptr resid, uaecptr resname, uae_u8 type, uae_s8 prior
dw (0x0000); /* end of table */
return datatable;
}
+
diff --git a/src/blitter.cpp b/src/blitter.cpp
index f5f0f223..ccac0e83 100644
--- a/src/blitter.cpp
+++ b/src/blitter.cpp
@@ -1,11 +1,11 @@
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Custom chip emulation
- *
- * (c) 1995 Bernd Schmidt, Alessandro Bissacco
- * (c) 2002 - 2005 Toni Wilen
- */
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* Custom chip emulation
+*
+* (c) 1995 Bernd Schmidt, Alessandro Bissacco
+* (c) 2002 - 2005 Toni Wilen
+*/
#include "sysconfig.h"
#include "sysdeps.h"
@@ -423,8 +423,7 @@ static void blitter_dofast (void)
if (bltadatptr) {
blt_info.bltadat = bltadat = chipmem_wget_indirect (bltadatptr);
bltadatptr += 2;
- }
- else
+ } else
bltadat = blt_info.bltadat;
bltadat &= blit_masktable[i];
blitahold = (((uae_u32)blt_info.bltaold << 16) | bltadat) >> blt_info.blitashift;
@@ -505,11 +504,10 @@ static void blitter_dofast_desc (void)
bltddatptr = bltdpt;
bltdpt -= (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize;
}
- if (blitfunc_dofast_desc[mt] && !blitfill) {
- (*blitfunc_dofast_desc[mt])(bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, &blt_info);
- }
- else
- {
+ if (blitfunc_dofast_desc[mt] && !blitfill) {
+ (*blitfunc_dofast_desc[mt])(bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, &blt_info);
+ } else
+ {
uae_u32 blitbhold = blt_info.bltbhold;
uaecptr dstp = 0;
int dodst = 0;
diff --git a/src/blkdev.cpp b/src/blkdev.cpp
index f069f3fc..37b9844b 100644
--- a/src/blkdev.cpp
+++ b/src/blkdev.cpp
@@ -7,18 +7,23 @@
*
*/
-#include
-#include
-#include
-
+#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
+#include "memory.h"
+#include "traps.h"
#include "blkdev.h"
+#include "scsidev.h"
+#include
+
#include "savestate.h"
#include "crc32.h"
#include "threaddep/thread.h"
+#include "execio.h"
#include "zfile.h"
+#include "scsi.h"
+#include "statusline.h"
#define PRE_INSERT_DELAY (3 * (currprefs.ntscmode ? 60 : 50))
@@ -39,9 +44,12 @@ struct blkdevstate
int imagechangetime;
bool cdimagefileinuse;
int wasopen;
+ bool mediawaschanged;
+ struct scsi_data_tape *tape;
+ bool showstatusline;
};
-static struct blkdevstate state[MAX_TOTAL_SCSI_DEVICES];
+struct blkdevstate state[MAX_TOTAL_SCSI_DEVICES];
static bool dev_init;
@@ -94,11 +102,18 @@ static struct cd_toc *gettoc (int unitnum, struct cd_toc_head *th, int block)
for (int i = th->first_track_offset + 1; i <= th->last_track_offset; i++) {
struct cd_toc *t = &th->toc[i];
if (block < t->paddress)
- return t - 1;
+ return t - 1;
}
return &th->toc[th->last_track_offset];
}
+int cdtracknumber(struct cd_toc_head *th, int block)
+{
+ struct cd_toc *t = gettoc(-1, th, block);
+ if (!t)
+ return -1;
+ return t->track;
+}
int isaudiotrack (struct cd_toc_head *th, int block)
{
struct cd_toc *t = gettoc (-1, th, block);
@@ -115,9 +130,19 @@ static int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES];
static struct device_functions *devicetable[] = {
NULL,
- &devicefunc_cdimage
+ &devicefunc_cdimage,
+#ifdef WITH_SCSI_IOCTL
+ &devicefunc_scsi_ioctl,
+#else
+ NULL,
+#endif
+#ifdef WITH_SCSI_SPTI
+ &devicefunc_scsi_spti,
+#else
+ NULL,
+#endif
};
-#define NUM_DEVICE_TABLE_ENTRIES 2
+#define NUM_DEVICE_TABLE_ENTRIES 4
static int driver_installed[NUM_DEVICE_TABLE_ENTRIES];
static void install_driver (int flags)
@@ -139,18 +164,33 @@ static void install_driver (int flags)
switch (cdscsidevicetype[i])
{
case SCSI_UNIT_IMAGE:
- st->device_func = devicetable[SCSI_UNIT_IMAGE];
- st->scsiemu = true;
- break;
+ st->device_func = devicetable[SCSI_UNIT_IMAGE];
+ st->scsiemu = true;
+ break;
+ case SCSI_UNIT_IOCTL:
+ st->device_func = devicetable[SCSI_UNIT_IOCTL];
+ st->scsiemu = true;
+ break;
+ case SCSI_UNIT_SPTI:
+ //if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) {
+ // st->device_func = devicetable[SCSI_UNIT_IOCTL];
+ // st->scsiemu = true;
+ //} else {
+ // st->device_func = devicetable[SCSI_UNIT_SPTI];
+ //}
+ break;
}
- // use image mode if driver disabled
- for (int j = 1; j < NUM_DEVICE_TABLE_ENTRIES; j++) {
- if (devicetable[j] == st->device_func && driver_installed[j] < 0) {
- st->device_func = devicetable[SCSI_UNIT_IMAGE];
- st->scsiemu = true;
- }
- }
- }
+ // do not default to image mode if unit 1+ and automount
+ if (i == 0) {
+ // use image mode if driver disabled
+ for (int j = 1; j < NUM_DEVICE_TABLE_ENTRIES; j++) {
+ if (devicetable[j] == st->device_func && driver_installed[j] < 0) {
+ st->device_func = devicetable[SCSI_UNIT_IMAGE];
+ st->scsiemu = true;
+ }
+ }
+ }
+ }
}
for (int j = 1; j < NUM_DEVICE_TABLE_ENTRIES; j++) {
@@ -168,7 +208,7 @@ static void install_driver (int flags)
write_log (_T("Fallback to image mode, unit %d.\n"), i);
driver_installed[j] = -1;
} else {
- driver_installed[j] = 1;
+ driver_installed[j] = 1;
}
write_log (_T("%s driver installed, ok=%d\n"), st->device_func->name, ok);
break;
@@ -199,10 +239,25 @@ void blkdev_fix_prefs (struct uae_prefs *p)
}
for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- if (cdscsidevicetype[i] != SCSI_UNIT_DEFAULT)
+ if (cdscsidevicetype[i] != SCSI_UNIT_DEFAULT && (currprefs.scsi == 0))
continue;
if (p->cdslots[i].inuse || p->cdslots[i].name[0]) {
- cdscsidevicetype[i] = SCSI_UNIT_IMAGE;
+ TCHAR *name = p->cdslots[i].name;
+ if (_tcslen (name) == 3 && name[1] == ':' && name[2] == '\\') {
+ //if (currprefs.scsi && (currprefs.win32_uaescsimode == UAESCSI_SPTI || currprefs.win32_uaescsimode == UAESCSI_SPTISCAN))
+ // cdscsidevicetype[i] = SCSI_UNIT_SPTI;
+ //else
+ cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
+ } else {
+ cdscsidevicetype[i] = SCSI_UNIT_IMAGE;
+ }
+ } else if (currprefs.scsi) {
+ //if (currprefs.win32_uaescsimode == UAESCSI_CDEMU)
+ // cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
+ //else
+ cdscsidevicetype[i] = SCSI_UNIT_SPTI;
+ } else {
+ cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
}
}
@@ -275,15 +330,58 @@ static int sys_command_open_internal (int unitnum, const TCHAR *ident, cd_standa
return ret;
}
+static int getunitinfo (int unitnum, int drive, cd_standard_unit csu, int *isaudio)
+{
+ struct device_info di;
+ if (sys_command_info (unitnum, &di, 0)) {
+ write_log (_T("Scanning drive %s: "), di.label);
+ if (di.media_inserted) {
+ if (isaudiotrack (&di.toc, 0)) {
+ if (*isaudio == 0)
+ *isaudio = drive;
+ write_log (_T("CDA"));
+ }
+ uae_u8 buffer[2048];
+ if (sys_command_cd_read (unitnum, buffer, 16, 1)) {
+ if (!memcmp (buffer + 8, "CDTV", 4) || !memcmp (buffer + 8, "CD32", 4) || !memcmp (buffer + 8, "COMM", 4)) {
+ uae_u32 crc;
+ write_log (_T("CD32 or CDTV"));
+ if (sys_command_cd_read (unitnum, buffer, 21, 1)) {
+ crc = get_crc32 (buffer, sizeof buffer);
+ if (crc == 0xe56c340f) {
+ write_log (_T(" [CD32.TM]"));
+ if (csu == CD_STANDARD_UNIT_CD32) {
+ write_log (_T("\n"));
+ return 1;
+ }
+ }
+ }
+ if (csu == CD_STANDARD_UNIT_CDTV || csu == CD_STANDARD_UNIT_CD32) {
+ write_log (_T("\n"));
+ return 1;
+ }
+ }
+ }
+ } else {
+ write_log (_T("no media"));
+ }
+ }
+ write_log (_T("\n"));
+ return 0;
+}
+
static int get_standard_cd_unit2 (struct uae_prefs *p, cd_standard_unit csu)
{
int unitnum = 0;
int isaudio = 0;
if (p->cdslots[unitnum].name[0] || p->cdslots[unitnum].inuse) {
if (p->cdslots[unitnum].name[0]) {
- device_func_init (SCSI_UNIT_IMAGE);
- if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu))
- goto fallback;
+ device_func_init (SCSI_UNIT_IOCTL);
+ if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu)) {
+ device_func_init (SCSI_UNIT_IMAGE);
+ if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu))
+ goto fallback;
+ }
} else {
goto fallback;
}
@@ -304,19 +402,49 @@ fallback:
return unitnum;
}
+static void cd_statusline_label(int unitnum)
+{
+ TCHAR *p = currprefs.cdslots[unitnum].name;
+ if (p[0]) {
+ TCHAR name[MAX_DPATH];
+ struct device_info di;
+ cfgfile_resolve_path_out_load(p, name, sizeof(name) / sizeof(TCHAR), PATH_CD);
+ const TCHAR *fname = my_getfilepart(name);
+ if (sys_command_info(unitnum, &di, 0) && di.volume_id[0])
+ statusline_add_message(STATUSTYPE_CD, _T("CD%d: [%s] %s"), unitnum, di.volume_id, fname);
+ else
+ statusline_add_message(STATUSTYPE_CD, _T("CD%d: %s"), unitnum, fname);
+ }
+}
+
int get_standard_cd_unit (cd_standard_unit csu)
{
int unitnum = get_standard_cd_unit2 (&currprefs, csu);
if (unitnum < 0)
return -1;
struct blkdevstate *st = &state[unitnum];
+#ifdef RETROPLATFORM
+ rp_cd_device_enable (unitnum, true);
+#endif
st->delayed = 0;
if (currprefs.cdslots[unitnum].delayed) {
st->delayed = PRE_INSERT_DELAY;
}
+ st->showstatusline = true;
return unitnum;
}
+void close_standard_cd_unit (int unitnum)
+{
+ sys_command_close (unitnum);
+}
+
+int sys_command_isopen (int unitnum)
+{
+ struct blkdevstate *st = &state[unitnum];
+ return st->isopen;
+}
+
int sys_command_open (int unitnum)
{
struct blkdevstate *st = &state[unitnum];
@@ -333,6 +461,9 @@ int sys_command_open (int unitnum)
int v = sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT);
if (!v)
return 0;
+#ifdef RETROPLATFORM
+ rp_cd_device_enable (unitnum, true);
+#endif
return v;
}
@@ -343,6 +474,10 @@ void sys_command_close (int unitnum)
st->isopen--;
return;
}
+ //if (st->tape) {
+ // tape_free (st->tape);
+ // st->tape = NULL;
+ //}
sys_command_close_internal (unitnum);
}
@@ -350,6 +485,9 @@ void blkdev_cd_change (int unitnum, const TCHAR *name)
{
struct device_info di;
sys_command_info (unitnum, &di, 1);
+#ifdef RETROPLATFORM
+ rp_cd_image_change (unitnum, name);
+#endif
}
void device_func_reset(void)
@@ -360,11 +498,11 @@ void device_func_reset(void)
if (st->imagechangetime > 0 && st->newimagefile[0] && !currprefs.cdslots[i].name[0]) {
_tcscpy(changed_prefs.cdslots[i].name, st->newimagefile);
_tcscpy(currprefs.cdslots[i].name, st->newimagefile);
- //cd_statusline_label(i);
+ cd_statusline_label(i);
}
st->imagechangetime = 0;
st->newimagefile[0] = 0;
- //st->mediawaschanged = false;
+ st->mediawaschanged = false;
st->waspaused = false;
}
}
@@ -375,6 +513,7 @@ void device_func_free(void)
struct blkdevstate *st = &state[i];
st->wasopen = 0;
st->waspaused = false;
+ st->mediawaschanged = false;
st->imagechangetime = 0;
st->cdimagefileinuse = false;
st->newimagefile[0] = 0;
@@ -382,7 +521,7 @@ void device_func_free(void)
dev_init = false;
}
-static int device_func_init (int flags)
+int device_func_init (int flags)
{
blkdev_fix_prefs (&currprefs);
install_driver (flags);
@@ -390,21 +529,21 @@ static int device_func_init (int flags)
return 1;
}
-bool blkdev_get_info(struct uae_prefs* p, int unitnum, struct device_info* di)
+bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di)
{
bool open = true, opened = false, ok = false;
- struct blkdevstate* st = &state[unitnum];
+ struct blkdevstate *st = &state[unitnum];
if (!st->isopen) {
- blkdev_fix_prefs(p);
- install_driver(0);
+ blkdev_fix_prefs (p);
+ install_driver (0);
opened = true;
- open = sys_command_open_internal(unitnum, p->cdslots[unitnum].name[0] ? p->cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT) != 0;
+ open = sys_command_open_internal (unitnum, p->cdslots[unitnum].name[0] ? p->cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT) != 0;
}
if (open) {
- ok = sys_command_info(unitnum, di, true) != 0;
+ ok = sys_command_info (unitnum, di, true) != 0;
}
if (open && opened)
- sys_command_close_internal(unitnum);
+ sys_command_close_internal (unitnum);
return ok;
}
@@ -434,7 +573,7 @@ void blkdev_exitgui (void)
}
}
-void check_prefs_changed_cd(void)
+void check_prefs_changed_cd (void)
{
if (!config_changed)
return;
@@ -449,6 +588,11 @@ static void check_changes (int unitnum)
if (st->device_func == NULL)
return;
+ if (st->showstatusline) {
+ cd_statusline_label(unitnum);
+ st->showstatusline = 0;
+ }
+
if (st->delayed) {
st->delayed--;
if (st->delayed == 0)
@@ -462,6 +606,7 @@ static void check_changes (int unitnum)
changed = true;
if (changed) {
+ bool wasimage = currprefs.cdslots[unitnum].name[0] != 0;
if (st->sema)
gotsem = getsem (unitnum, true);
st->cdimagefileinuse = changed_prefs.cdslots[unitnum].inuse;
@@ -477,9 +622,23 @@ static void check_changes (int unitnum)
if (st->wasopen) {
st->device_func->closedev (unitnum);
st->wasopen = -1;
+ if (currprefs.scsi) {
+ scsi_do_disk_change (unitnum, 0, &pollmode);
+ if (pollmode)
+ st->imagechangetime = 8 * 50;
+ if (filesys_do_disk_change (unitnum, 0)) {
+ st->imagechangetime = st->newimagefile[0] ? 3 * 50 : 0;
+ pollmode = 0;
+ }
+ }
}
write_log (_T("CD: eject (%s) open=%d\n"), pollmode ? _T("slow") : _T("fast"), st->wasopen ? 1 : 0);
+ if (wasimage)
+ statusline_add_message(STATUSTYPE_CD, _T("CD%d: -"), unitnum);
+#ifdef RETROPLATFORM
+ rp_cd_image_change (unitnum, NULL);
+#endif
if (gotsem) {
freesem (unitnum);
gotsem = false;
@@ -507,12 +666,29 @@ static void check_changes (int unitnum)
write_log (_T("-> device reopened\n"));
}
}
+ if (currprefs.scsi && st->wasopen) {
+ struct device_info di;
+ st->device_func->info (unitnum, &di, 0, -1);
+ int pollmode;
+ if (gotsem) {
+ freesem (unitnum);
+ gotsem = false;
+ }
+ scsi_do_disk_change (unitnum, 1, &pollmode);
+ filesys_do_disk_change (unitnum, 1);
+ }
+ st->mediawaschanged = true;
+ st->showstatusline = true;
if (gotsem) {
freesem (unitnum);
gotsem = false;
}
+#ifdef RETROPLATFORM
+ rp_cd_image_change (unitnum, currprefs.cdslots[unitnum].name);
+#endif
set_config_changed ();
+
}
void blkdev_vsync (void)
@@ -521,6 +697,19 @@ void blkdev_vsync (void)
check_changes (i);
}
+static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen)
+{
+ uae_u8 *p = state[unitnum].device_func->exec_out (unitnum, cmd, cmdlen);
+ return p != NULL;
+}
+static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *out, int outsize)
+{
+ uae_u8 *p = state[unitnum].device_func->exec_in (unitnum, cmd, cmdlen, &outsize);
+ if (p)
+ memcpy (out, p, outsize);
+ return p != NULL;
+}
+
static int failunit (int unitnum)
{
if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES)
@@ -530,6 +719,18 @@ static int failunit (int unitnum)
return 0;
}
+static int audiostatus (int unitnum)
+{
+ if (!getsem (unitnum))
+ return 0;
+ uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0};
+ uae_u8 *p = state[unitnum].device_func->exec_in (unitnum, cmd, sizeof (cmd), 0);
+ freesem (unitnum);
+ if (!p)
+ return 0;
+ return p[1];
+}
+
/* pause/unpause CD audio */
int sys_command_cd_pause (int unitnum, int paused)
{
@@ -538,7 +739,14 @@ int sys_command_cd_pause (int unitnum, int paused)
if (!getsem (unitnum))
return 0;
int v;
- v = state[unitnum].device_func->pause (unitnum, paused);
+ if (state[unitnum].device_func->pause == NULL) {
+ int as = audiostatus (unitnum);
+ uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,(uae_u8)(paused?0:1),0};
+ do_scsi (unitnum, cmd, sizeof cmd);
+ v = as == AUDIO_STATUS_PAUSED;
+ } else {
+ v = state[unitnum].device_func->pause (unitnum, paused);
+ }
freesem (unitnum);
return v;
}
@@ -550,7 +758,13 @@ void sys_command_cd_stop (int unitnum)
return;
if (!getsem (unitnum))
return;
- state[unitnum].device_func->stop (unitnum);
+ if (state[unitnum].device_func->stop == NULL) {
+ int as = audiostatus (unitnum);
+ uae_u8 cmd[6] = {0x4e,0,0,0,0,0};
+ do_scsi (unitnum, cmd, sizeof cmd);
+ } else {
+ state[unitnum].device_func->stop (unitnum);
+ }
freesem (unitnum);
}
@@ -563,7 +777,21 @@ int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan)
if (!getsem (unitnum))
return 0;
state[unitnum].play_end_pos = endlsn;
- v = state[unitnum].device_func->play (unitnum, startlsn, endlsn, scan, NULL, NULL);
+ if (state[unitnum].device_func->play == NULL) {
+ uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
+ int startmsf = lsn2msf (startlsn);
+ int endmsf = lsn2msf (endlsn);
+ cmd[0] = 0x47;
+ cmd[3] = (uae_u8)(startmsf >> 16);
+ cmd[4] = (uae_u8)(startmsf >> 8);
+ cmd[5] = (uae_u8)(startmsf >> 0);
+ cmd[6] = (uae_u8)(endmsf >> 16);
+ cmd[7] = (uae_u8)(endmsf >> 8);
+ cmd[8] = (uae_u8)(endmsf >> 0);
+ v = do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1;
+ } else {
+ v = state[unitnum].device_func->play (unitnum, startlsn, endlsn, scan, NULL, NULL);
+ }
freesem (unitnum);
return v;
}
@@ -577,7 +805,10 @@ int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_s
if (!getsem (unitnum))
return 0;
state[unitnum].play_end_pos = endlsn;
- v = state[unitnum].device_func->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc);
+ if (state[unitnum].device_func->play == NULL)
+ v = sys_command_cd_play (unitnum, startlsn, endlsn, scan);
+ else
+ v = state[unitnum].device_func->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc);
freesem (unitnum);
return v;
}
@@ -590,7 +821,10 @@ uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_
return 0;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->volume (unitnum, volume_left, volume_right);
+ if (state[unitnum].device_func->volume == NULL)
+ v = -1;
+ else
+ v = state[unitnum].device_func->volume (unitnum, volume_left, volume_right);
freesem (unitnum);
return v;
}
@@ -603,33 +837,87 @@ int sys_command_cd_qcode (int unitnum, uae_u8 *buf, int sector, bool all)
return 0;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->qcode (unitnum, buf, sector, all);
+ if (state[unitnum].device_func->qcode == NULL) {
+ if (all) {
+ v = 0;
+ } else {
+ uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(SUBQ_SIZE>>8),(uae_u8)(SUBQ_SIZE&0xff),0};
+ v = do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE);
+ }
+ } else {
+ v = state[unitnum].device_func->qcode (unitnum, buf, sector, all);
+ }
freesem (unitnum);
return v;
};
/* read table of contents */
-int sys_command_cd_toc (int unitnum, struct cd_toc_head *toc)
+int sys_command_cd_toc (int unitnum, struct cd_toc_head *th)
{
int v;
if (failunit (unitnum))
return 0;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->toc (unitnum, toc);
+ if (state[unitnum].device_func->toc == NULL) {
+ uae_u8 buf[4 + 8 * 103];
+ int size = sizeof buf;
+ uae_u8 cmd [10] = { 0x43,0,0,0,0,0,0,(uae_u8)(size>>8),(uae_u8)(size&0xff),0};
+ v = do_scsi(unitnum, cmd, sizeof cmd, buf, size);
+ if (v > 0) {
+ th->first_track = buf[2];
+ th->last_track = buf[3];
+ th->tracks = th->last_track - th->first_track + 1;
+ th->firstaddress = 0;
+ th->points = th->tracks + 1;
+ int len = (buf[0] << 8) | buf[1];
+ uae_u8 *p = buf + 4;
+ if ((th->tracks + 1) * 8 > len) {
+ freesem(unitnum);
+ return 0;
+ }
+ struct cd_toc *t = &th->toc[th->first_track];
+ for (int i = th->first_track; i <= th->last_track; i++) {
+ t->adr = p[1] >> 4;
+ t->control = p[1] & 15;
+ t->point = t->track = p[2];
+ t->paddress = (p[5] << 16) | (p[6] << 8) | (p[7] << 0);
+ p += 8;
+ t++;
+ }
+ th->lastaddress = (p[5] << 16) | (p[6] << 8) | (p[7] << 0);
+ t->track = t->point = 0xaa;
+ th->first_track_offset = 0;
+ th->last_track_offset = th->last_track;
+ v = 1;
+ }
+ } else {
+ v = state[unitnum].device_func->toc (unitnum, th);
+ }
freesem (unitnum);
return v;
}
/* read one cd sector */
-static int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size)
+int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size)
{
int v;
if (failunit (unitnum))
return 0;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->read (unitnum, data, block, size);
+ if (state[unitnum].device_func->read == NULL) {
+ uae_u8 cmd1[12] = { 0x28, 0, (uae_u8)(block >> 24), (uae_u8)(block >> 16), (uae_u8)(block >> 8), (uae_u8)(block >> 0), 0, (uae_u8)(size >> 8), (uae_u8)(size >> 0), 0, 0, 0 };
+ v = do_scsi (unitnum, cmd1, sizeof cmd1, data, size * 2048);
+#if 0
+ if (!v) {
+ uae_u8 cmd2[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 };
+ v = do_scsi (unitnum, cmd2, sizeof cmd2, data, size * 2048);
+ }
+#endif
+ } else {
+ v = state[unitnum].device_func->read (unitnum, data, block, size);
+ }
freesem (unitnum);
return v;
}
@@ -640,7 +928,12 @@ int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int
return -1;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->rawread (unitnum, data, block, size, sectorsize, 0xffffffff);
+ if (state[unitnum].device_func->rawread == NULL) {
+ uae_u8 cmd[12] = { 0xbe, 0, (uae_u8)(block >> 24), (uae_u8)(block >> 16), (uae_u8)(block >> 8), (uae_u8)(block >> 0), (uae_u8)(size >> 16), (uae_u8)(size >> 8), (uae_u8)(size >> 0), 0x10, 0, 0 };
+ v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize);
+ } else {
+ v = state[unitnum].device_func->rawread (unitnum, data, block, size, sectorsize, 0xffffffff);
+ }
freesem (unitnum);
return v;
}
@@ -651,7 +944,51 @@ int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int
return -1;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->rawread (unitnum, data, block, size, sectorsize, (sectortype << 16) | (scsicmd9 << 8) | subs);
+ if (state[unitnum].device_func->rawread == NULL) {
+ uae_u8 cmd[12] = { 0xbe, 0, (uae_u8)(block >> 24), (uae_u8)(block >> 16), (uae_u8)(block >> 8), (uae_u8)(block >> 0), (uae_u8)(size >> 16), (uae_u8)(size >> 8), (uae_u8)(size >> 0), 0x10, 0, 0 };
+ v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize);
+ } else {
+ v = state[unitnum].device_func->rawread (unitnum, data, block, size, sectorsize, (sectortype << 16) | (scsicmd9 << 8) | subs);
+ }
+ freesem (unitnum);
+ return v;
+}
+
+/* read block */
+int sys_command_read (int unitnum, uae_u8 *data, int block, int size)
+{
+ int v;
+ if (failunit (unitnum))
+ return 0;
+ if (!getsem (unitnum))
+ return 0;
+ if (state[unitnum].device_func->read == NULL) {
+ uae_u8 cmd[12] = { 0xa8, 0, 0, 0, 0, 0, (uae_u8)(size >> 24), (uae_u8)(size >> 16), (uae_u8)(size >> 8), (uae_u8)(size >> 0), 0, 0 };
+ cmd[2] = (uae_u8)(block >> 24);
+ cmd[3] = (uae_u8)(block >> 16);
+ cmd[4] = (uae_u8)(block >> 8);
+ cmd[5] = (uae_u8)(block >> 0);
+ v = do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048);
+ } else {
+ v = state[unitnum].device_func->read (unitnum, data, block, size);
+ }
+ freesem (unitnum);
+ return v;
+}
+
+/* write block */
+int sys_command_write (int unitnum, uae_u8 *data, int offset, int size)
+{
+ int v;
+ if (failunit (unitnum))
+ return 0;
+ if (!getsem (unitnum))
+ return 0;
+ if (state[unitnum].device_func->write == NULL) {
+ v = 0;
+ } else {
+ v = state[unitnum].device_func->write (unitnum, data, offset, size);
+ }
freesem (unitnum);
return v;
}
@@ -666,12 +1003,17 @@ int sys_command_ismedia (int unitnum, int quick)
return 0;
if (!getsem (unitnum))
return 0;
- v = state[unitnum].device_func->ismedia (unitnum, quick);
+ if (state[unitnum].device_func->ismedia == NULL) {
+ uae_u8 cmd[6] = { 0, 0, 0, 0, 0, 0 };
+ v = do_scsi (unitnum, cmd, sizeof cmd);
+ } else {
+ v = state[unitnum].device_func->ismedia (unitnum, quick);
+ }
freesem (unitnum);
return v;
}
-static struct device_info *sys_command_info_session (int unitnum, struct device_info *di, int quick, int session)
+struct device_info *sys_command_info_session (int unitnum, struct device_info *di, int quick, int session)
{
struct blkdevstate *st = &state[unitnum];
if (failunit (unitnum))
@@ -713,6 +1055,1273 @@ struct device_info *sys_command_info (int unitnum, struct device_info *di, int q
return dix;
}
+#define MODE_SELECT_6 0x15
+#define MODE_SENSE_6 0x1a
+#define MODE_SELECT_10 0x55
+#define MODE_SENSE_10 0x5a
+
+void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **datap, int *datalenp, int *parm)
+{
+ uae_u8 cmd, *p, *data = *datap;
+ int l, datalen = *datalenp;
+
+ *parm = 0;
+ cmd = scsi_cmd[0];
+ if (cmd != MODE_SELECT_6 && cmd != MODE_SENSE_6)
+ return;
+ l = scsi_cmd[4];
+ if (l > 4)
+ l += 4;
+ scsi_cmd[7] = l >> 8;
+ scsi_cmd[8] = l;
+ if (cmd == MODE_SELECT_6) {
+ scsi_cmd[0] = MODE_SELECT_10;
+ scsi_cmd[9] = scsi_cmd[5];
+ scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = scsi_cmd[6] = 0;
+ *len = 10;
+ p = xmalloc (uae_u8, 8 + datalen + 4);
+ if (datalen > 4)
+ memcpy (p + 8, data + 4, datalen - 4);
+ p[0] = 0;
+ p[1] = data[0];
+ p[2] = data[1];
+ p[3] = data[2];
+ p[4] = p[5] = p[6] = 0;
+ p[7] = data[3];
+ if (l > 8)
+ datalen += 4;
+ *parm = MODE_SELECT_10;
+ *datap = p;
+ } else {
+ scsi_cmd[0] = MODE_SENSE_10;
+ scsi_cmd[9] = scsi_cmd[5];
+ scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = scsi_cmd[6] = 0;
+ if (l > 8)
+ datalen += 4;
+ *datap = xmalloc (uae_u8, datalen);
+ *len = 10;
+ *parm = MODE_SENSE_10;
+ }
+ *datalenp = datalen;
+}
+
+void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalenp, int parm)
+{
+ int datalen = *datalenp;
+ if (!data || !datalen)
+ return;
+ if (parm == MODE_SENSE_10) {
+ olddata[0] = data[1];
+ olddata[1] = data[2];
+ olddata[2] = data[3];
+ olddata[3] = data[7];
+ datalen -= 4;
+ if (datalen > 4)
+ memcpy (olddata + 4, data + 8, datalen - 4);
+ *datalenp = datalen;
+ }
+}
+
+static void scsi_atapi_fixup_inquiry (struct amigascsi *as)
+{
+ uae_u8 *scsi_data = as->data;
+ uae_u32 scsi_len = as->len;
+ uae_u8 *scsi_cmd = as->cmd;
+ uae_u8 cmd;
+
+ cmd = scsi_cmd[0];
+ /* CDROM INQUIRY: most Amiga programs expect ANSI version == 2
+ * (ATAPI normally responds with zero)
+ */
+ if (cmd == 0x12 && scsi_len > 2 && scsi_data) {
+ uae_u8 per = scsi_data[0];
+ uae_u8 b = scsi_data[2];
+ /* CDROM and ANSI version == 0 ? */
+ if ((per & 31) == 5 && (b & 7) == 0) {
+ b |= 2;
+ scsi_data[2] = b;
+ }
+ }
+}
+
+void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen)
+{
+ int i;
+ for (i = 0; i < cdblen; i++) {
+ write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), cdb[i]);
+ }
+ write_log (_T("\n"));
+ if (data) {
+ write_log (_T("DATAOUT: %d\n"), datalen);
+ for (i = 0; i < datalen && i < 100; i++)
+ write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), data[i]);
+ if (datalen > 0)
+ write_log (_T("\n"));
+ }
+}
+
+void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen)
+{
+ int i;
+ write_log (_T("DATAIN: %d\n"), datalen);
+ for (i = 0; i < datalen && i < 100 && data; i++)
+ write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), data[i]);
+ if (data && datalen > 0)
+ write_log (_T("\n"));
+ if (senselen > 0) {
+ write_log (_T("SENSE: %d,"), senselen);
+ for (i = 0; i < senselen && i < 32; i++) {
+ write_log (_T("%s%02X"), i > 0 ? _T(".") : _T(""), sense[i]);
+ }
+ write_log (_T("\n"));
+ }
+}
+
+static bool nodisk (struct device_info *di)
+{
+ return di->media_inserted == 0;
+}
+static int cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len)
+{
+ if (!getsem (unitnum))
+ return 0;
+ int v = state[unitnum].device_func->read (unitnum, dataptr, offset, len);
+ freesem (unitnum);
+ if (v >= 0)
+ return len;
+ return v;
+}
+
+static void wl (uae_u8 *p, int v)
+{
+ p[0] = v >> 24;
+ p[1] = v >> 16;
+ p[2] = v >> 8;
+ p[3] = v;
+}
+static void ww (uae_u8 *p, int v)
+{
+ p[0] = v >> 8;
+ p[1] = v;
+}
+static int rl (uae_u8 *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
+}
+static int rw (uae_u8 *p)
+{
+ return (p[0] << 8) | (p[1]);
+}
+
+static void stopplay (int unitnum)
+{
+ sys_command_cd_stop (unitnum);
+}
+
+static int addtocentry (uae_u8 **dstp, int *len, int point, int newpoint, int msf, uae_u8 *head, struct cd_toc_head *th)
+{
+ uae_u8 *dst = *dstp;
+
+ for (int i = 0; i < th->points; i++) {
+ struct cd_toc *t = &th->toc[i];
+ if (t->point == point) {
+ if (*len < 8)
+ return 0;
+ int addr = t->paddress;
+ if (msf)
+ addr = lsn2msf (addr);
+ dst[0] = 0;
+ dst[1] = (t->adr << 4) | t->control;
+ dst[2] = newpoint >= 0 ? newpoint : point;
+ dst[3] = 0;
+ dst[4] = addr >> 24;
+ dst[5] = addr >> 16;
+ dst[6] = addr >> 8;
+ dst[7] = addr >> 0;
+
+ if (point >= 1 && point <= 99) {
+ if (head[2] == 0)
+ head[2] = point;
+ head[3] = point;
+ }
+
+ *len -= 8;
+ *dstp = dst + 8;
+ return 1;
+ }
+ }
+ return -1;
+}
+
+static int scsiemudrv (int unitnum, uae_u8 *cmd)
+{
+ if (failunit (unitnum))
+ return -1;
+ if (!getsem (unitnum))
+ return 0;
+ int v = 0;
+ if (state[unitnum].device_func->scsiemu)
+ v = state[unitnum].device_func->scsiemu (unitnum, cmd);
+ freesem (unitnum);
+ return v;
+}
+
+static int scsi_read_cd_da(int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di)
+{
+ struct blkdevstate *st = &state[unitnum];
+ int msf = cmd[0] == 0xd9;
+ int start = msf ? msf2lsn(rl(cmd + 2) & 0x00ffffff) : rl(cmd + 2);
+ int len = rl(cmd + 6) & 0x00ffffff;
+ int sectorsize;
+ uae_u8 subcode = cmd[10];
+ switch (subcode)
+ {
+ case 0:
+ sectorsize = 2352;
+ break;
+ case 1:
+ sectorsize = 2368;
+ break;
+ case 2:
+ sectorsize = 2448;
+ break;
+ case 3:
+ sectorsize = 96;
+ break;
+ default:
+ return -1;
+ }
+ if (msf) {
+ int end = msf2lsn(len);
+ len = end - start;
+ if (len < 0)
+ return -1;
+ }
+ if (len == 0)
+ return 0;
+ int v = sys_command_cd_rawread(unitnum, data, start, len, sectorsize);
+ if (v > 0)
+ st->current_pos = start + len;
+ return v;
+}
+
+static int scsi_read_cd(int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di)
+{
+ struct blkdevstate *st = &state[unitnum];
+ int msf = cmd[0] == 0xb9;
+ int start = msf ? msf2lsn (rl (cmd + 2) & 0x00ffffff) : rl (cmd + 2);
+ int len = rl (cmd + 5) & 0x00ffffff;
+ if (msf) {
+ int end = msf2lsn (len);
+ len = end - start;
+ if (len < 0)
+ return -1;
+ }
+ int subs = cmd[10] & 7;
+ if (len == 0)
+ return 0;
+ int v = sys_command_cd_rawread (unitnum, data, start, len, 0, (cmd[1] >> 2) & 7, cmd[9], subs);
+ if (v > 0)
+ st->current_pos = start + len;
+ return v;
+}
+
+static int scsi_read_cd_data (int unitnum, uae_u8 *scsi_data, uae_u32 offset, uae_u32 len, struct device_info *di, int *scsi_len, struct cd_toc *t)
+{
+ struct blkdevstate *st = &state[unitnum];
+ int end = t[1].paddress;
+
+ if (len == 0) {
+ if (offset >= end)
+ return -1;
+ *scsi_len = 0;
+ return 0;
+ } else {
+ if (offset >= end)
+ return -1;
+ int v = cmd_readx (unitnum, scsi_data, offset, len) * di->bytespersector;
+ if (v > 0) {
+ st->current_pos = offset + len;
+ *scsi_len = v;
+ return 0;
+ }
+ return -2;
+ }
+}
+
+int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
+ uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len, bool atapi)
+{
+ struct blkdevstate *st = &state[unitnum];
+ uae_u32 len, offset;
+ int lr = 0, ls = 0;
+ int scsi_len = -1;
+ int v;
+ int status = 0;
+ struct device_info di;
+ uae_u8 cmd;
+ int dlen, lun;
+
+ if (cmdbuf == NULL) {
+ if (st->mediawaschanged) {
+ st->mediawaschanged = false;
+ return (0x28 << 8) | (0x00);
+ }
+ return 0;
+ }
+
+ cmd = cmdbuf[0];
+
+ if (cmd == 0x03) {
+ return 0;
+ }
+
+ dlen = *data_len;
+ *reply_len = *sense_len = 0;
+
+ lun = cmdbuf[1] >> 5;
+ if (cmdbuf[0] != 0x03 && cmdbuf[0] != 0x12 && lun) {
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 5; /* ILLEGAL REQUEST */
+ s[12] = 0x25; /* INVALID LUN */
+ ls = 0x12;
+ write_log (_T("CD SCSIEMU %d: CMD=%02X LUN=%d ignored\n"), unitnum, cmdbuf[0], lun);
+ goto end;
+ }
+
+ sys_command_info (unitnum, &di, 1);
+
+ switch (cmdbuf[0])
+ {
+ case 0x00: /* TEST UNIT READY */
+ if (nodisk (&di))
+ goto nodisk;
+ scsi_len = 0;
+ break;
+ case 0x1e: /* PREVENT/ALLOW MEDIUM REMOVAL */
+ scsi_len = 0;
+ break;
+ case 0xbd: /* MECHANISM STATUS */
+ len = (cmdbuf[8] << 8) | cmdbuf[9];
+ if (len > 8)
+ len = 8;
+ scsi_len = len;
+ r[2] = st->current_pos >> 16;
+ r[3] = st->current_pos >> 8;
+ r[4] = st->current_pos >> 0;
+ break;
+ case 0x12: /* INQUIRY */
+ {
+ if ((cmdbuf[1] & 1) || cmdbuf[2] != 0)
+ goto err;
+ len = cmdbuf[4];
+ if (cmdbuf[1] >> 5) {
+ r[0] = 0x7f;
+ } else {
+ r[0] = 5; // CDROM
+ }
+ r[1] |= 0x80; // removable
+ r[2] = 2; /* supports SCSI-2 */
+ r[3] = 2; /* response data format */
+ if (atapi)
+ r[3] |= 3 << 5; // atapi transport version
+ r[4] = 32; /* additional length */
+ r[7] = 0;
+ scsi_len = lr = len < 36 ? len : 36;
+ r[2] = 2;
+ r[3] = 2;
+ char *s = ua (di.vendorid);
+ memcpy (r + 8, s, strlen (s));
+ xfree (s);
+ s = ua (di.productid);
+ memcpy (r + 16, s, strlen (s));
+ xfree (s);
+ s = ua (di.revision);
+ memcpy (r + 32, s, strlen (s));
+ xfree (s);
+ for (int i = 8; i < 36; i++) {
+ if (r[i] == 0)
+ r[i] = 32;
+ }
+ }
+ break;
+ case 0xd8: // READ CD-DA
+ case 0xd9: // READ CD-DA MSF
+ if (nodisk(&di))
+ goto nodisk;
+ scsi_len = scsi_read_cd_da(unitnum, cmdbuf, scsi_data, &di);
+ if (scsi_len == -2)
+ goto wrongtracktype;
+ if (scsi_len == -1)
+ goto errreq;
+ break;
+ case 0xbe: // READ CD
+ case 0xb9: // READ CD MSF
+ if (nodisk (&di))
+ goto nodisk;
+ scsi_len = scsi_read_cd(unitnum, cmdbuf, scsi_data, &di);
+ if (scsi_len == -2)
+ goto wrongtracktype;
+ if (scsi_len == -1)
+ goto errreq;
+ break;
+ case 0x55: // MODE SELECT(10)
+ case 0x15: // MODE SELECT(6)
+ {
+ uae_u8 *p;
+ bool mode10 = cmdbuf[0] == 0x55;
+ p = scsi_data + 4;
+ if (mode10)
+ p += 4;
+ int pcode = p[0] & 0x3f;
+ if (pcode == 14) { // CD audio control
+ uae_u16 vol_left = (p[9] << 7) | (p[9] >> 1);
+ uae_u16 vol_right = (p[11] << 7) | (p[11] >> 1);
+ sys_command_cd_volume (unitnum, vol_left, vol_right);
+ scsi_len = 0;
+ } else {
+ goto errreq;
+ }
+ }
+ break;
+ case 0x5a: // MODE SENSE(10)
+ case 0x1a: /* MODE SENSE(6) */
+ {
+ uae_u8 *p;
+ int maxlen;
+ bool pcodeloop = false;
+ bool sense10 = cmdbuf[0] == 0x5a;
+ int psize, totalsize, bdsize;
+ int pc = cmdbuf[2] >> 6;
+ int pcode = cmdbuf[2] & 0x3f;
+ int dbd = cmdbuf[1] & 8;
+
+ if (atapi) {
+ if (!sense10)
+ goto err;
+ dbd = 1;
+ }
+ p = r;
+ if (sense10) {
+ totalsize = 8 - 2;
+ maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+ p[2] = 0;
+ p[3] = 0;
+ p[4] = 0;
+ p[5] = 0;
+ p[6] = 0;
+ p[7] = 0;
+ p += 8;
+ } else {
+ totalsize = 4 - 1;
+ maxlen = cmdbuf[4];
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p += 4;
+ }
+ bdsize = 0;
+ if (!dbd) {
+ wl(p + 0, 0);
+ wl(p + 4, di.bytespersector);
+ bdsize = 8;
+ p += bdsize;
+ }
+ if (pcode == 0x3f) {
+ pcode = 1; // page = 0 must be last
+ pcodeloop = true;
+ }
+ for (;;) {
+ psize = 0;
+ if (pcode == 0) {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0x20;
+ p[3] = 0;
+ psize = 4;
+ } else if (pcode == 14) { // CD audio control
+ uae_u32 vol = sys_command_cd_volume (unitnum, 0xffff, 0xffff);
+ p[0] = 0x0e;
+ p[1] = 0x0e;
+ p[2] = 4|1;
+ p[3] = 4;
+ p[6] = 0;
+ p[7] = 75;
+ p[8] = 1;
+ p[9] = pc == 0 ? (vol >> 7) & 0xff : 0xff;
+ p[10] = 2;
+ p[11] = pc == 0 ? (vol >> (16 + 7)) & 0xff : 0xff;
+ psize = p[1] + 2;
+ } else if (pcode == 0x2a) { // cd/dvd capabilities
+ p[0] = 0x2a;
+ p[1] = 0x18;
+ p[2] = 1; // | 0x10 | 0x20; // read: CD-R/DVD-ROM/DVD-R
+ p[3] = 0; // write: nothing
+ p[4] = 0x40 | 0x20 | 0x10 | 0x01;
+ p[5] = 0x08 | 0x04 | 0x02 | 0x01;
+ p[6] = (1 << 5) | 0x10; // type = tray, eject supported
+ p[7] = 3; // separate channel mute and volume
+ p[8] = 2; p[9] = 0;
+ p[10] = 0xff; p[11] = 0xff; // number of volume levels
+ p[12] = 4; p[13] = 0; // "1M buffer"
+ p[14] = 2; p[15] = 0;
+ p[16] = 0;
+ p[17] = 0;
+ p[18] = p[19] = 0;
+ p[20] = p[21] = 0;
+ p[22] = p[23] = 0;
+ psize = p[1] + 2;
+ } else {
+ if (!pcodeloop)
+ goto err;
+ }
+ totalsize += psize;
+ p += psize;
+ if (!pcodeloop)
+ break;
+ if (pcode == 0)
+ break;
+ pcode++;
+ if (pcode == 0x3f)
+ pcode = 0;
+ }
+ if (sense10) {
+ totalsize += bdsize;
+ r[6] = bdsize >> 8;
+ r[7] = bdsize & 0xff;
+ r[0] = totalsize >> 8;
+ r[1] = totalsize & 0xff;
+ } else {
+ totalsize += bdsize;
+ r[3] = bdsize & 0xff;
+ r[0] = totalsize & 0xff;
+ }
+ scsi_len = totalsize + 1;
+ if (scsi_len > maxlen)
+ scsi_len = maxlen;
+ lr = scsi_len;
+ }
+ break;
+ case 0x01: /* REZERO UNIT */
+ scsi_len = 0;
+ break;
+ case 0x1d: /* SEND DIAGNOSTICS */
+ scsi_len = 0;
+ break;
+ case 0x25: /* READ CAPACITY */
+ {
+ int pmi = cmdbuf[8] & 1;
+ uae_u32 lba = (cmdbuf[2] << 24) | (cmdbuf[3] << 16) | (cmdbuf[4] << 8) | cmdbuf[5];
+ int cyl, cylsec, head, tracksec;
+ if (nodisk (&di))
+ goto nodisk;
+ uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder - 1;
+ cyl = di.cylinders;
+ head = 1;
+ cylsec = tracksec = di.trackspercylinder;
+ if (pmi == 0 && lba != 0)
+ goto errreq;
+ if (pmi) {
+ lba += tracksec * head;
+ lba /= tracksec * head;
+ lba *= tracksec * head;
+ if (lba > blocks)
+ lba = blocks;
+ blocks = lba;
+ }
+ wl (r, blocks);
+ wl (r + 4, di.bytespersector);
+ scsi_len = lr = 8;
+ }
+ break;
+ case 0x0b: /* SEEK (6) */
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ stopplay (unitnum);
+ offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3];
+ struct cd_toc *t = gettoc (unitnum, &di.toc, offset);
+ if (!t)
+ goto readerr;
+ v = scsi_read_cd_data (unitnum, scsi_data, offset, 0, &di, &scsi_len, t);
+ if (v == -1)
+ goto outofbounds;
+ }
+ break;
+ case 0x08: /* READ (6) */
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ stopplay (unitnum);
+ offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3];
+ struct cd_toc *t = gettoc (unitnum, &di.toc, offset);
+ if (!t)
+ goto readerr;
+ if ((t->control & 0x0c) == 0x04) {
+ len = cmdbuf[4];
+ if (!len)
+ len = 256;
+ v = scsi_read_cd_data (unitnum, scsi_data, offset, len, &di, &scsi_len, t);
+ if (v == -1)
+ goto outofbounds;
+ if (v == -2)
+ goto readerr;
+ } else {
+ goto wrongtracktype;
+ }
+ }
+ break;
+ case 0x0a: /* WRITE (6) */
+ goto readprot;
+ case 0x2b: /* SEEK (10) */
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ stopplay (unitnum);
+ offset = rl (cmdbuf + 2);
+ struct cd_toc *t = gettoc (unitnum, &di.toc, offset);
+ if (!t)
+ goto readerr;
+ v = scsi_read_cd_data (unitnum, scsi_data, offset, 0, &di, &scsi_len, t);
+ if (v == -1)
+ goto outofbounds;
+ }
+ break;
+ case 0x28: /* READ (10) */
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ stopplay (unitnum);
+ offset = rl (cmdbuf + 2);
+ struct cd_toc *t = gettoc (unitnum, &di.toc, offset);
+ if (!t)
+ goto readerr;
+ if ((t->control & 0x0c) == 0x04) {
+ len = rl (cmdbuf + 7 - 2) & 0xffff;
+ v = scsi_read_cd_data (unitnum, scsi_data, offset, len, &di, &scsi_len, t);
+ if (v == -1)
+ goto outofbounds;
+ if (v == -2)
+ goto readerr;
+ } else {
+ goto wrongtracktype;
+ }
+ }
+ break;
+ case 0x2a: /* WRITE (10) */
+ goto readprot;
+ case 0xa8: /* READ (12) */
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ stopplay (unitnum);
+ offset = rl (cmdbuf + 2);
+ struct cd_toc *t = gettoc (unitnum, &di.toc, offset);
+ if (!t)
+ goto readerr;
+ if ((t->control & 0x0c) == 0x04) {
+ len = rl (cmdbuf + 6);
+ v = scsi_read_cd_data (unitnum, scsi_data, offset, len, &di, &scsi_len, t);
+ if (v == -1)
+ goto outofbounds;
+ if (v == -2)
+ goto readerr;
+ } else {
+ goto wrongtracktype;
+ }
+ }
+ break;
+ case 0xaa: /* WRITE (12) */
+ goto readprot;
+ case 0x51: /* READ DISC INFORMATION */
+ {
+ struct cd_toc_head ttoc;
+ int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+ if (nodisk (&di))
+ goto nodisk;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ uae_u8 *p = scsi_data;
+ p[0] = 0;
+ p[1] = 34 - 2;
+ p[2] = 2 | (3 << 2); // complete cd rom, last session is complete
+ p[3] = toc->first_track;
+ p[4] = 1;
+ p[5] = toc->first_track;
+ p[6] = toc->last_track;
+ wl (p + 16, lsn2msf (toc->lastaddress));
+ wl (p + 20, 0x00ffffff);
+ scsi_len = p[1] + 2;
+ if (scsi_len > maxlen)
+ scsi_len = maxlen;
+ }
+ break;
+ case 0x52: /* READ TRACK INFORMATION */
+ {
+ struct cd_toc_head ttoc;
+ int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+ if (nodisk (&di))
+ goto nodisk;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ uae_u8 *p = scsi_data;
+ int lsn;
+ if (cmdbuf[1] & 1) {
+ int track = cmdbuf[5];
+ lsn = toc->toc[track].address;
+ } else {
+ lsn = rl (p + 2);
+ }
+ struct cd_toc *t = gettoc (unitnum, toc, lsn);
+ if (!t)
+ goto readerr;
+ p[0] = 0;
+ p[1] = 28 - 2;
+ p[2] = t->track;
+ p[3] = 1;
+ p[5] = t->control;
+ p[6] = 0; // data mode, fixme
+ wl (p + 8, t->address);
+ wl (p + 24, t[1].address - t->address);
+ scsi_len = p[1] + 2;
+ if (scsi_len > maxlen)
+ scsi_len = maxlen;
+ }
+ break;
+ case 0x43: // READ TOC
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ uae_u8 *p = scsi_data;
+ int strack = cmdbuf[6];
+ int msf = cmdbuf[1] & 2;
+ int format = cmdbuf[2] & 7;
+ if (format >= 3)
+ goto errreq;
+ int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+ int maxlen2 = maxlen;
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ if (format == 1) {
+ p[0] = 0;
+ p[1] = 2 + 8;
+ p[2] = 1;
+ p[3] = 1;
+ p[4] = 0;
+ p[5] = (toc->toc[0].adr << 4) | toc->toc[0].control;
+ p[6] = toc->first_track;
+ p[7] = 0;
+ if (msf)
+ wl (p + 8, lsn2msf (toc->toc[0].address));
+ else
+ wl (p + 8 , toc->toc[0].address);
+ scsi_len = 12;
+ } else if (format == 2 || format == 0) {
+ if (format == 2 && !msf)
+ goto errreq;
+ if (strack == 0)
+ strack = toc->first_track;
+ if (format == 0 && strack >= 100 && strack != 0xaa)
+ goto errreq;
+ uae_u8 *p2 = p + 4;
+ p[2] = 0;
+ p[3] = 0;
+ maxlen -= 4;
+ if (format == 2) {
+ if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc))
+ break;
+ if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc))
+ break;
+ if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc))
+ break;
+ }
+ while (strack < 100) {
+ if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc))
+ break;
+ strack++;
+ }
+ addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc);
+ int tlen = p2 - (p + 2);
+ p[0] = tlen >> 8;
+ p[1] = tlen >> 0;
+ scsi_len = tlen + 2;
+ }
+ if (scsi_len > maxlen2)
+ scsi_len = maxlen2;
+ }
+ break;
+ case 0x42: // READ SUB-CHANNEL
+ {
+ int msf = cmdbuf[1] & 2;
+ int subq = cmdbuf[2] & 0x40;
+ int format = cmdbuf[3];
+ int track = cmdbuf[6];
+ int maxlen = rw(cmdbuf + 7);
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+
+ if (nodisk (&di))
+ goto nodisk;
+ sys_command_cd_qcode (unitnum, buf, -1, false);
+ scsi_len = 4;
+ scsi_data[0] = 0;
+ scsi_data[1] = buf[1];
+ if (subq && format == 1) {
+ scsi_data[2] = 0;
+ scsi_data[3] = 12;
+ scsi_len += 12;
+ scsi_data[4] = 1;
+ scsi_data[5] = (buf[4 + 0] << 4) | (buf[4 + 0] >> 4);
+ scsi_data[6] = frombcd (buf[4 + 1]); // track
+ scsi_data[7] = frombcd (buf[4 + 2]); // index
+ int reladdr = fromlongbcd (&buf[4 + 3]);
+ int absaddr = fromlongbcd (&buf[4 + 7]);
+ if (!msf) {
+ reladdr = msf2lsn (reladdr);
+ absaddr = msf2lsn (absaddr);
+ }
+ wl (scsi_data + 8, absaddr);
+ wl (scsi_data + 12, reladdr);
+ } else {
+ scsi_data[2] = 0;
+ scsi_data[3] = 0;
+ }
+ if (scsi_len > maxlen)
+ scsi_len = maxlen;
+ }
+ break;
+ case 0x1b: // START/STOP
+ sys_command_cd_stop (unitnum);
+ scsiemudrv (unitnum, cmdbuf);
+ scsi_len = 0;
+ break;
+ case 0x4e: // STOP PLAY/SCAN
+ if (nodisk (&di))
+ goto nodisk;
+ sys_command_cd_stop (unitnum);
+ scsi_len = 0;
+ break;
+ case 0xba: // SCAN
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ int scan = (cmdbuf[1] & 0x10) ? -1 : 1;
+ int start = rl (cmdbuf + 1) & 0x00ffffff;
+ int end = scan > 0 ? toc->lastaddress : toc->toc[toc->first_track_offset].paddress;
+ int type = cmdbuf[9] >> 6;
+ if (type == 1)
+ start = lsn2msf (start);
+ if (type == 3)
+ goto errreq;
+ if (type == 2) {
+ if (toc->first_track_offset + start >= toc->last_track_offset)
+ goto errreq;
+ start = toc->toc[toc->first_track_offset + start].paddress;
+ }
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_play (unitnum, start, end, scan);
+ scsi_len = 0;
+ }
+ break;
+ case 0x48: // PLAY AUDIO TRACK/INDEX
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int strack = cmdbuf[4];
+ int etrack = cmdbuf[7];
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ if (strack < toc->first_track || strack > toc->last_track ||
+ etrack < toc->first_track || etrack > toc->last_track ||
+ strack > etrack)
+ goto errreq;
+ int start = toc->toc[toc->first_track_offset + strack - 1].paddress;
+ int end = etrack == toc->last_track ? toc->lastaddress : toc->toc[toc->first_track_offset + etrack - 1 + 1].paddress;
+ sys_command_cd_pause (unitnum, 0);
+ if (!sys_command_cd_play (unitnum, start, end, 0))
+ goto wrongtracktype;
+ scsi_len = 0;
+ }
+ break;
+ case 0x49: // PLAY AUDIO TRACK RELATIVE (10)
+ case 0xa9: // PLAY AUDIO TRACK RELATIVE (12)
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int len = cmd == 0xa9 ? rl (cmdbuf + 6) : rw (cmdbuf + 7);
+ int track = cmd == 0xa9 ? cmdbuf[10] : cmdbuf[6];
+ if (track < di.toc.first_track || track > di.toc.last_track)
+ goto errreq;
+ int start = di.toc.toc[di.toc.first_track_offset + track - 1].paddress;
+ int rel = rl (cmdbuf + 2);
+ start += rel;
+ int end = start + len;
+ if (end > di.toc.lastaddress)
+ end = di.toc.lastaddress;
+ if (len > 0) {
+ sys_command_cd_pause (unitnum, 0);
+ if (!sys_command_cd_play (unitnum, start, start + len, 0))
+ goto wrongtracktype;
+ }
+ scsi_len = 0;
+ }
+ break;
+ case 0x47: // PLAY AUDIO MSF
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = rl (cmdbuf + 2) & 0x00ffffff;
+ if (start == 0x00ffffff) {
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (unitnum, buf, -1, false);
+ start = fromlongbcd (buf + 4 + 7);
+ }
+ int end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff);
+ if (end > di.toc.lastaddress)
+ end = di.toc.lastaddress;
+ start = msf2lsn (start);
+ if (start > end)
+ goto errreq;
+ if (start < end)
+ sys_command_cd_pause (unitnum, 0);
+ if (!sys_command_cd_play (unitnum, start, end, 0))
+ goto wrongtracktype;
+ scsi_len = 0;
+ }
+ break;
+ case 0x45: // PLAY AUDIO (10)
+ case 0xa5: // PLAY AUDIO (12)
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = rl (cmdbuf + 2);
+ int len;
+ if (cmd == 0xa5)
+ len = rl (cmdbuf + 6);
+ else
+ len = rw (cmdbuf + 7);
+ if (len > 0) {
+ if (start == -1) {
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (unitnum, buf, -1, false);
+ start = msf2lsn (fromlongbcd (buf + 4 + 7));
+ }
+ int end = start + len;
+ if (end > di.toc.lastaddress)
+ end = di.toc.lastaddress;
+ sys_command_cd_pause (unitnum, 0);
+ if (!sys_command_cd_play (unitnum, start, end, 0))
+ goto wrongtracktype;
+ }
+ scsi_len = 0;
+ }
+ break;
+ case 0xbc: // PLAY CD
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = -1;
+ int end = -1;
+ if (cmdbuf[1] & 2) {
+ start = msf2lsn (rl (cmdbuf + 2) & 0x00ffffff);
+ end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff);
+ } else {
+ start = rl (cmdbuf + 2);
+ end = start + rl (cmdbuf + 6);
+ }
+ if (end > di.toc.lastaddress)
+ end = di.toc.lastaddress;
+ if (start > end)
+ goto errreq;
+ if (start < end) {
+ sys_command_cd_pause (unitnum, 0);
+ if (!sys_command_cd_play (unitnum, start, end, 0))
+ goto wrongtracktype;
+ }
+ }
+ break;
+ case 0x4b: // PAUSE/RESUME
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ int resume = cmdbuf[8] & 1;
+ sys_command_cd_qcode (unitnum, buf, -1, false);
+ if (buf[1] != AUDIO_STATUS_IN_PROGRESS && buf[1] != AUDIO_STATUS_PAUSED)
+ goto errreq;
+ sys_command_cd_pause (unitnum, resume ? 0 : 1);
+ scsi_len = 0;
+ }
+ break;
+ case 0x35: /* SYNCRONIZE CACHE (10) */
+ scsi_len = 0;
+ break;
+
+ default:
+err:
+ write_log (_T("CD SCSIEMU: unsupported scsi command 0x%02X\n"), cmdbuf[0]);
+readprot:
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 5;
+ s[12] = 0x20; /* INVALID COMMAND */
+ ls = 0x12;
+ break;
+nodisk:
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 2; /* NOT READY */
+ s[12] = 0x3A; /* MEDIUM NOT PRESENT */
+ ls = 0x12;
+ break;
+readerr:
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 2; /* NOT READY */
+ s[12] = 0x11; /* UNRECOVERED READ ERROR */
+ ls = 0x12;
+ break;
+wrongtracktype:
+ status = 2;
+ s[0] = 0x70;
+ s[2] = 5;
+ s[12] = 0x64; /* ILLEGAL MODE FOR THIS TRACK */
+ ls = 0x12;
+ break;
+outofbounds:
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 5; /* ILLEGAL REQUEST */
+ s[12] = 0x21; /* LOGICAL BLOCK OUT OF RANGE */
+ ls = 0x12;
+ break;
+errreq:
+ lr = -1;
+ status = 2; /* CHECK CONDITION */
+ s[0] = 0x70;
+ s[2] = 5; /* ILLEGAL REQUEST */
+ s[12] = 0x24; /* ILLEGAL FIELD IN CDB */
+ ls = 0x12;
+ break;
+ }
+end:
+ *data_len = scsi_len;
+ *reply_len = lr;
+ *sense_len = ls;
+
+ if (ls) {
+ //s[0] |= 0x80;
+ if (ls > 7)
+ s[7] = ls - 8; // additional sense length
+ }
+
+ return status;
+}
+
+static int emulate_cd_audio = 1;
+
+int blkdev_is_audio_command(uae_u8 cmd)
+{
+ if (!emulate_cd_audio)
+ return false;
+ // audio cd command?
+ switch (cmd)
+ {
+ case 0x42:
+ case 0x45:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4b:
+ case 0x4e:
+ case 0xa5:
+ case 0xa9:
+ case 0xba:
+ case 0xbc:
+ case 0xcd:
+ return 1;
+ }
+
+ // commands that won't stop cd audio
+ switch (cmd)
+ {
+ case 0x00:
+ case 0x03:
+ case 0x12:
+ case 0x15:
+ case 0x1a:
+ case 0x1e:
+ case 0x25:
+ case 0x35:
+ case 0x55:
+ case 0x5a:
+ return 0;
+ }
+
+ // all other commands stop cd audio
+ return -1;
+}
+
+int blkdev_execute_audio_command(int unitnum, uae_u8 *cdb, int cdblen, uae_u8 *inbuf, int inlen, uae_u8 *sense, int *senselen)
+{
+ int len = inlen;
+ uae_u8 reply[256];
+ int replylen = sizeof(reply);
+ int status = scsi_cd_emulate(unitnum, cdb, cdblen, inbuf, &len, reply, &replylen, sense, senselen, true);
+ if (status)
+ return -1;
+ return len;
+}
+
+static int execscsicmd_direct (int unitnum, int type, struct amigascsi *as)
+{
+ int io_error = 0;
+ uae_u8 *scsi_datap, *scsi_datap_org;
+ uae_u32 scsi_cmd_len_orig = as->cmd_len;
+ uae_u8 cmd[16] = { 0 };
+ uae_u8 replydata[256] = { 0 };
+ int datalen = as->len;
+ int senselen = as->sense_len;
+ int replylen = 0;
+
+ memcpy (cmd, as->cmd, as->cmd_len);
+ scsi_datap = scsi_datap_org = as->len ? as->data : 0;
+ if (as->sense_len > 32)
+ as->sense_len = 32;
+
+ /* never report media change state if uaescsi.device */
+ state[unitnum].mediawaschanged = false;
+
+ switch (type)
+ {
+ case INQ_ROMD:
+ as->status = scsi_cd_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen, false);
+ break;
+ case INQ_SEQD:
+ //as->status = scsi_tape_emulate (state[unitnum].tape, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen);
+ break;
+ default:
+ as->status = 2;
+ break;
+ }
+
+ as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */
+ if (as->status) {
+ io_error = IOERR_BadStatus;
+ as->sactual = senselen;
+ as->actual = 0; /* scsi_Actual */
+ } else {
+ int i;
+ if (replylen > 0) {
+ for (int i = 0; i < replylen; i++) {
+ scsi_datap[i] = replydata[i];
+ }
+ datalen = replylen;
+ }
+ for (i = 0; i < as->sense_len; i++)
+ as->sensedata[i] = 0;
+ if (datalen < 0) {
+ io_error = IOERR_NotSpecified;
+ as->actual = 0; /* scsi_Actual */
+ } else {
+ as->len = datalen;
+ io_error = 0;
+ as->actual = as->len; /* scsi_Actual */
+ }
+ }
+
+ return io_error;
+}
+
+int sys_command_scsi_direct_native(int unitnum, int type, struct amigascsi *as)
+{
+ struct blkdevstate *st = &state[unitnum];
+ if (st->scsiemu || (type >= 0 && st->type != type)) {
+ return execscsicmd_direct (unitnum, type, as);
+ } else {
+ if (!st->device_func->exec_direct)
+ return -1;
+ }
+ int ret = st->device_func->exec_direct (unitnum, as);
+ if (!ret && st->device_func->isatapi(unitnum))
+ scsi_atapi_fixup_inquiry (as);
+ return ret;
+}
+
+int sys_command_scsi_direct(TrapContext *ctx, int unitnum, int type, uaecptr acmd)
+{
+ int ret;
+ struct amigascsi as = { 0 };
+ uaecptr ap;
+ addrbank *bank;
+ uae_u8 scsicmd[30];
+
+ trap_get_bytes(ctx, scsicmd, acmd, sizeof scsicmd);
+
+ as.cmd_len = get_word_host(scsicmd + 16);
+ if (as.cmd_len > sizeof as.cmd)
+ return IOERR_BADLENGTH;
+ as.flags = get_byte_host(scsicmd + 20);
+ ap = get_long_host(scsicmd + 0);
+ as.len = get_long_host(scsicmd + 4);
+
+ if (trap_is_indirect()) {
+ if (!(as.flags & 1)) { // write?
+ as.data = xmalloc(uae_u8, as.len);
+ trap_get_bytes(ctx, as.data, ap, as.len);
+ } else {
+ as.data = xcalloc(uae_u8, as.len);
+ }
+ } else {
+ bank = &get_mem_bank (ap);
+ if (!bank || !bank->check(ap, as.len))
+ return IOERR_BADADDRESS;
+ as.data = bank->xlateaddr (ap);
+ }
+
+ ap = get_long_host(scsicmd + 12);
+ trap_get_bytes(ctx, as.cmd, ap, as.cmd_len);
+ as.sense_len = get_word_host(scsicmd + 26);
+
+
+ ret = sys_command_scsi_direct_native (unitnum, type, &as);
+
+ put_long_host(scsicmd + 8, as.actual);
+ put_word_host(scsicmd + 18, as.cmdactual);
+ put_byte_host(scsicmd + 21, as.status);
+ put_word_host(scsicmd + 28, as.sactual);
+
+ if (as.flags & (2 | 4)) { // autosense
+ ap = get_long_host(scsicmd + 22);
+ if (as.sactual)
+ trap_put_bytes(ctx, as.sensedata, ap, as.sactual > as.sense_len ? as.sense_len : as.sactual);
+ if (as.sense_len > as.sactual)
+ trap_set_bytes(ctx, ap + as.sactual, 0, as.sense_len - as.sactual);
+ }
+
+ trap_put_bytes(ctx, scsicmd, acmd, sizeof scsicmd);
+
+ if (trap_is_indirect()) {
+ if (as.flags & 1) { // read?
+ int len = as.actual > as.len ? as.len : as.actual;
+ trap_put_bytes(ctx, as.data, get_long_host(scsicmd + 0), len);
+ }
+ xfree(as.data);
+ }
+
+ return ret;
+}
+
#ifdef SAVESTATE
void restore_blkdev_start(void)
@@ -734,7 +2343,7 @@ uae_u8 *save_cd (int num, int *len)
memset(st->play_qcode, 0, SUBQ_SIZE);
if (!currprefs.cdslots[num].inuse || num >= MAX_TOTAL_SCSI_DEVICES)
return NULL;
- if (!currprefs.cs_cd32cd)
+ if (!currprefs.cs_cd32cd && !currprefs.cs_cdtvcd && !currprefs.scsi)
return NULL;
dstbak = dst = xmalloc (uae_u8, 4 + MAX_DPATH + 4 + 4 + 4 + 2 * MAX_DPATH);
save_u32 (4 | 8 | 16);
@@ -774,9 +2383,9 @@ uae_u8 *restore_cd (int num, uae_u8 *src)
s = restore_path_full();
}
if (flags & 4) {
- if (currprefs.cdslots[num].name[0] == 0 || zfile_exists (s)) {
- _tcscpy (changed_prefs.cdslots[num].name, s);
- _tcscpy (currprefs.cdslots[num].name, s);
+ if (currprefs.cdslots[num].name[0] == 0 || zfile_exists(s)) {
+ _tcscpy(changed_prefs.cdslots[num].name, s);
+ _tcscpy(currprefs.cdslots[num].name, s);
}
changed_prefs.cdslots[num].type = currprefs.cdslots[num].type = type;
changed_prefs.cdslots[num].temporary = currprefs.cdslots[num].temporary = true;
diff --git a/src/blkdev_cdimage.cpp b/src/blkdev_cdimage.cpp
index 0d564311..fe5b256b 100644
--- a/src/blkdev_cdimage.cpp
+++ b/src/blkdev_cdimage.cpp
@@ -11,10 +11,6 @@
* Copyright 2010-2013 Toni Wilen
*
*/
-
-#include
-#include
-#include
#include "sysconfig.h"
#ifdef HAVE_SYS_TIMEB_H
#include
@@ -24,6 +20,7 @@
#include "sysdeps.h"
#include "options.h"
+#include "traps.h"
#include "blkdev.h"
#include "zfile.h"
#include "gui.h"
@@ -31,15 +28,24 @@
#include "threaddep/thread.h"
#include "mp3decoder.h"
#include "cda_play.h"
-#include "include/memory.h"
+#include "memory.h"
+#include "audio.h"
#include "uae.h"
#define FLAC__NO_DLL
#include "FLAC/stream_decoder.h"
+#ifdef WITH_CHD
+#include "archivers/chd/chdtypes.h"
+#include "archivers/chd/chd.h"
+#include "archivers/chd/chdcd.h"
+#endif
+
+#define scsi_log write_log
+
#define CDDA_BUFFERS 12
-enum audenc { AUDENC_NONE, AUDENC_PCM, AUDENC_MP3, AUDENC_FLAC };
+enum audenc { AUDENC_NONE, AUDENC_PCM, AUDENC_MP3, AUDENC_FLAC, ENC_CHD };
struct cdtoc
{
@@ -52,6 +58,7 @@ struct cdtoc
uae_s64 filesize;
TCHAR *fname;
+ TCHAR *extrainfo;
int address;
uae_u8 adr, ctrl;
int track;
@@ -63,6 +70,9 @@ struct cdtoc
audenc enctype;
int writeoffset;
int subcode;
+#ifdef WITH_CHD
+ const cdrom_track_info *chdtrack;
+#endif
};
struct cdunit {
@@ -90,8 +100,13 @@ struct cdunit {
TCHAR imgname_out[MAX_DPATH];
uae_sem_t sub_sem;
struct device_info di;
+#ifdef WITH_CHD
+ chd_file *chd_f;
+ cdrom_file *chd_cdf;
+#endif
volatile int cda_bufon[2];
cda_audio *cda;
+ struct cd_audio_state cas;
};
static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES];
@@ -99,6 +114,7 @@ static int bus_open;
static volatile int cdimage_unpack_thread, cdimage_unpack_active;
static smp_comm_pipe unpack_pipe;
+static uae_sem_t play_sem;
static struct cdunit *unitisopen (int unitnum)
{
@@ -137,7 +153,36 @@ static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp, bool data)
static int do_read (struct cdunit *cdu, struct cdtoc *t, uae_u8 *data, int sector, int offset, int size, bool audio)
{
- if (t->handle) {
+ if (t->enctype == ENC_CHD) {
+#ifdef WITH_CHD
+ int type = CD_TRACK_MODE1_RAW;
+ uae_u8 tmpbuf[2352];
+ if (size > 2352)
+ return 0;
+ switch (size)
+ {
+ case 2352:
+ type = CD_TRACK_MODE1_RAW;
+ offset = 0;
+ break;
+ case 2336:
+ type = CD_TRACK_MODE2;
+ offset = 0;
+ break;
+ case 2048:
+ type = CD_TRACK_MODE1;
+ offset = 0;
+ break;
+ }
+ if (audio && size == 2352)
+ type = CD_TRACK_AUDIO;
+ if (cdrom_read_data(cdu->chd_cdf, sector + t->offset, tmpbuf, type, true)) {
+ memcpy(data, tmpbuf + offset, size);
+ return 1;
+ }
+ return 0;
+#endif
+ } else if (t->handle) {
int ssize = t->size + t->skipsize;
zfile_fseek (t->handle, t->offset + (uae_u64)sector * ssize + offset, SEEK_SET);
return zfile_fread (data, 1, size, t->handle) == size;
@@ -153,6 +198,8 @@ static void flac_metadata_callback (const FLAC__StreamDecoder *decoder, const FL
return;
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
t->filesize = metadata->data.stream_info.total_samples * (metadata->data.stream_info.bits_per_sample / 8) * metadata->data.stream_info.channels;
+ } else if (metadata->type == FLAC__METADATA_TYPE_CUESHEET) {
+ write_log("!");
}
}
static void flac_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
@@ -206,6 +253,7 @@ static void flac_get_size (struct cdtoc *t)
FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new ();
if (decoder) {
FLAC__stream_decoder_set_md5_checking (decoder, false);
+ FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_CUESHEET);
int init_status = FLAC__stream_decoder_init_stream (decoder,
&file_read_callback, &file_seek_callback, &file_tell_callback,
&file_len_callback, &file_eof_callback,
@@ -245,7 +293,7 @@ void sub_to_interleaved (const uae_u8 *s, uae_u8 *d)
d++;
}
}
-static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d)
+void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d)
{
for (int i = 0; i < 8 * SUB_ENTRY_SIZE; i ++) {
int dmask = 0x80;
@@ -264,7 +312,13 @@ static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *
int ret = 0;
uae_sem_wait (&cdu->sub_sem);
if (t->subcode) {
- if (t->subhandle) {
+ if (t->enctype == ENC_CHD) {
+#ifdef WITH_CHD
+ const cdrom_track_info *cti = t->chdtrack;
+ if (cdrom_read_subcode(cdu->chd_cdf, sector, dst, false))
+ ret = t->subcode;
+#endif
+ } else if (t->subhandle) {
int offset = 0;
int totalsize = SUB_CHANNEL_SIZE;
if (t->skipsize) {
@@ -384,6 +438,24 @@ static void audio_unpack (struct cdunit *cdu, struct cdtoc *t)
sleep_millis(10);
}
+static void next_cd_audio_buffer_callback(int bufnum, void *params)
+{
+ struct cdunit *cdu = (struct cdunit*)params;
+ uae_sem_wait(&play_sem);
+ if (bufnum >= 0) {
+ cdu->cda_bufon[bufnum] = 0;
+ bufnum = 1 - bufnum;
+ if (cdu->cda_bufon[bufnum])
+ audio_cda_new_buffer(&cdu->cas, (uae_s16*)cdu->cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, next_cd_audio_buffer_callback, cdu);
+ else
+ bufnum = -1;
+ }
+ if (bufnum < 0) {
+ audio_cda_new_buffer(&cdu->cas, NULL, -1, 0, NULL, cdu);
+ }
+ uae_sem_post(&play_sem);
+}
+
static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
{
int cdda_pos = cdu->cdda_start;
@@ -393,10 +465,12 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
int silentframes = 0;
bool foundsub;
int oldtrack = -1;
+ int mode = currprefs.sound_cdaudio;
bool restart = false;
bool first = true;
cdu->thread_active = true;
+ memset(&cdu->cas, 0, sizeof(struct cd_audio_state));
while (cdu->cdda_play == 0)
sleep_millis(10);
@@ -436,9 +510,9 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
sector = cdu->cd_last_pos = cdda_pos + 2 * 75;
t = findtoc (cdu, §or, false);
if (!t) {
- write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
+ write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
setstate (cdu, AUDIO_STATUS_PLAY_ERROR, -1);
- } else {
+ } else {
audio_unpack (cdu, t);
}
} else {
@@ -548,29 +622,39 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
audio_unpack (cdu, t);
}
if (!(t->ctrl & 4)) {
- if (t->handle) {
- int totalsize = t->size + t->skipsize;
+ if (t->enctype == ENC_CHD) {
+#ifdef WITH_CHD
+ do_read (cdu, t, dst, sector, 0, t->size, true);
+ for (int i = 0; i < 2352; i+=2) {
+ uae_u8 p;
+ p = dst[i + 0];
+ dst[i + 0] = dst[i + 1];
+ dst[i +1] = p;
+ }
+#endif
+ } else if (t->handle) {
+ int totalsize = t->size + t->skipsize;
int offset = t->offset;
if (offset >= 0) {
- if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
+ if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
if (t->filesize >= sector * totalsize + offset + t->size)
memcpy (dst, t->data + sector * totalsize + offset, t->size);
- } else if (t->enctype == AUDENC_PCM) {
+ } else if (t->enctype == AUDENC_PCM) {
if (sector * totalsize + offset + totalsize < t->filesize) {
zfile_fseek (t->handle, (uae_u64)sector * totalsize + offset, SEEK_SET);
- zfile_fread (dst, t->size, 1, t->handle);
+ zfile_fread (dst, t->size, 1, t->handle);
}
- }
- }
- }
+ }
+ }
+ }
}
getsub_deinterleaved (subbuf, cdu, t, cdda_pos);
}
if (idleframes > 0 || silentframes > 0) {
- if (idleframes > 0) {
- idleframes--;
- memset (subbuf, 0, SUB_CHANNEL_SIZE);
+ if (idleframes > 0) {
+ idleframes--;
+ memset (subbuf, 0, SUB_CHANNEL_SIZE);
}
if (silentframes > 0)
silentframes--;
@@ -635,8 +719,8 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
end:
*outpos = cdda_pos;
- cdu->cda->wait (0);
- cdu->cda->wait (1);
+ cdu->cda->wait (0);
+ cdu->cda->wait (1);
while (cdimage_unpack_active == 1)
sleep_millis(10);
@@ -655,7 +739,7 @@ static int cdda_play_func (void *v)
cd_audio_mode_changed = false;
for (;;) {
if (!cdda_play_func2(cdu, &outpos)) {
- cdu->cdda_play = 0;
+ cdu->cdda_play = 0;
break;
}
cdu->cdda_start = outpos;
@@ -692,7 +776,7 @@ static int command_pause (int unitnum, int paused)
return -1;
int old = cdu->cdda_paused;
if ((paused && cdu->cdda_play) || !paused)
- cdu->cdda_paused = paused;
+ cdu->cdda_paused = paused;
return old;
}
@@ -784,7 +868,7 @@ static int command_qcode (int unitnum, uae_u8 *buf, int sector, bool all)
if (all) {
memcpy(buf, subbuf, SUB_CHANNEL_SIZE);
} else {
- memcpy (p, subbuf + 12, 12);
+ memcpy (p, subbuf + 12, 12);
}
if (cdu->cdda_play_state == AUDIO_STATUS_PLAY_COMPLETE || cdu->cdda_play_state == AUDIO_STATUS_PLAY_ERROR)
@@ -829,13 +913,13 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
if (isaudiotrack(&cdu->di.toc, sector)) {
do_read(cdu, t, data, sector, 0, t->size, true);
} else {
- data[0] = 0x00;
- memset(data + 1, 0xff, 11);
- data[12] = tobcd((uae_u8)(address / (60 * 75)));
- data[13] = tobcd((uae_u8)((address / 75) % 60));
- data[14] = tobcd((uae_u8)(address % 75));
- data[15] = 2; /* MODE2 */
- do_read(cdu, t, data + 16, sector, 0, t->size, false);
+ data[0] = 0x00;
+ memset(data + 1, 0xff, 11);
+ data[12] = tobcd((uae_u8)(address / (60 * 75)));
+ data[13] = tobcd((uae_u8)((address / 75) % 60));
+ data[14] = tobcd((uae_u8)(address % 75));
+ data[15] = 2; /* MODE2 */
+ do_read(cdu, t, data + 16, sector, 0, t->size, false);
}
sector++;
asector++;
@@ -849,7 +933,7 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
uae_u8 subs[SUB_CHANNEL_SIZE];
getsub_deinterleaved(subs, cdu, t, sector);
memcpy(data - SUBQ_SIZE, subs + SUBQ_SIZE, SUBQ_SIZE);
- }
+}
}
} else if ((sectorsize == 2352 || sectorsize == 2368 || sectorsize == 2448) && t->size == 2048) {
// 2048 -> 2352
@@ -888,7 +972,7 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
uae_u8 b = 0;
do_read (cdu, t, &b, sector, 15, 1, false);
if (b != 2 && b != 0) // MODE0 or MODE2 only allowed
- return 0;
+ return 0;
do_read (cdu, t, data, sector, 16, sectorsize, false);
sector++;
asector++;
@@ -901,7 +985,7 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
if (sectorsize == 2352 && isaudiotrack(&cdu->di.toc, sector)) {
do_read(cdu, t, data, sector, 0, sectorsize, true);
} else {
- do_read (cdu, t, data, sector, 0, sectorsize, false);
+ do_read(cdu, t, data, sector, 0, sectorsize, false);
}
sector++;
asector++;
@@ -922,6 +1006,12 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
} else {
uae_u8 sectortype = extra >> 16;
+ uae_u8 cmd9 = extra >> 8;
+ int sync = (cmd9 >> 7) & 1;
+ int headercodes = (cmd9 >> 5) & 3;
+ int userdata = (cmd9 >> 4) & 1;
+ int edcecc = (cmd9 >> 3) & 1;
+ int errorfield = (cmd9 >> 1) & 3;
uae_u8 subs = extra & 7;
if (subs != 0 && subs != 1 && subs != 2 && subs != 4) {
ret = -1;
@@ -937,7 +1027,7 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int
goto end;
}
for (int i = 0; i < size; i++) {
- do_read (cdu, t, data, sector, 0, t->size, true);
+ do_read (cdu, t, data, sector, 0, t->size, true);
uae_u8 *p = data + t->size;
if (subs) {
uae_u8 subdata[SUB_CHANNEL_SIZE];
@@ -1191,7 +1281,7 @@ typedef struct {
#pragma pack()
-static int parsemds(struct cdunit* cdu, struct zfile* zmds, const TCHAR* img, const TCHAR* curdir, const TCHAR* occurdir)
+static int parsemds (struct cdunit *cdu, struct zfile *zmds, const TCHAR *img, const TCHAR *curdir, const TCHAR *occurdir)
{
MDS_Header *head;
struct cdtoc *t;
@@ -1201,7 +1291,7 @@ static int parsemds(struct cdunit* cdu, struct zfile* zmds, const TCHAR* img, co
if (curdir)
my_setcurrentdir(occurdir, NULL);
-
+
write_log (_T("MDS TOC: '%s'\n"), img);
size = zfile_size (zmds);
mds = xmalloc (uae_u8, size);
@@ -1248,7 +1338,7 @@ static int parsemds(struct cdunit* cdu, struct zfile* zmds, const TCHAR* img, co
if (footer) {
TCHAR *fname = NULL;
if (footer->widechar_filename == 0)
- fname = au ((char*)(mds + footer->filename_offset));
+ fname = au ((char*)(mds + footer->filename_offset));
else
fname = my_strdup ((TCHAR*)(mds + footer->filename_offset));
if (fname[0] == '*' && fname[1] == '.') {
@@ -1285,7 +1375,99 @@ end:
return cdu->tracks;
}
-static int parseccd(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, const TCHAR* curdir, const TCHAR* ocurdir)
+#ifdef WITH_CHD
+static int parsechd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img, const TCHAR *curdir, const TCHAR *ocurdir)
+{
+ if (curdir)
+ my_setcurrentdir(ocurdir, NULL);
+
+ chd_error err;
+ struct cdrom_file *cdf;
+ struct zfile *f = zfile_dup (zcue);
+ if (!f)
+ return 0;
+ chd_file *cf = new chd_file();
+ err = cf->open(*f, false, NULL);
+ if (err != CHDERR_NONE) {
+ write_log (_T("CHD '%s' err=%d\n"), zfile_getname (zcue), err);
+ zfile_fclose (f);
+ return 0;
+ }
+ if (!(cdf = cdrom_open (cf))) {
+ write_log (_T("Couldn't open CHD '%s' as CD\n"), zfile_getname (zcue));
+ cf->close ();
+ zfile_fclose (f);
+ return 0;
+ }
+ cdu->chd_f = cf;
+ cdu->chd_cdf = cdf;
+
+ const cdrom_toc *stoc = cdrom_get_toc (cdf);
+ cdu->tracks = stoc->numtrks;
+ uae_u32 hunkcnt = cf->hunk_count ();
+ uae_u32 hunksize = cf->hunk_bytes ();
+ uae_u32 cbytes;
+ chd_codec_type compr;
+
+ for (int i = 0; i tracks; i++) {
+ int size;
+ const cdrom_track_info *strack = &stoc->tracks[i];
+ struct cdtoc *dtrack = &cdu->toc[i];
+ dtrack->address = strack->physframeofs;
+ dtrack->offset = strack->chdframeofs;
+ dtrack->adr = cdrom_get_adr_control (cdf, i) >> 4;
+ dtrack->ctrl = cdrom_get_adr_control (cdf, i) & 15;
+ switch (strack->trktype)
+ {
+ case CD_TRACK_MODE1:
+ case CD_TRACK_MODE2_FORM1:
+ size = 2048;
+ break;
+ case CD_TRACK_MODE1_RAW:
+ case CD_TRACK_MODE2_RAW:
+ case CD_TRACK_AUDIO:
+ default:
+ size = 2352;
+ break;
+ case CD_TRACK_MODE2:
+ case CD_TRACK_MODE2_FORM_MIX:
+ size = 2336;
+ break;
+ case CD_TRACK_MODE2_FORM2:
+ size = 2324;
+ break;
+ }
+ dtrack->suboffset = size;
+ dtrack->subcode = strack->subtype == CD_SUB_NONE ? 0 : strack->subtype == CD_SUB_RAW ? 1 : 2;
+ dtrack->chdtrack = strack;
+ dtrack->size = size;
+ dtrack->enctype = ENC_CHD;
+ dtrack->fname = my_strdup (zfile_getname (zcue));
+ dtrack->filesize = cf->logical_bytes ();
+ dtrack->track = i + 1;
+ dtrack[1].address = dtrack->address + strack->frames;
+ if (cf->hunk_info(dtrack->offset * CD_FRAME_SIZE / hunksize, compr, cbytes) == CHDERR_NONE) {
+ TCHAR tmp[100];
+ uae_u32 c = (uae_u32)compr;
+ for (int j = 0; j < 4; j++) {
+ uae_u8 b = c >> ((3 - j) * 8);
+ if (c < 10) {
+ b += '0';
+ }
+ if (b < ' ' || b >= 127)
+ b = '.';
+ tmp[j] = b;
+ }
+ tmp[4] = 0;
+ dtrack->extrainfo = my_strdup (tmp);
+ }
+
+ }
+ return cdu->tracks;
+}
+#endif
+
+static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img, const TCHAR *curdir, const TCHAR *ocurdir)
{
int mode;
int num, tracknum, trackmode;
@@ -1316,7 +1498,7 @@ static int parseccd(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, co
if (curdir)
my_setcurrentdir(ocurdir, NULL);
-
+
num = -1;
mode = -1;
for (;;) {
@@ -1419,7 +1601,7 @@ static int parseccd(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, co
return cdu->tracks;
}
-static int parsecue(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, const TCHAR* curdir, const TCHAR* ocurdir)
+static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img, const TCHAR *curdir, const TCHAR *ocurdir)
{
int tracknum, pregap, postgap, lastpregap, lastpostgap;
int newfile, secoffset;
@@ -1459,15 +1641,19 @@ static int parsecue(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, co
fname = my_strdup (nextstring (&p));
fnametype = nextstring (&p);
fnametypeid = AUDENC_NONE;
+ TCHAR *ext = _tcsrchr(fname, '.');
+ if (ext) {
+ ext++;
+ }
if (!fnametype)
break;
if (_tcsicmp (fnametype, _T("BINARY")) && _tcsicmp (fnametype, _T("WAVE")) && _tcsicmp (fnametype, _T("MP3")) && _tcsicmp (fnametype, _T("FLAC"))) {
write_log (_T("CUE: unknown file type '%s' ('%s')\n"), fnametype, fname);
}
fnametypeid = AUDENC_PCM;
- if (!_tcsicmp (fnametype, _T("MP3")))
+ if (!_tcsicmp (fnametype, _T("MP3")) || (ext && !_tcsicmp(ext, _T("MP3"))))
fnametypeid = AUDENC_MP3;
- else if (!_tcsicmp (fnametype, _T("FLAC")))
+ else if (!_tcsicmp (fnametype, _T("FLAC")) || (ext && !_tcsicmp(ext, _T("FLAC"))))
fnametypeid = AUDENC_FLAC;
fileoffset = 0;
newfile = 1;
@@ -1684,7 +1870,7 @@ static int parsecue(struct cdunit* cdu, struct zfile* zcue, const TCHAR* img, co
return cdu->tracks;
}
-static int parsenrg(struct cdunit* cdu, struct zfile* znrg, const TCHAR* img, const TCHAR* curdir, const TCHAR* ocurdir)
+static int parsenrg(struct cdunit *cdu, struct zfile *znrg, const TCHAR *img, const TCHAR *curdir, const TCHAR *ocurdir)
{
uae_s64 size;
uae_s64 offset;
@@ -1696,7 +1882,7 @@ static int parsenrg(struct cdunit* cdu, struct zfile* znrg, const TCHAR* img, co
if (curdir)
my_setcurrentdir(ocurdir, NULL);
-
+
size = zfile_size(znrg);
zfile_fseek(znrg, size - 12, SEEK_SET);
zfile_fread(buf, 12, 1, znrg);
@@ -1875,11 +2061,11 @@ static int parse_image (struct cdunit *cdu, const TCHAR *img)
if (ext) {
TCHAR curdir[MAX_DPATH];
TCHAR oldcurdir[MAX_DPATH], *p;
- TCHAR* pcurdir = NULL;
-
+ TCHAR *pcurdir = NULL;
+
ext++;
oldcurdir[0] = 0;
- _tcscpy (curdir, img);
+ _tcscpy(curdir, img);
p = curdir + _tcslen(curdir);
while (p > curdir) {
if (*p == '/' || *p == '\\')
@@ -1892,14 +2078,18 @@ static int parse_image (struct cdunit *cdu, const TCHAR *img)
my_setcurrentdir(pcurdir, oldcurdir);
}
- if (!_tcsicmp (ext, _T("cue"))) {
+ if (!_tcsicmp(ext, _T("cue"))) {
parsecue(cdu, zcue, img, pcurdir, oldcurdir);
- } else if (!_tcsicmp (ext, _T("ccd"))) {
+ } else if (!_tcsicmp(ext, _T("ccd"))) {
parseccd(cdu, zcue, img, pcurdir, oldcurdir);
- } else if (!_tcsicmp (ext, _T("mds"))) {
+ } else if (!_tcsicmp(ext, _T("mds"))) {
parsemds(cdu, zcue, img, pcurdir, oldcurdir);
} else if (!_tcsicmp(ext, _T("nrg"))) {
parsenrg(cdu, zcue, img, pcurdir, oldcurdir);
+#ifdef WITH_CHD
+ } else if (!_tcsicmp(ext, _T("chd"))) {
+ parsechd (cdu, zcue, img, pcurdir, oldcurdir);
+#endif
}
if (oldcurdir[0])
@@ -1945,11 +2135,12 @@ static int parse_image (struct cdunit *cdu, const TCHAR *img)
write_log (_T("%7d %02d:%02d:%02d"),
t->address, (msf >> 16) & 0x7fff, (msf >> 8) & 0xff, (msf >> 0) & 0xff);
if (i < cdu->tracks) {
- write_log (_T(" %s %x %10lld %10lld %s"),
- (t->ctrl & 4) ? _T("DATA ") : (t->subcode ? _T("CDA+SUB") : _T("CDA ")),
- t->ctrl, t->offset, t->filesize,
- t->handle == NULL ? _T("[FILE ERROR]") : _T(""));
- }
+ write_log (_T(" %s %x %10lld %10lld %s%s"),
+ (t->ctrl & 4) ? _T("DATA ") : (t->subcode ? _T("CDA+SUB") : _T("CDA ")),
+ t->ctrl, t->offset, t->filesize,
+ t->extrainfo ? t->extrainfo : _T(""),
+ t->handle == NULL && t->enctype != ENC_CHD ? _T("[FILE ERROR]") : _T(""));
+ }
write_log (_T("\n"));
if (i < cdu->tracks)
write_log (_T(" - %s\n"), t->fname);
@@ -1984,8 +2175,16 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int
if (!cdu->enabled)
return NULL;
di->open = cdu->open;
+ di->removable = 1;
+ di->bus = unitnum;
+ di->target = 0;
+ di->lun = 0;
di->media_inserted = 0;
+ di->bytespersector = 2048;
di->mediapath[0] = 0;
+ di->cylinders = 1;
+ di->trackspercylinder = 1;
+ di->sectorspertrack = (int)(cdu->cdsize / di->bytespersector);
if (ismedia (unitnum, 1)) {
di->media_inserted = 1;
_tcscpy (di->mediapath, cdu->imgname_out);
@@ -1993,6 +2192,7 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int
}
memset (&di->toc, 0, sizeof (struct cd_toc_head));
command_toc (unitnum, &di->toc);
+ di->write_protected = 1;
di->type = INQ_ROMD;
di->unitnum = unitnum + 1;
if (di->mediapath[0]) {
@@ -2001,6 +2201,10 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int
} else {
_tcscpy (di->label, _T("IMG:"));
}
+ _tcscpy (di->vendorid, _T("UAE"));
+ _stprintf (di->productid, _T("SCSICD%d"), unitnum);
+ _tcscpy (di->revision, _T("1.0"));
+ di->backend = _T("IMAGE");
return di;
}
@@ -2016,7 +2220,15 @@ static void unload_image (struct cdunit *cdu)
xfree (t->fname);
xfree (t->data);
xfree (t->subdata);
+ xfree (t->extrainfo);
}
+#ifdef WITH_CHD
+ cdrom_close (cdu->chd_cdf);
+ cdu->chd_cdf = NULL;
+ if (cdu->chd_f)
+ cdu->chd_f->close();
+ cdu->chd_f = NULL;
+#endif
memset (cdu->toc, 0, sizeof cdu->toc);
cdu->tracks = 0;
cdu->cdsize = 0;
@@ -2036,7 +2248,7 @@ static int open_device (int unitnum, const TCHAR *ident, int flags)
_tcscpy(cdu->imgname_in, ident);
cfgfile_resolve_path_out_load(cdu->imgname_in, cdu->imgname_out, MAX_DPATH, PATH_CD);
parse_image(cdu, cdu->imgname_out);
- }
+ }
cdu->open = true;
cdu->enabled = true;
cdu->cdda_volume[0] = 0x7fff;
@@ -2087,6 +2299,7 @@ static void close_bus (void)
cdu->enabled = false;
}
bus_open = 0;
+ uae_sem_destroy(&play_sem);
write_log (_T("IMAGE driver closed.\n"));
}
@@ -2097,6 +2310,7 @@ static int open_bus (int flags)
return 1;
}
bus_open = 1;
+ uae_sem_init(&play_sem, 0, 1);
write_log (_T("Image driver open.\n"));
return 1;
}
@@ -2104,7 +2318,8 @@ static int open_bus (int flags)
struct device_functions devicefunc_cdimage = {
_T("IMAGE"),
open_bus, close_bus, open_device, close_device, info_device,
+ 0, 0, 0,
command_pause, command_stop, command_play, command_volume, command_qcode,
- command_toc, command_read, command_rawread,
- ismedia
+ command_toc, command_read, command_rawread, 0,
+ 0, ismedia
};
diff --git a/src/cdtv.cpp b/src/cdtv.cpp
new file mode 100644
index 00000000..ec901a70
--- /dev/null
+++ b/src/cdtv.cpp
@@ -0,0 +1,1948 @@
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* CDTV DMAC/CDROM controller emulation
+*
+* Copyright 2004/2007-2010 Toni Wilen
+*
+* Thanks to Mark Knibbs for CDTV Technical information
+*
+*/
+
+//#define CDTV_SUB_DEBUG
+//#define CDTV_DEBUG
+//#define CDTV_DEBUG_CMD
+//#define CDTV_DEBUG_6525
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "memory.h"
+#include "custom.h"
+#include "newcpu.h"
+//#include "debug.h"
+#include "cdtv.h"
+#include "blkdev.h"
+#include "gui.h"
+#include "zfile.h"
+#include "threaddep/thread.h"
+//#include "a2091.h"
+#include "uae.h"
+#include "savestate.h"
+#include "scsi.h"
+#include "devices.h"
+#include "rommgr.h"
+
+/* DMAC CNTR bits. */
+#define CNTR_TCEN (1<<7)
+#define CNTR_PREST (1<<6)
+#define CNTR_PDMD (1<<5)
+#define CNTR_INTEN (1<<4)
+#define CNTR_DDIR (1<<3)
+/* ISTR bits. */
+#define ISTR_INTX (1<<8)
+#define ISTR_INT_F (1<<7)
+#define ISTR_INTS (1<<6)
+#define ISTR_E_INT (1<<5)
+#define ISTR_INT_P (1<<4)
+#define ISTR_UE_INT (1<<3)
+#define ISTR_OE_INT (1<<2)
+#define ISTR_FF_FLG (1<<1)
+#define ISTR_FE_FLG (1<<0)
+
+#define MODEL_NAME "MATSHITA0.96"
+/* also MATSHITA0.97 exists but is apparently rare */
+
+#define MAX_SUBCODEBUFFER 36
+static volatile int subcodebufferoffset, subcodebufferoffsetw, subcodeoffset;
+static uae_u8 subcodebufferinuse[MAX_SUBCODEBUFFER];
+static uae_u8 subcodebuffer[MAX_SUBCODEBUFFER * SUB_CHANNEL_SIZE];
+static uae_sem_t sub_sem, cda_sem;
+
+static smp_comm_pipe requests;
+static volatile int thread_alive;
+
+static int configured;
+static int cdtvscsi;
+static uae_u8 dmacmemory[128];
+
+static struct cd_toc_head toc;
+static uae_u32 last_cd_position, play_start, play_end;
+static uae_u8 cdrom_qcode[4 + 12], cd_audio_status;
+static int datatrack;
+
+static volatile uae_u8 dmac_istr, dmac_cntr;
+static volatile uae_u16 dmac_dawr;
+static volatile uae_u32 dmac_acr;
+static volatile int dmac_wtc;
+static volatile int dmac_dma;
+
+static volatile int activate_stch, cdrom_command_done;
+static volatile int cdrom_sector, cdrom_sectors, cdrom_length, cdrom_offset;
+static volatile int cd_playing, cd_paused, cd_motor, cd_media, cd_error, cd_finished, cd_isready, cd_audio_finished;
+static uae_u32 last_play_pos, last_play_end;
+
+static volatile int cdtv_hsync, dma_finished, cdtv_sectorsize;
+static volatile uae_u64 dma_wait;
+static int cd_volume, cd_volume_stored;
+static uae_u16 dac_control_data_format;
+static int cd_led;
+static int frontpanel;
+
+static uae_u8 cdrom_command_input[16];
+static int cdrom_command_cnt_in;
+
+static uae_u8 tp_a, tp_b, tp_c, tp_ad, tp_bd, tp_cd;
+static uae_u8 tp_imask, tp_cr, tp_air, tp_ilatch, tp_ilatch2;
+static int volstrobe1, volstrobe2;
+
+static void do_stch (void);
+
+static void INT2 (void)
+{
+ safe_interrupt_set(false);
+ cd_led ^= LED_CD_ACTIVE2;
+}
+
+static volatile int cdrom_command_cnt_out, cdrom_command_size_out;
+static uae_u8 cdrom_command_output[16];
+
+static volatile int stch, sten, scor, sbcp;
+static volatile int cmd, enable, xaen, dten;
+
+static int unitnum = -1;
+
+static void subreset (void)
+{
+ uae_sem_wait (&sub_sem);
+ memset (subcodebufferinuse, 0, sizeof subcodebufferinuse);
+ subcodebufferoffsetw = subcodebufferoffset = 0;
+ subcodeoffset = -1;
+ sbcp = 0;
+ scor = 0;
+ uae_sem_post (&sub_sem);
+}
+
+static int get_toc (void)
+{
+ datatrack = 0;
+ if (!sys_command_cd_toc (unitnum, &toc))
+ return 0;
+ last_cd_position = toc.lastaddress;
+ if (toc.first_track == 1 && (toc.toc[toc.first_track_offset].control & 0x0c) == 0x04)
+ datatrack = 1;
+ return 1;
+}
+
+static int get_qcode (void)
+{
+ if (!sys_command_cd_qcode (unitnum, cdrom_qcode, -1, false))
+ return 0;
+ cdrom_qcode[1] = cd_audio_status;
+ return 1;
+}
+
+static void cdaudiostop_do (void)
+{
+ if (unitnum < 0)
+ return;
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
+}
+
+static void cdaudiostop (void)
+{
+ cd_finished = 0;
+ cd_audio_status = AUDIO_STATUS_NO_STATUS;
+ if (cd_playing) {
+ cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE;
+ cd_finished = 1;
+ }
+ cd_playing = 0;
+ cd_paused = 0;
+ cd_motor = 0;
+ cd_audio_finished = 0;
+ write_comm_pipe_u32 (&requests, 0x0104, 1);
+}
+
+static void cdaudiostopfp (void)
+{
+ cdaudiostop_do ();
+ cd_audio_status = AUDIO_STATUS_NO_STATUS;
+ activate_stch = 1;
+ cd_finished = 0;
+ cd_playing = 0;
+ cd_paused = 0;
+ cd_motor = 0;
+}
+
+static int pause_audio (int pause)
+{
+ sys_command_cd_pause (unitnum, pause);
+ if (!cd_playing) {
+ cd_paused = 0;
+ cd_audio_status = AUDIO_STATUS_NO_STATUS;
+ return 0;
+ }
+ cd_paused = pause;
+ cd_audio_status = pause ? AUDIO_STATUS_PAUSED : AUDIO_STATUS_IN_PROGRESS;
+ subreset ();
+ return 1;
+}
+
+static int read_sectors (int start, int length)
+{
+ if (cd_playing)
+ cdaudiostop ();
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("READ DATA sector %d, %d sectors (blocksize=%d)\n"), start, length, cdtv_sectorsize);
+#endif
+ cdrom_sector = start;
+ cdrom_sectors = length;
+ cdrom_offset = start * cdtv_sectorsize;
+ cdrom_length = length * cdtv_sectorsize;
+ cd_motor = 1;
+ cd_audio_status = AUDIO_STATUS_NOT_SUPPORTED;
+ return 0;
+}
+
+static int ismedia (void)
+{
+ if (unitnum < 0)
+ return 0;
+ return sys_command_ismedia (unitnum, 0);
+}
+
+static int issub (void)
+{
+ return 1;
+}
+
+static void subfunc (uae_u8 *data, int cnt)
+{
+ if (!issub ())
+ return;
+ uae_sem_wait (&sub_sem);
+#ifdef CDTV_SUB_DEBUG
+ int total = 0;
+ for (int i = 0; i < MAX_SUBCODEBUFFER; i++) {
+ if (subcodebufferinuse[i])
+ total++;
+ }
+ write_log (_T("%d "), total);
+#endif
+ if (subcodebufferinuse[subcodebufferoffsetw]) {
+ memset (subcodebufferinuse, 0, sizeof subcodebufferinuse);
+ subcodebufferoffsetw = subcodebufferoffset = 0;
+ subcodeoffset = -1;
+ uae_sem_post (&sub_sem);
+#ifdef CDTV_SUB_DEBUG
+ write_log (_T("CDTV: subcode buffer overflow 1\n"));
+#endif
+ return;
+ }
+ int offset = subcodebufferoffsetw;
+ while (cnt > 0) {
+ if (subcodebufferinuse[offset]) {
+#ifdef CDTV_SUB_DEBUG
+ write_log (_T("CDTV: subcode buffer overflow 2\n"));
+#endif
+ break;
+ }
+ subcodebufferinuse[offset] = 1;
+ memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE);
+ data += SUB_CHANNEL_SIZE;
+ offset++;
+ if (offset >= MAX_SUBCODEBUFFER)
+ offset = 0;
+ cnt--;
+ }
+ subcodebufferoffsetw = offset;
+ uae_sem_post (&sub_sem);
+}
+static int statusfunc (int status, int playpos)
+{
+ if (status == -1)
+ return 150;
+ if (status == -2)
+ return 20;
+ if (status < 0)
+ return 0;
+ if (cd_audio_status != status) {
+ if (status == AUDIO_STATUS_PLAY_COMPLETE || status == AUDIO_STATUS_PLAY_ERROR) {
+ cd_audio_finished = 1;
+ } else {
+ if (status == AUDIO_STATUS_IN_PROGRESS)
+ cd_playing = 1;
+ activate_stch = 1;
+ }
+ }
+ if (status == AUDIO_STATUS_IN_PROGRESS)
+ last_play_pos = playpos;
+ cd_audio_status = status;
+ return 0;
+}
+
+static int statusfunc_imm(int status, int playpos)
+{
+ if (status == -3 || status > AUDIO_STATUS_IN_PROGRESS)
+ uae_sem_post(&cda_sem);
+ if (status < 0)
+ return 0;
+ if (status == AUDIO_STATUS_IN_PROGRESS)
+ cd_audio_status = status;
+ return statusfunc(status, playpos);
+}
+
+static void do_play(bool immediate)
+{
+ uae_u32 start = read_comm_pipe_u32_blocking (&requests);
+ uae_u32 end = read_comm_pipe_u32_blocking (&requests);
+ uae_u32 scan = read_comm_pipe_u32_blocking (&requests);
+ subreset ();
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_volume (unitnum, (cd_volume_stored << 5) | (cd_volume_stored >> 5), (cd_volume_stored << 5) | (cd_volume_stored >> 5));
+ sys_command_cd_play (unitnum, start, end, 0, immediate ? statusfunc_imm : statusfunc, subfunc);
+}
+
+static void startplay (void)
+{
+ subreset ();
+ write_comm_pipe_u32 (&requests, 0x0110, 0);
+ write_comm_pipe_u32 (&requests, play_start, 0);
+ write_comm_pipe_u32 (&requests, play_end, 0);
+ write_comm_pipe_u32 (&requests, 0, 1);
+ if (!cd_motor) {
+ cd_motor = 1;
+ activate_stch = 1;
+ }
+}
+
+static int play_cdtrack (uae_u8 *p)
+{
+ int track_start = p[1];
+ int index_start = p[2];
+ int track_end = p[3];
+ int index_end = p[4];
+ int start_found, end_found;
+ uae_u32 start, end;
+ int j;
+
+ if (track_start == 0 && track_end == 0)
+ return 0;
+
+ end = last_cd_position;
+ start_found = end_found = 0;
+ for (j = toc.first_track_offset; j <= toc.last_track_offset; j++) {
+ struct cd_toc *s = &toc.toc[j];
+ if (track_start == s->track) {
+ start_found++;
+ start = s->paddress;
+ }
+ if (track_end == s->track) {
+ end = s->paddress;
+ end_found++;
+ }
+ }
+ if (start_found == 0) {
+ cdaudiostop ();
+ cd_error = 1;
+ activate_stch = 1;
+ write_log (_T("PLAY CD AUDIO: illegal start track %d\n"), track_start);
+ return 0;
+ }
+ play_end = end;
+ play_start = start;
+ last_play_pos = start;
+ last_play_end = end;
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("PLAY CD AUDIO from %d-%d, %06X (%d) to %06X (%d)\n"),
+ track_start, track_end, start, start, end, end);
+#endif
+ startplay ();
+ return 0;
+}
+
+
+static int play_cd (uae_u8 *p)
+{
+ uae_u32 start, end;
+
+ start = (p[1] << 16) | (p[2] << 8) | p[3];
+ end = (p[4] << 16) | (p[5] << 8) | p[6];
+ if (p[0] == 0x09) /* end is length in lsn-mode */
+ end += start;
+ if (start == 0 && end == 0) {
+ cd_finished = 0;
+ if (cd_playing)
+ cd_finished = 1;
+ cd_playing = 0;
+ cd_paused = 0;
+ cd_motor = 0;
+ write_comm_pipe_u32 (&requests, 0x0104, 1);
+ cd_audio_status = AUDIO_STATUS_NO_STATUS;
+ cd_error = 1;
+ activate_stch = 1;
+ return 0;
+ }
+ if (p[0] != 0x09) { /* msf */
+ start = msf2lsn (start);
+ if (end < 0x00ffffff)
+ end = msf2lsn (end);
+ }
+ if (end >= 0x00ffffff || end > last_cd_position)
+ end = last_cd_position;
+ play_end = end;
+ play_start = start;
+ last_play_pos = start;
+ last_play_end = end;
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("PLAY CD AUDIO from %06X (%d) to %06X (%d)\n"),
+ lsn2msf (start), start, lsn2msf (end), end);
+#endif
+ startplay ();
+ return 0;
+}
+
+static int cdrom_subq (uae_u8 *out, int msflsn)
+{
+ uae_u8 *s = cdrom_qcode;
+ uae_u32 trackposlsn, trackposmsf;
+ uae_u32 diskposlsn, diskposmsf;
+
+ out[0] = cd_audio_status;
+ s += 4;
+ out[1] = (s[0] >> 4) | (s[0] << 4);
+ out[2] = frombcd (s[1]); // track
+ out[3] = frombcd (s[2]); // index
+ trackposmsf = fromlongbcd (s + 3);
+ diskposmsf = fromlongbcd (s + 7);
+ trackposlsn = msf2lsn (trackposmsf);
+ diskposlsn = msf2lsn (diskposmsf);
+ out[4] = 0;
+ out[5] = (msflsn ? diskposmsf : diskposlsn) >> 16;
+ out[6] = (msflsn ? diskposmsf : diskposlsn) >> 8;
+ out[7] = (msflsn ? diskposmsf : diskposlsn) >> 0;
+ out[8] = 0;
+ out[9] = (msflsn ? trackposmsf : trackposlsn) >> 16;
+ out[10] = (msflsn ? trackposmsf : trackposlsn) >> 8;
+ out[11] = (msflsn ? trackposmsf : trackposlsn) >> 0;
+ out[12] = 0;
+ if (cd_audio_status == AUDIO_STATUS_IN_PROGRESS)
+ last_play_pos = diskposlsn;
+ return 13;
+}
+
+static int cdrom_info (uae_u8 *out)
+{
+ uae_u32 size;
+
+ if (ismedia () <= 0)
+ return -1;
+ cd_motor = 1;
+ out[0] = toc.first_track;
+ out[1] = toc.last_track;
+ size = lsn2msf (toc.lastaddress);
+ out[2] = size >> 16;
+ out[3] = size >> 8;
+ out[4] = size >> 0;
+ cd_finished = 1;
+ return 5;
+}
+
+static int read_toc (int track, int msflsn, uae_u8 *out)
+{
+ int j;
+
+ if (ismedia () <= 0)
+ return -1;
+ if (!out)
+ return 0;
+ cd_motor = 1;
+ for (j = 0; j < toc.points; j++) {
+ if (track == toc.toc[j].point) {
+ int lsn = toc.toc[j].paddress;
+ int msf = lsn2msf (lsn);
+ out[0] = 0;
+ out[1] = (toc.toc[j].adr << 4) | (toc.toc[j].control << 0);
+ out[2] = toc.toc[j].point;
+ out[3] = toc.tracks;
+ out[4] = 0;
+ out[5] = (msflsn ? msf : lsn) >> 16;
+ out[6] = (msflsn ? msf : lsn) >> 8;
+ out[7] = (msflsn ? msf : lsn) >> 0;
+ cd_finished = 1;
+ return 8;
+ }
+ }
+ return -1;
+}
+
+static int cdrom_modeset (uae_u8 *cmd)
+{
+ cdtv_sectorsize = (cmd[2] << 8) | cmd[3];
+ if (cdtv_sectorsize != 2048 && cdtv_sectorsize != 2336 && cdtv_sectorsize != 2352 && cdtv_sectorsize != 2328) {
+ write_log (_T("CDTV: tried to set unknown sector size %d\n"), cdtv_sectorsize);
+ cdtv_sectorsize = 2048;
+ }
+ return 0;
+}
+
+static void cdrom_command_accepted (int size, uae_u8 *cdrom_command_input, int *cdrom_command_cnt_in)
+{
+#ifdef CDTV_DEBUG_CMD
+ TCHAR tmp[200];
+ int i;
+#endif
+ cdrom_command_size_out = size;
+#ifdef CDTV_DEBUG_CMD
+ tmp[0] = 0;
+ for (i = 0; i < *cdrom_command_cnt_in; i++)
+ _stprintf (tmp + i * 3, _T("%02X%c"), cdrom_command_input[i], i < *cdrom_command_cnt_in - 1 ? '.' : ' ');
+ write_log (_T("CD<-: %s\n"), tmp);
+ if (size > 0) {
+ tmp[0] = 0;
+ for (i = 0; i < size; i++)
+ _stprintf (tmp + i * 3, _T("%02X%c"), cdrom_command_output[i], i < size - 1 ? '.' : ' ');
+ write_log (_T("CD->: %s\n"), tmp);
+ }
+#endif
+ *cdrom_command_cnt_in = 0;
+ cdrom_command_cnt_out = 0;
+ cdrom_command_done = 1;
+}
+
+static void cdrom_command_thread (uae_u8 b)
+{
+ uae_u8 *s;
+
+ cdrom_command_input[cdrom_command_cnt_in] = b;
+ cdrom_command_cnt_in++;
+ s = cdrom_command_input;
+
+ switch (cdrom_command_input[0])
+ {
+ case 0x01: /* seek */
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ if (currprefs.cd_speed)
+ sleep_millis (500);
+ activate_stch = 1;
+ }
+ break;
+ case 0x02: /* read */
+ if (cdrom_command_cnt_in == 7) {
+ read_sectors ((s[1] << 16) | (s[2] << 8) | (s[3] << 0), (s[4] << 8) | (s[5] << 0));
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x04: /* motor on */
+ if (cdrom_command_cnt_in == 7) {
+ cd_motor = 1;
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ case 0x05: /* motor off */
+ if (cdrom_command_cnt_in == 7) {
+ cd_motor = 0;
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ case 0x09: /* play (lsn) */
+ case 0x0a: /* play (msf) */
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (play_cd (cdrom_command_input), s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x0b:
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (play_cdtrack (cdrom_command_input), s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x81:
+ if (cdrom_command_cnt_in == 1) {
+ uae_u8 flag = 0;
+ if (!cd_isready)
+ flag |= 1 << 0; // 01
+ if (cd_playing)
+ flag |= 1 << 2; // 04
+ if (cd_finished)
+ flag |= 1 << 3; // 08
+ if (cd_error)
+ flag |= 1 << 4; // 10
+ if (cd_motor)
+ flag |= 1 << 5; // 20
+ if (cd_media)
+ flag |= 1 << 6; // 40
+ cdrom_command_output[0] = flag;
+ cdrom_command_accepted (1, s, &cdrom_command_cnt_in);
+ cd_finished = 0;
+ }
+ break;
+ case 0x82:
+ if (cdrom_command_cnt_in == 7) {
+ if (cd_error)
+ cdrom_command_output[2] |= 1 << 4;
+ cd_error = 0;
+ cd_isready = 0;
+ cdrom_command_accepted (6, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ case 0x83:
+ if (cdrom_command_cnt_in == 7) {
+ memcpy (cdrom_command_output, MODEL_NAME, strlen (MODEL_NAME));
+ cdrom_command_accepted (strlen (MODEL_NAME), s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ case 0x84:
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (cdrom_modeset (cdrom_command_input), s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ case 0x87: /* subq */
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (cdrom_subq (cdrom_command_output, cdrom_command_input[1] & 2), s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x89:
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (cdrom_info (cdrom_command_output), s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x8a: /* read toc */
+ if (cdrom_command_cnt_in == 7) {
+ cdrom_command_accepted (read_toc (cdrom_command_input[2], cdrom_command_input[1] & 2, cdrom_command_output), s, &cdrom_command_cnt_in);
+ }
+ break;
+ case 0x8b:
+ if (cdrom_command_cnt_in == 7) {
+ pause_audio (s[1] == 0x00 ? 1 : 0);
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ case 0xa3: /* front panel */
+ if (cdrom_command_cnt_in == 7) {
+ frontpanel = s[1] ? 1 : 0;
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ cd_finished = 1;
+ }
+ break;
+ default:
+ write_log (_T("unknown CDROM command %02X!\n"), s[0]);
+ cd_error = 1;
+ cdrom_command_accepted (0, s, &cdrom_command_cnt_in);
+ break;
+ }
+}
+
+static void dma_do_thread (void)
+{
+ static int readsector;
+ int didread = 0;
+ int cnt;
+
+ while (dma_finished)
+ sleep_millis (2);
+
+ if (!cdtv_sectorsize)
+ return;
+ cnt = dmac_wtc;
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("DMAC DMA: sector=%d, addr=%08X, words=%d (of %d)\n"),
+ cdrom_offset / cdtv_sectorsize, dmac_acr, cnt, cdrom_length / 2);
+#endif
+ dma_wait += cnt * (uae_u64)312 * 50 / 75 + 1;
+ if (currprefs.cd_speed == 0)
+ dma_wait = 1;
+ while (cnt > 0 && dmac_dma) {
+ uae_u8 buffer[2352];
+ if (!didread || readsector != (cdrom_offset / cdtv_sectorsize)) {
+ readsector = cdrom_offset / cdtv_sectorsize;
+ if (cdtv_sectorsize != 2048)
+ didread = sys_command_cd_rawread (unitnum, buffer, readsector, 1, cdtv_sectorsize);
+ else
+ didread = sys_command_cd_read (unitnum, buffer, readsector, 1);
+ if (!didread) {
+ cd_error = 1;
+ activate_stch = 1;
+ write_log (_T("CDTV: CD read error!\n"));
+ break;
+ }
+
+ }
+ put_byte (dmac_acr, buffer[(cdrom_offset % cdtv_sectorsize) + 0]);
+ put_byte (dmac_acr + 1, buffer[(cdrom_offset % cdtv_sectorsize) + 1]);
+ cnt--;
+ dmac_acr += 2;
+ cdrom_length -= 2;
+ cdrom_offset += 2;
+ }
+ dmac_wtc = 0;
+ dmac_dma = 0;
+ dma_finished = 1;
+ cd_finished = 1;
+}
+
+static int dev_thread (void *p)
+{
+ write_log (_T("CDTV: CD thread started\n"));
+ thread_alive = 1;
+ for (;;) {
+
+ uae_u32 b = read_comm_pipe_u32_blocking (&requests);
+ if (b == 0xffff) {
+ thread_alive = -1;
+ return 0;
+ }
+ if (unitnum < 0)
+ continue;
+
+ switch (b)
+ {
+ case 0x0100:
+ dma_do_thread ();
+ break;
+ case 0x0101:
+ {
+ int m = ismedia ();
+ if (m < 0) {
+ write_log (_T("CDTV: device %d lost\n"), unitnum);
+ activate_stch = 1;
+ cd_media = 0;
+ } else if (m != cd_media) {
+ cd_media = m;
+ get_toc ();
+ activate_stch = 1;
+ if (cd_playing)
+ cd_error = 1;
+ }
+ if (cd_media)
+ get_qcode ();
+ }
+ break;
+ case 0x0102: // pause
+ sys_command_cd_pause (unitnum, 1);
+ break;
+ case 0x0103: // unpause
+ sys_command_cd_pause (unitnum, 0);
+ break;
+ case 0x0104: // stop
+ cdaudiostop_do ();
+ break;
+ case 0x0105: // pause
+ pause_audio (1);
+ break;
+ case 0x0106: // unpause
+ pause_audio (0);
+ break;
+ case 0x0107: // frontpanel stop
+ cdaudiostopfp ();
+ break;
+ case 0x0110: // do_play!
+ do_play(false);
+ break;
+ case 0x0111: // do_play immediate
+ do_play(true);
+ break;
+ default:
+ cdrom_command_thread (b);
+ break;
+ }
+
+ }
+}
+
+static void cdrom_command (uae_u8 b)
+{
+ write_comm_pipe_u32 (&requests, b, 1);
+}
+
+static void init_play (int start, int end)
+{
+ play_end = end;
+ play_start = start;
+ last_play_pos = start;
+ last_play_end = end;
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("PLAY CD AUDIO from %06X (%d) to %06X (%d)\n"),
+ lsn2msf (start), start, lsn2msf (end), end);
+#endif
+ startplay ();
+}
+
+bool cdtv_front_panel (int button)
+{
+ if (!frontpanel || configured <= 0)
+ return false;
+ if (button < 0)
+ return true;
+ switch (button)
+ {
+ case 0: // stop
+ if (cd_paused)
+ write_comm_pipe_u32 (&requests, 0x0106, 1);
+ write_comm_pipe_u32 (&requests, 0x0107, 1);
+ break;
+ case 1: // playpause
+ if (cd_playing) {
+ write_comm_pipe_u32 (&requests, cd_paused ? 0x0106 : 0x0105, 1);
+ } else if (cd_media) {
+ init_play (0, last_cd_position);
+ }
+ break;
+ case 2: // prev
+ case 3: // next
+ if (!cd_playing)
+ return true;
+ uae_u8 *sq = cdrom_qcode + 4;
+ int track = frombcd (sq[1]);
+ int pos = 0;
+ for (int j = 0; j < toc.points; j++) {
+ int t = toc.toc[j].track;
+ pos = toc.toc[j].paddress;
+ if (t == 1 && track == 1 && button == 2)
+ break;
+ else if (j == toc.points - 1 && t == track && button == 3)
+ break;
+ else if (t == track - 1 && track > 1 && button == 2)
+ break;
+ else if (t == track + 1 && track < 99 && button == 3)
+ break;
+ }
+ init_play (pos - 150, last_cd_position);
+ break;
+ }
+ return true;
+}
+
+static uae_u8 get_tp_c (void)
+{
+ uae_u8 v = (sbcp ? 0 : (1 << 0)) | (scor ? 0 : (1 << 1)) |
+ (stch ? 0 : (1 << 2)) | (sten ? 0 : (1 << 3) | (1 << 4));
+ return v;
+}
+static uae_u8 get_tp_c_level (void)
+{
+ uae_u8 v = (sbcp == 1 ? 0 : (1 << 0)) | (scor == 1 ? 0 : (1 << 1)) |
+ (stch == 1 ? 0 : (1 << 2)) | (sten == 1 ? 0 : (1 << 3)) | (1 << 4);
+ if (sten == 1)
+ sten = -1;
+ if (scor == 1)
+ scor = -1;
+ if (sbcp == 1)
+ sbcp = -1;
+ return v;
+}
+
+static void tp_check_interrupts (void)
+{
+ /* MC = 1 ? */
+ if ((tp_cr & 1) != 1) {
+ get_tp_c_level ();
+ return;
+ }
+
+ tp_ilatch |= get_tp_c_level () ^ 0x1f;
+ stch = 0;
+ if (!(tp_ilatch & (1 << 5)) && (tp_ilatch & tp_imask)) {
+ tp_air = 0;
+ int mask = 0x10;
+ while (((tp_ilatch & tp_imask) & mask) == 0)
+ mask >>= 1;
+ tp_air |= tp_ilatch & mask;
+ tp_ilatch |= 1 << 5; // IRQ
+ tp_ilatch2 = tp_ilatch & mask;
+ tp_ilatch &= ~mask;
+ }
+ if (tp_ilatch & (1 << 5))
+ INT2 ();
+}
+
+// MC=1, C lines 0-4 = input irq lines, 5 = irq out, 6-7 IO
+
+static void tp_bput (int addr, uae_u8 v)
+{
+#ifdef CDTV_DEBUG_6525
+ if (addr != 1)
+ write_log (_T("6525 write %x=%02X PC=%x %d\n"), addr, v, M68K_GETPC, regs.s);
+#endif
+ switch (addr)
+ {
+ case 0:
+ tp_a = v;
+ break;
+ case 1:
+ tp_b = v;
+ break;
+ case 2:
+ if (tp_cr & 1) {
+ // 0 = clear, 1 = ignored
+ tp_ilatch &= 0xe0 | v;
+ } else {
+ tp_c = get_tp_c () & ~tp_cd;
+ tp_c |= v & tp_cd;
+ if (tp_c & (1 << 5))
+ INT2 ();
+ }
+ break;
+ case 3:
+ tp_ad = v;
+ break;
+ case 4:
+ tp_bd = v;
+ break;
+ case 5:
+ // data direction (mode=0), interrupt mask (mode=1)
+ if (tp_cr & 1) {
+ tp_imask = v & 0x1f;
+ } else {
+ tp_cd = v;
+ }
+ break;
+ case 6:
+ tp_cr = v;
+ break;
+ case 7:
+ tp_air = v;
+ break;
+ }
+ cmd = (tp_b >> 0) & 1;
+ enable = (tp_b >> 1) & 1;
+ xaen = (tp_b >> 2) & 1;
+ dten = (tp_b >> 3) & 1;
+
+ if (!volstrobe1 && ((tp_b >> 6) & 1)) {
+ dac_control_data_format >>= 1;
+ dac_control_data_format |= ((tp_b >> 5) & 1) << 11;
+ volstrobe1 = 1;
+ } else if (volstrobe1 && !((tp_b >> 6) & 1)) {
+ volstrobe1 = 0;
+ }
+ if (!volstrobe2 && ((tp_b >> 7) & 1)) {
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("CDTV CD volume = %d\n"), cd_volume);
+#endif
+ cd_volume = dac_control_data_format & 1023;
+ if (unitnum >= 0)
+ sys_command_cd_volume (unitnum, (cd_volume << 5) | (cd_volume >> 5), (cd_volume << 5) | (cd_volume >> 5));
+ cd_volume_stored = cd_volume;
+ volstrobe2 = 1;
+ } else if (volstrobe2 && !((tp_b >> 7) & 1)) {
+ volstrobe2 = 0;
+ }
+ tp_check_interrupts ();
+}
+
+static uae_u8 subtransferbuf[SUB_CHANNEL_SIZE];
+
+#define SUBCODE_CYCLES (2 * maxhpos)
+static int subcode_activecnt;
+
+static void subcode_interrupt (uae_u32 v)
+{
+ subcode_activecnt--;
+ if (subcode_activecnt > 0) {
+ if (subcode_activecnt > 1)
+ subcode_activecnt = 1;
+ return;
+ }
+
+ if (subcodeoffset < -1)
+ return;
+ if (sbcp && scor == 0) {
+ sbcp = 0;
+ // CD+G interrupt didn't read data fast enough, just abort until next packet
+ return;
+ }
+ if (scor < 0) {
+ scor = 0;
+ if (issub ()) {
+ subcodeoffset = 0;
+ }
+ tp_check_interrupts ();
+ }
+ if (subcodeoffset >= SUB_CHANNEL_SIZE)
+ return;
+ sbcp = 1;
+ tp_check_interrupts ();
+ subcode_activecnt++;
+ event2_newevent2 (SUBCODE_CYCLES, 0, subcode_interrupt);
+}
+
+static uae_u8 tp_bget (int addr)
+{
+ uae_u8 v = 0;
+ switch (addr)
+ {
+ case 0:
+ // A = subchannel byte input from serial to parallel converter
+ if (subcodeoffset < 0 || subcodeoffset >= SUB_CHANNEL_SIZE) {
+#ifdef CDTV_SUB_DEBUG
+ write_log (_T("CDTV: requested non-existing subchannel data!? %d\n"), subcodeoffset);
+#endif
+ v = 0;
+ } else {
+ v = subtransferbuf[subcodeoffset];
+ tp_a = 0;
+ tp_a |= (v >> 7) & 1;
+ tp_a |= (v >> 5) & 2;
+ tp_a |= (v >> 3) & 4;
+ tp_a |= (v >> 1) & 8;
+ tp_a |= (v << 1) & 16;
+ tp_a |= (v << 3) & 32;
+ tp_a |= (v << 5) & 64;
+ tp_a |= (v << 7) & 128;
+ v = tp_a;
+ subcodeoffset++;
+ sbcp = 0;
+ if (subcodeoffset >= SUB_CHANNEL_SIZE)
+ subcodeoffset = -2;
+ }
+ break;
+ case 1:
+ v = tp_b;
+ break;
+ case 2:
+ if (tp_cr & 1) {
+ v = tp_ilatch | tp_ilatch2;
+ } else {
+ v = get_tp_c ();
+ }
+ break;
+ case 3:
+ v = tp_ad;
+ break;
+ case 4:
+ v = tp_bd;
+ break;
+ case 5:
+ // data direction (mode=0), interrupt mask (mode=1)
+ if (tp_cr & 1)
+ v = tp_imask;
+ else
+ v = tp_cd;
+ break;
+ case 6:
+ v = tp_cr;
+ break;
+ case 7:
+ v = tp_air;
+ if (tp_cr & 1) {
+ tp_ilatch &= ~(1 << 5);
+ tp_ilatch2 = 0;
+ }
+ tp_air = 0;
+ break;
+ }
+
+ tp_check_interrupts ();
+
+#ifdef CDTV_DEBUG_6525
+ if (addr < 7 && addr != 1)
+ write_log (_T("6525 read %x=%02X PC=%x %d\n"), addr, v, M68K_GETPC, regs.s);
+#endif
+ return v;
+}
+
+static uae_u32 REGPARAM3 dmac_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 dmac_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM3 dmac_bget (uaecptr) REGPARAM;
+static void REGPARAM3 dmac_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 dmac_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM3 dmac_bput (uaecptr, uae_u32) REGPARAM;
+
+static void dmac_start_dma (void)
+{
+ if (!(dmac_cntr & CNTR_PDMD)) { // non-scsi dma
+ write_comm_pipe_u32 (&requests, 0x0100, 1);
+ }
+ //else {
+ // scsi_dmac_a2091_start_dma (wd_cdtv);
+ //}
+}
+static void dmac_stop_dma (void)
+{
+ if (!(dmac_cntr & CNTR_PDMD)) { // non-scsi dma
+ ;
+ }
+ //else {
+ // scsi_dmac_a2091_stop_dma (wd_cdtv);
+ //}
+}
+
+void cdtv_getdmadata (uae_u32 *acr)
+{
+ *acr = dmac_acr;
+}
+
+static void checkint (void)
+{
+ int irq = 0;
+
+ //if (cdtvscsi && (wdscsi_getauxstatus (&wd_cdtv->wc) & 0x80)) {
+ // dmac_istr |= ISTR_INTS;
+ // if ((dmac_cntr & CNTR_INTEN) && (dmac_istr & ISTR_INTS))
+ // irq = 1;
+ //}
+ if ((dmac_cntr & CNTR_INTEN) && (dmac_istr & ISTR_E_INT))
+ irq = 1;
+ if (irq)
+ INT2 ();
+}
+
+void cdtv_scsi_int (void)
+{
+ checkint ();
+}
+void cdtv_scsi_clear_int (void)
+{
+ dmac_istr &= ~ISTR_INTS;
+}
+
+static void rethink_cdtv (void)
+{
+ checkint ();
+ tp_check_interrupts ();
+}
+
+
+static void CDTV_hsync_handler (void)
+{
+ static int subqcnt;
+
+ if (!currprefs.cs_cdtvcd || configured <= 0 || currprefs.cs_cdtvcr)
+ return;
+
+ cdtv_hsync++;
+
+ if (dma_wait >= 1024)
+ dma_wait -= 1024;
+ if (dma_wait >= 0 && dma_wait < 1024 && dma_finished) {
+ if ((dmac_cntr & (CNTR_INTEN | CNTR_TCEN)) == (CNTR_INTEN | CNTR_TCEN)) {
+ dmac_istr |= ISTR_INT_P | ISTR_E_INT;
+#ifdef CDTV_DEBUG_CMD
+ write_log (_T("DMA finished\n"));
+#endif
+ }
+ dma_finished = 0;
+ cdtv_hsync = -1;
+ }
+ checkint ();
+
+ if (cdrom_command_done) {
+ cdrom_command_done = 0;
+ sten = 1;
+ stch = 0;
+ tp_check_interrupts ();
+ }
+
+ if (sten < 0) {
+ sten--;
+ if (sten < -3)
+ sten = 0;
+ }
+
+ if (cd_audio_finished) {
+ cd_audio_finished = 0;
+ cd_playing = 0;
+ cd_finished = 1;
+ cd_paused = 0;
+ //cd_error = 1;
+ write_log (_T("audio finished\n"));
+ activate_stch = 1;
+ }
+
+ static int subchannelcounter;
+ int cntmax = (int)(maxvpos * vblank_hz / 75 - 6);
+ if (subchannelcounter > 0)
+ subchannelcounter--;
+ if (subchannelcounter <= 0) {
+ if (cd_playing || cd_media) {
+ if (subcodebufferoffset != subcodebufferoffsetw) {
+ uae_sem_wait (&sub_sem);
+#ifdef CDTV_SUB_DEBUG
+ if (subcodeoffset >= 0)
+ write_log (_T("CDTV: frame interrupt, subchannel not empty! %d\n"), subcodeoffset);
+#endif
+ subcodeoffset = -1;
+ if (subcodebufferinuse[subcodebufferoffset]) {
+ subcodebufferinuse[subcodebufferoffset] = 0;
+ memcpy (subtransferbuf, subcodebuffer + subcodebufferoffset * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE);
+ subcodebufferoffset++;
+ if (subcodebufferoffset >= MAX_SUBCODEBUFFER)
+ subcodebufferoffset -= MAX_SUBCODEBUFFER;
+ sbcp = 0;
+ scor = 1;
+ subcode_activecnt++;
+ event2_newevent2 (SUBCODE_CYCLES, 0, subcode_interrupt);
+ tp_check_interrupts ();
+ }
+ uae_sem_post (&sub_sem);
+ subchannelcounter = cntmax;
+ }
+ }
+ if (!scor && !cd_playing) {
+ // frame interrupts happen all the time motor is running
+ scor = 1;
+ tp_check_interrupts ();
+ scor = 0;
+ subchannelcounter = cntmax;
+ }
+ }
+
+ if (cdtv_hsync < cntmax && cdtv_hsync >= 0)
+ return;
+ cdtv_hsync = 0;
+#if 0
+ if (cd_isready > 0) {
+ cd_isready--;
+ if (!cd_isready)
+ do_stch ();
+ }
+#endif
+ if (dmac_dma || dma_finished)
+ cd_led |= LED_CD_ACTIVE;
+ else
+ cd_led &= ~LED_CD_ACTIVE;
+ if ((cd_led & ~LED_CD_ACTIVE2) && !cd_playing)
+ gui_flicker_led (LED_CD, 0, cd_led);
+
+ subqcnt--;
+ if (subqcnt < 0) {
+ write_comm_pipe_u32 (&requests, 0x0101, 1);
+ if (cd_playing)
+ subqcnt = 10;
+ else
+ subqcnt = 75;
+ }
+
+ if (activate_stch)
+ do_stch ();
+}
+
+static void do_stch (void)
+{
+ if ((tp_cr & 1) && !(tp_air & (1 << 2))) {
+ stch = 1;
+ activate_stch = 0;
+ tp_check_interrupts ();
+#ifdef CDTV_DEBUG
+ static int stch_cnt;
+ write_log (_T("STCH %d\n"), stch_cnt++);
+#endif
+ }
+}
+
+static void cdtv_reset_int (void)
+{
+ write_log (_T("CDTV: reset\n"));
+ cdaudiostop ();
+ cd_playing = cd_paused = 0;
+ cd_motor = 0;
+ cd_media = 0;
+ cd_error = 0;
+ cd_finished = 0;
+ cd_led = 0;
+ stch = 1;
+ frontpanel = 1;
+}
+
+static uae_u32 dmac_bget2 (uaecptr addr)
+{
+ static uae_u8 last_out;
+ uae_u8 v = 0;
+
+ if (addr < 0x40)
+ return dmacmemory[addr];
+
+ if (addr >= 0xb0 && addr < 0xc0)
+ return tp_bget ((addr - 0xb0) / 2);
+
+ switch (addr)
+ {
+ case 0x41:
+ v = dmac_istr;
+ if (v)
+ v |= ISTR_INT_P;
+ dmac_istr &= ~0xf;
+ break;
+ case 0x43:
+ v = dmac_cntr;
+ break;
+ case 0x91:
+ //if (cdtvscsi)
+ // v = wdscsi_getauxstatus (&wd_cdtv->wc);
+ break;
+ case 0x93:
+ //if (cdtvscsi) {
+ // v = wdscsi_get (&wd_cdtv->wc, wd_cdtv);
+ // checkint ();
+ //}
+ break;
+ case 0xa1:
+ sten = 0;
+ if (cdrom_command_cnt_out >= 0) {
+ v = last_out = cdrom_command_output[cdrom_command_cnt_out];
+ cdrom_command_output[cdrom_command_cnt_out++] = 0;
+ if (cdrom_command_cnt_out >= cdrom_command_size_out) {
+ cdrom_command_size_out = 0;
+ cdrom_command_cnt_out = -1;
+ sten = 0;
+ tp_check_interrupts ();
+ } else {
+ sten = 1;
+ tp_check_interrupts ();
+ }
+ } else {
+ write_log (_T("CDTV: command register read while empty\n"));
+ v = last_out;
+ }
+ break;
+ case 0xe8:
+ case 0xe9:
+ dmac_istr |= ISTR_FE_FLG;
+ break;
+ /* XT IO */
+ case 0xa3:
+ case 0xa5:
+ case 0xa7:
+ v = 0xff;
+ break;
+ }
+
+#ifdef CDTV_DEBUG
+ if (addr != 0x41)
+ write_log (_T("dmac_bget %04X=%02X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+
+ return v;
+}
+
+static void dmac_bput2 (uaecptr addr, uae_u32 b)
+{
+ if (addr >= 0xb0 && addr < 0xc0) {
+ tp_bput ((addr - 0xb0) / 2, b);
+ return;
+ }
+
+#ifdef CDTV_DEBUG
+ write_log (_T("dmac_bput %04X=%02X PC=%08X\n"), addr, b & 255, M68K_GETPC);
+#endif
+
+ switch (addr)
+ {
+ case 0x43:
+ dmac_cntr = b;
+ if (dmac_cntr & CNTR_PREST)
+ cdtv_reset_int ();
+ break;
+ case 0x80:
+ dmac_wtc &= 0x00ffffff;
+ dmac_wtc |= b << 24;
+ break;
+ case 0x81:
+ dmac_wtc &= 0xff00ffff;
+ dmac_wtc |= b << 16;
+ break;
+ case 0x82:
+ dmac_wtc &= 0xffff00ff;
+ dmac_wtc |= b << 8;
+ break;
+ case 0x83:
+ dmac_wtc &= 0xffffff00;
+ dmac_wtc |= b << 0;
+ break;
+ case 0x84:
+ dmac_acr &= 0x00ffffff;
+ dmac_acr |= b << 24;
+ break;
+ case 0x85:
+ dmac_acr &= 0xff00ffff;
+ dmac_acr |= b << 16;
+ break;
+ case 0x86:
+ dmac_acr &= 0xffff00ff;
+ dmac_acr |= b << 8;
+ break;
+ case 0x87:
+ dmac_acr &= 0xffffff01;
+ dmac_acr |= (b & ~ 1) << 0;
+ break;
+ case 0x8e:
+ dmac_dawr &= 0x00ff;
+ dmac_dawr |= b << 8;
+ break;
+ case 0x8f:
+ dmac_dawr &= 0xff00;
+ dmac_dawr |= b << 0;
+ break;
+ case 0x91:
+ //if (cdtvscsi) {
+ // wdscsi_sasr (&wd_cdtv->wc, b);
+ // checkint ();
+ //}
+ break;
+ case 0x93:
+ //if (cdtvscsi) {
+ // wdscsi_put (&wd_cdtv->wc, wd_cdtv, b);
+ // checkint ();
+ //}
+ break;
+ case 0xa1:
+ cdrom_command (b);
+ break;
+ case 0xe0:
+ case 0xe1:
+ if (!dmac_dma) {
+ dmac_dma = 1;
+ dmac_start_dma ();
+ }
+ break;
+ case 0xe2:
+ case 0xe3:
+ if (dmac_dma) {
+ dmac_dma = 0;
+ dmac_stop_dma ();
+ }
+ dma_finished = 0;
+ break;
+ case 0xe4:
+ case 0xe5:
+ dmac_istr = 0;
+ checkint ();
+ break;
+ case 0xe8:
+ case 0xe9:
+ dmac_istr |= ISTR_FE_FLG;
+ break;
+ }
+
+ tp_check_interrupts ();
+}
+
+static uae_u32 REGPARAM2 dmac_lget (uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = (dmac_bget2 (addr) << 24) | (dmac_bget2 (addr + 1) << 16) |
+ (dmac_bget2 (addr + 2) << 8) | (dmac_bget2 (addr + 3));
+#ifdef CDTV_DEBUG
+ write_log (_T("dmac_lget %08X=%08X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static uae_u32 REGPARAM2 dmac_wget (uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = (dmac_bget2 (addr) << 8) | dmac_bget2 (addr + 1);
+#ifdef CDTV_DEBUG
+ write_log (_T("dmac_wget %08X=%04X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static uae_u32 REGPARAM2 dmac_bget (uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = dmac_bget2 (addr);
+ if (configured <= 0)
+ return v;
+ return v;
+}
+
+static void REGPARAM2 dmac_lput (uaecptr addr, uae_u32 l)
+{
+ addr &= 65535;
+#ifdef CDTV_DEBUG
+ write_log (_T("dmac_lput %08X=%08X PC=%08X\n"), addr, l, M68K_GETPC);
+#endif
+ dmac_bput2 (addr, l >> 24);
+ dmac_bput2 (addr + 1, l >> 16);
+ dmac_bput2 (addr + 2, l >> 8);
+ dmac_bput2 (addr + 3, l);
+}
+
+static void REGPARAM2 dmac_wput (uaecptr addr, uae_u32 w)
+{
+ addr &= 65535;
+#ifdef CDTV_DEBUG
+ write_log (_T("dmac_wput %04X=%04X PC=%08X\n"), addr, w & 65535, M68K_GETPC);
+#endif
+ dmac_bput2 (addr, w >> 8);
+ dmac_bput2 (addr + 1, w);
+}
+
+static void REGPARAM2 dmac_bput(uaecptr addr, uae_u32 b);
+
+static uae_u32 REGPARAM2 dmac_wgeti(uaecptr addr)
+{
+ uae_u32 v = 0xffff;
+ return v;
+}
+static uae_u32 REGPARAM2 dmac_lgeti(uaecptr addr)
+{
+ uae_u32 v = 0xffff;
+ return v;
+}
+
+static addrbank dmac_bank = {
+ dmac_lget, dmac_wget, dmac_bget,
+ dmac_lput, dmac_wput, dmac_bput,
+ default_xlate, default_check, NULL, NULL, _T("CDTV DMAC/CD Controller"),
+ dmac_wgeti,
+ ABFLAG_IO, S_READ, S_WRITE
+};
+
+static void REGPARAM2 dmac_bput (uaecptr addr, uae_u32 b)
+{
+ addr &= 65535;
+ b &= 0xff;
+ if (addr == 0x48) {
+ map_banks_z2 (&dmac_bank, b, 0x10000 >> 16);
+ configured = b;
+ expamem_next(&dmac_bank, NULL);
+ return;
+ }
+ if (addr == 0x4c) {
+ configured = -1;
+ expamem_shutup(&dmac_bank);
+ return;
+ }
+ if (configured <= 0)
+ return;
+ dmac_bput2 (addr, b);
+}
+
+static void open_unit (void)
+{
+ struct device_info di;
+ unitnum = get_standard_cd_unit (CD_STANDARD_UNIT_CDTV);
+ sys_command_info (unitnum, &di, 0);
+ write_log (_T("using drive %s (unit %d, media %d)\n"), di.label, unitnum, di.media_inserted);
+}
+static void close_unit (void)
+{
+ if (unitnum >= 0)
+ sys_command_close (unitnum);
+ unitnum = -1;
+}
+
+static void ew (int addr, uae_u32 value)
+{
+ addr &= 0xffff;
+ if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
+ dmacmemory[addr] = (value & 0xf0);
+ dmacmemory[addr + 2] = (value & 0x0f) << 4;
+ } else {
+ dmacmemory[addr] = ~(value & 0xf0);
+ dmacmemory[addr + 2] = ~((value & 0x0f) << 4);
+ }
+}
+
+/* CDTV batterybacked RAM emulation */
+#define CDTV_NVRAM_MASK 16383
+#define CDTV_NVRAM_SIZE 32768
+static uae_u8 cdtv_battram[CDTV_NVRAM_SIZE];
+static TCHAR flashfilepath[MAX_DPATH];
+
+static void cdtv_loadcardmem (uae_u8 *p, int size)
+{
+ struct zfile *f;
+
+ if (!size)
+ return;
+ memset (p, 0, size);
+ cfgfile_resolve_path_out_load(currprefs.flashfile, flashfilepath, MAX_DPATH, PATH_ROM);
+ f = zfile_fopen (flashfilepath, _T("rb"), ZFD_NORMAL);
+ if (!f)
+ return;
+ zfile_fseek (f, CDTV_NVRAM_SIZE, SEEK_SET);
+ zfile_fread (p, size, 1, f);
+ zfile_fclose (f);
+}
+
+static void cdtv_savecardmem (uae_u8 *p, int size)
+{
+ struct zfile *f;
+
+ if (!size)
+ return;
+ cfgfile_resolve_path_out_load(currprefs.flashfile, flashfilepath, MAX_DPATH, PATH_ROM);
+ f = zfile_fopen (flashfilepath, _T("rb+"), ZFD_NORMAL);
+ if (!f)
+ return;
+ zfile_fseek (f, CDTV_NVRAM_SIZE, SEEK_SET);
+ zfile_fwrite (p, size, 1, f);
+ zfile_fclose (f);
+}
+
+static void cdtv_battram_reset (void)
+{
+ struct zfile *f;
+ int v;
+
+ memset (cdtv_battram, 0, CDTV_NVRAM_SIZE);
+ cfgfile_resolve_path_out_load(currprefs.flashfile, flashfilepath, MAX_DPATH, PATH_ROM);
+ f = zfile_fopen (flashfilepath, _T("rb+"), ZFD_NORMAL);
+ if (!f) {
+ f = zfile_fopen (flashfilepath, _T("wb"), 0);
+ if (f) {
+ zfile_fwrite (cdtv_battram, CDTV_NVRAM_SIZE, 1, f);
+ zfile_fclose (f);
+ }
+ return;
+ }
+ v = zfile_fread (cdtv_battram, 1, CDTV_NVRAM_SIZE, f);
+ if (v < CDTV_NVRAM_SIZE)
+ zfile_fwrite (cdtv_battram + v, 1, CDTV_NVRAM_SIZE - v, f);
+ zfile_fclose (f);
+}
+
+void cdtv_battram_write (int addr, int v)
+{
+ struct zfile *f;
+ int offset = addr & CDTV_NVRAM_MASK;
+
+ if (offset >= CDTV_NVRAM_SIZE)
+ return;
+ gui_flicker_led (LED_MD, 0, 2);
+ if (cdtv_battram[offset] == v)
+ return;
+ cdtv_battram[offset] = v;
+ f = zfile_fopen (flashfilepath, _T("rb+"), ZFD_NORMAL);
+ if (!f)
+ return;
+ zfile_fseek (f, offset, SEEK_SET);
+ zfile_fwrite (cdtv_battram + offset, 1, 1, f);
+ zfile_fclose (f);
+}
+
+uae_u8 cdtv_battram_read (int addr)
+{
+ uae_u8 v;
+ int offset;
+ offset = addr & CDTV_NVRAM_MASK;
+ if (offset >= CDTV_NVRAM_SIZE)
+ return 0;
+ gui_flicker_led (LED_MD, 0, 1);
+ v = cdtv_battram[offset];
+ return v;
+}
+
+/* CDTV expension memory card memory */
+
+MEMORY_FUNCTIONS(cardmem);
+
+addrbank cardmem_bank = {
+ cardmem_lget, cardmem_wget, cardmem_bget,
+ cardmem_lput, cardmem_wput, cardmem_bput,
+ cardmem_xlate, cardmem_check, NULL, _T("rom_e0"), _T("CDTV memory card"),
+ cardmem_wget,
+ ABFLAG_RAM, 0, 0
+};
+
+static void cdtv_free (void)
+{
+ if (thread_alive > 0) {
+ dmac_dma = 0;
+ dma_finished = 0;
+ cdaudiostop ();
+ write_comm_pipe_u32 (&requests, 0xffff, 1);
+ while (thread_alive > 0)
+ sleep_millis (10);
+ uae_sem_destroy(&sub_sem);
+ uae_sem_destroy(&cda_sem);
+ }
+ thread_alive = 0;
+ close_unit ();
+ if (cardmem_bank.baseaddr) {
+ cdtv_savecardmem(cardmem_bank.baseaddr, cardmem_bank.allocated_size);
+ mapped_free(&cardmem_bank);
+ cardmem_bank.baseaddr = NULL;
+ }
+ configured = 0;
+}
+
+bool cdtvsram_init(struct autoconfig_info *aci)
+{
+ return true;
+}
+
+bool cdtv_init(struct autoconfig_info *aci)
+{
+ memset(dmacmemory, 0xff, sizeof dmacmemory);
+ ew(0x00, 0xc0 | 0x01);
+ ew(0x04, 0x03);
+ ew(0x08, 0x40);
+ ew(0x10, 0x02);
+ ew(0x14, 0x02);
+
+ ew(0x18, 0x00); /* ser.no. Byte 0 */
+ ew(0x1c, 0x00); /* ser.no. Byte 1 */
+ ew(0x20, 0x00); /* ser.no. Byte 2 */
+ ew(0x24, 0x00); /* ser.no. Byte 3 */
+
+ if (aci) {
+ aci->label = dmac_bank.name;
+ aci->hardwired = true;
+ aci->addrbankp = &dmac_bank;
+ if (!aci->doinit) {
+ memcpy(aci->autoconfig_raw, dmacmemory, sizeof dmacmemory);
+ return true;
+ }
+ }
+
+ close_unit ();
+ if (!thread_alive) {
+ init_comm_pipe (&requests, 100, 1);
+ uae_start_thread (_T("cdtv"), dev_thread, NULL, NULL);
+ while (!thread_alive)
+ sleep_millis (10);
+ uae_sem_init(&sub_sem, 0, 1);
+ uae_sem_init(&cda_sem, 0, 0);
+ }
+ write_comm_pipe_u32 (&requests, 0x0104, 1);
+
+ cdrom_command_cnt_out = -1;
+ cmd = enable = xaen = dten = 0;
+
+ /* KS autoconfig handles the rest */
+ if (!savestate_state) {
+ cdtv_reset_int ();
+ configured = 0;
+ tp_a = tp_b = tp_c = tp_ad = tp_bd = tp_cd = 0;
+ tp_imask = tp_cr = tp_air = tp_ilatch = 0;
+ stch = 0;
+ sten = 0;
+ scor = 0;
+ sbcp = 0;
+ cdtvscsi = 0;
+ }
+
+ int cardsize = 0;
+ if (aci && is_board_enabled(aci->prefs, ROMTYPE_CDTVSRAM, 0)) {
+ struct romconfig *rc = get_device_romconfig(aci->prefs, ROMTYPE_CDTVSRAM, 0);
+ cardsize = 64 << (rc->device_settings & 3);
+ }
+ if (cardmem_bank.reserved_size != cardsize * 1024) {
+ mapped_free(&cardmem_bank);
+ cardmem_bank.baseaddr = NULL;
+
+ cardmem_bank.reserved_size = cardsize * 1024;
+ cardmem_bank.mask = cardmem_bank.reserved_size - 1;
+ cardmem_bank.start = 0xe00000;
+ if (cardmem_bank.reserved_size) {
+ if (!mapped_malloc(&cardmem_bank)) {
+ write_log(_T("Out of memory for cardmem.\n"));
+ cardmem_bank.reserved_size = 0;
+ }
+ }
+ cdtv_loadcardmem(cardmem_bank.baseaddr, cardmem_bank.reserved_size);
+ }
+ if (cardmem_bank.baseaddr)
+ map_banks(&cardmem_bank, cardmem_bank.start >> 16, cardmem_bank.allocated_size >> 16, 0);
+
+ cdtv_battram_reset ();
+ open_unit ();
+ gui_flicker_led (LED_CD, 0, -1);
+
+ device_add_hsync(CDTV_hsync_handler);
+ device_add_rethink(rethink_cdtv);
+ device_add_exit(cdtv_free);
+
+ return true;
+}
+
+bool cdtvscsi_init(struct autoconfig_info *aci)
+{
+ aci->parent_name = _T("CDTV DMAC");
+ aci->hardwired = true;
+ if (!aci->doinit)
+ return true;
+ cdtvscsi = true;
+ //init_wd_scsi(wd_cdtv);
+ //wd_cdtv->dmac_type = COMMODORE_DMAC;
+ if (configured > 0)
+ map_banks_z2(&dmac_bank, configured, 0x10000 >> 16);
+ return true;
+}
+
+#ifdef SAVESTATE
+
+uae_u8 *save_cdtv_dmac (int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dstbak, *dst;
+
+ if (!currprefs.cs_cdtvcd || currprefs.cs_cdtvcr)
+ return NULL;
+ if (dstptr)
+ dstbak = dst = dstptr;
+ else
+ dstbak = dst = xmalloc (uae_u8, 1000);
+
+ // model (0=original,1=rev2,2=superdmac)
+ save_u32 (1);
+ save_u32 (0); // reserved flags
+ save_u8 (dmac_istr);
+ save_u8 (dmac_cntr);
+ save_u32 (dmac_wtc);
+ save_u32 (dmac_acr);
+ save_u16 (dmac_dawr);
+ save_u32 (dmac_dma ? 1 : 0);
+ save_u8 (configured);
+ *len = dst - dstbak;
+ return dstbak;
+
+}
+
+uae_u8 *restore_cdtv_dmac (uae_u8 *src)
+{
+ restore_u32 ();
+ restore_u32 ();
+ dmac_istr = restore_u8 ();
+ dmac_cntr = restore_u8 ();
+ dmac_wtc = restore_u32 ();
+ dmac_acr = restore_u32 ();
+ dmac_dawr = restore_u16 ();
+ restore_u32 ();
+ configured = restore_u8 ();
+ return src;
+}
+
+uae_u8 *save_cdtv (int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dstbak, *dst;
+
+ if (!currprefs.cs_cdtvcd || currprefs.cs_cdtvcr)
+ return NULL;
+
+ if (dstptr)
+ dstbak = dst = dstptr;
+ else
+ dstbak = dst = xmalloc (uae_u8, 1000);
+
+ save_u32 (1);
+
+ // tri-port
+ save_u8 (tp_a);
+ save_u8 (tp_b);
+ save_u8 (tp_c);
+ save_u8 (tp_ad);
+ save_u8 (tp_bd);
+ save_u8 (tp_cd);
+ save_u8 (tp_cr);
+ save_u8 (tp_air);
+ save_u8 (tp_imask);
+ save_u8 (tp_ilatch);
+ save_u8 (tp_ilatch2);
+ save_u8 (0);
+ // misc cd stuff
+ save_u32 ((cd_playing ? 1 : 0) | (cd_paused ? 2 : 0) | (cd_media ? 4 : 0) |
+ (cd_motor ? 8 : 0) | (cd_error ? 16 : 0) | (cd_finished ? 32 : 0) | (cdrom_command_done ? 64 : 0) |
+ (activate_stch ? 128 : 0) | (sten ? 256 : 0) | (stch ? 512 : 0) | (frontpanel ? 1024 : 0));
+ save_u8 (cd_isready);
+ save_u8 (0);
+ save_u16 (dac_control_data_format);
+ if (cd_playing)
+ get_qcode ();
+ save_u32 (last_play_pos);
+ save_u32 (last_play_end);
+ save_u64 (dma_wait);
+ for (int i = 0; i < sizeof (cdrom_command_input); i++)
+ save_u8 (cdrom_command_input[i]);
+ save_u8 (cdrom_command_cnt_in);
+ save_u16 (cdtv_sectorsize);
+
+ *len = dst - dstbak;
+ return dstbak;
+}
+
+uae_u8 *restore_cdtv (uae_u8 *src)
+{
+ cdtv_free ();
+ if (!currprefs.cs_cdtvcd) {
+ changed_prefs.cs_cdtvcd = changed_prefs.cs_cdtvram = true;
+ currprefs.cs_cdtvcd = currprefs.cs_cdtvram = true;
+ cdtv_init(NULL);
+ }
+ restore_u32 ();
+
+ // tri-port
+ tp_a = restore_u8 ();
+ tp_b = restore_u8 ();
+ tp_c = restore_u8 ();
+ tp_ad = restore_u8 ();
+ tp_bd = restore_u8 ();
+ tp_cd = restore_u8 ();
+ tp_cr = restore_u8 ();
+ tp_air = restore_u8 ();
+ tp_imask = restore_u8 ();
+ tp_ilatch = restore_u8 ();
+ tp_ilatch2 = restore_u8 ();
+ restore_u8 ();
+ // misc cd stuff
+ uae_u32 v = restore_u32 ();
+ cd_playing = (v & 1) ? 1 : 0;
+ cd_paused = (v & 2) ? 1 : 0;
+ cd_media = (v & 4) ? 1 : 0;
+ cd_motor = (v & 8) ? 1 : 0;
+ cd_error = (v & 16) ? 1 : 0;
+ cd_finished = (v & 32) ? 1 : 0;
+ cdrom_command_done = (v & 64) ? 1 : 0;
+ activate_stch = (v & 128) ? 1 : 0;
+ sten = (v & 256) ? 1 : 0;
+ stch = (v & 512) ? 1 : 0;
+ frontpanel = (v & 1024) ? 1 : 0;
+ cd_isready = restore_u8 ();
+ restore_u8 ();
+ dac_control_data_format = restore_u16 ();
+ last_play_pos = restore_u32 ();
+ last_play_end = restore_u32 ();
+ dma_wait = restore_u64 ();
+ for (int i = 0; i < sizeof (cdrom_command_input); i++)
+ cdrom_command_input[i] = restore_u8 ();
+ cdrom_command_cnt_in = restore_u8 ();
+ cdtv_sectorsize = restore_u16 ();
+ cd_audio_status = 0;
+ cd_volume_stored = dac_control_data_format & 1023;
+ volstrobe1 = volstrobe2 = 1;
+
+ return src;
+}
+
+void restore_cdtv_finish (void)
+{
+ if (!currprefs.cs_cdtvcd || currprefs.cs_cdtvcr)
+ return;
+ cdtv_init (0);
+ get_toc ();
+ configured = 0xe90000;
+ map_banks_z2(&dmac_bank, configured >> 16, 0x10000 >> 16);
+ write_comm_pipe_u32 (&requests, 0x0104, 1);
+}
+
+void restore_cdtv_final(void)
+{
+ if (!currprefs.cs_cdtvcd || currprefs.cs_cdtvcr)
+ return;
+ if (cd_playing) {
+ cd_volume = cd_volume_stored;
+ write_comm_pipe_u32(&requests, 0x0111, 0); // play
+ write_comm_pipe_u32(&requests, last_play_pos, 0);
+ write_comm_pipe_u32(&requests, last_play_end, 0);
+ write_comm_pipe_u32(&requests, 0, 1);
+ uae_sem_wait(&cda_sem);
+ }
+}
+
+#endif
diff --git a/src/cdtvcr.cpp b/src/cdtvcr.cpp
new file mode 100644
index 00000000..27ef26e0
--- /dev/null
+++ b/src/cdtvcr.cpp
@@ -0,0 +1,1574 @@
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* CDTV-CR emulation
+* (4510 microcontroller only simulated)
+*
+* Copyright 2014 Toni Wilen
+*
+*
+*/
+
+#define CDTVCR_4510_EMULATION 0
+
+#define CDTVCR_DEBUG 0
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "memory.h"
+#include "newcpu.h"
+//#include "debug.h"
+#include "zfile.h"
+#include "gui.h"
+#include "cdtvcr.h"
+#include "blkdev.h"
+#include "threaddep/thread.h"
+#include "uae.h"
+#include "custom.h"
+#include "rommgr.h"
+#include "devices.h"
+
+#if CDTVCR_4510_EMULATION
+static void init_65c02(void);
+static void cpu_4510(void);
+#endif
+
+#define CDTVCR_MASK 0xffff
+
+#define CDTVCR_RAM_OFFSET 0x1000
+#define CDTVCR_RAM_SIZE 4096
+#define CDTVCR_RAM_MASK (CDTVCR_RAM_SIZE - 1)
+
+#define CDTVCR_CLOCK 0xc10
+#define CDTVCR_ID 0x9dc
+
+#define CDTVCR_RESET 0xc00
+
+#define CDTVCR_CD_CMD 0xc40
+#define CDTVCR_CD_CMD_DO 0xc52
+#define CDTVCR_CD_CMD_STATUS 0xc4e
+#define CDTVCR_CD_CMD_STATUS2 0xc4f
+
+#define CDTVCR_CD_STATE 0xc53
+#define CDTVCR_SYS_STATE 0xc54
+#define CDTVCR_CD_SPEED 0xc59
+#define CDTVCR_CD_PLAYING 0xc5b
+#define CDTVCR_CD_SUBCODES 0xc60
+#define CDTVCR_CD_ALLOC 0xc61
+
+#define CDTVCR_INTDISABLE 0xc04
+#define CDTVCR_INTACK 0xc05
+#define CDTVCR_INTENA 0xc55
+#define CDTVCR_INTREQ 0xc56
+#define CDTVCR_4510_TRIGGER 0x4000
+
+#define CDTVCR_KEYCMD 0xc80
+
+#define CDTVCR_SUBQ 0x906
+#define CDTVCR_SUBBANK 0x917
+#define CDTVCR_SUBC 0x918
+#define CDTVCR_TOC 0xa00
+
+#define CDTVCR_PLAYLIST_TRACK 0xc2f
+#define CDTVCR_PLAYLIST_TIME_MINS 0xc35
+#define CDTVCR_PLAYLIST_TIME_SECS 0xc36
+#define CDTVCR_PLAYLIST_TIME_MODE 0xc22
+#define CDTVCR_PLAYLIST_TIME_MODE2 0xc84
+#define CDTVCR_PLAYLIST_STATE 0xc86
+#define CDTVCR_PLAYLIST_CURRENT 0xc8a
+#define CDTVCR_PLAYLIST_ENTRIES 0xc8b
+#define CDTVCR_PLAYLIST_DATA 0xc8c
+
+
+static uae_u8 cdtvcr_4510_ram[CDTVCR_RAM_OFFSET];
+static uae_u8 cdtvcr_ram[CDTVCR_RAM_SIZE];
+static uae_u8 cdtvcr_clock[2];
+
+static smp_comm_pipe requests;
+static uae_sem_t sub_sem;
+static volatile int thread_alive;
+static int unitnum = -1;
+static struct cd_toc_head toc;
+static int datatrack;
+static int cdtvcr_media;
+static int subqcnt;
+static int cd_audio_status;
+static int cdtvcr_wait_sectors;
+static int cd_led;
+
+#define MAX_SUBCODEBUFFER 36
+static volatile int subcodebufferoffset, subcodebufferoffsetw;
+static uae_u8 subcodebufferinuse[MAX_SUBCODEBUFFER];
+static uae_u8 subcodebuffer[MAX_SUBCODEBUFFER * SUB_CHANNEL_SIZE];
+static TCHAR flashfilepath[MAX_DPATH];
+
+static void cdtvcr_battram_reset (void)
+{
+ struct zfile *f;
+ int v;
+
+ memset (cdtvcr_ram, 0, CDTVCR_RAM_SIZE);
+ cfgfile_resolve_path_out_load(currprefs.flashfile, flashfilepath, MAX_DPATH, PATH_ROM);
+ f = zfile_fopen (flashfilepath, _T("rb+"), ZFD_NORMAL);
+ if (!f) {
+ f = zfile_fopen (flashfilepath, _T("wb"), 0);
+ if (f) {
+ zfile_fwrite (cdtvcr_ram, CDTVCR_RAM_SIZE, 1, f);
+ zfile_fclose (f);
+ }
+ return;
+ }
+ v = zfile_fread (cdtvcr_ram, 1, CDTVCR_RAM_SIZE, f);
+ if (v < CDTVCR_RAM_SIZE)
+ zfile_fwrite (cdtvcr_ram + v, 1, CDTVCR_RAM_SIZE - v, f);
+ zfile_fclose (f);
+}
+
+static void cdtvcr_battram_write (int addr, int v)
+{
+ struct zfile *f;
+ int offset = addr & CDTVCR_RAM_MASK;
+
+ if (offset >= CDTVCR_RAM_SIZE)
+ return;
+ gui_flicker_led (LED_MD, 0, 2);
+ if (cdtvcr_ram[offset] == v)
+ return;
+ cdtvcr_ram[offset] = v;
+ f = zfile_fopen (flashfilepath, _T("rb+"), ZFD_NORMAL);
+ if (!f)
+ return;
+ zfile_fseek (f, offset, SEEK_SET);
+ zfile_fwrite (cdtvcr_ram + offset, 1, 1, f);
+ zfile_fclose (f);
+}
+
+static uae_u8 cdtvcr_battram_read (int addr)
+{
+ uae_u8 v;
+ int offset;
+ offset = addr & CDTVCR_RAM_MASK;
+ if (offset >= CDTVCR_RAM_SIZE)
+ return 0;
+ gui_flicker_led (LED_MD, 0, 1);
+ v = cdtvcr_ram[offset];
+ return v;
+}
+
+static int ismedia (void)
+{
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~8;
+ if (unitnum < 0)
+ return 0;
+ if (sys_command_ismedia (unitnum, 0)) {
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 8;
+ return 1;
+ }
+ return 0;
+}
+
+static int get_qcode (void)
+{
+#if 0
+ if (!sys_command_cd_qcode (unitnum, cdrom_qcode))
+ return 0;
+ cdrom_qcode[1] = cd_audio_status;
+#endif
+ return 1;
+}
+
+static int get_toc (void)
+{
+ uae_u32 msf;
+ uae_u8 *p, *pl;
+
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~4;
+ datatrack = 0;
+ if (!sys_command_cd_toc (unitnum, &toc))
+ return 0;
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 4 | 8;
+ if (toc.first_track == 1 && (toc.toc[toc.first_track_offset].control & 0x0c) == 0x04)
+ datatrack = 1;
+ p = &cdtvcr_4510_ram[CDTVCR_TOC];
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT] = 0;
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_ENTRIES] = 0;
+ pl = &cdtvcr_4510_ram[CDTVCR_PLAYLIST_DATA];
+ p[0] = toc.first_track;
+ p[1] = toc.last_track;
+ msf = lsn2msf(toc.lastaddress);
+ p[2] = msf >> 16;
+ p[3] = msf >> 8;
+ p[4] = msf >> 0;
+ p += 5;
+ for (int j = toc.first_track_offset; j <= toc.last_track_offset; j++) {
+ struct cd_toc *s = &toc.toc[j];
+ p[0] = (s->adr << 0) | (s->control << 4);
+ p[1] = s->track;
+ msf = lsn2msf(s->address);
+ p[2] = msf >> 16;
+ p[3] = msf >> 8;
+ p[4] = msf >> 0;
+ p += 5;
+ *pl++ = s->track | 0x80;
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_ENTRIES]++;
+ }
+ return 1;
+}
+
+static void cdtvcr_4510_reset(uae_u8 v)
+{
+ cdtvcr_4510_ram[CDTVCR_ID + 0] = 'C';
+ cdtvcr_4510_ram[CDTVCR_ID + 1] = 'D';
+ cdtvcr_4510_ram[CDTVCR_ID + 2] = 'T';
+ cdtvcr_4510_ram[CDTVCR_ID + 3] = 'V';
+
+ write_log(_T("4510 reset %d\n"), v);
+ if (v == 3) {
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
+ cdtvcr_4510_ram[CDTVCR_CD_PLAYING] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 0;
+ return;
+ } else if (v == 2 || v == 1) {
+ cdtvcr_4510_ram[CDTVCR_INTENA] = 0;
+ cdtvcr_4510_ram[CDTVCR_INTREQ] = 0;
+ if (v == 1) {
+ memset(cdtvcr_4510_ram, 0, 4096);
+ }
+ cdtvcr_4510_ram[CDTVCR_INTDISABLE] = 1;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 1;
+ }
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_TIME_MODE] = 2;
+ uae_sem_wait (&sub_sem);
+ memset (subcodebufferinuse, 0, sizeof subcodebufferinuse);
+ subcodebufferoffsetw = subcodebufferoffset = 0;
+ uae_sem_post (&sub_sem);
+
+ if (ismedia())
+ get_toc();
+}
+
+static void rethink_cdtvcr(void)
+{
+ if ((cdtvcr_4510_ram[CDTVCR_INTREQ] & cdtvcr_4510_ram[CDTVCR_INTENA]) && !cdtvcr_4510_ram[CDTVCR_INTDISABLE]) {
+ safe_interrupt_set(false);
+ cd_led ^= LED_CD_ACTIVE2;
+ }
+}
+
+static void cdtvcr_cmd_done(void)
+{
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~3;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_DO] = 0;
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x40;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS2] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS + 2] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS2 + 2] = 0;
+}
+
+static void cdtvcr_play_done(void)
+{
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~3;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_DO] = 0;
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x80;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS2] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS + 2] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS2 + 2] = 0;
+}
+
+static void cdtvcr_state_stopped(void)
+{
+ cdtvcr_4510_ram[CDTVCR_CD_PLAYING] = 0;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 1;
+}
+
+static void cdtvcr_state_play(void)
+{
+ cdtvcr_4510_ram[CDTVCR_CD_PLAYING] = 1;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 3;
+}
+
+static void cdtvcr_cmd_play_started(void)
+{
+ cdtvcr_cmd_done();
+ cdtvcr_state_play();
+}
+
+static void cdtvcr_start (void)
+{
+ if (unitnum < 0)
+ return;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 0;
+}
+
+static void cdtvcr_stop (void)
+{
+ if (unitnum < 0)
+ return;
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
+ if (cdtvcr_4510_ram[CDTVCR_CD_PLAYING]) {
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x80;
+ }
+ cdtvcr_state_stopped();
+}
+
+static void cdtvcr_state_pause(bool pause)
+{
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 3;
+ if (pause)
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 2;
+}
+
+static void cdtvcr_pause(bool pause)
+{
+ sys_command_cd_pause (unitnum, pause ? 1 : 0);
+ cdtvcr_state_pause(pause);
+ cdtvcr_cmd_done();
+}
+
+static void setsubchannel(uae_u8 *s)
+{
+ uae_u8 *d;
+
+ // q-channel
+ d = &cdtvcr_4510_ram[CDTVCR_SUBQ];
+ s += SUB_ENTRY_SIZE;
+ int track = frombcd(s[1]);
+ /* CtlAdr */
+ d[0] = s[0];
+ /* Track */
+ d[1] = s[1];
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_TRACK] = track;
+ /* Index */
+ d[2] = s[2];
+ /* TrackPos */
+ d[3] = s[3];
+ d[4] = s[4];
+ d[5] = s[5];
+ /* DiskPos */
+ d[6] = s[6];
+ d[7] = s[7];
+ d[8] = s[8];
+ d[9] = s[9];
+
+ uae_u8 mins = 0, secs = 0;
+ uae_s32 trackpos = msf2lsn(fromlongbcd(s + 3));
+ if (trackpos < 0)
+ trackpos = 0;
+ uae_s32 diskpos = msf2lsn(fromlongbcd(s + 7));
+ if (diskpos < 0)
+ diskpos = 0;
+ switch (cdtvcr_4510_ram[CDTVCR_PLAYLIST_TIME_MODE2])
+ {
+ case 0:
+ secs = (trackpos / 75) % 60;
+ mins = trackpos / (75 * 60);
+ break;
+ case 1:
+ trackpos = toc.toc[toc.first_track_offset + track].paddress - diskpos;
+ secs = (trackpos / 75) % 60;
+ mins = trackpos / (75 * 60);
+ break;
+ case 2:
+ secs = (diskpos / 75) % 60;
+ mins = diskpos / (75 * 60);
+ break;
+ case 3:
+ diskpos = toc.lastaddress - diskpos;
+ secs = (diskpos / 75) % 60;
+ mins = diskpos / (75 * 60);
+ break;
+ }
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_TIME_MINS] = mins;
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_TIME_SECS] = secs;
+
+ cdtvcr_4510_ram[CDTVCR_SUBQ - 2] = 1; // qcode valid
+ cdtvcr_4510_ram[CDTVCR_SUBQ - 1] = 0;
+
+ if (cdtvcr_4510_ram[CDTVCR_CD_SUBCODES])
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 4;
+}
+
+static void subfunc(uae_u8 *data, int cnt)
+{
+ uae_u8 out[SUB_CHANNEL_SIZE];
+ sub_to_deinterleaved(data, out);
+ setsubchannel(out);
+
+ uae_sem_wait(&sub_sem);
+ if (subcodebufferinuse[subcodebufferoffsetw]) {
+ memset (subcodebufferinuse, 0,sizeof (subcodebufferinuse));
+ subcodebufferoffsetw = subcodebufferoffset = 0;
+ } else {
+ int offset = subcodebufferoffsetw;
+ while (cnt > 0) {
+ if (subcodebufferinuse[offset]) {
+ write_log (_T("CD32: subcode buffer overflow 2\n"));
+ break;
+ }
+ subcodebufferinuse[offset] = 1;
+ memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE);
+ data += SUB_CHANNEL_SIZE;
+ offset++;
+ if (offset >= MAX_SUBCODEBUFFER)
+ offset = 0;
+ cnt--;
+ }
+ subcodebufferoffsetw = offset;
+ }
+ uae_sem_post(&sub_sem);
+}
+
+static int statusfunc(int status, int playpos)
+{
+ if (status == -1)
+ return 75;
+ if (status == -2)
+ return 75;
+ if (status < 0)
+ return 0;
+ if (cd_audio_status != status) {
+ if (status == AUDIO_STATUS_PLAY_COMPLETE || status == AUDIO_STATUS_PLAY_ERROR) {
+ cdtvcr_play_done();
+ } else if (status == AUDIO_STATUS_IN_PROGRESS) {
+ cdtvcr_cmd_play_started();
+ }
+ }
+ cd_audio_status = status;
+ return 0;
+}
+
+static void cdtvcr_play(uae_u32 start, uae_u32 end)
+{
+ sys_command_cd_pause(unitnum, 0);
+ if (!sys_command_cd_play(unitnum, start, end, 0, statusfunc, subfunc))
+ cdtvcr_play_done();
+}
+
+static void cdtvcr_play_track(uae_u32 track_start, uae_u32 track_end)
+{
+ int start_found, end_found;
+ uae_u32 start, end;
+
+ start_found = end_found = 0;
+ for (int j = toc.first_track_offset; j <= toc.last_track_offset; j++) {
+ struct cd_toc *s = &toc.toc[j];
+ if (track_start == s->track) {
+ start_found++;
+ start = s->paddress;
+ end = toc.toc[toc.last_track_offset].paddress;
+ }
+ if (track_end == s->track) {
+ end = s->paddress;
+ end_found++;
+ }
+ }
+ if (start_found == 0) {
+ write_log (_T("PLAY CD AUDIO: illegal start track %d\n"), track_start);
+ cdtvcr_stop();
+ cdtvcr_cmd_done();
+ return;
+ }
+ cdtvcr_play(start, end);
+}
+
+static void cdtvcr_read_data(uae_u32 start, uae_u32 addr, uae_u32 len)
+{
+ uae_u8 buffer[2048];
+ int didread;
+
+ cdtvcr_wait_sectors = 0;
+ while (len) {
+ didread = sys_command_cd_read (unitnum, buffer, start, 1);
+ if (!didread)
+ break;
+ for (int i = 0; i < 2048 && len > 0; i++) {
+ put_byte(addr + i, buffer[i]);
+ len--;
+ }
+ addr += 2048;
+ start++;
+ cdtvcr_wait_sectors++;
+ }
+}
+
+static void cdtvcr_player_state_change(void)
+{
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x10;
+}
+
+static void cdtvcr_player_pause(void)
+{
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] == 4)
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] = 3;
+ else if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] == 3)
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] = 4;
+ else
+ return;
+ cdtvcr_pause(cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] == 4);
+ cdtvcr_state_pause(cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] == 4);
+ cdtvcr_player_state_change();
+}
+
+static void cdtvcr_player_stop(void)
+{
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] = 1;
+ cdtvcr_stop();
+ cdtvcr_state_stopped();
+ cdtvcr_player_state_change();
+}
+
+static void cdtvcr_player_play(void)
+{
+ int start_found, end_found;
+ uae_u32 start, end;
+
+ int entry = cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT];
+ int track = cdtvcr_4510_ram[CDTVCR_PLAYLIST_DATA + entry] & 0x7f;
+ start_found = end_found = 0;
+ for (int j = toc.first_track_offset; j <= toc.last_track_offset; j++) {
+ struct cd_toc *s = &toc.toc[j];
+ if (track == s->track) {
+ start_found++;
+ start = s->paddress;
+ end = s[1].paddress;
+ }
+ }
+ if (start_found == 0) {
+ cdtvcr_player_stop();
+ return;
+ }
+ cdtvcr_play(start, end);
+ cdtvcr_state_play();
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] = 3;
+ cdtvcr_player_state_change();
+}
+
+static void cdtvcr_do_cmd(void)
+{
+ uae_u32 addr, len, start, end, datalen;
+ uae_u32 startlsn, endlsn;
+ uae_u8 starttrack, endtrack;
+ uae_u8 *p = &cdtvcr_4510_ram[CDTVCR_CD_CMD];
+
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 2;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS] = 2;
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_STATUS2] = 0;
+ write_log(_T("CDTVCR CD command %02x\n"), p[0]);
+ for(int i = 0; i < 14; i++)
+ write_log(_T(".%02x"), p[i]);
+ write_log(_T("\n"));
+
+ start = (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
+ startlsn = msf2lsn(start);
+ end = (p[4] << 16) | (p[5] << 8) | (p[6] << 0);
+ endlsn = msf2lsn(end);
+ addr = (p[7] << 24) | (p[8] << 16) | (p[9] << 8) | (p[10] << 0);
+ len = (p[4] << 16) | (p[5] << 8) | (p[6] << 0);
+ datalen = (p[11] << 16) | (p[12] << 8) | (p[13] << 0);
+ starttrack = p[1];
+ endtrack = p[3];
+
+ switch(p[0])
+ {
+ case 2: // start
+ cdtvcr_start();
+ cdtvcr_cmd_done();
+ break;
+ case 3: // stop
+ cdtvcr_stop();
+ cdtvcr_cmd_done();
+ break;
+ case 4: // toc
+ cdtvcr_stop();
+ get_toc();
+ cdtvcr_cmd_done();
+ break;
+ case 6: // play
+ cdtvcr_stop();
+ cdtvcr_play(startlsn, endlsn);
+ break;
+ case 7: // play track
+ cdtvcr_stop();
+ cdtvcr_play_track(starttrack, endtrack);
+ break;
+ case 8: // read
+ cdtvcr_stop();
+ cdtvcr_read_data(start, addr, datalen);
+ break;
+ case 9:
+ cdtvcr_pause(true);
+ break;
+ case 10:
+ cdtvcr_pause(false);
+ break;
+ case 11: // stop play
+ cdtvcr_stop();
+ cdtvcr_cmd_done();
+ break;
+ default:
+ write_log(_T("unsupported command!\n"));
+ break;
+ }
+}
+
+static void cdtvcr_4510_do_something(void)
+{
+ if (cdtvcr_4510_ram[CDTVCR_INTACK]) {
+ cdtvcr_4510_ram[CDTVCR_INTACK] = 0;
+ rethink_cdtvcr();
+ }
+ if (cdtvcr_4510_ram[CDTVCR_CD_CMD_DO]) {
+ cdtvcr_4510_ram[CDTVCR_CD_CMD_DO] = 0;
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 2;
+ write_comm_pipe_u32 (&requests, 0x0100, 1);
+ }
+}
+
+static bool cdtvcr_debug(uaecptr addr)
+{
+ addr &= CDTVCR_MASK;
+ return !(addr >= CDTVCR_RAM_OFFSET && addr < CDTVCR_RAM_OFFSET + CDTVCR_RAM_SIZE);
+}
+
+static void cdtvcr_bput2 (uaecptr addr, uae_u8 v)
+{
+ addr &= CDTVCR_MASK;
+ if (addr == CDTVCR_4510_TRIGGER) {
+ if (v & 0x80)
+ cdtvcr_4510_do_something();
+ } else if (addr >= CDTVCR_RAM_OFFSET && addr < CDTVCR_RAM_OFFSET + CDTVCR_RAM_SIZE) {
+ cdtvcr_battram_write(addr - CDTVCR_RAM_OFFSET, v);
+ } else if (addr >= CDTVCR_CLOCK && addr < CDTVCR_CLOCK + 0x20) {
+ int reg = addr - CDTVCR_CLOCK;
+ switch (reg)
+ {
+ case 0:
+ cdtvcr_clock[0] = v;
+ case 1:
+ cdtvcr_clock[1] = v;
+ break;
+ }
+ } else {
+ switch(addr)
+ {
+ case CDTVCR_RESET:
+ cdtvcr_4510_reset(v);
+ break;
+ }
+ }
+ if (addr >= 0xc00 && addr < CDTVCR_RAM_OFFSET) {
+ switch (addr)
+ {
+ case CDTVCR_KEYCMD:
+ {
+ uae_u8 keycode = cdtvcr_4510_ram[CDTVCR_KEYCMD + 1];
+ write_log(_T("Got keycode %x\n"), keycode);
+ cdtvcr_4510_ram[CDTVCR_KEYCMD + 1] = 0;
+ switch(keycode)
+ {
+ case 0x73: // PLAY
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] >= 3) {
+ cdtvcr_player_pause();
+ } else {
+ cdtvcr_player_play();
+ }
+ break;
+ case 0x72: // STOP
+ cdtvcr_player_stop();
+ break;
+ case 0x74: // <-
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT] > 0) {
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT]--;
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] >= 3) {
+ cdtvcr_player_play();
+ }
+ }
+ break;
+ case 0x75: // ->
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT] < cdtvcr_4510_ram[CDTVCR_PLAYLIST_ENTRIES] - 1) {
+ cdtvcr_4510_ram[CDTVCR_PLAYLIST_CURRENT]++;
+ if (cdtvcr_4510_ram[CDTVCR_PLAYLIST_STATE] >= 3) {
+ cdtvcr_player_play();
+ }
+ }
+ break;
+ }
+ v = 0;
+ break;
+ }
+ }
+ cdtvcr_4510_ram[addr] = v;
+
+ if (addr >= 0xc80)
+ write_log(_T("%04x %02x\n"), addr, v);
+
+ }
+}
+
+static uae_u8 cdtvcr_bget2 (uaecptr addr)
+{
+ uae_u8 v = 0;
+ addr &= CDTVCR_MASK;
+ if (addr < CDTVCR_RAM_OFFSET) {
+ v = cdtvcr_4510_ram[addr];
+ }
+ if (addr >= CDTVCR_RAM_OFFSET && addr < CDTVCR_RAM_OFFSET + CDTVCR_RAM_SIZE) {
+ v = cdtvcr_battram_read(addr - CDTVCR_RAM_OFFSET);
+ } else if (addr >= CDTVCR_CLOCK && addr < CDTVCR_CLOCK + 0x20) {
+ int reg = addr - CDTVCR_CLOCK;
+ int days, mins, ticks;
+ int tickcount = currprefs.ntscmode ? 60 : 50;
+ struct timeval tv;
+ struct mytimeval mtv;
+ gettimeofday (&tv, NULL);
+ tv.tv_sec -= _timezone;
+ mtv.tv_sec = tv.tv_sec;
+ mtv.tv_usec = tv.tv_usec;
+ timeval_to_amiga(&mtv, &days, &mins, &ticks, tickcount);
+ switch (reg)
+ {
+ case 0:
+ case 1:
+ v = cdtvcr_clock[reg];
+ break;
+ case 2:
+ v = days >> 8;
+ break;
+ case 3:
+ v = days;
+ break;
+ case 4:
+ v = mins / 60;
+ break;
+ case 5:
+ v = mins % 60;
+ break;
+ case 6:
+ v = ticks / tickcount;
+ break;
+ case 7:
+ v = ticks % tickcount;
+ break;
+ case 8:
+ v = tickcount;
+ break;
+
+ }
+ } else {
+ switch(addr)
+ {
+ case CDTVCR_RESET:
+ v = 0;
+ break;
+ }
+ }
+ return v;
+}
+
+static uae_u32 REGPARAM2 cdtvcr_lget (uaecptr addr)
+{
+ uae_u32 v;
+ v = (cdtvcr_bget2 (addr) << 24) | (cdtvcr_bget2 (addr + 1) << 16) |
+ (cdtvcr_bget2 (addr + 2) << 8) | (cdtvcr_bget2 (addr + 3));
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_lget %08X=%08X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static uae_u32 REGPARAM2 cdtvcr_wgeti (uaecptr addr)
+{
+ uae_u32 v = 0xffff;
+ return v;
+}
+static uae_u32 REGPARAM2 cdtvcr_lgeti (uaecptr addr)
+{
+ uae_u32 v = 0xffff;
+ return v;
+}
+
+static uae_u32 REGPARAM2 cdtvcr_wget (uaecptr addr)
+{
+ uae_u32 v;
+ v = (cdtvcr_bget2 (addr) << 8) | cdtvcr_bget2 (addr + 1);
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_wget %08X=%04X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static uae_u32 REGPARAM2 cdtvcr_bget (uaecptr addr)
+{
+ uae_u32 v;
+ v = cdtvcr_bget2 (addr);
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_bget %08X=%02X PC=%08X\n"), addr, v, M68K_GETPC);
+#endif
+ return v;
+}
+
+static void REGPARAM2 cdtvcr_lput (uaecptr addr, uae_u32 l)
+{
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_lput %08X=%08X PC=%08X\n"), addr, l, M68K_GETPC);
+#endif
+ cdtvcr_bput2 (addr, l >> 24);
+ cdtvcr_bput2 (addr + 1, l >> 16);
+ cdtvcr_bput2 (addr + 2, l >> 8);
+ cdtvcr_bput2 (addr + 3, l);
+}
+
+static void REGPARAM2 cdtvcr_wput (uaecptr addr, uae_u32 w)
+{
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_wput %08X=%04X PC=%08X\n"), addr, w & 65535, M68K_GETPC);
+#endif
+ cdtvcr_bput2 (addr, w >> 8);
+ cdtvcr_bput2 (addr + 1, w);
+}
+
+static void REGPARAM2 cdtvcr_bput (uaecptr addr, uae_u32 b)
+{
+#if CDTVCR_DEBUG
+ if (cdtvcr_debug(addr))
+ write_log (_T("cdtvcr_bput %08X=%02X PC=%08X\n"), addr, b & 255, M68K_GETPC);
+#endif
+ cdtvcr_bput2 (addr, b);
+}
+
+
+static addrbank cdtvcr_bank = {
+ cdtvcr_lget, cdtvcr_wget, cdtvcr_bget,
+ cdtvcr_lput, cdtvcr_wput, cdtvcr_bput,
+ default_xlate, default_check, NULL, NULL, _T("CDTV-CR"),
+ cdtvcr_wgeti,
+ ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
+};
+
+static int dev_thread (void *p)
+{
+ write_log (_T("CDTV-CR: CD thread started\n"));
+ thread_alive = 1;
+ for (;;) {
+
+ uae_u32 b = read_comm_pipe_u32_blocking (&requests);
+ if (b == 0xffff) {
+ thread_alive = -1;
+ return 0;
+ }
+ if (unitnum < 0)
+ continue;
+ switch (b)
+ {
+ case 0x0100:
+ cdtvcr_do_cmd();
+ break;
+ case 0x0101:
+ {
+ int m = ismedia ();
+ if (m < 0) {
+ write_log (_T("CDTV: device %d lost\n"), unitnum);
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~(4 | 8);
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x10 | 8;
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 0;
+ } else if (m != cdtvcr_media) {
+ cdtvcr_media = m;
+ get_toc ();
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 0x10 | 8;
+ if (cdtvcr_media) {
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 2;
+ } else {
+ cdtvcr_4510_ram[CDTVCR_CD_STATE] = 1;
+ cdtvcr_4510_ram[CDTVCR_SYS_STATE] &= ~(4 | 8);
+ }
+ }
+ if (cdtvcr_media)
+ get_qcode ();
+ }
+ break;
+ }
+ }
+}
+
+static void CDTVCR_hsync_handler (void)
+{
+ static int subqcnt, readcnt;
+
+ if (!currprefs.cs_cdtvcr)
+ return;
+
+#if CDTVCR_4510_EMULATION
+ for (int i = 0; i < 10; i++) {
+ cpu_4510();
+ }
+#endif
+
+ if (cdtvcr_wait_sectors > 0 && currprefs.cd_speed == 0) {
+ cdtvcr_wait_sectors = 0;
+ cdtvcr_cmd_done();
+ }
+ readcnt--;
+ if (readcnt <= 0) {
+ int cdspeed = cdtvcr_4510_ram[CDTVCR_CD_SPEED] ? 150 : 75;
+ readcnt = (int)(maxvpos * vblank_hz / cdspeed);
+ if (cdtvcr_wait_sectors > 0) {
+ cdtvcr_wait_sectors--;
+ if (cdtvcr_wait_sectors == 0)
+ cdtvcr_cmd_done();
+ }
+ }
+ subqcnt--;
+ if (subqcnt <= 0) {
+ write_comm_pipe_u32 (&requests, 0x0101, 1);
+ subqcnt = (int)(maxvpos * vblank_hz / 75 - 1);
+ if (subcodebufferoffset != subcodebufferoffsetw) {
+ uae_sem_wait (&sub_sem);
+ cdtvcr_4510_ram[CDTVCR_SUBBANK] = cdtvcr_4510_ram[CDTVCR_SUBBANK] ? 0 : SUB_CHANNEL_SIZE + 2;
+ uae_u8 *d = &cdtvcr_4510_ram[CDTVCR_SUBC];
+ d[cdtvcr_4510_ram[CDTVCR_SUBBANK] + SUB_CHANNEL_SIZE + 0] = 0x1f;
+ d[cdtvcr_4510_ram[CDTVCR_SUBBANK] + SUB_CHANNEL_SIZE + 1] = 0x3d;
+ for (int i = 0; i < SUB_CHANNEL_SIZE; i++) {
+ d[cdtvcr_4510_ram[CDTVCR_SUBBANK] + i] = subcodebuffer[subcodebufferoffset * SUB_CHANNEL_SIZE + i] & 0x3f;
+ }
+ subcodebufferinuse[subcodebufferoffset] = 0;
+ subcodebufferoffset++;
+ if (subcodebufferoffset >= MAX_SUBCODEBUFFER)
+ subcodebufferoffset -= MAX_SUBCODEBUFFER;
+ uae_sem_post (&sub_sem);
+ if (cdtvcr_4510_ram[CDTVCR_CD_SUBCODES])
+ cdtvcr_4510_ram[CDTVCR_INTREQ] |= 2;
+ } else if (cdtvcr_4510_ram[CDTVCR_CD_SUBCODES] && !cdtvcr_4510_ram[CDTVCR_CD_PLAYING]) {
+ // want subcodes but not playing?
+ // just return fake stuff, for some reason cdtv-cr driver requires something
+ // that looks valid, even when not playing or it gets stuck in infinite loop
+ uae_u8 dst[SUB_CHANNEL_SIZE];
+ // regenerate Q-subchannel
+ uae_u8 *s = dst + 12;
+ struct cd_toc *cdtoc = &toc.toc[toc.first_track];
+ int sector = 150;
+ memset (dst, 0, SUB_CHANNEL_SIZE);
+ s[0] = (cdtoc->control << 4) | (cdtoc->adr << 0);
+ s[1] = tobcd (cdtoc->track);
+ s[2] = tobcd (1);
+ int msf = lsn2msf (sector);
+ tolongbcd (s + 7, msf);
+ msf = lsn2msf (sector - cdtoc->address - 150);
+ tolongbcd (s + 3, msf);
+ setsubchannel(dst);
+ }
+ }
+
+ if (cdtvcr_wait_sectors)
+ cd_led |= LED_CD_ACTIVE;
+ else
+ cd_led &= ~LED_CD_ACTIVE;
+ if ((cd_led & ~LED_CD_ACTIVE2) && !cdtvcr_4510_ram[CDTVCR_CD_PLAYING])
+ gui_flicker_led(LED_CD, 0, cd_led);
+
+ rethink_cdtvcr();
+}
+
+static void open_unit (void)
+{
+ struct device_info di;
+ unitnum = get_standard_cd_unit (CD_STANDARD_UNIT_CDTV);
+ sys_command_info (unitnum, &di, 0);
+ write_log (_T("using drive %s (unit %d, media %d)\n"), di.label, unitnum, di.media_inserted);
+}
+
+static void close_unit (void)
+{
+ if (unitnum >= 0)
+ sys_command_close (unitnum);
+ unitnum = -1;
+}
+
+static void cdtvcr_reset(int hardreset)
+{
+ if (!currprefs.cs_cdtvcr)
+ return;
+ close_unit ();
+ if (!thread_alive) {
+ init_comm_pipe (&requests, 100, 1);
+ uae_start_thread (_T("cdtv-cr"), dev_thread, NULL, NULL);
+ while (!thread_alive)
+ sleep_millis (10);
+ uae_sem_init (&sub_sem, 0, 1);
+ }
+ open_unit ();
+ gui_flicker_led (LED_CD, 0, -1);
+
+ cdtvcr_4510_reset(0);
+ cdtvcr_battram_reset();
+ cdtvcr_clock[0] = 0xe3;
+ cdtvcr_clock[1] = 0x1b;
+
+#if CDTVCR_4510_EMULATION
+ init_65c02();
+#endif
+}
+
+static void cdtvcr_free(void)
+{
+ if (thread_alive > 0) {
+ write_comm_pipe_u32 (&requests, 0xffff, 1);
+ while (thread_alive > 0)
+ sleep_millis (10);
+ uae_sem_destroy (&sub_sem);
+ }
+ thread_alive = 0;
+ close_unit ();
+}
+
+bool cdtvcr_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xb80000;
+ aci->size = 0x10000;
+ aci->zorro = 0;
+ device_add_reset(cdtvcr_reset);
+ if (!aci->doinit)
+ return true;
+ map_banks(&cdtvcr_bank, 0xB8, 1, 0);
+
+ device_add_hsync(CDTVCR_hsync_handler);
+ device_add_rethink(rethink_cdtvcr);
+ device_add_exit(cdtvcr_free);
+
+ return true;
+}
+
+#if CDTVCR_4510_EMULATION
+
+// VICE 65C02 emulator, waiting for future full CDTV-CR 4510 emulation.
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int CLOCK;
+
+static void cpu65c02_reset(void)
+{
+}
+
+#define CLOCK_MAX (~((CLOCK)0))
+#define TRAP_OPCODE 0x02
+#define STATIC_ASSERT(_x)
+
+#define NUM_MEMSPACES e_invalid_space
+
+enum mon_int {
+ MI_NONE = 0,
+ MI_BREAK = 1 << 0,
+ MI_WATCH = 1 << 1,
+ MI_STEP = 1 << 2
+};
+
+enum t_memspace {
+ e_default_space = 0,
+ e_comp_space,
+ e_disk8_space,
+ e_disk9_space,
+ e_disk10_space,
+ e_disk11_space,
+ e_invalid_space
+};
+typedef enum t_memspace MEMSPACE;
+static unsigned monitor_mask[NUM_MEMSPACES];
+static void monitor_check_icount_interrupt(void)
+{
+}
+static void monitor_check_icount(WORD a)
+{
+}
+static int monitor_force_import(int mem)
+{
+ return 0;
+}
+static int monitor_check_breakpoints(int mem, WORD addr)
+{
+ return 0;
+}
+static void monitor_check_watchpoints(unsigned int lastpc, unsigned int pc)
+{
+}
+static void monitor_startup(int mem)
+{
+}
+
+#define CYCLE_EXACT_ALARM
+
+#define INTERRUPT_DELAY 2
+
+#define INTRRUPT_MAX_DMA_PER_OPCODE (7+10000)
+
+enum cpu_int {
+ IK_NONE = 0,
+ IK_NMI = 1 << 0,
+ IK_IRQ = 1 << 1,
+ IK_RESET = 1 << 2,
+ IK_TRAP = 1 << 3,
+ IK_MONITOR = 1 << 4,
+ IK_DMA = 1 << 5,
+ IK_IRQPEND = 1 << 6
+};
+
+struct interrupt_cpu_status_s {
+ /* Number of interrupt lines. */
+ unsigned int num_ints;
+
+ /* Define, for each interrupt source, whether it has a pending interrupt
+ (IK_IRQ, IK_NMI, IK_RESET and IK_TRAP) or not (IK_NONE). */
+ unsigned int *pending_int;
+
+ /* Name for each interrupt source */
+ char **int_name;
+
+ /* Number of active IRQ lines. */
+ int nirq;
+
+ /* Tick when the IRQ was triggered. */
+ CLOCK irq_clk;
+
+ /* Number of active NMI lines. */
+ int nnmi;
+
+ /* Tick when the NMI was triggered. */
+ CLOCK nmi_clk;
+
+ /* If an opcode is intercepted by a DMA, save the number of cycles
+ left at the start of this particular DMA (needed by *_set_irq() to
+ calculate irq_clk). */
+ unsigned int num_dma_per_opcode;
+ unsigned int num_cycles_left[INTRRUPT_MAX_DMA_PER_OPCODE];
+ CLOCK dma_start_clk[INTRRUPT_MAX_DMA_PER_OPCODE];
+
+ /* counters for delay between interrupt request and handler */
+ unsigned int irq_delay_cycles;
+ unsigned int nmi_delay_cycles;
+
+ /* If 1, do a RESET. */
+ int reset;
+
+ /* If 1, call the trapping function. */
+ int trap;
+
+ /* Debugging function. */
+ void(*trap_func)(WORD, void *data);
+
+ /* Data to pass to the debugging function when called. */
+ void *trap_data;
+
+ /* Pointer to the last executed opcode information. */
+ unsigned int *last_opcode_info_ptr;
+
+ /* Number of cycles we have stolen to the processor last time. */
+ int num_last_stolen_cycles;
+
+ /* Clock tick at which these cycles have been stolen. */
+ CLOCK last_stolen_cycles_clk;
+
+ /* Clock tick where just ACK'd IRQs may still trigger an interrupt.
+ Set to CLOCK_MAX when irrelevant. */
+ CLOCK irq_pending_clk;
+
+ unsigned int global_pending_int;
+
+ void(*nmi_trap_func)(void);
+
+ void(*reset_trap_func)(void);
+};
+typedef struct interrupt_cpu_status_s interrupt_cpu_status_t;
+
+/* Masks to extract information. */
+#define OPINFO_DELAYS_INTERRUPT_MSK (1 << 8)
+#define OPINFO_DISABLES_IRQ_MSK (1 << 9)
+#define OPINFO_ENABLES_IRQ_MSK (1 << 10)
+
+/* Return nonzero if `opinfo' causes a 1-cycle interrupt delay. */
+#define OPINFO_DELAYS_INTERRUPT(opinfo) \
+ ((opinfo) & OPINFO_DELAYS_INTERRUPT_MSK)
+
+/* Return nonzero if `opinfo' has changed the I flag from 0 to 1, so that an
+IRQ that happened 2 or more cycles before the end of the opcode should be
+allowed. */
+#define OPINFO_DISABLES_IRQ(opinfo) \
+ ((opinfo) & OPINFO_DISABLES_IRQ_MSK)
+
+/* Return nonzero if `opinfo' has changed the I flag from 1 to 0, so that an
+IRQ that happened 2 or more cycles before the end of the opcode should not
+be allowed. */
+#define OPINFO_ENABLES_IRQ(opinfo) \
+ ((opinfo) & OPINFO_ENABLES_IRQ_MSK)
+
+/* Set the information for `opinfo'. `number' is the opcode number,
+`delays_interrupt' must be non-zero if it causes a 1-cycle interrupt
+delay, `disables_interrupts' must be non-zero if it disabled IRQs. */
+#define OPINFO_SET(opinfo, \
+ number, delays_interrupt, disables_irq, enables_irq) \
+ ((opinfo) = ((number) \
+ | ((delays_interrupt) ? OPINFO_DELAYS_INTERRUPT_MSK : 0) \
+ | ((disables_irq) ? OPINFO_DISABLES_IRQ_MSK : 0) \
+ | ((enables_irq) ? OPINFO_ENABLES_IRQ_MSK : 0)))
+
+/* Set whether the opcode causes the 1-cycle interrupt delay according to
+`delay'. */
+#define OPINFO_SET_DELAYS_INTERRUPT(opinfo, delay) \
+ do { \
+ if ((delay)) \
+ (opinfo) |= OPINFO_DELAYS_INTERRUPT_MSK; \
+ } while (0)
+
+/* Set whether the opcode disables previously enabled IRQs according to
+`disable'. */
+#define OPINFO_SET_DISABLES_IRQ(opinfo, disable) \
+ do { \
+ if ((disable)) \
+ (opinfo) |= OPINFO_DISABLES_IRQ_MSK; \
+ } while (0)
+
+/* Set whether the opcode enables previously disabled IRQs according to
+`enable'. */
+#define OPINFO_SET_ENABLES_IRQ(opinfo, enable) \
+ do { \
+ if ((enable)) \
+ (opinfo) |= OPINFO_ENABLES_IRQ_MSK; \
+ } while (0)
+
+
+
+typedef struct mos6510_regs_s {
+ unsigned int pc; /* `unsigned int' required by the drive code. */
+ BYTE a;
+ BYTE x;
+ BYTE y;
+ BYTE sp;
+ BYTE p;
+ BYTE n;
+ BYTE z;
+} mos6510_regs_t;
+
+typedef struct R65C02_regs_s
+{
+ unsigned int pc;
+ BYTE a;
+ BYTE x;
+ BYTE y;
+ BYTE sp;
+ BYTE p;
+ BYTE n;
+ BYTE z;
+} R65C02_regs_t;
+
+#define DRIVE_RAM_SIZE 65536
+
+typedef BYTE drive_read_func_t(struct drive_context_s *, WORD);
+typedef void drive_store_func_t(struct drive_context_s *, WORD,
+ BYTE);
+
+typedef struct drivecpud_context_s {
+ /* Drive RAM */
+ BYTE drive_ram[DRIVE_RAM_SIZE];
+
+ /* functions */
+ drive_read_func_t *read_func[0x101];
+ drive_store_func_t *store_func[0x101];
+// drive_read_func_t *read_func_watch[0x101];
+// drive_store_func_t *store_func_watch[0x101];
+// drive_read_func_t *read_func_nowatch[0x101];
+// drive_store_func_t *store_func_nowatch[0x101];
+
+ int sync_factor;
+} drivecpud_context_t;
+
+typedef struct drive_context_s {
+ int mynumber; /* init to [0123] */
+ CLOCK *clk_ptr; /* shortcut to drive_clk[mynumber] */
+
+ struct drivecpu_context_s *cpu;
+ struct drivecpud_context_s *cpud;
+ struct drivefunc_context_s *func;
+} drive_context_t;
+
+static int drive_trap_handler(drive_context_t *d)
+{
+ return -1;
+}
+
+typedef struct drivecpu_context_s
+{
+ int traceflg;
+ /* This is non-zero each time a Read-Modify-Write instructions that accesses
+ memory is executed. We can emulate the RMW bug of the 6502 this way. */
+ int rmw_flag; /* init to 0 */
+
+ /* Interrupt/alarm status. */
+ struct interrupt_cpu_status_s *int_status;
+
+ struct alarm_context_s *alarm_context;
+
+ /* Clk guard. */
+ struct clk_guard_s *clk_guard;
+
+ struct monitor_interface_s *monitor_interface;
+
+ /* Value of clk for the last time mydrive_cpu_execute() was called. */
+ CLOCK last_clk;
+
+ /* Number of cycles in excess we executed last time mydrive_cpu_execute()
+ was called. */
+ CLOCK last_exc_cycles;
+
+ CLOCK stop_clk;
+
+ CLOCK cycle_accum;
+ BYTE *d_bank_base;
+ unsigned int d_bank_start;
+ unsigned int d_bank_limit;
+
+ /* Information about the last executed opcode. */
+ unsigned int last_opcode_info;
+
+ /* Address of the last executed opcode. This is used by watchpoints. */
+ unsigned int last_opcode_addr;
+
+ /* Public copy of the registers. */
+ mos6510_regs_t cpu_regs;
+// R65C02_regs_t cpu_R65C02_regs;
+
+ BYTE *pageone; /* init to NULL */
+
+ int monspace; /* init to e_disk[89]_space */
+
+ char *snap_module_name;
+
+ char *identification_string;
+} drivecpu_context_t;
+
+#define LOAD(a) (drv->cpud->read_func[(a) >> 8](drv, (WORD)(a)))
+#define LOAD_ZERO(a) (drv->cpud->read_func[0](drv, (WORD)(a)))
+#define LOAD_ADDR(a) (LOAD(a) | (LOAD((a) + 1) << 8))
+#define LOAD_ZERO_ADDR(a) (LOAD_ZERO(a) | (LOAD_ZERO((a) + 1) << 8))
+#define STORE(a, b) (drv->cpud->store_func[(a) >> 8](drv, (WORD)(a), \
+ (BYTE)(b)))
+#define STORE_ZERO(a, b) (drv->cpud->store_func[0](drv, (WORD)(a), \
+ (BYTE)(b)))
+
+#define JUMP(addr) reg_pc = (unsigned int)(addr);
+
+#define P_SIGN 0x80
+#define P_OVERFLOW 0x40
+#define P_UNUSED 0x20
+#define P_BREAK 0x10
+#define P_DECIMAL 0x08
+#define P_INTERRUPT 0x04
+#define P_ZERO 0x02
+#define P_CARRY 0x01
+
+#define CPU_WDC65C02 0
+#define CPU_R65C02 1
+#define CPU_65SC02 2
+
+#define CLK (*(drv->clk_ptr))
+#define RMW_FLAG (cpu->rmw_flag)
+#define PAGE_ONE (cpu->pageone)
+#define LAST_OPCODE_INFO (cpu->last_opcode_info)
+#define LAST_OPCODE_ADDR (cpu->last_opcode_addr)
+#define TRACEFLG (debug.drivecpu_traceflg[drv->mynumber])
+
+#define CPU_INT_STATUS (cpu->int_status)
+
+#define ALARM_CONTEXT (cpu->alarm_context)
+
+#define ROM_TRAP_ALLOWED() 1
+
+#define ROM_TRAP_HANDLER() drive_trap_handler(drv)
+
+#define CALLER (cpu->monspace)
+
+#define DMA_FUNC drive_generic_dma()
+
+#define DMA_ON_RESET
+
+#define cpu_reset() (cpu_reset)(drv)
+#define bank_limit (cpu->d_bank_limit)
+#define bank_start (cpu->d_bank_start)
+#define bank_base (cpu->d_bank_base)
+
+/* WDC_STP() and WDC_WAI() are not used on the R65C02. */
+#define WDC_STP()
+#define WDC_WAI()
+
+#define GLOBAL_REGS cpu->cpu_R65C02_regs
+
+#define DRIVE_CPU
+
+static void drive_generic_dma(void)
+{
+}
+static void interrupt_trigger_dma(interrupt_cpu_status_t *cs, CLOCK cpu_clk)
+{
+ cs->global_pending_int = (enum cpu_int)
+ (cs->global_pending_int | IK_DMA);
+}
+static void interrupt_ack_dma(interrupt_cpu_status_t *cs)
+{
+ cs->global_pending_int = (enum cpu_int)
+ (cs->global_pending_int & ~IK_DMA);
+}
+static void interrupt_do_trap(interrupt_cpu_status_t *cs, WORD address)
+{
+ cs->global_pending_int &= ~IK_TRAP;
+ cs->trap_func(address, cs->trap_data);
+}
+static void interrupt_ack_reset(interrupt_cpu_status_t *cs)
+{
+ cs->global_pending_int &= ~IK_RESET;
+
+ if (cs->reset_trap_func)
+ cs->reset_trap_func();
+}
+static void interrupt_ack_nmi(interrupt_cpu_status_t *cs)
+{
+ cs->global_pending_int =
+ (cs->global_pending_int & ~IK_NMI);
+
+ if (cs->nmi_trap_func) {
+ cs->nmi_trap_func();
+ }
+}
+static void interrupt_ack_irq(interrupt_cpu_status_t *cs)
+{
+ cs->global_pending_int =
+ (cs->global_pending_int & ~IK_IRQPEND);
+ cs->irq_pending_clk = CLOCK_MAX;
+}
+static int interrupt_check_nmi_delay(interrupt_cpu_status_t *cs,
+ CLOCK cpu_clk)
+{
+ CLOCK nmi_clk = cs->nmi_clk + INTERRUPT_DELAY;
+
+ /* Branch instructions delay IRQs and NMI by one cycle if branch
+ is taken with no page boundary crossing. */
+ if (OPINFO_DELAYS_INTERRUPT(*cs->last_opcode_info_ptr))
+ nmi_clk++;
+
+ if (cpu_clk >= nmi_clk)
+ return 1;
+
+ return 0;
+}
+static int interrupt_check_irq_delay(interrupt_cpu_status_t *cs,
+ CLOCK cpu_clk)
+{
+ CLOCK irq_clk = cs->irq_clk + INTERRUPT_DELAY;
+
+ /* Branch instructions delay IRQs and NMI by one cycle if branch
+ is taken with no page boundary crossing. */
+ if (OPINFO_DELAYS_INTERRUPT(*cs->last_opcode_info_ptr))
+ irq_clk++;
+
+ /* If an opcode changes the I flag from 1 to 0, the 6510 needs
+ one more opcode before it triggers the IRQ routine. */
+ if (cpu_clk >= irq_clk) {
+ if (!OPINFO_ENABLES_IRQ(*cs->last_opcode_info_ptr)) {
+ return 1;
+ } else {
+ cs->global_pending_int |= IK_IRQPEND;
+ }
+ }
+ return 0;
+}
+
+struct alarm_context_s {
+ CLOCK next_pending_alarm_clk;
+};
+typedef struct alarm_context_s alarm_context_t;
+
+static void alarm_context_dispatch(alarm_context_t *context, CLOCK cpu_clk)
+{
+}
+static CLOCK alarm_context_next_pending_clk(alarm_context_t *context)
+{
+ return context->next_pending_alarm_clk;
+}
+
+static struct drive_context_s m_4510_context;
+static struct drivecpu_context_s m_4510_cpu_context;
+static struct drivecpud_context_s m_4510_cpud_context;
+static CLOCK m_4510_clk;
+static struct alarm_context_s m_4510_alarm_context;
+static struct interrupt_cpu_status_s m_4510_interrupt;
+
+static void cpu_4510(void)
+{
+ int cpu_type = CPU_R65C02;
+ drivecpu_context_t *cpu = &m_4510_cpu_context;
+ drive_context_t *drv = &m_4510_context;
+
+#define reg_a (cpu->cpu_regs.a)
+#define reg_x (cpu->cpu_regs.x)
+#define reg_y (cpu->cpu_regs.y)
+#define reg_pc (cpu->cpu_regs.pc)
+#define reg_sp (cpu->cpu_regs.sp)
+#define reg_p (cpu->cpu_regs.p)
+#define flag_z (cpu->cpu_regs.z)
+#define flag_n (cpu->cpu_regs.n)
+
+#include "65c02core.cpp"
+}
+
+BYTE read_4510(struct drive_context_s *c, WORD offset)
+{
+ if (offset >= 32768)
+ return c->cpud->drive_ram[offset];
+ return 0;
+}
+void write_4510(struct drive_context_s *c, WORD offset, BYTE v)
+{
+ if (offset >= 32768)
+ return;
+ c->cpud->drive_ram[offset] = v;
+}
+
+static void init_65c02(void)
+{
+ drive_context_s *d = &m_4510_context;
+ drivecpu_context_s *cpu = &m_4510_cpu_context;
+ drivecpud_context_s *cpud = &m_4510_cpud_context;
+
+ d->cpu = cpu;
+ d->cpud = cpud;
+ d->clk_ptr = &m_4510_clk;
+
+ cpu->rmw_flag = 0;
+ cpu->d_bank_limit = 0;
+ cpu->d_bank_start = 0;
+ cpu->pageone = NULL;
+ cpu->alarm_context = &m_4510_alarm_context;
+ cpu->int_status = &m_4510_interrupt;
+
+ cpu->int_status->global_pending_int = IK_RESET;
+
+ for(int i = 0; i < 256; i++) {
+ cpud->read_func[i] = read_4510;
+ cpud->store_func[i] = write_4510;
+ }
+
+ struct zfile *zf = read_rom_name(_T("d:\\amiga\\roms\\cdtv-cr-4510.bin"));
+ if (zf) {
+ zfile_fread(cpud->drive_ram + 32768, 1, 32768, zf);
+ zfile_fclose(zf);
+ }
+}
+
+#endif
diff --git a/src/cfgfile.cpp b/src/cfgfile.cpp
index 9b91bd56..548075d3 100644
--- a/src/cfgfile.cpp
+++ b/src/cfgfile.cpp
@@ -10,13 +10,15 @@
#include "sysconfig.h"
#include "sysdeps.h"
+#include
+
#include "options.h"
-#include "memory.h"
#include "uae.h"
#include "audio.h"
#include "custom.h"
#include "inputdevice.h"
#include "savestate.h"
+#include "memory.h"
#include "autoconf.h"
#include "rommgr.h"
#include "gui.h"
@@ -33,14 +35,14 @@
#define cfgfile_warning_obsolete write_log
static int config_newfilesystem;
-static struct strlist* temp_lines;
-static struct strlist* error_lines;
+static struct strlist *temp_lines;
+static struct strlist *error_lines;
static struct zfile *default_file, *configstore;
static int uaeconfig;
static int unicode_config = 0;
/* @@@ need to get rid of this... just cut part of the manual and print that
- * as a help text. */
+* as a help text. */
struct cfg_lines
{
const TCHAR *config_label, *config_help;
@@ -129,7 +131,7 @@ static const TCHAR *linemode[] = {
_T("double3"), _T("scanlines3"), _T("scanlines3p2"), _T("scanlines3p3"),
nullptr
};
-static const TCHAR* speedmode[] = {_T("max"), _T("real"), _T("turbo"), nullptr};
+static const TCHAR* speedmode[] = {_T("max"), _T("real"), nullptr};
static const TCHAR* colormode1[] = { _T("8bit"), _T("15bit"), _T("16bit"), _T("8bit_dither"), _T("4bit_dither"), _T("32bit"), 0 };
static const TCHAR* colormode2[] = { _T("8"), _T("15"), _T("16"), _T("8d"), _T("4d"), _T("32"), 0 };
static const TCHAR* soundmode1[] = {_T("none"), _T("interrupts"), _T("normal"), _T("exact"), nullptr};
@@ -239,11 +241,17 @@ struct hdcontrollerconfig
};
static const struct hdcontrollerconfig hdcontrollers[] = {
- {_T("uae"), 0},
- {_T("ide%d"), 0},
- {_T("ide%d_mainboard"), ROMTYPE_MB_IDE},
+ { _T("uae"), 0 },
- {nullptr}
+ { _T("ide%d"), 0 },
+ { _T("ide%d_mainboard"), ROMTYPE_MB_IDE },
+
+ { _T("scsi%d"), 0 },
+ { _T("scsi%d_a3000"), ROMTYPE_SCSI_A3000 },
+ { _T("scsi%d_a4000t"), ROMTYPE_SCSI_A4000T },
+ { _T("scsi%d_cdtv"), ROMTYPE_CDTVSCSI },
+
+ { NULL }
};
static const TCHAR* z3mapping[] = {
_T("auto"),
@@ -2286,6 +2294,10 @@ void cfgfile_save_options(struct zfile* f, struct uae_prefs* p, int type)
cfgfile_dwrite_bool(f, _T("cd32c2p"), p->cs_cd32c2p);
cfgfile_dwrite_bool(f, _T("cd32nvram"), p->cs_cd32nvram);
cfgfile_dwrite(f, _T("cd32nvram_size"), _T("%d"), p->cs_cd32nvram_size / 1024);
+ cfgfile_dwrite_bool(f, _T("cdtvcd"), p->cs_cdtvcd);
+ cfgfile_dwrite_bool(f, _T("cdtv-cr"), p->cs_cdtvcr);
+ cfgfile_dwrite_bool(f, _T("cdtvram"), p->cs_cdtvram);
+ cfgfile_dwrite_bool(f, _T("a1000ram"), p->cs_a1000ram);
cfgfile_dwrite(f, _T("fatgary"), _T("%d"), p->cs_fatgaryrev);
cfgfile_dwrite(f, _T("ramsey"), _T("%d"), p->cs_ramseyrev);
cfgfile_dwrite_bool(f, _T("pcmcia"), p->cs_pcmcia);
@@ -4449,6 +4461,18 @@ static int cfgfile_parse_hardware(struct uae_prefs* p, const TCHAR* option, TCHA
return 1;
}
+ //if (cfgfile_intval(option, value, _T("cdtvramcard"), &utmpval, 1)) {
+ // if (utmpval)
+ // addbcromtype(p, ROMTYPE_CDTVSRAM, true, NULL, 0);
+ // return 1;
+ //}
+
+ if (cfgfile_yesno(option, value, _T("scsi_cdtv"), &tmpval)) {
+ if (tmpval)
+ addbcromtype(p, ROMTYPE_CDTVSCSI, true, NULL, 0);
+ return 1;
+ }
+
if (cfgfile_yesno(option, value, _T("pcmcia"), &p->cs_pcmcia))
{
if (p->cs_pcmcia)
@@ -4777,7 +4801,22 @@ void cfgfile_compatibility_romtype(struct uae_prefs* p)
addbcromtype(p, ROMTYPE_MB_IDE, p->cs_ide != 0, nullptr, 0);
- addbcromtype(p, ROMTYPE_CD32CART, p->cs_cd32fmv, p->cartfile, 0);
+ if (p->cs_mbdmac == 1) {
+ addbcromtype(p, ROMTYPE_SCSI_A4000T, false, NULL, 0);
+ addbcromtype(p, ROMTYPE_SCSI_A3000, true, NULL, 0);
+ } else if (p->cs_mbdmac == 2) {
+ addbcromtype(p, ROMTYPE_SCSI_A3000, false, NULL, 0);
+ addbcromtype(p, ROMTYPE_SCSI_A4000T, true, NULL, 0);
+ } else {
+ addbcromtype(p, ROMTYPE_SCSI_A3000, false, NULL, 0);
+ addbcromtype(p, ROMTYPE_SCSI_A4000T, false, NULL, 0);
+ }
+
+ addbcromtype(p, ROMTYPE_CDTVDMAC, p->cs_cdtvcd && !p->cs_cdtvcr, NULL, 0);
+
+ addbcromtype(p, ROMTYPE_CDTVCR, p->cs_cdtvcr, NULL, 0);
+
+ addbcromtype(p, ROMTYPE_CD32CART, p->cs_cd32fmv, p->cartfile,0);
}
@@ -7169,6 +7208,7 @@ int built_in_chipset_prefs(struct uae_prefs* p)
return 1;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = false;
+ p->cs_cdtvcd = p->cs_cdtvram = p->cs_cdtvcr = 0;
p->cs_fatgaryrev = -1;
p->cs_ide = 0;
p->cs_ramseyrev = -1;
diff --git a/src/cia.cpp b/src/cia.cpp
index 80462502..947dbce3 100644
--- a/src/cia.cpp
+++ b/src/cia.cpp
@@ -21,6 +21,7 @@
#include "inputdevice.h"
#include "ar.h"
#include "akiko.h"
+#include "cdtv.h"
#include "audio.h"
#include "keyboard.h"
#include "rtc.h"
diff --git a/src/crc32.cpp b/src/crc32.cpp
index 6a722f36..200da20b 100644
--- a/src/crc32.cpp
+++ b/src/crc32.cpp
@@ -1,5 +1,5 @@
-#include
+#include "sysconfig.h"
#include "sysdeps.h"
#include "crc32.h"
diff --git a/src/custom.cpp b/src/custom.cpp
index 342c1685..428056fc 100644
--- a/src/custom.cpp
+++ b/src/custom.cpp
@@ -28,9 +28,11 @@
#include "xwin.h"
#include "inputdevice.h"
#include "autoconf.h"
+#include "traps.h"
#include "gui.h"
#include "picasso96.h"
#include "drawing.h"
+#include "savestate.h"
#include "ar.h"
#include "akiko.h"
#include "devices.h"
@@ -7817,20 +7819,20 @@ static void vsync_handler_post (void)
#ifdef AMIBERRY
eventtab[ev_copper].active = false;
#endif
- COPJMP(1, 1);
+ COPJMP (1, 1);
- init_hardware_frame();
+ init_hardware_frame ();
- vsync_cycles = get_cycles();
+ vsync_cycles = get_cycles ();
}
-static void copper_check(int n)
+static void copper_check (int n)
{
if (cop_state.state == COP_wait) {
int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
if (vp < cop_state.vcmp) {
if (copper_enabled_thisline)
- write_log(_T("COPPER BUG %d: vp=%d vpos=%d vcmp=%d thisline=%d\n"), n, vp, vpos, cop_state.vcmp, copper_enabled_thisline);
+ write_log (_T("COPPER BUG %d: vp=%d vpos=%d vcmp=%d thisline=%d\n"), n, vp, vpos, cop_state.vcmp, copper_enabled_thisline);
}
}
}
@@ -7989,7 +7991,7 @@ static void events_dmal (int hp)
{
if (!dmal)
return;
- if (currprefs.cpu_memory_cycle_exact) {
+ if (currprefs.cpu_compatible) {
while (dmal) {
if (dmal & 3)
break;
@@ -8085,9 +8087,9 @@ static void hsync_handler_pre (bool onvsync)
finish_decisions ();
if (thisline_decision.plfleft >= 0) {
if (currprefs.collision_level > 1)
- do_sprite_collisions();
+ do_sprite_collisions ();
if (currprefs.collision_level > 2)
- do_playfield_collisions();
+ do_playfield_collisions ();
}
hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
@@ -8267,7 +8269,7 @@ static void hsync_handler_post (bool onvsync)
if (currprefs.cpu_memory_cycle_exact || currprefs.blitter_cycle_exact) {
int hp = maxhpos - 1, i;
for (i = 0; i < 4; i++) {
- alloc_cycle(hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */
+ alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */
#ifdef DEBUGGER
if (debug_dma) {
uae_u16 strobe = 0x3c;
@@ -8279,7 +8281,7 @@ static void hsync_handler_post (bool onvsync)
strobe = 0x38;
else if ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) && lol)
strobe = 0x3e;
- record_dma(i == 0 ? strobe : 0x1fe, 0xffff, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i);
+ record_dma (i == 0 ? strobe : 0x1fe, 0xffff, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i);
}
#endif
hp += 2;
@@ -8288,16 +8290,17 @@ static void hsync_handler_post (bool onvsync)
}
}
#endif
-
+
events_dmal_hsync ();
if (!currprefs.cpu_thread && !cpu_sleepmode && currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) {
static int sleeps_remaining;
- if (is_last_line()) {
+ if (is_last_line ()) {
sleeps_remaining = (165 - currprefs.cpu_idle) / 6;
if (sleeps_remaining < 0)
sleeps_remaining = 0;
+ /* really last line, just run the cpu emulation until whole vsync time has been used */
if (regs.stopped && currprefs.cpu_idle) {
// CPU in STOP state: sleep if enough time left.
frame_time_t rpt = read_processor_time();
@@ -8315,7 +8318,6 @@ static void hsync_handler_post (bool onvsync)
//maybe_process_pull_audio();
}
else {
- /* really last line, just run the cpu emulation until whole vsync time has been used */
vsyncmintime = vsyncmaxtime; /* emulate if still time left */
is_syncline_end = read_processor_time() + vsynctimebase; /* far enough in future, we never wait that long */
is_syncline = -12;
diff --git a/src/devices.cpp b/src/devices.cpp
index 3d5b33a1..f99cc55d 100644
--- a/src/devices.cpp
+++ b/src/devices.cpp
@@ -7,6 +7,8 @@
#include "threaddep/thread.h"
#include "memory.h"
#include "audio.h"
+#include "scsi.h"
+#include "scsidev.h"
#ifdef CD32
#include "cd32_fmv.h"
#include "akiko.h"
@@ -153,7 +155,7 @@ void devices_reset(int hardreset)
memory_reset();
DISK_reset();
CIA_reset();
- //a1000_reset();
+ a1000_reset();
#ifdef JIT
compemu_reset();
#endif
diff --git a/src/disk.cpp b/src/disk.cpp
index 84f7e631..8c8a75f8 100644
--- a/src/disk.cpp
+++ b/src/disk.cpp
@@ -2036,11 +2036,13 @@ static void drive_fill_bigbuf (drive * drv, int force)
#ifdef CAPS
caps_loadtrack (drv->bigmfmbuf, drv->tracktiming, drv - floppy, tr, &drv->tracklen, &drv->multi_revolution, &drv->skipoffset, &drv->lastrev, retrytrack);
#endif
+
} else if (drv->filetype == ADF_SCP) {
#ifdef SCP
scp_loadtrack (drv->bigmfmbuf, drv->tracktiming, drv - floppy, tr, &drv->tracklen, &drv->multi_revolution, &drv->skipoffset, &drv->lastrev, retrytrack);
#endif
+
} else if (drv->filetype == ADF_FDI) {
#ifdef FDI2RAW
diff --git a/src/diskutil.cpp b/src/diskutil.cpp
index 391e8bb7..47ba93ad 100644
--- a/src/diskutil.cpp
+++ b/src/diskutil.cpp
@@ -1,17 +1,18 @@
-#include
+#include "sysconfig.h"
#include "sysdeps.h"
#include "crc32.h"
+#include "diskutil.h"
#define MFMMASK 0x55555555
-static uae_u32 getmfmlong(uae_u16 * mbuf)
+static uae_u32 getmfmlong (uae_u16 * mbuf)
{
return (uae_u32)(((*mbuf << 16) | *(mbuf + 1)) & MFMMASK);
}
#define FLOPPY_WRITE_LEN 6250
-static int drive_write_adf_amigados(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
+static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
{
int i;
uae_u32 odd, even, chksum, id, dlong;
@@ -34,20 +35,20 @@ static int drive_write_adf_amigados(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writeb
do {
while (*mbuf++ != 0x4489) {
if (mbuf >= mend) {
- write_log(_T("* track %d, unexpected end of data\n"), track);
+ write_log (_T("* track %d, unexpected end of data\n"), track);
return 1;
}
}
} while (*mbuf++ != 0x4489);
- odd = getmfmlong(mbuf);
- even = getmfmlong(mbuf + 2);
+ odd = getmfmlong (mbuf);
+ even = getmfmlong (mbuf + 2);
mbuf += 4;
id = (odd << 1) | even;
trackoffs = (id & 0xff00) >> 8;
if (trackoffs > 10) {
- write_log(_T("* track %d, corrupt sector number %d\n"), track, trackoffs);
+ write_log (_T("* track %d, corrupt sector number %d\n"), track, trackoffs);
goto next;
}
/* this sector is already ok? */
@@ -56,30 +57,30 @@ static int drive_write_adf_amigados(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writeb
chksum = odd ^ even;
for (i = 0; i < 4; i++) {
- odd = getmfmlong(mbuf);
- even = getmfmlong(mbuf + 8);
+ odd = getmfmlong (mbuf);
+ even = getmfmlong (mbuf + 8);
mbuf += 2;
dlong = (odd << 1) | even;
if (dlong) {
- write_log(_T("* track %d, sector %d header crc error\n"), track, trackoffs);
+ write_log (_T("* track %d, sector %d header crc error\n"), track, trackoffs);
goto next;
}
chksum ^= odd ^ even;
} /* could check here if the label is nonstandard */
mbuf += 8;
- odd = getmfmlong(mbuf);
- even = getmfmlong(mbuf + 2);
+ odd = getmfmlong (mbuf);
+ even = getmfmlong (mbuf + 2);
mbuf += 4;
if (((odd << 1) | even) != chksum || ((id & 0x00ff0000) >> 16) != (uae_u32)track) return 3;
- odd = getmfmlong(mbuf);
- even = getmfmlong(mbuf + 2);
+ odd = getmfmlong (mbuf);
+ even = getmfmlong (mbuf + 2);
mbuf += 4;
chksum = (odd << 1) | even;
secdata = secbuf + 32;
for (i = 0; i < 128; i++) {
- odd = getmfmlong(mbuf);
- even = getmfmlong(mbuf + 256);
+ odd = getmfmlong (mbuf);
+ even = getmfmlong (mbuf + 256);
mbuf += 2;
dlong = (odd << 1) | even;
*secdata++ = (uae_u8)(dlong >> 24);
@@ -90,13 +91,13 @@ static int drive_write_adf_amigados(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writeb
}
mbuf += 256;
if (chksum) {
- write_log(_T("* track %d, sector %d data crc error\n"), track, trackoffs);
+ write_log (_T("* track %d, sector %d data crc error\n"), track, trackoffs);
goto next;
}
- memcpy(writebuffer + trackoffs * 512, secbuf + 32, 512);
+ memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
writebuffer_ok[trackoffs] = 0xff;
continue;
- next:
+next:
mbuf += 8;
}
}
@@ -131,17 +132,17 @@ int isamigatrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writ
}
}
if (sync)
- return drive_write_adf_amigados(amigamfmbuffer, dst, writebuffer, writebuffer_ok, track, outsize);
+ return drive_write_adf_amigados (amigamfmbuffer, dst, writebuffer, writebuffer_ok, track, outsize);
return -1;
}
-static uae_u16 getmfmword(uae_u16 *mbuf, int shift)
+static uae_u16 getmfmword (uae_u16 *mbuf, int shift)
{
return (mbuf[0] << shift) | (mbuf[1] >> (16 - shift));
}
-static uae_u8 mfmdecode(uae_u16 **mfmp, int shift)
+static uae_u8 mfmdecode (uae_u16 **mfmp, int shift)
{
- uae_u16 mfm = getmfmword(*mfmp, shift);
+ uae_u16 mfm = getmfmword (*mfmp, shift);
uae_u8 out = 0;
int i;
@@ -156,7 +157,7 @@ static uae_u8 mfmdecode(uae_u16 **mfmp, int shift)
return out;
}
-static int drive_write_adf_pc(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsecs)
+static int drive_write_adf_pc (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsecs)
{
int sectors, shift, sector, i;
uae_u8 mark;
@@ -175,12 +176,12 @@ static int drive_write_adf_pc(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer,
*outsecs = sectors;
mfmcount = 0;
- while (getmfmword(mbuf, shift) != 0x4489) {
+ while (getmfmword (mbuf, shift) != 0x4489) {
mfmcount++;
if (mbuf >= mend) {
if (sectors >= 1)
return 0;
- write_log(_T("* track %d, unexpected end of data\n"), track);
+ write_log (_T("* track %d, unexpected end of data\n"), track);
return 1;
}
shift++;
@@ -192,7 +193,7 @@ static int drive_write_adf_pc(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer,
sector = -1;
}
mfmcount = 0;
- while (getmfmword(mbuf, shift) == 0x4489) {
+ while (getmfmword (mbuf, shift) == 0x4489) {
mfmcount++;
if (mbuf >= mend) {
if (sectors >= 1)
@@ -203,48 +204,48 @@ static int drive_write_adf_pc(uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer,
}
if (mfmcount < 3) // ignore if less than 3 sync markers
continue;
- mark = mfmdecode(&mbuf, shift);
+ mark = mfmdecode (&mbuf, shift);
if (mark == 0xfe) {
uae_u8 tmp[8];
uae_u8 cyl, head, size;
- cyl = mfmdecode(&mbuf, shift);
- head = mfmdecode(&mbuf, shift);
- sector = mfmdecode(&mbuf, shift);
- size = mfmdecode(&mbuf, shift);
- crc = (mfmdecode(&mbuf, shift) << 8) | mfmdecode(&mbuf, shift);
+ cyl = mfmdecode (&mbuf, shift);
+ head = mfmdecode (&mbuf, shift);
+ sector = mfmdecode (&mbuf, shift);
+ size = mfmdecode (&mbuf, shift);
+ crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
tmp[0] = 0xa1; tmp[1] = 0xa1; tmp[2] = 0xa1; tmp[3] = mark;
tmp[4] = cyl; tmp[5] = head; tmp[6] = sector; tmp[7] = size;
// skip 28 bytes
for (i = 0; i < 28; i++)
- mfmdecode(&mbuf, shift);
+ mfmdecode (&mbuf, shift);
- if (get_crc16(tmp, 8) != crc || cyl != track / 2 || head != (track & 1) || size != 2 || sector < 1 || sector > 20) {
- write_log(_T("PCDOS: track %d, corrupted sector header\n"), track);
+ if (get_crc16 (tmp, 8) != crc || cyl != track / 2 || head != (track & 1) || size != 2 || sector < 1 || sector > 20) {
+ write_log (_T("PCDOS: track %d, corrupted sector header\n"), track);
continue;
}
sector--;
continue;
}
if (mark != 0xfb && mark != 0xfa) {
- write_log(_T("PCDOS: track %d: unknown address mark %02X\n"), track, mark);
+ write_log (_T("PCDOS: track %d: unknown address mark %02X\n"), track, mark);
continue;
}
if (sector < 0) {
- write_log(_T("PCDOS: track %d: data mark without header\n"), track);
+ write_log (_T("PCDOS: track %d: data mark without header\n"), track);
continue;
}
for (i = 0; i < 512; i++)
- secbuf[i + 4] = mfmdecode(&mbuf, shift);
- crc = (mfmdecode(&mbuf, shift) << 8) | mfmdecode(&mbuf, shift);
- if (get_crc16(secbuf, 3 + 1 + 512) != crc) {
- write_log(_T("PCDOS: track %d, sector %d data checksum error\n"),
+ secbuf[i + 4] = mfmdecode (&mbuf, shift);
+ crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
+ if (get_crc16 (secbuf, 3 + 1 + 512) != crc) {
+ write_log (_T("PCDOS: track %d, sector %d data checksum error\n"),
track, sector + 1);
continue;
}
- memcpy(writebuffer + sector * 512, secbuf + 4, 512);
+ memcpy (writebuffer + sector * 512, secbuf + 4, 512);
sectors++;
sector = -1;
}
@@ -256,7 +257,7 @@ int ispctrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebu
int i, outsecs;
for (i = 0; i < len / 2; i++)
amigamfmbuffer[i] = mfmdata[i * 2 + 1] | (mfmdata[i * 2 + 0] << 8);
- i = drive_write_adf_pc(amigamfmbuffer, amigamfmbuffer + len / 2, writebuffer, writebuffer_ok, track, &outsecs);
+ i = drive_write_adf_pc (amigamfmbuffer, amigamfmbuffer + len / 2, writebuffer, writebuffer_ok, track, &outsecs);
*outsize = outsecs * 512;
if (*outsize < 9 * 512)
*outsize = 9 * 512;
diff --git a/src/drawing.cpp b/src/drawing.cpp
index 19414799..3f7f7e83 100644
--- a/src/drawing.cpp
+++ b/src/drawing.cpp
@@ -484,7 +484,7 @@ void check_custom_limits(void)
void set_custom_limits (int w, int h, int dx, int dy)
{
- struct gfx_filterdata* fd = &currprefs.gf[0];
+ struct gfx_filterdata *fd = &currprefs.gf[0];
int vls = visible_left_start;
int vrs = visible_right_stop;
int vts = visible_top_start;
@@ -796,6 +796,7 @@ STATIC_INLINE xcolnr getbgc (int blank)
return (blank >= 0 && (blank > 0 || hposblank || ce_is_borderblank(colors_for_drawing.extra))) ? 0 : colors_for_drawing.acolors[0];
}
+
static void set_res_shift(void)
{
int shift = lores_shift - bplres;
@@ -870,6 +871,7 @@ static void pfield_init_linetoscr (bool border)
// Sprite hpos don't include DIW_DDF_OFFSET and can appear 1 lores pixel
// before first bitplane pixel appears.
// This means "bordersprite" condition is possible under OCS/ECS too. Argh!
+
if (dip_for_drawing->nr_sprites) {
if (!ce_is_borderblank(colors_for_drawing.extra)) {
/* bordersprite off or not supported: sprites are visible until diw_end */
@@ -914,7 +916,6 @@ static void pfield_init_linetoscr (bool border)
}
#if 0
min = coord_hw_to_window_x(min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
-
if (min < playfield_start)
playfield_start = min;
if (playfield_start < visible_left_border)
@@ -2322,6 +2323,7 @@ Don't touch this if you don't know what you are doing. */
b ^= (tmp << shift); \
} while (0)
+
#define GETLONG(P) (*(uae_u32 *)P)
#define GETLONG64(P) (*(uae_u64 *)P)
@@ -2357,7 +2359,7 @@ static pfield_doline_func pfield_doline_n[9]={
#else
-STATIC_INLINE void pfield_doline_1(uae_u32 *pixels, int wordcount, int planes)
+STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes)
{
while (wordcount-- > 0) {
uae_u32 b0, b1, b2, b3, b4, b5, b6, b7;
@@ -3277,7 +3279,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
}
}
-static void center_image(void)
+static void center_image (void)
{
auto ad = &adisplays;
auto vidinfo = &ad->gfxvidinfo;
diff --git a/src/events.cpp b/src/events.cpp
index a6863ffd..b1fa2827 100644
--- a/src/events.cpp
+++ b/src/events.cpp
@@ -7,12 +7,15 @@
* Copyright 1995 Alessandro Bissacco
* Copyright 2000-2012 Toni Wilen
*/
+
+#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
-#include "include/memory.h"
+#include "memory.h"
#include "newcpu.h"
#include "xwin.h"
+#include "audio.h"
static const int pissoff_nojit_value = 256 * CYCLE_UNIT;
diff --git a/src/expansion.cpp b/src/expansion.cpp
index 99c1c9b8..df5e3246 100644
--- a/src/expansion.cpp
+++ b/src/expansion.cpp
@@ -20,6 +20,8 @@
#include "custom.h"
#include "newcpu.h"
#include "savestate.h"
+#include "cdtv.h"
+#include "cdtvcr.h"
#include "gfxboard.h"
#ifdef CD32
#include "cd32_fmv.h"
@@ -30,6 +32,8 @@
#define CARD_FLAG_CAN_Z3 1
+#define CARD_FLAG_CHILD 8
+#define CARD_FLAG_UAEROM 16
// More information in first revision HRM Appendix_G
#define BOARD_PROTOAUTOCONFIG 1
@@ -81,8 +85,19 @@
/* Manufacturer */
#define commodore_g 513 /* Commodore Braunschweig (Germany) */
#define commodore 514 /* Commodore West Chester */
+#define gvp 2017 /* GVP */
+#define ass 2102 /* Advanced Systems & Software */
#define hackers_id 2011 /* Special ID for test cards */
+/* Card Type */
+#define commodore_a2091 3 /* A2091 / A590 Card from C= */
+#define commodore_a2091_ram 10 /* A2091 / A590 Ram on HD-Card */
+#define commodore_a2232 70 /* A2232 Multiport Expansion */
+#define ass_nexus_scsi 1 /* Nexus SCSI Controller */
+
+#define gvp_series_2_scsi 11
+#define gvp_iv_24_gfx 32
+
/* ********************************************************** */
/* 08 - 0A */
/* er_Flags */
@@ -131,6 +146,7 @@
#define rom_install (0x01<<12) /* run code at install time */
#define rom_binddrv (0x02<<12) /* run code with binddrivers */
+uaecptr ROM_filesys_resname, ROM_filesys_resid;
uaecptr ROM_filesys_diagentry;
uaecptr ROM_hardfile_resname, ROM_hardfile_resid;
uaecptr ROM_hardfile_init;
@@ -158,6 +174,7 @@ struct card_data
uae_u32 size;
// parsing updated fields
const struct expansionromtype *ert;
+ const struct cpuboardsubtype *cst;
struct autoconfig_info aci;
};
@@ -211,14 +228,16 @@ static bool ks11orolder(void)
/* Autoconfig address space at 0xE80000 */
static uae_u8 expamem[65536 + 4];
+static uae_u8 expamem_write_space[65536 + 4];
#define AUTOMATIC_AUTOCONFIG_MAX_ADDRESS 0x80
static int expamem_autoconfig_mode;
static addrbank*(*expamem_map)(struct autoconfig_info*);
static uae_u8 expamem_lo;
static uae_u16 expamem_hi;
-static uaecptr expamem_z3_pointer_real, expamem_z3_pointer_uae;
-static uaecptr expamem_z3_highram_real, expamem_z3_highram_uae;
+uaecptr expamem_z3_pointer_real, expamem_z3_pointer_uae;
+uaecptr expamem_z3_highram_real, expamem_z3_highram_uae;
+uaecptr expamem_highmem_pointer;
uae_u32 expamem_board_size;
uaecptr expamem_board_pointer;
static uae_u8 slots_e8[8] = { 0 };
@@ -231,7 +250,7 @@ void set_expamem_z3_hack_mode(int mode)
z3hack_override = mode;
}
-static bool expamem_z3hack(struct uae_prefs *p)
+bool expamem_z3hack(struct uae_prefs *p)
{
if (z3hack_override == Z3MAPPING_UAE)
return true;
@@ -283,28 +302,28 @@ static void addextrachip (uae_u32 sysbase)
first = get_long (next);
}
if (next) {
- uae_u32 bytes = get_long (next + 4);
- if (next + bytes == 0x00200000) {
- put_long (next + 4, currprefs.chipmem_size - next);
- } else {
- put_long (0x00200000 + 0, 0);
- put_long (0x00200000 + 4, added);
- put_long (next, 0x00200000);
+ uae_u32 bytes = get_long(next + 4);
+ if (next + bytes == 0x00200000) {
+ put_long(next + 4, currprefs.chipmem_size - next);
+ } else {
+ put_long(0x00200000 + 0, 0);
+ put_long(0x00200000 + 4, added);
+ put_long(next, 0x00200000);
}
- }
+ }
return;
}
}
-addrbank expamem_null;
+addrbank expamem_null, expamem_none;
DECLARE_MEMORY_FUNCTIONS(expamem);
addrbank expamem_bank = {
- expamem_lget, expamem_wget, expamem_bget,
- expamem_lput, expamem_wput, expamem_bput,
+ expamem_lget, expamem_wget, expamem_bget,
+ expamem_lput, expamem_wput, expamem_bput,
default_xlate, default_check, NULL, NULL, _T("Autoconfig Z2"),
dummy_wgeti,
- ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
+ ABFLAG_IO | ABFLAG_SAFE | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
};
DECLARE_MEMORY_FUNCTIONS(expamemz3);
static addrbank expamemz3_bank = {
@@ -312,12 +331,18 @@ static addrbank expamemz3_bank = {
expamemz3_lput, expamemz3_wput, expamemz3_bput,
default_xlate, default_check, NULL, NULL, _T("Autoconfig Z3"),
dummy_wgeti,
- ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
+ ABFLAG_IO | ABFLAG_SAFE | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
};
+static addrbank *expamem_map_clear (void)
+{
+ write_log (_T("expamem_map_clear() got called. Shouldn't happen.\n"));
+ return NULL;
+}
+
static void expamem_init_clear (void)
{
- memset (expamem, 0xff, sizeof expamem);
+ memset (expamem, 0xff, sizeof expamem);
expamem_hi = expamem_lo = 0;
expamem_map = NULL;
}
@@ -325,9 +350,9 @@ static void expamem_init_clear (void)
static void expamem_init_clear_zero (void)
{
if (currprefs.cpu_model < 68020) {
- map_banks (&dummy_bank, 0xe8, 1, 0);
- if (!currprefs.address_space_24)
- map_banks (&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
+ map_banks(&dummy_bank, 0xe8, 1, 0);
+ if (!currprefs.address_space_24)
+ map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
} else {
map_banks(&expamem_bank, 0xe8, 1, 0);
if (!currprefs.address_space_24)
@@ -340,13 +365,15 @@ static void expamem_init_clear2 (void)
{
expamem_bank.name = _T("Autoconfig Z2");
expamemz3_bank.name = _T("Autoconfig Z3");
- expamem_init_clear_zero();
- ecard = cardno;
+ expamem_init_clear_zero ();
+ ecard = cardno;
}
static addrbank *expamem_init_last (void)
{
- expamem_init_clear2();
+ expamem_init_clear2 ();
+ write_log (_T("Memory map after autoconfig:\n"));
+ //memory_map_dump ();
return NULL;
}
@@ -359,16 +386,16 @@ static uae_u8 REGPARAM2 expamem_read(int addr)
return b;
}
-static void REGPARAM2 expamem_write (uaecptr addr, uae_u32 value)
+static void REGPARAM2 expamem_write(uaecptr addr, uae_u32 value)
{
- addr &= 0xffff;
- if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
+ addr &= 0xffff;
+ if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
expamem[addr] = (value & 0xf0);
expamem[addr + 2] = (value & 0x0f) << 4;
- } else {
+ } else {
expamem[addr] = ~(value & 0xf0);
expamem[addr + 2] = ~((value & 0x0f) << 4);
- }
+ }
}
static int REGPARAM2 expamem_type (void)
@@ -376,8 +403,6 @@ static int REGPARAM2 expamem_type (void)
return expamem_read(0) & 0xc0;
}
-static void expamem_next (addrbank *mapped, addrbank *next);
-
static void call_card_init(int index)
{
addrbank *ab, *abe;
@@ -390,6 +415,7 @@ static void call_card_init(int index)
aci->doinit = true;
aci->devnum = (cd->flags >> 16) & 255;
aci->ert = cd->ert;
+ aci->cst = cd->cst;
aci->rc = cd->rc;
aci->zorro = cd->zorro;
memset(aci->autoconfig_raw, 0xff, sizeof aci->autoconfig_raw);
@@ -433,22 +459,22 @@ static void call_card_init(int index)
map_banks(&expamemz3_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
map_banks(&dummy_bank, 0xE8, 1, 0);
} else {
- map_banks(&expamem_bank, 0xE8, 1, 0);
- if (!currprefs.address_space_24)
- map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
- }
+ map_banks(&expamem_bank, 0xE8, 1, 0);
+ if (!currprefs.address_space_24)
+ map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
+ }
} else {
if ((cd->flags & CARD_FLAG_CAN_Z3) && currprefs.cs_z3autoconfig && !currprefs.address_space_24) {
map_banks(&expamemz3_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
map_banks(&dummy_bank, 0xE8, 1, 0);
expamem_bank_current = &expamem_bank;
- } else {
- map_banks(&expamem_bank, 0xE8, 1, 0);
- if (!currprefs.address_space_24)
- map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
- expamem_bank_current = NULL;
+ } else {
+ map_banks(&expamem_bank, 0xE8, 1, 0);
+ if (!currprefs.address_space_24)
+ map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
+ expamem_bank_current = NULL;
}
- }
+ }
}
static void boardmessage(addrbank *mapped, bool success)
@@ -470,12 +496,20 @@ static void boardmessage(addrbank *mapped, bool success)
success ? _T("") : _T(" [SHUT UP]"));
}
-static void expamem_next(addrbank *mapped, addrbank *next)
+void expamem_shutup(addrbank *mapped)
+{
+ if (mapped) {
+ mapped->start = 0xffffffff;
+ boardmessage(mapped, false);
+ }
+}
+
+void expamem_next(addrbank *mapped, addrbank *next)
{
if (mapped)
boardmessage(mapped, mapped->start != 0xffffffff);
- expamem_init_clear();
+ expamem_init_clear();
expamem_init_clear_zero();
for (;;) {
++ecard;
@@ -526,7 +560,7 @@ static uae_u32 REGPARAM2 expamem_lget (uaecptr addr)
return expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->lget(addr) : expamem_bank_current->lget(addr);
}
write_log (_T("warning: Z2 READ.L from address $%08x PC=%x\n"), addr, M68K_GETPC);
- return (expamem_wget (addr) << 16) | expamem_wget (addr + 2);
+ return (expamem_wget (addr) << 16) | expamem_wget (addr + 2);
}
static uae_u32 REGPARAM2 expamem_wget (uaecptr addr)
@@ -541,14 +575,14 @@ static uae_u32 REGPARAM2 expamem_wget (uaecptr addr)
if (expamem_bank_current && expamem_bank_current != &expamem_bank)
return expamem_bank_current->bget(addr) << 8;
}
- uae_u32 v = (expamem_bget (addr) << 8) | expamem_bget (addr + 1);
+ uae_u32 v = (expamem_bget (addr) << 8) | expamem_bget (addr + 1);
write_log (_T("warning: READ.W from address $%08x=%04x PC=%x\n"), addr, v & 0xffff, M68K_GETPC);
- return v;
+ return v;
}
static uae_u32 REGPARAM2 expamem_bget (uaecptr addr)
{
- uae_u8 b;
+ uae_u8 b;
if (!chipdone) {
chipdone = true;
addextrachip (get_long (4));
@@ -559,9 +593,9 @@ static uae_u32 REGPARAM2 expamem_bget (uaecptr addr)
}
return expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bget(addr) : expamem_bank_current->bget(addr);
}
- addr &= 0xFFFF;
- b = expamem[addr];
- return b;
+ addr &= 0xFFFF;
+ b = expamem[addr];
+ return b;
}
static void REGPARAM2 expamem_lput (uaecptr addr, uae_u32 value)
@@ -578,9 +612,9 @@ static void REGPARAM2 expamem_lput (uaecptr addr, uae_u32 value)
static void REGPARAM2 expamem_wput (uaecptr addr, uae_u32 value)
{
- value &= 0xffff;
- if (ecard >= cardno)
- return;
+ value &= 0xffff;
+ if (ecard >= cardno)
+ return;
card_data *cd = cards[ecard];
if (!expamem_map)
expamem_map = cd->map;
@@ -588,53 +622,53 @@ static void REGPARAM2 expamem_wput (uaecptr addr, uae_u32 value)
write_log (_T("warning: WRITE.W to address $%08x : value $%x PC=%08x\n"), addr, value, M68K_GETPC);
}
switch (addr & 0xff) {
- case 0x48:
- // A2630 boot rom writes WORDs to Z2 boards!
- if (expamem_type() == zorroII) {
- expamem_lo = 0;
- expamem_hi = (value >> 8) & 0xff;
- expamem_board_pointer = (expamem_hi | (expamem_lo >> 4)) << 16;
- if (expamem_map) {
- expamem_next(expamem_map(&cd->aci), NULL);
- return;
- }
- if (expamem_autoconfig_mode) {
- map_banks_z2(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
- cd->initrc(&cd->aci);
- expamem_next(cd->aci.addrbankp, NULL);
- return;
- }
- if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
- expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bput(addr, value >> 8) : expamem_bank_current->bput(addr, value >> 8);
- return;
- }
- }
- // Z3 = do nothing
- break;
- case 0x44:
- if (expamem_type() == zorroIII) {
- expamem_hi = (value & 0xff00) >> 8;
- expamem_lo = value & 0x00ff;
- expamemz3_map();
- }
- if (expamem_map) {
- expamem_next(expamem_map(&cd->aci), NULL);
- return;
- }
- if (expamem_autoconfig_mode) {
- map_banks_z3(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
- cd->initrc(&cd->aci);
- expamem_next(cd->aci.addrbankp, NULL);
- return;
- }
- break;
- case 0x4c:
- if (expamem_map) {
- expamem_next (NULL, NULL);
- return;
- }
- break;
- }
+ case 0x48:
+ // A2630 boot rom writes WORDs to Z2 boards!
+ if (expamem_type() == zorroII) {
+ expamem_lo = 0;
+ expamem_hi = (value >> 8) & 0xff;
+ expamem_board_pointer = (expamem_hi | (expamem_lo >> 4)) << 16;
+ if (expamem_map) {
+ expamem_next(expamem_map(&cd->aci), NULL);
+ return;
+ }
+ if (expamem_autoconfig_mode) {
+ map_banks_z2(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
+ cd->initrc(&cd->aci);
+ expamem_next(cd->aci.addrbankp, NULL);
+ return;
+ }
+ if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
+ expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bput(addr, value >> 8) : expamem_bank_current->bput(addr, value >> 8);
+ return;
+ }
+ }
+ // Z3 = do nothing
+ break;
+ case 0x44:
+ if (expamem_type() == zorroIII) {
+ expamem_hi = (value & 0xff00) >> 8;
+ expamem_lo = value & 0x00ff;
+ expamemz3_map();
+ }
+ if (expamem_map) {
+ expamem_next(expamem_map(&cd->aci), NULL);
+ return;
+ }
+ if (expamem_autoconfig_mode) {
+ map_banks_z3(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
+ cd->initrc(&cd->aci);
+ expamem_next(cd->aci.addrbankp, NULL);
+ return;
+ }
+ break;
+ case 0x4c:
+ if (expamem_map) {
+ expamem_next (NULL, NULL);
+ return;
+ }
+ break;
+ }
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->wput(addr, value) : expamem_bank_current->wput(addr, value);
}
@@ -642,25 +676,25 @@ static void REGPARAM2 expamem_wput (uaecptr addr, uae_u32 value)
static void REGPARAM2 expamem_bput (uaecptr addr, uae_u32 value)
{
- value &= 0xff;
- if (ecard >= cardno)
- return;
+ value &= 0xff;
+ if (ecard >= cardno)
+ return;
card_data *cd = cards[ecard];
if (!expamem_map)
expamem_map = cd->map;
if (expamem_type() == protoautoconfig) {
switch (addr & 0xff) {
- case 0x22:
- expamem_hi = value & 0x7f;
- expamem_board_pointer = AUTOCONFIG_Z2 | (expamem_hi * 4096);
- if (expamem_map) {
- expamem_next(expamem_map(&cd->aci), NULL);
- return;
- }
- break;
+ case 0x22:
+ expamem_hi = value & 0x7f;
+ expamem_board_pointer = AUTOCONFIG_Z2 | (expamem_hi * 4096);
+ if (expamem_map) {
+ expamem_next(expamem_map(&cd->aci), NULL);
+ return;
+ }
+ break;
}
} else {
- switch (addr & 0xff) {
+ switch (addr & 0xff) {
case 0x48:
if (expamem_type () == zorroII) {
expamem_hi = value & 0xff;
@@ -703,7 +737,7 @@ static void REGPARAM2 expamem_bput (uaecptr addr, uae_u32 value)
return;
break;
- case 0x4c:
+ case 0x4c:
if (expamem_map) {
expamem_hi = expamem_lo = 0xff;
expamem_board_pointer = 0xffffffff;
@@ -807,10 +841,14 @@ static bool expamem_init_cd32fmv (struct autoconfig_info *aci)
/* ********************************************************** */
/*
- * Fast Memory
- */
+* Fast Memory
+*/
+
MEMORY_ARRAY_FUNCTIONS(fastmem, 0);
+MEMORY_ARRAY_FUNCTIONS(fastmem, 1);
+MEMORY_ARRAY_FUNCTIONS(fastmem, 2);
+MEMORY_ARRAY_FUNCTIONS(fastmem, 3);
addrbank fastmem_bank[MAX_RAM_BOARDS] =
{
@@ -827,7 +865,7 @@ addrbank fastmem_bank[MAX_RAM_BOARDS] =
/*
* Filesystem device ROM/RAM space
- */
+*/
DECLARE_MEMORY_FUNCTIONS(filesys);
addrbank filesys_bank = {
@@ -868,6 +906,7 @@ static uae_u32 REGPARAM2 filesys_bget (uaecptr addr)
return filesys_bank.baseaddr[addr];
}
+
static void REGPARAM2 filesys_bput(uaecptr addr, uae_u32 b)
{
addr -= filesys_bank.start;
@@ -923,7 +962,8 @@ addrbank uaeboard_bank = {
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
};
-static uae_u32 uaeboard_base; /* Determined by the OS */
+uae_u32 uaeboard_base; /* Determined by the OS */
+static uae_u32 uaeboard_ram_start;
#define UAEBOARD_WRITEOFFSET 0x4000
static bool uaeboard_write(uaecptr addr)
@@ -1171,15 +1211,15 @@ static bool fastmem_autoconfig(struct uae_prefs *p, struct autoconfig_info *aci,
ac[0x08 / 4] = flags;
}
} else {
- ac[0x00 / 4] = type;
- ac[0x04 / 4] = pid;
- ac[0x08 / 4] = flags;
- ac[0x10 / 4] = mid >> 8;
- ac[0x14 / 4] = (uae_u8)mid;
- ac[0x18 / 4] = serial >> 24;
- ac[0x1c / 4] = serial >> 16;
- ac[0x20 / 4] = serial >> 8;
- ac[0x24 / 4] = serial >> 0;
+ ac[0x00 / 4] = type;
+ ac[0x04 / 4] = pid;
+ ac[0x08 / 4] = flags;
+ ac[0x10 / 4] = mid >> 8;
+ ac[0x14 / 4] = (uae_u8)mid;
+ ac[0x18 / 4] = serial >> 24;
+ ac[0x1c / 4] = serial >> 16;
+ ac[0x20 / 4] = serial >> 8;
+ ac[0x24 / 4] = serial >> 0;
}
expamem_write(0x00, ac[0x00 / 4]);
@@ -1654,32 +1694,44 @@ static void allocate_expamem (void)
#endif /* SAVESTATE */
}
-static uaecptr check_boot_rom (struct uae_prefs *p, int *boot_rom_type)
+static uaecptr check_boot_rom(struct uae_prefs* p, int* boot_rom_type)
{
- uaecptr b = RTAREA_DEFAULT;
- addrbank *ab;
+ uaecptr b = RTAREA_DEFAULT;
+ addrbank* ab;
*boot_rom_type = 0;
if (p->boot_rom == 1)
return 0;
*boot_rom_type = 1;
- ab = &get_mem_bank (RTAREA_DEFAULT);
- if (ab) {
- if (valid_address (RTAREA_DEFAULT, 65536))
- b = RTAREA_BACKUP;
- }
- if (nr_directory_units (NULL))
- return b;
- if (nr_directory_units (p))
- return b;
+ if (p->cs_cdtvcd || is_device_rom(p, ROMTYPE_CDTVSCSI, 0) >= 0 || p->uae_hide > 1)
+ b = RTAREA_BACKUP;
+ if (p->cs_mbdmac == 1 || p->cpuboard_type)
+ b = RTAREA_BACKUP;
+ ab = &get_mem_bank(RTAREA_DEFAULT);
+ if (ab) {
+ if (valid_address(RTAREA_DEFAULT, 65536))
+ b = RTAREA_BACKUP;
+ }
+ if (nr_directory_units(NULL))
+ return b;
+ if (nr_directory_units(p))
+ return b;
if (p->socket_emu)
return b;
+ if (p->uaeserial)
+ return b;
+ if (p->scsi == 1)
+ return b;
+ if (p->sana2)
+ return b;
if (p->input_tablet > 0)
- return b;
+ return b;
if (p->rtgboards[0].rtgmem_size)
return b;
if (p->chipmem_size > 2 * 1024 * 1024)
- return b;
+ return b;
+ if (p->z3chipmem_size)
+ return b;
if (p->boot_rom >= 3)
return b;
if (p->boot_rom == 2 && b == 0xf00000) {
@@ -1687,20 +1739,20 @@ static uaecptr check_boot_rom (struct uae_prefs *p, int *boot_rom_type)
return b;
}
*boot_rom_type = 0;
- return 0;
+ return 0;
}
-uaecptr need_uae_boot_rom (struct uae_prefs *p)
+uaecptr need_uae_boot_rom(struct uae_prefs* p)
{
- uaecptr v;
+ uaecptr v;
- uae_boot_rom_type = 0;
- v = check_boot_rom (p, &uae_boot_rom_type);
- if (!rtarea_base) {
- uae_boot_rom_type = 0;
- v = 0;
- }
- return v;
+ uae_boot_rom_type = 0;
+ v = check_boot_rom(p, &uae_boot_rom_type);
+ if (!rtarea_base) {
+ uae_boot_rom_type = 0;
+ v = 0;
+ }
+ return v;
}
static void add_expansions(struct uae_prefs *p, int zorro, int *fastmem_nump, int mode)
@@ -2286,7 +2338,8 @@ static void expansion_add_autoconfig(struct uae_prefs *p)
cards_set[cardno].zorro = BOARD_NONAUTOCONFIG_BEFORE;
cards_set[cardno].initnum = expamem_rtarea_init;
cards_set[cardno++].map = NULL;
- }
+
+ }
#endif
#ifdef PICASSO96
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
@@ -2364,7 +2417,7 @@ void expamem_reset (int hardreset)
devices_reset_ext(hardreset);
if (cardno == 0 || savestate_state) {
- expamem_init_clear_zero ();
+ expamem_init_clear_zero ();
} else {
set_ks12_boot_hack();
call_card_init(0);
@@ -2634,28 +2687,986 @@ void restore_expansion_finish(void)
#endif /* SAVESTATE */
-const struct expansionromtype expansionroms[] = {
-
- /* built-in controllers */
-#ifdef CD32
+static const struct expansionboardsettings cdtvsram_settings[] = {
{
- _T("cd32fmv"), _T("CD32 FMV"), _T("Commodore"),
- expamem_init_cd32fmv, NULL, ROMTYPE_CD32CART, BOARD_AUTOCONFIG_Z2,
- EXPANSIONTYPE_INTERNAL
+ _T("SRAM size\0") _T("64k\0") _T("128k\0") _T("256k\0"),
+ _T("sram\0") _T("64k\0") _T("128k\0") _T("256k\0"),
+ true
},
-#endif
- {
- _T("ide_mb"), _T("A600/A1200/A4000 IDE"), _T("Commodore"),
- gayle_ide_init, gayle_add_ide_unit, ROMTYPE_MB_IDE | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE,
- EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_IDE
- },
- {
- _T("pcmcia_mb"), _T("A600/A1200 PCMCIA"), _T("Commodore"),
- gayle_init_pcmcia, NULL, ROMTYPE_MB_PCMCIA | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE,
- EXPANSIONTYPE_INTERNAL
- },
-
{
NULL
}
};
+
+const struct expansionromtype expansionroms[] = {
+ //{
+ // _T("cpuboard"), _T("Accelerator"), _T("Accelerator"),
+ // NULL, NULL, NULL, add_cpuboard_unit, ROMTYPE_CPUBOARD, 0, 0, 0, true,
+ // NULL, 0,
+ // false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
+ //},
+
+ /* built-in controllers */
+ {
+ _T("cd32fmv"), _T("CD32 FMV"), _T("Commodore"),
+ NULL, expamem_init_cd32fmv, NULL, NULL, ROMTYPE_CD32CART, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL
+ },
+ {
+ _T("cdtvdmac"), _T("CDTV DMAC"), _T("Commodore"),
+ NULL, cdtv_init, NULL, NULL, ROMTYPE_CDTVDMAC | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL
+ },
+ //{
+ // _T("cdtvscsi"), _T("CDTV SCSI"), _T("Commodore"),
+ // NULL, cdtvscsi_init, NULL, cdtv_add_scsi_unit, ROMTYPE_CDTVSCSI | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+ // NULL, 0,
+ // false, EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_SCSI
+ //},
+ {
+ _T("cdtvsram"), _T("CDTV SRAM"), _T("Commodore"),
+ NULL, cdtvsram_init, NULL, NULL, ROMTYPE_CDTVSRAM | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL,
+ 0, 0, 0, false, NULL,
+ false, 0, cdtvsram_settings
+ },
+ {
+ _T("cdtvcr"), _T("CDTV-CR"), _T("Commodore"),
+ NULL, cdtvcr_init, NULL, NULL, ROMTYPE_CDTVCR | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL
+ },
+ //{
+ // _T("scsi_a3000"), _T("A3000 SCSI"), _T("Commodore"),
+ // NULL, a3000scsi_init, NULL, a3000_add_scsi_unit, ROMTYPE_SCSI_A3000 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+ // NULL, 0,
+ // false, EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_SCSI
+ //},
+ //{
+ // _T("scsi_a4000t"), _T("A4000T SCSI"), _T("Commodore"),
+ // NULL, a4000t_scsi_init, NULL, a4000t_add_scsi_unit, ROMTYPE_SCSI_A4000T | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+ // NULL, 0,
+ // false, EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_SCSI
+ //},
+ {
+ _T("ide_mb"), _T("A600/A1200/A4000 IDE"), _T("Commodore"),
+ NULL, gayle_ide_init, NULL, gayle_add_ide_unit, ROMTYPE_MB_IDE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_IDE,
+ 0, 0, 0, false, NULL, false, 1
+ },
+ {
+ _T("pcmcia_mb"), _T("A600/A1200 PCMCIA"), _T("Commodore"),
+ NULL, gayle_init_pcmcia, NULL, NULL, ROMTYPE_MB_PCMCIA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+ NULL, 0,
+ false, EXPANSIONTYPE_INTERNAL
+ },
+
+ /* PCI Bridgeboards */
+//
+// {
+// _T("grex"), _T("G-REX"), _T("DCE"),
+// NULL, grex_init, NULL, NULL, ROMTYPE_GREX | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_PCI_BRIDGE
+// },
+// {
+// _T("mediator"), _T("Mediator"), _T("Elbox"),
+// NULL, mediator_init, mediator_init2, NULL, ROMTYPE_MEDIATOR | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// mediator_sub, 0,
+// false, EXPANSIONTYPE_PCI_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, mediator_settings
+// },
+// {
+// _T("prometheus"), _T("Prometheus"), _T("Matay"),
+// NULL, prometheus_init, NULL, NULL, ROMTYPE_PROMETHEUS | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_PCI_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, bridge_settings
+// },
+//
+// /* SCSI/IDE expansion */
+//
+// {
+// _T("pcmciaide"), _T("PCMCIA IDE"), NULL,
+// NULL, gayle_init_board_io_pcmcia, NULL, NULL, ROMTYPE_PCMCIAIDE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE | EXPANSIONTYPE_PCMCIA,
+// },
+// {
+// _T("apollo"), _T("Apollo 500/2000"), _T("3-State"),
+// NULL, apollo_init_hd, NULL, apollo_add_scsi_unit, ROMTYPE_APOLLOHD, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+// 8738, 0, 0
+// },
+// {
+// _T("add500"), _T("ADD-500"), _T("Archos"),
+// NULL, add500_init, NULL, add500_add_scsi_unit, ROMTYPE_ADD500, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 8498, 27, 0, true, NULL
+// },
+// {
+// _T("overdrivehd"), _T("Overdrive HD"), _T("Archos"),
+// NULL, gayle_init_board_common_pcmcia, NULL, NULL, ROMTYPE_ARCHOSHD, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE | EXPANSIONTYPE_PCMCIA,
+// },
+// {
+// _T("addhard"), _T("AddHard"), _T("Ashcom Design"),
+// NULL, addhard_init, NULL, addhard_add_scsi_unit, ROMTYPE_ADDHARD, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 0x30, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("blizzardscsikitiii"), _T("SCSI Kit III"), _T("Phase 5"),
+// NULL, NULL, NULL, cpuboard_ncr9x_add_scsi_unit, ROMTYPE_BLIZKIT3, 0, 0, 0, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("blizzardscsikitiv"), _T("SCSI Kit IV"), _T("Phase 5"),
+// NULL, NULL, NULL, cpuboard_ncr9x_add_scsi_unit, ROMTYPE_BLIZKIT4, 0, 0, 0, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("accessx"), _T("AccessX"), _T("Breitfeld Computersysteme"),
+// NULL, accessx_init, NULL, accessx_add_ide_unit, ROMTYPE_ACCESSX, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// accessx_sub, 0,
+// true, EXPANSIONTYPE_IDE,
+// 0, 0, 0, true, NULL,
+// false, 2
+// },
+// {
+// _T("oktagon2008"), _T("Oktagon 2008"), _T("BSC/Alfa Data"),
+// NULL, ncr_oktagon_autoconfig_init, NULL, oktagon_add_scsi_unit, ROMTYPE_OKTAGON, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("alfapower"), _T("AlfaPower/AT-Bus 2008"), _T("BSC/Alfa Data"),
+// NULL, alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFA, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE,
+// 2092, 8, 0
+// },
+// {
+// _T("alfapowerplus"), _T("AlfaPower Plus"), _T("BSC/Alfa Data"),
+// NULL, alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFAPLUS, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE,
+// 2092, 8, 0
+// },
+// {
+// _T("tandem"), _T("Tandem"), _T("BSC"),
+// NULL, tandem_init, NULL, tandem_add_ide_unit, ROMTYPE_TANDEM | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 6, 0x00, 0x00, 0x08, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+// },
+// {
+// _T("malibu"), _T("Malibu"), _T("California Access"),
+// NULL, malibu_init, NULL, malibu_add_scsi_unit, ROMTYPE_MALIBU, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00 },
+// },
+// {
+// _T("cltda1000scsi"), _T("A1000/A2000 SCSI"), _T("C-Ltd"),
+// NULL, cltda1000scsi_init, NULL, cltda1000scsi_add_scsi_unit, ROMTYPE_CLTDSCSI | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 0x0c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+// },
+// {
+// _T("a2090a"), _T("A2090a"), _T("Commodore"),
+// NULL, a2090_init, NULL, a2090_add_scsi_unit, ROMTYPE_A2090 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_CUSTOM_SECONDARY,
+// 0, 0, 0, false, NULL,
+// false, 0, a2090a_settings
+// },
+// {
+// _T("a2090b"), _T("A2090 Combitec"), _T("Commodore"),
+// a2090b_preinit, a2090b_init, NULL, a2090_add_scsi_unit, ROMTYPE_A2090B | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_CUSTOM_SECONDARY,
+// 0, 0, 0, false, NULL,
+// false, 0, a2090a_settings
+// },
+// {
+// _T("a2091"), _T("A590/A2091"), _T("Commodore"),
+// NULL, a2091_init, NULL, a2091_add_scsi_unit, ROMTYPE_A2091 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// a2091_sub, 1,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_CUSTOM_SECONDARY,
+// commodore, commodore_a2091, 0, true, NULL
+// },
+// {
+// _T("a4091"), _T("A4091"), _T("Commodore"),
+// NULL, ncr710_a4091_autoconfig_init, NULL, a4091_add_scsi_unit, ROMTYPE_A4091, 0, 0, BOARD_AUTOCONFIG_Z3, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// true, 0, a4091_settings
+// },
+// {
+// _T("comspec"), _T("SA series"), _T("Comspec Communications"),
+// comspec_preinit, comspec_init, NULL, comspec_add_scsi_unit, ROMTYPE_COMSPEC, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// comspec_sub, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, comspec_settings
+// },
+// {
+// _T("rapidfire"), _T("RapidFire/SpitFire"), _T("DKB"),
+// NULL, ncr_rapidfire_init, NULL, rapidfire_add_scsi_unit, ROMTYPE_RAPIDFIRE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 2012, 1, 0, true, NULL,
+// true, 0, NULL,
+// { 0xd2, 0x0f ,0x00, 0x00, 0x07, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },
+// },
+// {
+// _T("fastata4000"), _T("FastATA 4000"), _T("Elbox"),
+// NULL, fastata4k_init, NULL, fastata4k_add_ide_unit, ROMTYPE_FASTATA4K, 0, 0, BOARD_AUTOCONFIG_Z3, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE,
+// 0, 0, 0, true, NULL,
+// true, 2, fastata_settings,
+// { 0x90, 0, 0x10, 0x00, 0x08, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 },
+// },
+// {
+// _T("elsathd"), _T("Mega Ram HD"), _T("Elsat"),
+// NULL, elsathd_init, NULL, elsathd_add_ide_unit, ROMTYPE_ELSATHD, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE,
+// 17740, 1, 0
+// },
+// {
+// _T("eveshamref"), _T("Reference 40/100"), _T("Evesham Micros"),
+// NULL, eveshamref_init, NULL, eveshamref_add_scsi_unit, ROMTYPE_EVESHAMREF, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 8504, 2, 0
+// },
+// {
+// _T("dataflyerscsiplus"), _T("DataFlyer SCSI+"), _T("Expansion Systems"),
+// NULL, dataflyer_init, NULL, dataflyer_add_scsi_unit, ROMTYPE_DATAFLYERP | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("dataflyerplus"), _T("DataFlyer Plus"), _T("Expansion Systems"),
+// NULL, dataflyerplus_init, NULL, dataflyerplus_add_idescsi_unit, ROMTYPE_DATAFLYER, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// false, 0, dataflyersplus_settings
+// },
+// {
+// _T("arriba"), _T("Arriba"), _T("Gigatron"),
+// NULL, arriba_init, NULL, arriba_add_ide_unit, ROMTYPE_ARRIBA | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },
+// },
+// {
+// _T("gvp1"), _T("GVP Series I"), _T("Great Valley Products"),
+// NULL, gvp_init_s1, NULL, gvp_s1_add_scsi_unit, ROMTYPE_GVPS1 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, BOARD_AUTOCONFIG_Z2, false,
+// gvp1_sub, 1,
+// true, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("gvp"), _T("GVP Series II"), _T("Great Valley Products"),
+// NULL, gvp_init_s2, NULL, gvp_s2_add_scsi_unit, ROMTYPE_GVPS2 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 2017, 10, 0
+// },
+// {
+// _T("dotto"), _T("Dotto"), _T("Hardital"),
+// NULL, dotto_init, NULL, dotto_add_ide_unit, ROMTYPE_DOTTO, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE
+// },
+// {
+// _T("vector"), _T("Vector Falcon 8000"), _T("HK-Computer"),
+// NULL, vector_init, NULL, vector_add_scsi_unit, ROMTYPE_VECTOR, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("surfsquirrel"), _T("Surf Squirrel"), _T("HiSoft"),
+// NULL, gayle_init_board_io_pcmcia, NULL, NULL, ROMTYPE_SSQUIRREL | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_PCMCIA,
+// },
+// {
+// _T("adide"), _T("AdIDE"), _T("ICD"),
+// NULL, adide_init, NULL, adide_add_ide_unit, ROMTYPE_ADIDE | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE
+// },
+// {
+// _T("adscsi2000"), _T("AdSCSI Advantage 2000/2080"), _T("ICD"),
+// NULL, adscsi_init, NULL, adscsi_add_scsi_unit, ROMTYPE_ADSCSI, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 2071, 4, 0, false, NULL,
+// true, 0, adscsi2000_settings
+// },
+// {
+// _T("trifecta"), _T("Trifecta"), _T("ICD"),
+// NULL, trifecta_init, NULL, trifecta_add_idescsi_unit, ROMTYPE_TRIFECTA | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// trifecta_sub, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+// 2071, 32, 0, false, NULL,
+// true, 0, trifecta_settings,
+// { 0xd1, 0x23, 0x40, 0x00, 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }
+// },
+// {
+// _T("buddha"), _T("Buddha"), _T("Individual Computers"),
+// NULL, buddha_init, NULL, buddha_add_ide_unit, ROMTYPE_BUDDHA, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// false, 4, buddha_settings,
+// { 0xd1, 0x00, 0x00, 0x00, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 },
+// },
+// {
+// _T("trumpcard"), _T("Trumpcard"), _T("IVS"),
+// NULL, trumpcard_init, NULL, trumpcard_add_scsi_unit, ROMTYPE_IVSTC, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 2112, 4, 0, false, NULL,
+// true, 0, NULL,
+// { 0xd1, 0x30, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("trumpcardpro"), _T("Grand Slam"), _T("IVS"),
+// NULL, trumpcardpro_init, NULL, trumpcardpro_add_scsi_unit, ROMTYPE_IVSTPRO, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 2112, 4, 0, false, NULL,
+// true, 0, NULL,
+// { 0xd1, 0x34, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("trumpcardat"), _T("Trumpcard 500AT"), _T("IVS"),
+// NULL, trumpcard500at_init, NULL, trumpcard500at_add_ide_unit, ROMTYPE_IVST500AT, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE,
+// 2112, 4, 0, false, NULL,
+// true, 0, NULL,
+// { 0xd1, 0x31, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("kommos"), _T("Kommos A500/A2000 SCSI"), _T("Jürgen Kommos"),
+// NULL, kommos_init, NULL, kommos_add_scsi_unit, ROMTYPE_KOMMOS, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("golem"), _T("HD3000"), _T("Kupke"),
+// NULL, hd3000_init, NULL, hd3000_add_scsi_unit, ROMTYPE_GOLEMHD3000, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("golem"), _T("Golem SCSI II"), _T("Kupke"),
+// NULL, golem_init, NULL, golem_add_scsi_unit, ROMTYPE_GOLEM, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 2079, 3, 0
+// },
+// {
+// _T("golemfast"), _T("Golem Fast SCSI/IDE"), _T("Kupke"),
+// NULL, golemfast_init, NULL, golemfast_add_idescsi_unit, ROMTYPE_GOLEMFAST, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// true, 0, golemfast_settings
+// },
+// {
+// _T("multievolution"), _T("Multi Evolution 500/2000"), _T("MacroSystem"),
+// NULL, ncr_multievolution_init, NULL, multievolution_add_scsi_unit, ROMTYPE_MEVOLUTION, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 18260, 8, 0, true
+// },
+// {
+// _T("scram8490"), _T("SCRAM (DP8490V)"), _T("MegaMicro"),
+// NULL, scram5380_init, NULL, scram5380_add_scsi_unit, ROMTYPE_SCRAM5380, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 4096, 4, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 3, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00 }
+// },
+// {
+// _T("scram5394"), _T("SCRAM (NCR53C94)"), _T("MegaMicro"),
+// NULL, ncr_scram5394_init, NULL, scram5394_add_scsi_unit, ROMTYPE_SCRAM5394, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 4096, 4, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 7, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00 }
+// },
+// {
+// _T("paradox"), _T("Paradox SCSI"), _T("Mainhattan Data"),
+// NULL, paradox_init, NULL, paradox_add_scsi_unit, ROMTYPE_PARADOX | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_PARALLEL_ADAPTER
+// },
+// {
+// _T("ateam"), _T("A-Team"), _T("Mainhattan Data"),
+// NULL, ateam_init, NULL, ateam_add_ide_unit, ROMTYPE_ATEAM, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE
+// },
+// {
+// _T("mtecat"), _T("AT 500"), _T("M-Tec"),
+// NULL, mtec_init, NULL, mtec_add_ide_unit, ROMTYPE_MTEC, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_IDE
+// },
+// {
+// _T("mtecmastercard"), _T("Mastercard"), _T("M-Tec"),
+// NULL, ncr_mtecmastercard_init, NULL, mtecmastercard_add_scsi_unit, ROMTYPE_MASTERCARD, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("masoboshi"), _T("MasterCard"), _T("Masoboshi"),
+// NULL, masoboshi_init, NULL, masoboshi_add_idescsi_unit, ROMTYPE_MASOBOSHI | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// masoboshi_sub, 0,
+// true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
+// },
+// {
+// _T("hardframe"), _T("HardFrame"), _T("Microbotics"),
+// NULL, hardframe_init, NULL, hardframe_add_scsi_unit, ROMTYPE_HARDFRAME, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// true
+// },
+// {
+// _T("stardrive"), _T("StarDrive"), _T("Microbotics"),
+// NULL, stardrive_init, NULL, stardrive_add_scsi_unit, ROMTYPE_STARDRIVE | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 1010, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 2, 0x00, 0x00, 0x03, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+//
+// },
+// {
+// _T("filecard2000"), _T("Filecard 2000/OSSI 500"), _T("Otronic"),
+// NULL, ossi_init, NULL, ossi_add_scsi_unit, ROMTYPE_OSSI, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 1, 0x00, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+// },
+// {
+// _T("pacificoverdrive"), _T("Overdrive"), _T("Pacific Peripherals/IVS"),
+// NULL, overdrive_init, NULL, overdrive_add_scsi_unit, ROMTYPE_OVERDRIVE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 16, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }
+// },
+// {
+// _T("fastlane"), _T("Fastlane"), _T("Phase 5"),
+// NULL, ncr_fastlane_autoconfig_init, NULL, fastlane_add_scsi_unit, ROMTYPE_FASTLANE, 0, 0, BOARD_AUTOCONFIG_Z3, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 8512, 10, 0, false, fastlane_memory_callback
+// },
+// {
+// _T("phoenixboard"), _T("Phoenix Board SCSI"), _T("Phoenix Microtechnologies"),
+// NULL, phoenixboard_init, NULL, phoenixboard_add_scsi_unit, ROMTYPE_PHOENIXB, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// },
+// {
+// _T("ptnexus"), _T("Nexus"), _T("Preferred Technologies"),
+// NULL, ptnexus_init, NULL, ptnexus_add_scsi_unit, ROMTYPE_PTNEXUS | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 2102, 4, 0, false, nexus_memory_callback,
+// false, 0, nexus_settings,
+// { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("profex"), _T("HD 3300"), _T("Profex Electronics"),
+// NULL, profex_init, NULL, profex_add_scsi_unit, ROMTYPE_PROFEX, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// true, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("protar"), _T("A500 HD"), _T("Protar"),
+// NULL, protar_init, NULL, protar_add_ide_unit, ROMTYPE_PROTAR, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 4149, 51, 0
+// },
+// {
+// _T("rochard"), _T("RocHard RH800C"), _T("Roctec"),
+// NULL, rochard_init, NULL, rochard_add_idescsi_unit, ROMTYPE_ROCHARD | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// rochard_sub, 0,
+// true, EXPANSIONTYPE_IDE | EXPANSIONTYPE_SCSI,
+// 2144, 2, 0, false, NULL,
+// false, 2, NULL
+// },
+// {
+// _T("inmate"), _T("InMate"), _T("Spirit Technology"),
+// NULL, inmate_init, NULL, inmate_add_scsi_unit, ROMTYPE_INMATE | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, inmate_settings
+// },
+// {
+// _T("supradrive"), _T("SupraDrive"), _T("Supra Corporation"),
+// NULL, supra_init, NULL, supra_add_scsi_unit, ROMTYPE_SUPRA | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// supra_sub, 0,
+// true, EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("emplant"), _T("Emplant (SCSI only)"), _T("Utilities Unlimited"),
+// NULL, emplant_init, NULL, emplant_add_scsi_unit, ROMTYPE_EMPLANT | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 0x15, 0x40, 0x00, 0x08, 0x7b, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00 },
+// },
+//#if 0 /* driver is MIA, 3rd party ScottDevice driver is not enough for full implementation. */
+// {
+// NULL, _T("microforge"), _T("Hard Disk"), _T("Micro Forge"),
+// microforge_init, NULL, microforge_add_scsi_unit, ROMTYPE_MICROFORGE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI
+// },
+//#endif
+//
+// {
+// _T("omtiadapter"), _T("OMTI-Adapter"), _T("C't"),
+// NULL, omtiadapter_init, NULL, omtiadapter_scsi_unit, ROMTYPE_OMTIADAPTER | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("alf1"), _T("A.L.F."), _T("Elaborate Bytes"),
+// NULL, alf1_init, NULL, alf1_add_scsi_unit, ROMTYPE_ALF1 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("alf3"), _T("A.L.F.3"), _T("Elaborate Bytes"),
+// NULL, ncr_alf3_autoconfig_init, NULL, alf3_add_scsi_unit, ROMTYPE_ALF3 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// true, 0, alf3_settings
+// },
+// {
+// _T("promigos"), _T("Promigos"), _T("Flesch und Hörnemann"),
+// NULL, promigos_init, NULL, promigos_add_scsi_unit, ROMTYPE_PROMIGOS | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("wedge"), _T("Wedge"), _T("Reiter Software"),
+// wedge_preinit, wedge_init, NULL, wedge_add_scsi_unit, ROMTYPE_WEDGE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("tecmar"), _T("T-Card/T-Disk"), _T("Tecmar"),
+// NULL, tecmar_init, NULL, tecmar_add_scsi_unit, ROMTYPE_TECMAR | ROMTYPE_NOT, 0, 0, BOARD_PROTOAUTOCONFIG, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI,
+// 1001, 1, 0
+// },
+// {
+// _T("system2000"), _T("System 2000"), _T("Vortex"),
+// system2000_preinit, system2000_init, NULL, system2000_add_scsi_unit, ROMTYPE_SYSTEM2000 | ROMTYPE_NONE, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("xebec"), _T("9720H"), _T("Xebec"),
+// NULL, xebec_init, NULL, xebec_add_scsi_unit, ROMTYPE_XEBEC | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI
+// },
+// {
+// _T("kronos"), _T("Kronos"), _T("C-Ltd"),
+// NULL, kronos_init, NULL, kronos_add_scsi_unit, ROMTYPE_KRONOS, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xd1, 0x04, 0x40, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+// },
+// {
+// _T("hda506"), _T("HDA-506"), _T("Spirit Technology"),
+// NULL, hda506_init, NULL, hda506_add_scsi_unit, ROMTYPE_HDA506 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 0x04, 0x00, 0x00, 0x07, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+// },
+// {
+// _T("fasttrak"), _T("FastTrak"), _T("Xetec"),
+// NULL, fasttrak_init, NULL, fasttrak_add_scsi_unit, ROMTYPE_FASTTRAK, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+// NULL, 0,
+// true, EXPANSIONTYPE_SCSI,
+// 2022, 2, 0
+// },
+// {
+// _T("amax"), _T("AMAX ROM dongle"), _T("ReadySoft"),
+// NULL, NULL, NULL, NULL, ROMTYPE_AMAX | ROMTYPE_NONE, 0, 0, 0, false
+// },
+// {
+// _T("x86athdprimary"), _T("AT IDE Primary"), NULL,
+// NULL, x86_at_hd_init_1, NULL, x86_add_at_hd_unit_1, ROMTYPE_X86_AT_HD1 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION | EXPANSIONTYPE_IDE,
+// },
+// {
+// _T("x86athdxt"), _T("XTIDE Universal BIOS HD"), NULL,
+// NULL, x86_at_hd_init_xt, NULL, x86_add_at_hd_unit_xt, ROMTYPE_X86_XT_IDE | ROMTYPE_NONE, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION | EXPANSIONTYPE_IDE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_athdxt_settings
+// },
+// {
+// _T("x86rt1000"), _T("Rancho RT1000"), NULL,
+// NULL, x86_rt1000_init, NULL, x86_rt1000_add_unit, ROMTYPE_X86_RT1000 | ROMTYPE_NONE, 0, 0, BOARD_NONAUTOCONFIG_AFTER_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION | EXPANSIONTYPE_SCSI,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_rt1000_settings
+//
+// },
+//
+// /* PC Bridgeboards */
+//
+// {
+// _T("a1060"), _T("A1060 Sidecar"), _T("Commodore"),
+// NULL, a1060_init, NULL, NULL, ROMTYPE_A1060 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_bridge_sidecar_settings
+// },
+// {
+// _T("a2088"), _T("A2088"), _T("Commodore"),
+// NULL, a2088xt_init, NULL, NULL, ROMTYPE_A2088 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_bridge_settings
+// },
+// {
+// _T("a2088t"), _T("A2088T"), _T("Commodore"),
+// NULL, a2088t_init, NULL, NULL, ROMTYPE_A2088T | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_bridge_settings
+// },
+// {
+// _T("a2286"), _T("A2286"), _T("Commodore"),
+// NULL, a2286_init, NULL, NULL, ROMTYPE_A2286 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86at286_bridge_settings
+// },
+// {
+// _T("a2386"), _T("A2386SX"), _T("Commodore"),
+// NULL, a2386_init, NULL, NULL, ROMTYPE_A2386 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_BRIDGE,
+// 0, 0, 0, false, NULL,
+// false, 0, x86at386_bridge_settings
+// },
+//
+// // only here for rom selection and settings
+// {
+// _T("picassoiv"), _T("Picasso IV"), _T("Village Tronic"),
+// NULL, NULL, NULL, NULL, ROMTYPE_PICASSOIV | ROMTYPE_NONE, 0, 0, BOARD_IGNORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_RTG
+// },
+// {
+// _T("x86vga"), _T("x86 VGA"), NULL,
+// NULL, NULL, NULL, NULL, ROMTYPE_x86_VGA | ROMTYPE_NONE, 0, 0, BOARD_IGNORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION,
+// 0, 0, 0, false, NULL,
+// false, 0, x86vga_settings
+// },
+// {
+// _T("harlequin"), _T("Harlequin"), _T("ACS"),
+// NULL, NULL, NULL, NULL, ROMTYPE_HARLEQUIN | ROMTYPE_NOT, 0, 0, BOARD_IGNORE, false,
+// NULL, 0,
+// false, EXPANSIONTYPE_RTG,
+// 0, 0, 0, false, NULL,
+// false, 0, harlequin_settings
+// },
+//
+// /* Sound Cards */
+// {
+// _T("prelude"), _T("Prelude"), _T("Albrecht Computer Technik"),
+// NULL, prelude_init, NULL, NULL, ROMTYPE_PRELUDE | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, toccata_soundcard_settings,
+// { 0xc1, 1, 0, 0, 0x42, 0x31, 0, 0, 0, 3 }
+// },
+// {
+// _T("prelude1200"), _T("Prelude 1200"), _T("Albrecht Computer Technik"),
+// NULL, prelude1200_init, NULL, NULL, ROMTYPE_PRELUDE1200 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, toccata_soundcard_settings
+// },
+// {
+// _T("toccata"), _T("Toccata"), _T("MacroSystem"),
+// NULL, toccata_init, NULL, NULL, ROMTYPE_TOCCATA | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, toccata_soundcard_settings,
+// { 0xc1, 12, 0, 0, 18260 >> 8, 18260 & 255 }
+// },
+// {
+// _T("es1370"), _T("ES1370 PCI"), _T("Ensoniq"),
+// NULL, pci_expansion_init, NULL, NULL, ROMTYPE_ES1370 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND
+// },
+// {
+// _T("fm801"), _T("FM801 PCI"), _T("Fortemedia"),
+// NULL, pci_expansion_init, NULL, NULL, ROMTYPE_FM801 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND
+// },
+// {
+// _T("uaesnd_z2"), _T("UAESND Z2"), NULL,
+// NULL, uaesndboard_init_z2, NULL, NULL, ROMTYPE_UAESNDZ2 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 2, 0x00, 0x00, 6502 >> 8, 6502 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+// },
+// {
+// _T("uaesnd_z3"), _T("UAESND Z3"), NULL,
+// NULL, uaesndboard_init_z3, NULL, NULL, ROMTYPE_UAESNDZ3 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0x80, 2, 0x10, 0x00, 6502 >> 8, 6502 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+// },
+// {
+// _T("sb_isa"), _T("SoundBlaster ISA (Creative)"), NULL,
+// NULL, isa_expansion_init, NULL, NULL, ROMTYPE_SBISA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION | EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, sb_isa_settings
+// },
+//
+//
+//#if 0
+// {
+// _T("pmx"), _T("pmx"), NULL,
+// NULL, pmx_init, NULL, NULL, ROMTYPE_PMX | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_SOUND,
+// 0, 0, 0, false, NULL,
+// false, 0, NULL,
+// { 0xc1, 0x30, 0x00, 0x00, 0x0e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+// },
+//#endif
+//
+// /* Network */
+//{
+// _T("a2065"), _T("A2065"), _T("Commodore"),
+// NULL, a2065_init, NULL, NULL, ROMTYPE_A2065 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0x70, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("ariadne"), _T("Ariadne"), _T("Village Tronic"),
+// NULL, ariadne_init, NULL, NULL, ROMTYPE_ARIADNE | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0xc9, 0x00, 0x00, 2167 >> 8, 2167 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("ariadne2"), _T("Ariadne II"), _T("Village Tronic"),
+// NULL, ariadne2_init, NULL, NULL, ROMTYPE_ARIADNE2 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0xca, 0x00, 0x00, 2167 >> 8, 2167 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("hydra"), _T("AmigaNet"), _T("Hydra Systems"),
+// NULL, hydra_init, NULL, NULL, ROMTYPE_HYDRA | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0x01, 0x00, 0x00, 2121 >> 8, 2121 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("eb920"), _T("LAN Rover/EB920"), _T("ASDG"),
+// NULL, lanrover_init, NULL, NULL, ROMTYPE_LANROVER | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, lanrover_settings,
+// { 0xc1, 0xfe, 0x00, 0x00, 1023 >> 8, 1023 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("xsurf"), _T("X-Surf"), _T("Individual Computers"),
+// NULL, xsurf_init, NULL, NULL, ROMTYPE_XSURF | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0x17, 0x00, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+//},
+//{
+// _T("xsurf100z2"), _T("X-Surf-100 Z2"), _T("Individual Computers"),
+// NULL, xsurf100_init, NULL, NULL, ROMTYPE_XSURF100Z2 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0xc1, 0x64, 0x10, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00 }
+//},
+//{
+// _T("xsurf100z3"), _T("X-Surf-100 Z3"), _T("Individual Computers"),
+// NULL, xsurf100_init, NULL, NULL, ROMTYPE_XSURF100Z3 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+// { 0x82, 0x64, 0x32, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00 }
+//},
+//{
+// _T("ne2000pcmcia"), _T("RTL8019 PCMCIA (NE2000 compatible)"), NULL,
+// NULL, gayle_init_board_io_pcmcia, NULL, NULL, ROMTYPE_NE2KPCMCIA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET | EXPANSIONTYPE_PCMCIA,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+//},
+//{
+// _T("ne2000_pci"), _T("RTL8029 PCI (NE2000 compatible)"), NULL,
+// NULL, pci_expansion_init, NULL, NULL, ROMTYPE_NE2KPCI | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET,
+// 0, 0, 0, false, NULL,
+// false, 0, ethernet_settings,
+//},
+//{
+// _T("ne2000_isa"), _T("RTL8019 ISA (NE2000 compatible)"), NULL,
+// NULL, isa_expansion_init, NULL, NULL, ROMTYPE_NE2KISA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_NET | EXPANSIONTYPE_X86_EXPANSION,
+// 0, 0, 0, false, NULL,
+// false, 0, ne2k_isa_settings
+//},
+//
+///* Catweasel */
+//{
+// _T("catweasel"), _T("Catweasel"), _T("Individual Computers"),
+// NULL, expamem_init_catweasel, NULL, NULL, ROMTYPE_CATWEASEL | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_FLOPPY
+//},
+//
+//// misc
+//
+//{
+// _T("pcmciasram"), _T("PCMCIA SRAM"), NULL,
+// NULL, gayle_init_board_common_pcmcia, NULL, NULL, ROMTYPE_PCMCIASRAM | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM | EXPANSIONTYPE_PCMCIA | EXPANSIONTYPE_CUSTOMDISK,
+//},
+//{
+// _T("uaeboard_z2"), _T("UAEBOARD Z2"), NULL,
+// NULL, uaesndboard_init_z2, NULL, NULL, ROMTYPE_UAEBOARDZ2 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM
+//},
+//{
+// _T("uaeboard_z3"), _T("UAEBOARD Z3"), NULL,
+// NULL, uaesndboard_init_z3, NULL, NULL, ROMTYPE_UAEBOARDZ3 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM
+//},
+//{
+// _T("cubo"), _T("Cubo CD32"), NULL,
+// NULL, cubo_init, NULL, NULL, ROMTYPE_CUBO | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_CUSTOM,
+// 0, 0, 0, false, NULL,
+// false, 0, cubo_settings,
+//},
+//{
+// _T("x86_mouse"), _T("x86 Bridgeboard mouse"), NULL,
+// NULL, isa_expansion_init, NULL, NULL, ROMTYPE_X86MOUSE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+// NULL, 0,
+// false, EXPANSIONTYPE_X86_EXPANSION,
+// 0, 0, 0, false, NULL,
+// false, 0, x86_mouse_settings
+//},
+
+
+{
+ NULL
+}
+};
+
diff --git a/src/filesys.asm b/src/filesys.asm
index d5978fd3..d071661f 100644
--- a/src/filesys.asm
+++ b/src/filesys.asm
@@ -85,25 +85,25 @@ NRF_NOTIFY_INITIAL = 16
NRF_MAGIC = $80000000
; normal filehandler segment entrypoint
- dc.l (rom_end-start)>>2 ; 4
+ dc.l (rom_end-start)/4 ; 4
our_seglist:
dc.l 0 ; 8 /* NextSeg */
start:
bra.s startjmp
- dc.w 13 ; 0 12
+ dc.w 13 ; 0 12
startjmp:
- bra.w filesys_mainloop ; 1 16
- dc.l make_dev-start ; 2 20
- dc.l filesys_init-start ; 3 24
- dc.l moverom-start ; 4 28
- dc.l bootcode-start ; 5 32
- dc.l setup_exter-start ; 6 36
- dc.l bcplwrapper-start ; 7 40
- dc.l afterdos-start ; 8 44
- dc.l hwtrap_install-start ; 9 48
- dc.l hwtrap_entry-start ; 10 52
- dc.l 0 ; keymaphack-start ; 11 56
- dc.l 0 ; fpu060disable-start ; 12 60
+ bra.w filesys_mainloop ; 1 16
+ dc.l make_dev-start ; 2 20
+ dc.l filesys_init-start ; 3 24
+ dc.l moverom-start ; 4 28
+ dc.l bootcode-start ; 5 32
+ dc.l setup_exter-start ; 6 36
+ dc.l bcplwrapper-start ; 7 40
+ dc.l afterdos-start ; 8 44
+ dc.l hwtrap_install-start ; 9 48
+ dc.l hwtrap_entry-start ; 10 52
+ dc.l keymaphack-start ; 11 56
+ dc.l fpu060disable-start ; 12 60
bootcode:
lea.l doslibname(pc),a1
@@ -114,13 +114,19 @@ bootcode:
jsr (a0)
rts
+fpu060disable:
+ movec pcr,d0
+ bset #1,d0
+ movec d0,pcr
+ jmp (a5)
+
; BCPL filehandler segment entry point
; for KS 1.1 and older.
cnop 0,4
- dc.l ((bcpl_end-bcpl_start)>>2)+1
+ dc.l (bcpl_end-bcpl_start)/4+1
our_bcpl_seglist:
dc.l 0
- dc.l ((bcpl_end-bcpl_start)>>2)+1
+ dc.l (bcpl_end-bcpl_start)/4+1
bcpl_start:
; d1 = startup packet
lsl.l #2,d1
@@ -161,6 +167,10 @@ afterdos:
bsr.w getrtbase
move.l d1,(a0)
+ bsr.w clipboard_init
+ bsr.w consolehook
+ bsr.w segtrack_init
+
movem.l (sp)+,d2-d7/a2-a6
moveq #0,d0
rts
@@ -265,6 +275,7 @@ FSIN_none:
cmp.w #34,20(a6) ; 1.2 or older?
bcs.w FSIN_tooold
+ ; add MegaChipRAM
moveq #3,d4 ; MEMF_CHIP | MEMF_PUBLIC
cmp.w #36,20(a6)
bcs.s FSIN_ksold
@@ -272,8 +283,16 @@ FSIN_none:
FSIN_ksold
move.w #$FF80,d0
bsr.w getrtbase
- jsr (a0)
+ jsr (a0) ; d1 = size, a1 = start address
move.l d0,d5
+ move.l a1,a0
+ move.l d1,d0
+ beq.s FSIN_fchip_done
+ move.l d4,d1
+ moveq #-5,d2
+ lea fchipname(pc),a1
+ jsr -618(a6) ; AddMemList
+FSIN_fchip_done
; only if >=4M chip
cmp.l #$400000,d5
@@ -320,6 +339,8 @@ FSIN_chip_done
bsr.w getrtbase
jsr (a0)
+
+
FSIN_tooold
movem.l (sp)+,d0-d7/a0-a6
@@ -552,7 +573,7 @@ EXTT_cause:
bra.b EXTT_loop
EXTT_notificationhack:
cmp.w #5,d0
- bgt.b EXTT_loop
+ bgt.b EXTT_shellexec
movem.l a0-a1,-(sp)
moveq #38,d0
move.l #65536+1,d1
@@ -569,6 +590,20 @@ EXTT_notificationhack:
move.l a2,a1
jsr -366(a6) ; PutMsg
bra.w EXTT_loop
+EXTT_shellexec
+ cmp.w #6,d0
+ bgt.w EXTT_loop
+ lea shellexecname(pc),a0
+ lea shellexecproc(pc),a1
+ moveq #1,d0
+ move.l #10000,d1
+ bsr.w createproc
+ move.l d0,d1
+ move.w #$FF50,d0 ; exter_int_helper
+ bsr.w getrtbaselocal
+ moveq #20,d0
+ jsr (a0)
+ bra.w EXTT_loop
exter_server_new:
moveq #0,d0
@@ -577,6 +612,10 @@ exter_server_new:
beq.s .nouaeint
move.l (a1)+,a6 ; SysBase
+; movem.l d7/a0/a2,-(sp)
+; bsr.w exter_do
+; movem.l (sp)+,d7/a0/a2
+
move.l (a1),a1 ; Task
move.l #$100,d0 ; SIGF_DOS
jsr -$144(a6) ; Signal
@@ -587,6 +626,101 @@ exter_server_new:
rts
cnop 0,4
+ dc.l 16
+shellexecproc:
+ dc.l 0
+
+ move.l 4.w,a6
+ lea doslibname(pc),a1
+ moveq #0,d0
+ jsr -$228(a6) ; OpenLibrary
+ move.l d0,a5
+ exg a5,a6
+ bra.s .seproc1
+
+.seproc0
+ exg a5,a6
+ moveq #0,d0
+ bset #13,d0 ; SIGBREAK_CTRL_D
+ jsr -$013e(a6) ;Wait
+ exg a5,a6
+
+.seproc1
+ move.w #$FF50,d0 ; exter_int_helper
+ bsr.w getrtbaselocal
+ moveq #21,d0
+ jsr (a0)
+ ; a0 = command
+ move.l a0,d7
+ beq.s .seproc0
+
+ move.l sp,a4
+ lea -5*8-512(sp),sp
+ move.l sp,d6
+ move.l d6,a2
+
+ lea 5*8(a2),a3
+ move.l a3,a1
+ move.l d7,a0
+.seproc2
+ move.b (a0)+,(a1)+
+ bne.s .seproc2
+ move.l d7,a0
+ clr.b (a0)
+
+ ; SYS_Input
+ move.l #$80000000+32+1,(a2)+
+ lea nil_name(pc),a0
+ move.l a0,d1
+ move.l #1005,d2
+ jsr -$1e(a6) ;Open
+ move.l d0,(a2)+
+
+ ; SYS_Output
+ move.l #$80000000+32+2,(a2)+
+ lea nil_name(pc),a0
+ move.l a0,d1
+ jsr -$1e(a6) ;Open
+ move.l d0,(a2)+
+
+ ; SYS_Async
+ move.l #$80000000+32+3,(a2)+
+ moveq #-1,d0
+ move.l d0,(a2)+
+
+ clr.l (a2)+
+ clr.l (a2)
+
+ cmp.w #36,20(a6)
+ bcc.s .seproc3
+
+ move.l d6,a2
+ move.l a3,d1 ;Command
+ moveq #0,d2 ;Input
+ move.l 1*8+4(a2),d3 ;Output
+ jsr -$de(a6) ;Execute
+
+ move.l 0*8+4(a2),d1
+ jsr -$24(a6) ;Close
+ move.l 1*8+4(a2),d1
+ jsr -$24(a6) ;Close
+
+ bra.s .seproc4
+
+.seproc3
+ move.l a3,d1
+ move.l d6,d2
+ jsr -$25e(a6) ; SystemTagList
+
+.seproc4
+ move.l a4,sp
+
+ move.w #$FF50,d0 ; exter_int_helper
+ bsr.w getrtbaselocal
+ moveq #22,d0
+ jsr (a0)
+
+ bra.w .seproc0
; d0 = exter task, d1 = trap task
heartbeatvblank:
@@ -606,7 +740,7 @@ heartbeatvblank:
move.l #65536+1,d1
jsr AllocMem(a6)
move.l d0,a4
-
+
lea 22(a4),a3
move.l a3,a1
move.l a2,(a1)+
@@ -684,13 +818,13 @@ setup_exter:
move.l #$10001,d1
jsr AllocMem(a6)
move.l d0,a1
-
+
lea 26(a1),a0
move.l a2,(a0)+
move.l a6,(a0)+
move.l d2,(a0)+
move.l d3,(a0)
-
+
lea.l exter_name(pc),a0
move.l a0,10(a1)
lea 26(a1),a2
@@ -1306,7 +1440,12 @@ dont_mount:
move.l PP_FSPTR(a1),a0
tst.l PP_FSSIZE(a1)
bpl.s nordbfs4
- moveq #0,d0
+ movem.l d1/a0-a1,-(sp)
+ move.l PP_FSSIZE(a1),d0
+ neg.l d0
+ move.l PP_FSPTR(a1),a0
+ bsr.w fstrack_init
+ movem.l (sp)+,d1/a0-a1
move.l d0,PP_FSPTR(a1)
move.l d0,a0
clr.l PP_FSSIZE(a1)
@@ -1490,6 +1629,12 @@ addfsonthefly ; d1 = fs index
jsr FreeMem(a6)
.nomem move.l a4,a1
jsr -414(a6) ; CloseLibrary
+ ; reply done
+ moveq #4,d1
+ move.w #$FF48,d0
+ bsr.w getrtbaselocal
+ move.l d6,d0
+ jsr (a0)
movem.l (sp)+,d2-d7/a2-a6
rts
@@ -1640,11 +1785,28 @@ FSML_loop:
.noclk
btst #1,173(a3)
beq.s .nodebug
+ bsr.w debuggerstart
bclr #1,173(a3)
.nodebug
; disk change notification from native code
+ tst.b 172(a3)
+ beq.s .nodc
+ ; call filesys_media_change_reply (pre)
+ move.w #$ff58,d0 ; fsmisc_helper
+ bsr.w getrtbaselocal
+ moveq #1,d0 ; filesys_media_change_reply
+ jsr (a0)
+ tst.l d0
+ beq.s .nodc2
+ bsr.w diskchange
+.nodc2
clr.b 172(a3)
-
+ ; call filesys_media_change_reply (post)
+ move.w #$ff58,d0 ; fsmisc_helper
+ bsr.w getrtbaselocal
+ moveq #2,d0 ; filesys_media_change_reply
+ jsr (a0)
+.nodc
move.l a4,d0
beq.s nonnotif
@@ -2087,7 +2249,7 @@ getgfxlimits:
move.w 100(a0),d4
move.l MH_FOO_GFXBASE(a5),a6
- ; Text Overscan area needed
+ ; Text Overscan area needed
sub.l a0,a0
lea MH_FOO_DIMS(a5),a1
moveq #0,d0
@@ -2183,7 +2345,7 @@ mousehack_task:
moveq #-1,d0
move.w d0,MH_FOO_CNT(a3)
- ; send data structure address
+ ; send data structure address
move.w #$FF38,d0
moveq #5,d1
bsr.w getrtbaselocal
@@ -2396,7 +2558,7 @@ mhloop:
clr.l (a1) ;TAG_DONE
bsr.w mhdoio
-
+
.notablet
move.b MH_E(a4),d0
btst #MH_TABLET,d0
@@ -2532,6 +2694,461 @@ mousehackint:
moveq #0,d0
rts
+; clipboard sharing
+
+CLIP_WRITE_SIZE = 0
+CLIP_WRITE_ALLOC = (CLIP_WRITE_SIZE+4)
+CLIP_TASK = (CLIP_WRITE_ALLOC+4)
+CLIP_UNIT = (CLIP_TASK+4)
+CLIP_ID = (CLIP_UNIT+4)
+CLIP_EXEC = (CLIP_ID+4)
+CLIP_DOS = (CLIP_EXEC+4)
+CLIP_HOOK = (CLIP_DOS+4)
+CLIP_BUF = (CLIP_HOOK+20)
+CLIP_BUF_SIZE = 8
+CLIP_POINTER_NOTIFY = (CLIP_BUF+CLIP_BUF_SIZE)
+CLIP_POINTER_PREFS = (CLIP_POINTER_NOTIFY+48)
+CLIP_END = (CLIP_POINTER_PREFS+32)
+
+clipboard_init:
+ movem.l a5/a6,-(sp)
+
+ move.w #$FF38,d0
+ moveq #17,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ btst #0,d0
+ beq.s .noclip
+
+ move.l 4.w,a6
+ move.l #CLIP_END,d0
+ move.l #$10001,d1
+ jsr AllocMem(a6)
+ tst.l d0
+ beq.w clipdie
+ move.l d0,a5
+ move.l a6,CLIP_EXEC(a5)
+
+ move.w #$FF38,d0
+ moveq #14,d1
+ bsr.w getrtbaselocal
+ move.l a5,d0
+ jsr (a0)
+
+ ; we need to be a process, LoadLibrary() needs to call dos
+ lea clname(pc),a0
+ lea clipboard_proc(pc),a1
+ moveq #-10,d0
+ move.l #10000,d1
+ bsr.w createproc
+.noclip
+ moveq #0,d0
+ movem.l (sp)+,a5/a6
+ rts
+
+clipkill
+ move.w #$FF38,d0
+ moveq #10,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ rts
+
+clipdie:
+ bsr.s clipkill
+ move.l a5,d0
+ beq.s .cd1
+ move.l CLIP_EXEC(a5),a6
+ move.l CLIP_DOS(a5),d0
+ beq.s .cd2
+ move.l d0,a1
+ jsr -414(a6) ; CloseLibrary
+.cd2
+ move.l a5,a1
+ move.l #CLIP_END,d0
+ jsr FreeMem(a6)
+.cd1
+ moveq #0,d0
+ rts
+
+prefsread:
+ movem.l d2-d4/a2-a6,-(sp)
+ move.l CLIP_DOS(a5),a6
+ lea pointer_prefs(pc),a0
+ move.l a0,d1
+ move.l #1005,d2
+ jsr -$001e(a6) ;Open
+ move.l d0,d4
+ beq.s .pr1
+ lea CLIP_POINTER_PREFS(a5),a2
+.pr4
+ clr.l (a2)
+.pr3
+ move.w 2(a2),(a2)
+ move.l a2,d2
+ addq.l #2,d2
+ moveq #2,d3
+ move.l d4,d1
+ jsr -$002a(a6) ;Read
+ cmp.l d0,d3
+ bne.s .pr1
+ cmp.l #'PNTR',(a2)
+ bne.s .pr3
+ move.l a2,d2
+ moveq #4,d3
+ move.l d4,d1
+ jsr -$002a(a6) ;Read
+ move.l a2,d2
+ moveq #32,d3
+ move.l d4,d1
+ jsr -$002a(a6) ;Read
+ cmp.l d0,d3
+ bne.s .pr1
+ tst.w 16(a2) ;pp_Which
+ bne.s .pr4
+ move.w #$FF38,d0
+ moveq #16,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+.pr1
+ move.l d4,d1
+ beq.s .pr2
+ jsr -$0024(a6) ;Close
+.pr2
+ movem.l (sp)+,d2-d4/a2-a6
+ rts
+
+prefshook:
+ move.l CLIP_DOS(a5),a6
+ lea ram_name(pc),a0
+ move.l a0,d1
+ moveq #-2,d2
+ jsr -$0054(a6) ;Lock
+ move.l d0,d1
+ beq.s .ph1
+ jsr -$005a(a6) ;Unlock
+ move.l CLIP_EXEC(a5),a6
+ lea CLIP_POINTER_NOTIFY(a5),a2
+ moveq #-1,d0
+ jsr -$014a(a6) ;AllocSignal
+ move.b d0,20(a2) ;nr_SignalNum
+ lea pointer_prefs(pc),a0
+ move.l a0,(a2) ;nr_Name
+ move.l #NRF_SEND_SIGNAL|NRF_NOTIFY_INITIAL,12(a2) ;nr_Flags
+ move.l CLIP_TASK(a5),16(a2) ;nr_Task
+ move.l CLIP_DOS(a5),a6
+ move.l a2,d1
+ jsr -$378(a6) ;StartNotify
+.ph1
+ move.l CLIP_EXEC(a5),a6
+ rts
+
+ cnop 0,4
+ dc.l 16
+clipboard_proc:
+ dc.l 0
+
+ move.w #$FF38,d0
+ moveq #13,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ tst.l d0
+ beq.w clipdie
+ move.l d0,a5
+ move.l CLIP_EXEC(a5),a6
+
+ sub.l a1,a1
+ jsr -294(a6) ; FindTask
+ move.l d0,CLIP_TASK(a5)
+
+ lea doslibname(pc),a1
+ moveq #0,d0
+ jsr -$0228(a6) ; OpenLibrary
+ move.l d0,CLIP_DOS(a5)
+ beq.w clipdie
+ move.l d0,a6
+
+.devsloop
+ moveq #50,d1
+ jsr -$00c6(a6) ;Delay
+ lea devs_name(pc),a0
+ move.l a0,d1
+ moveq #-2,d2
+ jsr -$0054(a6) ;Lock
+ tst.l d0
+ beq.s .devsloop
+ move.l d0,d1
+ jsr -$005a(a6) ;Unlock
+ moveq #50,d1
+ jsr -$00c6(a6) ;Delay
+ lea clip_name(pc),a0
+ move.l a0,d1
+ moveq #-2,d2
+ jsr -$0054(a6) ;Lock
+ tst.l d0
+ beq.w clipdie
+ move.l d0,d1
+ jsr -$005a(a6) ;Unlock
+
+ move.l CLIP_EXEC(a5),a6
+
+ bsr.w createport
+ moveq #0,d1
+ move.w #52,d1
+ bsr.w createio
+ move.l d0,a4
+ tst.l d0
+ beq.w clipdie
+
+cfloop2
+ moveq #0,d0
+ bset #13,d0
+ jsr -$013e(a6) ;Wait
+
+ moveq #0,d1
+ move.l CLIP_UNIT(a5),d0
+ lea clip_dev(pc),a0
+ move.l a4,a1
+ jsr -$01bc(a6) ;OpenDevice
+ tst.l d0
+ bne.s cfloop2
+ move.l 20(a4),a0 ;device node
+ cmp.w #37,20(a0) ;must be at least v37
+ bcc.s cfversion
+ ;too lazy to free everything..
+ bsr.w clipkill
+cfloop3
+ moveq #0,d0
+ jsr -$013e(a6) ;Wait
+ bra.s cfloop3
+
+cfversion
+ bsr.w prefshook
+
+ lea CLIP_HOOK(a5),a0
+ move.l a0,40(a4)
+ moveq #1,d0
+ move.l d0,36(a4)
+ move.w #12,28(a4) ;CBD_CHANGEHOOK
+ move.l a5,CLIP_HOOK+16(a5)
+ lea cliphook(pc),a0
+ move.l a0,CLIP_HOOK+8(a5)
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+
+ move.w #$FF38,d0
+ moveq #15,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ tst.l CLIP_WRITE_SIZE(a5)
+ bne.s clipsignal
+
+cfloop
+ moveq #0,d0
+ moveq #0,d2
+ move.b CLIP_POINTER_NOTIFY+20(a5),d2
+ bset d2,d0
+ bset #13,d0
+ jsr -$013e(a6) ;Wait
+ btst d2,d0
+ beq.s clipsignal
+ bsr.w prefsread
+ bra.s cfloop
+
+clipsignal
+ move.l CLIP_WRITE_SIZE(a5),d0
+ beq.w clipread
+ ;allocate amiga-side space
+ moveq #1,d1
+ jsr AllocMem(a6)
+ move.l d0,CLIP_WRITE_ALLOC(a5)
+ ;and notify host-side
+ move.w #$FF38,d0
+ moveq #12,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ tst.l d0
+ beq.s .nowrite
+ ; and now we should have the data in CLIP_WRITE_ALLOC
+ tst.l CLIP_WRITE_ALLOC(a5)
+ beq.s .nowrite
+
+ move.w #3,28(a4) ;CMD_WRITE
+ clr.b 31(a4)
+ clr.l 32(a4)
+ move.l CLIP_WRITE_SIZE(a5),36(a4)
+ move.l CLIP_WRITE_ALLOC(a5),40(a4)
+ clr.l 44(a4)
+ clr.l 48(a4)
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+ move.l 48(a4),CLIP_ID(a5)
+ move.w #4,28(a4) ;CMD_UPDATE
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+
+.nowrite
+ move.l CLIP_WRITE_SIZE(a5),d0
+ clr.l CLIP_WRITE_SIZE(a5)
+ move.l CLIP_WRITE_ALLOC(a5),d1
+ beq.w cfloop
+ move.l d1,a1
+ jsr FreeMem(a6)
+ bra.w cfloop
+
+clipread:
+ ; read first 8 bytes
+ move.w #2,28(a4) ;CMD_READ
+ lea CLIP_BUF(a5),a0
+ clr.l (a0)
+ clr.l 4(a0)
+ clr.b 31(a4)
+ clr.l 44(a4)
+ clr.l 48(a4)
+ move.l a0,40(a4)
+ moveq #8,d0
+ move.l d0,36(a4)
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+ cmp.l #'FORM',CLIP_BUF(a5)
+ bne.s .cf1
+ move.l CLIP_BUF+4(a5),d0
+ beq.s .cf1
+ bmi.s .cf1
+ move.l 48(a4),CLIP_ID(a5)
+ addq.l #8,d0
+ move.l d0,d2
+ moveq #1,d1
+ jsr AllocMem(a6)
+ tst.l d0
+ beq.s .cf1
+ move.l d0,a2
+ ; read the rest
+ move.l a2,a0
+ move.l CLIP_BUF(a5),(a0)+
+ move.l CLIP_BUF+4(a5),(a0)+
+ move.l a0,40(a4)
+ move.l d2,d0
+ subq.l #8,d0
+ move.l d0,36(a4)
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+ move.w #$FF38,d0
+ moveq #11,d1
+ bsr.w getrtbaselocal
+ move.l 32(a4),d0
+ jsr (a0)
+ move.l a2,a1
+ move.l d2,d0
+ jsr FreeMem(a6)
+.cf1
+ ; tell clipboard.device that we are done (read until io_Actual==0)
+ tst.l 32(a4)
+ beq.w cfloop
+ lea CLIP_BUF(a5),a0
+ move.l a0,40(a4)
+ moveq #1,d0
+ move.l d0,36(a4)
+ clr.l 32(a4)
+ move.l a4,a1
+ jsr -$01c8(a6) ;DoIO
+ bra.s .cf1
+
+cliphook:
+ lea -CLIP_HOOK(a0),a0
+ move.l 8(a1),d0
+ cmp.l CLIP_ID(a0),d0 ;ClipHookMsg->chm_ClipID
+ beq.s .same
+ move.l d0,CLIP_ID(a0)
+ move.l a6,-(sp)
+ move.l CLIP_EXEC(a0),a6
+ move.l CLIP_TASK(a0),a1
+ moveq #0,d0
+ bset #13,d0 ;SIG_D
+ jsr -$0144(a6) ;Signal
+ move.l (sp)+,a6
+.same
+ moveq #0,d0
+ rts
+
+consolehook:
+ move.l 4.w,a6
+
+ moveq #-1,d2
+ move.w #$FF38,d0
+ moveq #17,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ btst #1,d0
+ beq.s .ch2
+
+ moveq #0,d2
+ jsr -$0084(a6) ;Forbid
+ lea 350(a6),a0 ;DeviceList
+ lea con_dev(pc),a1
+ jsr -$114(a6) ;FindName
+ tst.l d0
+ beq.s .ch1
+ move.l d0,a0
+ lea chook(pc),a1
+ move.l -$1e+2(a0),a2 ; BeginIO
+ move.l a1,-$1e+2(a0)
+ move.l a0,a1
+ move.w #$FF38,d0
+ moveq #101,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ moveq #1,d2
+.ch1
+ jsr -$008a(a6) ;Permit
+.ch2
+ move.l d2,d0
+ rts
+
+chook:
+ subq.l #4,sp ; native code fills with original return address
+ movem.l d0-d1/a0,-(sp)
+ move.w #$FF38,d0
+ moveq #102,d1
+ bsr.w getrtbaselocal
+ jsr (a0)
+ movem.l (sp)+,d0-d1/a0
+ rts
+
+debuggerstart
+ move.l 4.w,a6
+ lea debuggerprocname(pc),a0
+ lea debuggerproc(pc),a1
+ moveq #15,d0
+ move.l #8000,d1
+ bsr.w createproc
+ rts
+ cnop 0,4
+ dc.l 16
+debuggerproc
+ dc.l 0
+ move.l 4.w,a6
+ moveq #0,d0
+ lea doslibname(pc),a1
+ jsr -$0228(a6) ; OpenLibrary
+ move.l d0,a6
+ moveq #2,d1
+ move.w #$FF78,d0
+ bsr.w getrtbaselocal
+ move.l a0,a2
+ moveq #1,d1
+ jsr (a0) ; debugger init
+ tst.l d1
+ beq.s .dend
+ move.l d1,a3
+ jsr -$1f8(a6) ; RunCommand
+ moveq #2,d1
+ move.l a3,a0
+ jsr (a2) ; debugger end
+.dend
+ move.l a6,a1
+ move.l 4.w,a6
+ jsr -$19e(a6)
+ rts
bootres_code:
@@ -2653,10 +3270,10 @@ adddosnodec
;We need to put dospacket back in pr_MsgPort.
cnop 0,4
- dc.l ((bcplwrapper_end-bcplwrapper_start)>>2)+1
+ dc.l (bcplwrapper_end-bcplwrapper_start)/4+1
bcplwrapper:
dc.l 0
- dc.l ((bcplwrapper_end-bcplwrapper_start)>>2)+1
+ dc.l (bcplwrapper_end-bcplwrapper_start)/4+1
bcplwrapper_start:
move.l d1,d2
move.l 4.w,a6
@@ -2786,6 +3403,8 @@ hwtrap_entry:
move.l 1*4(sp),TRAP_DATA_DATA+1*4(a0) ;D1
move.l 2*4(sp),TRAP_DATA_DATA+8*4(a0) ;A0
move.l 3*4(sp),TRAP_DATA_DATA+8*4+1*4(a0) ;A1
+ lea 4*4+2+4(sp),a2
+ move.l a2,TRAP_DATA_DATA+8*4+7*4(a0) ;A7
move.l a0,a2 ; data
move.l a1,a3 ; status
@@ -3275,6 +3894,433 @@ moveromreloc:
dc.w exter_task_wait-start
dc.w 0
+keymaphack:
+ move.l 4.w,a6
+
+ moveq #keymapfunc_end-keymapfunc,d0
+ moveq #1,d1
+ jsr -$c6(a6) ;AllocMem
+ tst.l d0
+ beq.s .keymap0
+ move.l d0,a3
+
+ lea keymapfunc(pc),a0
+ move.l a3,a1
+ moveq #keymapfunc_end-keymapfunc-1,d0
+.keymap1
+ move.b (a0)+,(a1)+
+ dbf d0,.keymap1
+ lea keymapfunc_patch(pc),a0
+ move.l a0,keymap_func_ptr-keymapfunc+2(a3)
+ lea keymapfunc2_patch(pc),a0
+ move.l a0,keymaplibfunc-keymapfunc+2(a3)
+
+ jsr -$84(a6)
+
+ lea 350(a6),a0 ;DeviceList
+ lea con_dev(pc),a1
+ jsr -$114(a6) ;FindName
+ tst.l d0
+ beq.s .keymap2
+ move.l d0,a1
+ move.l a3,d0
+ move.w #-$1e,a0 ;BeginIO
+ jsr -$1a4(a6)
+ move.l d0,keymap_original-keymapfunc(a3)
+.keymap2
+
+ lea 378(a6),a0 ;LibList
+ lea key_lib(pc),a1
+ jsr -$114(a6) ;FindName
+ tst.l d0
+ beq.s .keymap3
+ move.l d0,a1
+ lea keymaplibfunc-keymapfunc(a3),a0
+ move.l a0,d0
+ move.w #-$1e,a0 ;SetKeyMapDefault
+ jsr -$1a4(a6)
+ move.l d0,keymap_original2-keymapfunc(a3)
+.keymap3
+
+ jsr -$8a(a6)
+
+.keymap0
+ rts
+
+keymapfunc
+ cmp.w #10,28(a1) ;CD_SETKEYMAP
+ beq.s keymap_func_ptr
+ cmp.w #12,28(a1) ;CD_SETDEFAULTKEYMAP
+ bne.s keymapfunc2
+keymap_func_ptr
+ jsr 0.l
+keymapfunc2
+ move.l keymap_original(pc),-(sp)
+ rts
+keymaplibfunc
+ jsr 0.l
+ move.l keymap_original2(pc),-(sp)
+ rts
+keymap_original
+ dc.l 0
+keymap_original2
+ dc.l 0
+keymapfunc_end
+
+ ; a0 = keymap
+keymapfunc2_patch
+ movem.l d0-d7/a0-a6,-(sp)
+ move.l a0,a2
+ bra.s keymapfunc_entry
+
+ ; a1 = request
+keymapfunc_patch
+ movem.l d0-d7/a0-a6,-(sp)
+ move.l 40(a1),a2 ;io_Data
+
+keymapfunc_entry
+ move.l 4.w,a6
+
+ subq.l #8,sp
+ move.l sp,a4
+
+ move.l a4,-(sp) ; &size
+ move.l a2,-(sp)
+ bsr.w GetKeyMapData
+ addq.l #8,sp
+ tst.l d0
+ beq.s .keymap0
+ move.l d0,d2
+
+ move.w #$ff38,d0
+ bsr.w getrtbase
+
+ moveq #21,d1
+ move.l d2,a1 ; a1 = data
+ move.l (a4),d0 ; d0 = size
+ jsr (a0)
+
+ move.l d2,a1
+ move.l (a4),d0
+ jsr -$d2(a6) ;FreeMem
+
+.keymap0
+ addq.l #8,sp
+ movem.l (sp)+,d0-d7/a0-a6
+ rts
+
+FSTRACK_DATA = 16
+
+ ; a0 = fsdata (raw)
+ ; d0 = size
+fstrack_init
+ movem.l d2-d7/a2-a6,-(sp)
+ move.l d0,d5
+ move.l a0,a5
+ moveq #0,d7
+
+ move.l 4.w,a6
+ cmp.w #37,20(a6)
+ bcs .noinit
+
+ move.w #$FF38,d0
+ move.l #208,d1
+ bsr.w getrtbaselocal
+ move.l a0,a4
+ jsr (a0)
+ btst #1,d0
+ beq .noinit
+
+ move.l #fstrack_end-fstrack_start+FSTRACK_DATA,d0
+ move.l #65536+1,d1
+ jsr -$c6(a6)
+ tst.l d0
+ beq .noinit
+ move.l d0,a2
+ add.w #FSTRACK_DATA,a2
+
+ move.l a2,a1
+ moveq #(fstrack_end-fstrack_start)/4-1,d0
+ lea fstrack_start(pc),a0
+.copyfstrack
+ move.l (a0)+,(a1)+
+ dbf d0,.copyfstrack
+
+ lea allocmem_uae_p+2-fstrack_start(a2),a0
+ move.l a4,(a0)
+ lea freemem_uae_p+2-fstrack_start(a2),a0
+ move.l a4,(a0)
+
+ lea allocvec_uae_p+2-fstrack_start(a2),a0
+ move.l a4,(a0)
+ lea freevec_uae_p+2-fstrack_start(a2),a0
+ move.l a4,(a0)
+
+ lea allocmem-fstrack_start(a2),a0
+ move.l a0,d0
+ move.l a6,a1
+ move.w #-$c6,a0
+ jsr -$1a4(a6)
+ lea allocmem_func+2-fstrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea freemem-fstrack_start(a2),a0
+ move.l a0,d0
+ move.l a6,a1
+ move.w #-$d2,a0
+ jsr -$1a4(a6)
+ lea freemem_func+2-fstrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea allocvec-fstrack_start(a2),a0
+ move.l a0,d0
+ move.l a6,a1
+ move.w #-$2ac,a0
+ jsr -$1a4(a6)
+ lea allocvec_func+2-fstrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea freevec-fstrack_start(a2),a0
+ move.l a0,d0
+ move.l a6,a1
+ move.w #-$2b2,a0
+ jsr -$1a4(a6)
+ lea freevec_func+2-fstrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea -FSTRACK_DATA(a2),a0
+ move.l a5,(a0)+
+ move.l d5,(a0)+
+ move.l a4,(a0)+
+
+ move.l a2,d7
+
+.noinit
+ move.l d7,d0
+ movem.l (sp)+,d2-d7/a2-a6
+ rts
+
+ cnop 0,4
+fstrack_start
+
+ ;dc.l 0 ;real_filesys_entry
+ ;dc.l 0 ;fs_size
+ ;dc.l 0 ;misc_funcs
+ ;dc.l 0
+
+fstrack_entry
+ nop
+ nop
+ move.l 4.w,a1
+ move.l 276(a1),a1 ;task
+ lea freemem+2(pc),a0
+ move.l a1,(a0)
+ lea allocmem+2(pc),a0
+ move.l a1,(a0)
+ lea freevec+2(pc),a0
+ move.l a1,(a0)
+ lea allocvec+2(pc),a0
+ move.l a1,(a0)
+ lea fstrack_entry-FSTRACK_DATA(pc),a2
+ move.l (a2)+,a0 ;data
+ move.l (a2)+,d0 ;len
+ move.l (a2),a2 ;misc_funcs
+ moveq #0,d2 ;stack
+ move.l #200,d1
+ jsr (a2)
+ move.l d0,-(sp)
+ rts
+
+ ; a1 / d0
+freemem
+ cmp.l #$ffffffff,276(a6)
+ beq.s freemem_uae
+freemem_func
+ jsr 0.l
+ rts
+freemem_uae
+ move.l #205,d1
+ move.l (sp),a0
+freemem_uae_p
+ jsr 0.l
+ tst.l d0
+ beq.s freemem_func
+ rts
+
+ ; d0 / d1
+allocmem
+ cmp.l #$ffffffff,276(a6)
+ beq.s allocmem_uae
+allocmem_func
+ jsr 0.l
+ rts
+allocmem_uae
+ move.l d1,a1
+ move.l (sp),a0
+ move.l #204,d1
+allocmem_uae_p
+ jsr 0.l
+ cmp.w #0,a0
+ beq.s allocmem_func
+ rts
+
+ ; a1
+freevec
+ cmp.l #$ffffffff,276(a6)
+ beq.s freevec_uae
+freevec_func
+ jsr 0.l
+ rts
+freevec_uae
+ move.l #207,d1
+ move.l (sp),a0
+freevec_uae_p
+ jsr 0.l
+ tst.l d0
+ beq.s freevec_func
+ rts
+
+ ; d0 / d1
+allocvec
+ cmp.l #$ffffffff,276(a6)
+ beq.s allocvec_uae
+allocvec_func
+ jsr 0.l
+ rts
+allocvec_uae
+ move.l d1,a1
+ move.l (sp),a0
+ move.l #206,d1
+allocvec_uae_p
+ jsr 0.l
+ cmp.w #0,a0
+ beq.s allocvec_func
+ rts
+
+ cnop 0,4
+fstrack_end
+
+segtrack_init
+ move.l 4.w,a0
+ cmp.w #37,20(a0)
+ bcs .noinit
+
+ move.w #$FF38,d0
+ move.l #208,d1
+ bsr.w getrtbaselocal
+ move.l a0,d4
+ jsr (a0)
+ btst #0,d0
+ beq .noinit
+
+ move.l #segtrack_end-segtrack_start,d0
+ move.l #65536+1,d1
+ jsr -$c6(a6)
+ tst.l d0
+ beq .noinit
+ move.l d0,a2
+
+ move.l a2,a1
+ moveq #(segtrack_end-segtrack_start)/4-1,d0
+ lea segtrack_start(pc),a0
+.copysegtrack
+ move.l (a0)+,(a1)+
+ dbf d0,.copysegtrack
+
+ lea doslibname(pc),a1
+ moveq #0,d0
+ jsr -$0228(a6) ; OpenLibrary
+ tst.l d0
+ beq.s .noinit
+ move.l d0,a4
+
+ lea loadseg_uae+2-segtrack_start(a2),a0
+ move.l d4,(a0)
+ lea unloadseg_uae+2-segtrack_start(a2),a0
+ move.l d4,(a0)
+
+ lea loadseg-segtrack_start(a2),a0
+ move.l a0,d0
+ move.l a4,a1
+ move.w #-$96,a0
+ jsr -$1a4(a6)
+ lea loadseg_ptr+2-segtrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea newloadseg-segtrack_start(a2),a0
+ move.l a0,d0
+ move.l a4,a1
+ move.w #-$300,a0
+ jsr -$1a4(a6)
+ lea newloadseg_ptr+2-segtrack_start(a2),a0
+ move.l d0,(a0)
+
+ lea unloadseg-segtrack_start(a2),a0
+ move.l a0,d0
+ move.l a4,a1
+ move.w #-$9c,a0
+ jsr -$1a4(a6)
+ lea unloadseg_ptr+2-segtrack_start(a2),a0
+ move.l d0,(a0)
+
+ moveq #0,d0
+ move.l d4,a0
+ move.l #209,d1
+ move.l a2,a1
+ jsr (a0)
+
+.noinit
+ rts
+
+ cnop 0,4
+segtrack_start
+
+newloadseg
+ move.l d1,-(sp)
+newloadseg_ptr
+ jsr 0.l
+ bra.s doloadseg
+
+loadseg
+ move.l d1,-(sp)
+loadseg_ptr
+ jsr 0.l
+
+doloadseg
+ movem.l d0-d3/a0-a1,-(sp)
+ move.l d0,d3 ; segment
+ move.l 6*4(sp),d1 ;name
+ jsr -$54(a6) ; Lock
+ move.l d0,d2
+ move.l #202,d1
+ move.l d3,a0
+ move.l 6*4(sp),a1 ;name
+loadseg_uae
+ jsr 0.l
+ move.l d2,d1
+ beq.s loadseg_nolock
+ jsr -$5a(a6) ;Unlock
+loadseg_nolock
+ movem.l (sp)+,d0-d3/a0-a1
+ addq.l #4,sp
+ rts
+
+unloadseg
+ movem.l d0-d1/a0-a1,-(sp)
+ move.l d1,a0
+ move.l #203,d1
+unloadseg_uae
+ jsr 0.l
+ movem.l (sp)+,d0-d1/a0-a1
+unloadseg_ptr
+ jsr 0.l
+ rts
+
+ cnop 0,4
+segtrack_end
+
+ include "filesys_helpers.asm"
+
cnop 0,4
getrtbaselocal:
lea start-8-4(pc),a0
@@ -3292,6 +4338,17 @@ getrtbase:
inp_dev: dc.b 'input.device',0
tim_dev: dc.b 'timer.device',0
+con_dev: dc.b 'console.device',0
+key_lib: dc.b 'keymap.library',0
+devsn_name: dc.b 'DEVS',0
+devs_name: dc.b 'DEVS:',0
+clip_name: dc.b 'DEVS:clipboard.device',0
+ram_name: dc.b 'RAM:',0
+nil_name: dc.b "NIL:",0
+clip_dev: dc.b 'clipboard.device',0
+ ;argghh but StartNotify()ing non-existing ENV: causes "Insert disk ENV: in any drive" dialog..
+pointer_prefs: dc.b 'RAM:Env/Sys/Pointer.prefs',0
+clname: dc.b 'UAE clipboard sharing',0
mhname: dc.b 'UAE mouse driver',0
kaname: dc.b 'UAE heart beat',0
exter_name: dc.b 'UAE fs',0
@@ -3299,14 +4356,19 @@ fstaskname: dc.b 'UAE fs automounter',0
fswtaskname: dc.b 'UAE fs worker',0
fstraptaskname: dc.b 'UAE trap worker',0
fsprocname: dc.b 'UAE fs automount process',0
+debuggerprocname: dc.b 'UAE debugger',0
doslibname: dc.b 'dos.library',0
intlibname: dc.b 'intuition.library',0
gfxlibname: dc.b 'graphics.library',0
explibname: dc.b 'expansion.library',0
fsresname: dc.b 'FileSystem.resource',0
+fchipname: dc.b 'megachip memory',0
bcplfsname: dc.b "File System",0
+shellexecname: dc.b "UAE shell execute",0
hwtrap_name: dc.b "UAE board",0
- even
+uaeres dc.b "uae.resource",0
+uaeres_func dc.b "misc_funcs",0
+ cnop 0,4
rom_end:
END
diff --git a/src/filesys.cpp b/src/filesys.cpp
index d5ee79c2..a4b3a7cf 100644
--- a/src/filesys.cpp
+++ b/src/filesys.cpp
@@ -22,10 +22,12 @@
* modified at the same time by another process while UAE is running.
*/
+#include "sysconfig.h"
#include "sysdeps.h"
#include "threaddep/thread.h"
#include "options.h"
+#include "traps.h"
#include "uae.h"
#include "memory.h"
#include "custom.h"
@@ -33,16 +35,19 @@
#include "autoconf.h"
#include "fsusage.h"
#include "native2amiga.h"
+#include "scsidev.h"
#include "fsdb.h"
#include "zfile.h"
#include "zarchive.h"
#include "gui.h"
#include "gayle.h"
#include "savestate.h"
+#include "cdtv.h"
#include "bsdsocket.h"
#include "uaeresource.h"
#include "inputdevice.h"
#include "blkdev.h"
+#include "isofs_api.h"
#include "scsi.h"
#include "newcpu.h"
#include "picasso96.h"
@@ -501,10 +506,10 @@ static void close_filesys_unit (UnitInfo *uip)
xfree (uip->unit_pipe);
if (uip->back_pipe)
xfree (uip->back_pipe);
- //if (uip->cd_open) {
- // sys_command_close (uip->cddevno);
- // isofs_unmount (uip->cdfs_superblock);
- //}
+ if (uip->cd_open) {
+ sys_command_close (uip->cddevno);
+ isofs_unmount (uip->cdfs_superblock);
+ }
uip->unit_pipe = 0;
uip->back_pipe = 0;
@@ -1158,7 +1163,7 @@ static bool add_ide_unit(int type, int unit, struct uaedev_config_info *uci)
if ((ert->deviceflags & 2) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
if (ert->add) {
struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
- write_log(_T("Adding IDE %s '%s' unit %d ('%s')\n"), _T("HD"),
+ write_log(_T("Adding IDE %s '%s' unit %d ('%s')\n"), getunittype(uci),
ert->name, unit, uci->rootdir);
ert->add(unit, uci, rc);
}
@@ -1170,6 +1175,30 @@ static bool add_ide_unit(int type, int unit, struct uaedev_config_info *uci)
return added;
}
+static bool add_scsi_unit(int type, int unit, struct uaedev_config_info *uci)
+{
+ bool added = false;
+ if (type >= HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
+ for (int i = 0; expansionroms[i].name; i++) {
+ if (i == type - HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST) {
+ const struct expansionromtype *ert = &expansionroms[i];
+ if ((ert->deviceflags & 1) && is_board_enabled(&currprefs, ert->romtype, uci->controller_type_unit)) {
+ //cpuboard_hd = 1;
+ if (ert->add) {
+ struct romconfig *rc = get_device_romconfig(&currprefs, ert->romtype, uci->controller_type_unit);
+ write_log(_T("Adding SCSI %s '%s' unit %d ('%s')\n"), getunittype(uci),
+ ert->name, unit, uci->rootdir);
+ ert->add(unit, uci, rc);
+ }
+ //if (cpuboard_hd)
+ added = true;
+ }
+ }
+ }
+ }
+ return added;
+}
+
static void initialize_mountinfo (void)
{
@@ -1189,9 +1218,43 @@ static void initialize_mountinfo (void)
allocuci (&currprefs, nr, idx);
}
}
+ //filesys_addexternals ();
nr = nr_units ();
cd_unit_offset = nr;
cd_unit_number = 0;
+ if (currprefs.scsi) {
+ uae_u32 mask = scsi_get_cd_drive_mask ();
+ for (int i = 0; i < 32; i++) {
+ if (mask & (1 << i)) {
+ struct uaedev_config_info ci = { 0 };
+ _stprintf (ci.devname, _T("CD%d"), i);
+ cd_unit_number++;
+ _tcscpy (ci.rootdir, _T("/"));
+ ci.readonly = true;
+ ci.sectors = 1;
+ ci.surfaces = 1;
+ ci.blocksize = 2048;
+ int idx = set_filesys_unit_1 (i + cd_unit_offset, &ci, true);
+ allocuci (&currprefs, nr, idx);
+ nr++;
+ }
+ }
+ }
+
+ for (nr = 0; nr < currprefs.mountitems; nr++) {
+ struct uaedev_config_data *uci = &currprefs.mountconfig[nr];
+ if (uci->ci.controller_type == HD_CONTROLLER_TYPE_UAE) {
+ if (uci->ci.type == UAEDEV_TAPE) {
+ struct uaedev_config_info ci;
+ memcpy (&ci, &uci->ci, sizeof (struct uaedev_config_info));
+ int unitnum = scsi_add_tape (&uci->ci);
+ if (unitnum >= 0) {
+ int idx = set_filesys_unit_1 (-1, &ci, false);
+ allocuci (&currprefs, nr, idx, unitnum);
+ }
+ }
+ }
+ }
// init all controllers first
for (int i = 0; expansionroms[i].name; i++) {
@@ -1224,10 +1287,43 @@ static void initialize_mountinfo (void)
if (added)
break;
}
+ } else if (type != HD_CONTROLLER_TYPE_SCSI_AUTO && type >= HD_CONTROLLER_TYPE_SCSI_FIRST && type <= HD_CONTROLLER_TYPE_SCSI_LAST) {
+ added = add_scsi_unit(type, unit, uci);
+ } else if (type == HD_CONTROLLER_TYPE_SCSI_AUTO) {
+ for (int st = HD_CONTROLLER_TYPE_SCSI_FIRST; st <= HD_CONTROLLER_TYPE_SCSI_LAST; st++) {
+ added = add_scsi_unit(st, unit, uci);
+ if (added)
+ break;
+ }
+#if 0
+ } else if (type == HD_CONTROLLER_TYPE_PCMCIA) {
+ if (uci->controller_type_unit == 0) {
+ gayle_add_pcmcia_sram_unit (uci);
+ added = true;
+ } else {
+ gayle_add_pcmcia_ide_unit (uci);
+ added = true;
+ }
+#endif
}
if (added)
allocuci (&currprefs, nr, -1);
}
+
+
+}
+
+int sprintf_filesys_unit (TCHAR *buffer, int num)
+{
+ UnitInfo *uip = mountinfo.ui;
+
+ if (uip[num].volname != 0)
+ _stprintf (buffer, _T("(DH%d:) Filesystem, %s: %s %s"), num, uip[num].volname,
+ uip[num].rootdir, uip[num].readonly ? _T("ro") : _T(""));
+ else
+ _stprintf (buffer, _T("(DH%d:) Hardfile, \"%s\", size %d Mbytes"), num,
+ uip[num].rootdir, (int)(uip[num].hf.virtsize / (1024 * 1024)));
+ return 0;
}
static void free_mountinfo (void)
@@ -1244,7 +1340,13 @@ struct hardfiledata *get_hardfile_data_controller(int nr)
for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
if (uip[i].open == 0)
continue;
- if (uip[i].hf.ci.controller_unit == nr)
+ if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type != UAEDEV_DIR)
+ return &uip[i].hf;
+ }
+ for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
+ if (uip[i].open == 0)
+ continue;
+ if (uip[i].hf.ci.controller_unit == nr && uip[i].hf.ci.type == UAEDEV_DIR)
return &uip[i].hf;
}
return NULL;
@@ -1452,12 +1554,11 @@ static struct fs_dirhandle *fs_opendir (Unit *u, a_inode *aino)
fsd->od = my_opendir (aino->nname);
if (fsd->od)
return fsd;
+ } else if (fsd->fstype == FS_CDFS) {
+ fsd->isod = isofs_opendir (u->ui.cdfs_superblock, aino->uniq_external);
+ if (fsd->isod)
+ return fsd;
}
- //else if (fsd->fstype == FS_CDFS) {
- // fsd->isod = isofs_opendir (u->ui.cdfs_superblock, aino->uniq_external);
- // if (fsd->isod)
- // return fsd;
- //}
xfree (fsd);
return NULL;
}
@@ -1469,8 +1570,8 @@ static void fs_closedir (struct fs_dirhandle *fsd)
zfile_closedir_archive (fsd->zd);
else if (fsd->fstype == FS_DIRECTORY)
my_closedir (fsd->od);
- //else if (fsd->fstype == FS_CDFS)
- // isofs_closedir (fsd->isod);
+ else if (fsd->fstype == FS_CDFS)
+ isofs_closedir (fsd->isod);
xfree (fsd);
}
static struct fs_filehandle *fs_openfile (Unit *u, a_inode *aino, int flags)
@@ -1485,12 +1586,11 @@ static struct fs_filehandle *fs_openfile (Unit *u, a_inode *aino, int flags)
fsf->of = my_open (aino->nname, flags);
if (fsf->of)
return fsf;
+ } else if (fsf->fstype == FS_CDFS) {
+ fsf->isof = isofs_openfile (u->ui.cdfs_superblock, aino->uniq_external, flags);
+ if (fsf->isof)
+ return fsf;
}
- //else if (fsf->fstype == FS_CDFS) {
- // fsf->isof = isofs_openfile (u->ui.cdfs_superblock, aino->uniq_external, flags);
- // if (fsf->isof)
- // return fsf;
- //}
xfree (fsf);
return NULL;
}
@@ -1502,10 +1602,9 @@ static void fs_closefile (struct fs_filehandle *fsf)
zfile_close_archive (fsf->zf);
} else if (fsf->fstype == FS_DIRECTORY) {
my_close (fsf->of);
+ } else if (fsf->fstype == FS_CDFS) {
+ isofs_closefile (fsf->isof);
}
- //else if (fsf->fstype == FS_CDFS) {
- // isofs_closefile (fsf->isof);
- //}
xfree (fsf);
}
static unsigned int fs_read (struct fs_filehandle *fsf, void *b, unsigned int size)
@@ -1514,8 +1613,8 @@ static unsigned int fs_read (struct fs_filehandle *fsf, void *b, unsigned int si
return zfile_read_archive (fsf->zf, b, size);
else if (fsf->fstype == FS_DIRECTORY)
return my_read (fsf->of, b, size);
- //else if (fsf->fstype == FS_CDFS)
- // return isofs_read (fsf->isof, b, size);
+ else if (fsf->fstype == FS_CDFS)
+ return isofs_read (fsf->isof, b, size);
return 0;
}
static unsigned int fs_write (struct fs_filehandle *fsf, void *b, unsigned int size)
@@ -1532,8 +1631,8 @@ static uae_s64 fs_lseek64 (struct fs_filehandle *fsf, uae_s64 offset, int whence
return zfile_lseek_archive (fsf->zf, offset, whence);
else if (fsf->fstype == FS_DIRECTORY)
return my_lseek (fsf->of, offset, whence);
- //else if (fsf->fstype == FS_CDFS)
- // return isofs_lseek (fsf->isof, offset, whence);
+ else if (fsf->fstype == FS_CDFS)
+ return isofs_lseek (fsf->isof, offset, whence);
return -1;
}
static uae_s32 fs_lseek (struct fs_filehandle *fsf, uae_s32 offset, int whence)
@@ -1549,8 +1648,8 @@ static uae_s64 fs_fsize64 (struct fs_filehandle *fsf)
return zfile_fsize_archive (fsf->zf);
else if (fsf->fstype == FS_DIRECTORY)
return my_fsize (fsf->of);
- //else if (fsf->fstype == FS_CDFS)
- // return isofs_fsize (fsf->isof);
+ else if (fsf->fstype == FS_CDFS)
+ return isofs_fsize (fsf->isof);
return -1;
}
static uae_u32 fs_fsize (struct fs_filehandle *fsf)
@@ -1806,7 +1905,7 @@ static uae_u32 filesys_media_change_reply (int mode)
if (mode == 0) {
write_log (_T("FILESYS: got media change reply, '%s' removal finished\n"), u->ui.volname);
flush_cache (u, -1);
- //isofs_unmount (u->ui.cdfs_superblock);
+ isofs_unmount (u->ui.cdfs_superblock);
ui->cdfs_superblock = u->ui.cdfs_superblock = NULL;
zfile_fclose_archive (ui->zarchive);
ui->zarchive = NULL;
@@ -1834,28 +1933,28 @@ static uae_u32 filesys_media_change_reply (int mode)
flush_cache (u, -1);
xfree (u->ui.volname);
ui->volname = u->ui.volname = NULL;
- if (0) {
-// uae_u64 uniq;
-// ui->cdfs_superblock = u->ui.cdfs_superblock = isofs_mount (ui->cddevno, &uniq);
-// u->rootnode.uniq_external = uniq;
-// u->ui.unknown_media = true;
-// if (!u->ui.cdfs_superblock)
-// return 0;
-// struct isofs_info ii;
-// set_highcyl(u->volume, 0);
-// bool r = isofs_mediainfo (ui->cdfs_superblock, &ii);
-// if (r && ii.media) {
-// u->ui.unknown_media = ii.unknown_media;
-// if (!ii.unknown_media) {
-// u->ui.volname = ui->volname = my_strdup (ii.volumename);
-// ctime.tv_sec = ii.creation;
-// ctime.tv_usec = 0;
-// set_highcyl(u->volume, ii.blocks);
-//#ifdef RETROPLATFORM
-// rp_cd_image_change (ui->cddevno, ii.devname);
-//#endif
-// }
-// }
+ if (ui->unit_type == UNIT_CDFS) {
+ uae_u64 uniq;
+ ui->cdfs_superblock = u->ui.cdfs_superblock = isofs_mount (ui->cddevno, &uniq);
+ u->rootnode.uniq_external = uniq;
+ u->ui.unknown_media = true;
+ if (!u->ui.cdfs_superblock)
+ return 0;
+ struct isofs_info ii;
+ set_highcyl(u->volume, 0);
+ bool r = isofs_mediainfo (ui->cdfs_superblock, &ii);
+ if (r && ii.media) {
+ u->ui.unknown_media = ii.unknown_media;
+ if (!ii.unknown_media) {
+ u->ui.volname = ui->volname = my_strdup (ii.volumename);
+ ctime.tv_sec = ii.creation;
+ ctime.tv_usec = 0;
+ set_highcyl(u->volume, ii.blocks);
+#ifdef RETROPLATFORM
+ rp_cd_image_change (ui->cddevno, ii.devname);
+#endif
+ }
+ }
} else {
if (set_filesys_volume (u->mount_rootdir, &u->mount_flags, &u->mount_readonly, &emptydrive, &ui->zarchive) < 0)
return 0;
@@ -2167,10 +2266,9 @@ static void dispose_aino (Unit *unit, a_inode **aip, a_inode *aino)
if (unit->volflags & MYVOLUMEINFO_ARCHIVE) {
;
+ } else if (unit->volflags & MYVOLUMEINFO_CDFS) {
+ isofs_dispose_inode (unit->ui.cdfs_superblock, aino->uniq_external);
}
- //else if (unit->volflags & MYVOLUMEINFO_CDFS) {
- // isofs_dispose_inode (unit->ui.cdfs_superblock, aino->uniq_external);
- //}
xfree (aino->aname);
xfree (aino->comment);
@@ -2431,12 +2529,11 @@ static TCHAR *get_nname (Unit *unit, a_inode *base, TCHAR *rel, TCHAR **modified
if (zfile_exists_archive (base->nname, rel))
return build_nname (base->nname, rel);
return NULL;
+ } else if (unit->volflags & MYVOLUMEINFO_CDFS) {
+ if (isofs_exists (unit->ui.cdfs_superblock, base->uniq_external, rel, uniq_ext))
+ return build_nname (base->nname, rel);
+ return NULL;
}
- //else if (unit->volflags & MYVOLUMEINFO_CDFS) {
- // if (isofs_exists (unit->ui.cdfs_superblock, base->uniq_external, rel, uniq_ext))
- // return build_nname (base->nname, rel);
- // return NULL;
- //}
aino_test (base);
@@ -2495,19 +2592,17 @@ static int fill_file_attrs (Unit *u, a_inode *base, a_inode *c)
c->amigaos_mode = flags;
c->comment = comment;
return 1;
- }
- //else if (u->volflags & MYVOLUMEINFO_CDFS) {
- // int isdir, flags;
- // TCHAR *comment;
- // isofss_fill_file_attrs (u->ui.cdfs_superblock, base->uniq_external, &isdir, &flags, &comment, c->uniq_external);
- // c->dir = isdir;
- // c->amigaos_mode = 0;
- // if (flags >= 0)
- // c->amigaos_mode = flags;
- // c->comment = comment;
- // return 1;
- //}
- else {
+ } else if (u->volflags & MYVOLUMEINFO_CDFS) {
+ int isdir, flags;
+ TCHAR *comment;
+ isofss_fill_file_attrs (u->ui.cdfs_superblock, base->uniq_external, &isdir, &flags, &comment, c->uniq_external);
+ c->dir = isdir;
+ c->amigaos_mode = 0;
+ if (flags >= 0)
+ c->amigaos_mode = flags;
+ c->comment = comment;
+ return 1;
+ } else {
return fsdb_fill_file_attrs (base, c);
}
return 0;
@@ -2899,36 +2994,36 @@ static Unit *startup_create_unit(TrapContext *ctx, UnitInfo *uinfo, int num)
static bool mount_cd(UnitInfo *uinfo, int nr, struct mytimeval *ctime, uae_u64 *uniq, uaecptr volume)
{
-// uinfo->cddevno = nr - cd_unit_offset;
-// if (!sys_command_open (uinfo->cddevno)) {
-// write_log (_T("Failed attempt to open CD unit %d\n"), uinfo->cddevno);
-// return false;
-// }
-//#ifdef RETROPLATFORM
-// rp_cd_device_enable (uinfo->cddevno, true);
-//#endif
-// uinfo->cdfs_superblock = isofs_mount(uinfo->cddevno, uniq);
-// uinfo->wasisempty = true;
-// struct isofs_info ii;
-// if (isofs_mediainfo (uinfo->cdfs_superblock, &ii)) {
-// xfree (uinfo->volname);
-// if (ii.media) {
-// uinfo->wasisempty = false;
-// if (!ii.unknown_media) {
-// uinfo->volname = my_strdup (ii.volumename);
-// if (ctime) {
-// ctime->tv_sec = ii.creation;
-// ctime->tv_usec = 0;
-// }
-// set_highcyl(volume, ii.totalblocks);
-//#ifdef RETROPLATFORM
-// rp_cd_image_change (uinfo->cddevno, ii.devname);
-//#endif
-// }
-// }
-// uinfo->unknown_media = ii.unknown_media;
-// }
-// uinfo->cd_open = true;
+ uinfo->cddevno = nr - cd_unit_offset;
+ if (!sys_command_open (uinfo->cddevno)) {
+ write_log (_T("Failed attempt to open CD unit %d\n"), uinfo->cddevno);
+ return false;
+ }
+#ifdef RETROPLATFORM
+ rp_cd_device_enable (uinfo->cddevno, true);
+#endif
+ uinfo->cdfs_superblock = isofs_mount(uinfo->cddevno, uniq);
+ uinfo->wasisempty = true;
+ struct isofs_info ii;
+ if (isofs_mediainfo (uinfo->cdfs_superblock, &ii)) {
+ xfree (uinfo->volname);
+ if (ii.media) {
+ uinfo->wasisempty = false;
+ if (!ii.unknown_media) {
+ uinfo->volname = my_strdup (ii.volumename);
+ if (ctime) {
+ ctime->tv_sec = ii.creation;
+ ctime->tv_usec = 0;
+ }
+ set_highcyl(volume, ii.totalblocks);
+#ifdef RETROPLATFORM
+ rp_cd_image_change (uinfo->cddevno, ii.devname);
+#endif
+ }
+ }
+ uinfo->unknown_media = ii.unknown_media;
+ }
+ uinfo->cd_open = true;
return true;
}
@@ -3118,21 +3213,19 @@ static void do_info(TrapContext *ctx, Unit *unit, dpacket *packet, uaecptr info,
ret = zfile_fs_usage_archive (unit->ui.rootdir, 0, &fsu);
fs = true;
media = filesys_isvolume(unit) != 0;
- }
- //else if (unit->volflags & MYVOLUMEINFO_CDFS) {
- // struct isofs_info ii;
- // ret = isofs_mediainfo (unit->ui.cdfs_superblock, &ii) ? 0 : 1;
- // if (!ret) {
- // media = ii.media;
- // nr = unit->unit - cd_unit_offset;
- // blocksize = ii.blocksize;
- // if (ii.media) {
- // fsu.total = ii.blocks * ii.blocksize;
- // fsu.avail = 0;
- // }
- // }
- //}
- else {
+ } else if (unit->volflags & MYVOLUMEINFO_CDFS) {
+ struct isofs_info ii;
+ ret = isofs_mediainfo (unit->ui.cdfs_superblock, &ii) ? 0 : 1;
+ if (!ret) {
+ media = ii.media;
+ nr = unit->unit - cd_unit_offset;
+ blocksize = ii.blocksize;
+ if (ii.media) {
+ fsu.total = ii.blocks * ii.blocksize;
+ fsu.avail = 0;
+ }
+ }
+ } else {
ret = get_fs_usage (unit->ui.rootdir, 0, &fsu);
if (ret)
err = dos_errno ();
@@ -3731,8 +3824,8 @@ static bool get_statinfo(Unit *unit, a_inode *aino, struct mystat *statbuf)
/* No error checks - this had better work. */
if (unit->volflags & MYVOLUMEINFO_ARCHIVE)
ok = zfile_stat_archive (aino->nname, statbuf) != 0;
- //else if (unit->volflags & MYVOLUMEINFO_CDFS)
- // ok = isofs_stat (unit->ui.cdfs_superblock, aino->uniq_external, statbuf);
+ else if (unit->volflags & MYVOLUMEINFO_CDFS)
+ ok = isofs_stat (unit->ui.cdfs_superblock, aino->uniq_external, statbuf);
else
my_stat (aino->nname, statbuf);
return ok;
@@ -4096,8 +4189,8 @@ static int exalldo(TrapContext *ctx, uaecptr exalldata, uae_u32 exalldatasize, u
memset (&statbuf, 0, sizeof statbuf);
if (unit->volflags & MYVOLUMEINFO_ARCHIVE)
zfile_stat_archive (aino->nname, &statbuf);
- //else if (unit->volflags & MYVOLUMEINFO_CDFS)
- // isofs_stat (unit->ui.cdfs_superblock, aino->uniq_external, &statbuf);
+ else if (unit->volflags & MYVOLUMEINFO_CDFS)
+ isofs_stat (unit->ui.cdfs_superblock, aino->uniq_external, &statbuf);
else
my_stat (aino->nname, &statbuf);
@@ -4213,8 +4306,8 @@ static int filesys_readdir(struct fs_dirhandle *d, TCHAR *fn, uae_u64 *uniq)
ok = zfile_readdir_archive(d->zd, fn);
else if (d->fstype == FS_DIRECTORY)
ok = my_readdir(d->od, fn);
- //else if (d->fstype == FS_CDFS)
- // ok = isofs_readdir(d->isod, fn, uniq);
+ else if (d->fstype == FS_CDFS)
+ ok = isofs_readdir(d->isod, fn, uniq);
return ok;
}
@@ -6638,7 +6731,7 @@ void filesys_start_threads (void)
}
}
-static void filesys_free_handles(void)
+void filesys_free_handles (void)
{
Unit *u, *u1;
for (u = units; u; u = u1) {
@@ -6734,6 +6827,7 @@ void filesys_prepare_reset (void)
filesys_prepare_reset2 ();
}
+
/* don't forget filesys.asm! */
#define PP_MAXSIZE 4 * 96
#define PP_FSSIZE 400
@@ -7998,31 +8092,31 @@ static uae_u32 REGPARAM2 filesys_dev_storeinfo (TrapContext *ctx)
type = FILESYS_VIRTUAL;
gui_flicker_led (LED_CD, cd_unit_no, 0);
- //write_log (_T("Mounting uaescsi.device %d: (%d)\n"), cd_unit_no, unit_no);
- //trap_put_long(ctx, parmpacket + 0, cdname_amiga);
- //trap_put_long(ctx, parmpacket + 4, cdfs_devname);
- //trap_put_long(ctx, parmpacket + 8, cd_unit_no);
- //trap_put_long(ctx, parmpacket + 12, 0); /* Device flags */
- //trap_put_long(ctx, parmpacket + 16, 19); /* Env. size */
- //trap_put_long(ctx, parmpacket + 20, 2048 >> 2); /* longwords per block */
- //trap_put_long(ctx, parmpacket + 24, 0); /* unused */
- //trap_put_long(ctx, parmpacket + 28, 1); /* heads */
- //trap_put_long(ctx, parmpacket + 32, 1); /* sectors per block */
- //trap_put_long(ctx, parmpacket + 36, 1); /* sectors per track */
- //trap_put_long(ctx, parmpacket + 40, 0); /* reserved blocks */
- //trap_put_long(ctx, parmpacket + 44, 0); /* unused */
- //trap_put_long(ctx, parmpacket + 48, 0); /* interleave */
- //trap_put_long(ctx, parmpacket + 52, 0); /* lowCyl */
- //trap_put_long(ctx, parmpacket + 56, 0); /* hiCyl */
- //trap_put_long(ctx, parmpacket + 60, 50); /* Number of buffers */
- //trap_put_long(ctx, parmpacket + 64, 1); /* Buffer mem type */
- //trap_put_long(ctx, parmpacket + 68, 0x7FFFFFFE); /* largest transfer */
- //trap_put_long(ctx, parmpacket + 72, 0xFFFFFFFE); /* dma mask */
- //trap_put_long(ctx, parmpacket + 76, scsi_get_cd_drive_media_mask () & (1 << cd_unit_no) ? -127 : -128); /* bootPri */
- //trap_put_long(ctx, parmpacket + 80, CDFS_DOSTYPE | (((cd_unit_no / 10) + '0') << 8) | ((cd_unit_no % 10) + '0'));
- //trap_put_long(ctx, parmpacket + 84, 0); /* baud */
- //trap_put_long(ctx, parmpacket + 88, 0); /* control */
- //trap_put_long(ctx, parmpacket + 92, 0); /* bootblocks */
+ write_log (_T("Mounting uaescsi.device %d: (%d)\n"), cd_unit_no, unit_no);
+ trap_put_long(ctx, parmpacket + 0, cdname_amiga);
+ trap_put_long(ctx, parmpacket + 4, cdfs_devname);
+ trap_put_long(ctx, parmpacket + 8, cd_unit_no);
+ trap_put_long(ctx, parmpacket + 12, 0); /* Device flags */
+ trap_put_long(ctx, parmpacket + 16, 19); /* Env. size */
+ trap_put_long(ctx, parmpacket + 20, 2048 >> 2); /* longwords per block */
+ trap_put_long(ctx, parmpacket + 24, 0); /* unused */
+ trap_put_long(ctx, parmpacket + 28, 1); /* heads */
+ trap_put_long(ctx, parmpacket + 32, 1); /* sectors per block */
+ trap_put_long(ctx, parmpacket + 36, 1); /* sectors per track */
+ trap_put_long(ctx, parmpacket + 40, 0); /* reserved blocks */
+ trap_put_long(ctx, parmpacket + 44, 0); /* unused */
+ trap_put_long(ctx, parmpacket + 48, 0); /* interleave */
+ trap_put_long(ctx, parmpacket + 52, 0); /* lowCyl */
+ trap_put_long(ctx, parmpacket + 56, 0); /* hiCyl */
+ trap_put_long(ctx, parmpacket + 60, 50); /* Number of buffers */
+ trap_put_long(ctx, parmpacket + 64, 1); /* Buffer mem type */
+ trap_put_long(ctx, parmpacket + 68, 0x7FFFFFFE); /* largest transfer */
+ trap_put_long(ctx, parmpacket + 72, 0xFFFFFFFE); /* dma mask */
+ trap_put_long(ctx, parmpacket + 76, scsi_get_cd_drive_media_mask () & (1 << cd_unit_no) ? -127 : -128); /* bootPri */
+ trap_put_long(ctx, parmpacket + 80, CDFS_DOSTYPE | (((cd_unit_no / 10) + '0') << 8) | ((cd_unit_no % 10) + '0'));
+ trap_put_long(ctx, parmpacket + 84, 0); /* baud */
+ trap_put_long(ctx, parmpacket + 88, 0); /* control */
+ trap_put_long(ctx, parmpacket + 92, 0); /* bootblocks */
return type;
} else {
diff --git a/src/fsdb.cpp b/src/fsdb.cpp
index 6a6fea3c..05ab705b 100644
--- a/src/fsdb.cpp
+++ b/src/fsdb.cpp
@@ -1,17 +1,13 @@
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Library of functions to make emulated filesystem as independent as
- * possible of the host filesystem's capabilities.
- *
- * Copyright 1999 Bernd Schmidt
- */
-
-#include
-#include
-#include
-#include
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* Library of functions to make emulated filesystem as independent as
+* possible of the host filesystem's capabilities.
+*
+* Copyright 1999 Bernd Schmidt
+*/
+#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
@@ -28,143 +24,143 @@
static TCHAR *nname_begin (TCHAR *nname)
{
- TCHAR *p = _tcsrchr (nname, FSDB_DIR_SEPARATOR);
- if (p)
- return p + 1;
- return nname;
+ TCHAR *p = _tcsrchr (nname, FSDB_DIR_SEPARATOR);
+ if (p)
+ return p + 1;
+ return nname;
}
#ifndef _WIN32
/* Find the name REL in directory DIRNAME. If we find a file that
- * has exactly the same name, return REL. If we find a file that
- * has the same name when compared case-insensitively, return a
- * malloced string that contains the name we found. If no file
- * exists that compares equal to REL, return 0. */
+* has exactly the same name, return REL. If we find a file that
+* has the same name when compared case-insensitively, return a
+* malloced string that contains the name we found. If no file
+* exists that compares equal to REL, return 0. */
TCHAR *fsdb_search_dir (const TCHAR *dirname, TCHAR *rel)
{
- TCHAR *p = 0;
+ TCHAR *p = 0;
int de;
my_opendir_s *dir;
- TCHAR fn[MAX_DPATH];
+ TCHAR fn[MAX_DPATH];
dir = my_opendir (dirname);
- /* This really shouldn't happen... */
- if (! dir)
- return 0;
-
+ /* This really shouldn't happen... */
+ if (! dir)
+ return 0;
+
while (p == 0 && (de = my_readdir (dir, fn)) != 0) {
if (strcmp (fn, rel) == 0)
p = rel;
else if (stricmp(fn, rel) == 0)
p = my_strdup (fn);
- }
+ }
my_closedir (dir);
- return p;
+ return p;
}
#endif
static FILE *get_fsdb (a_inode *dir, const TCHAR *mode)
{
- TCHAR *n;
- FILE *f;
-
+ TCHAR *n;
+ FILE *f;
+
if (!dir->nname)
return NULL;
- n = build_nname (dir->nname, FSDB_FILE);
+ n = build_nname (dir->nname, FSDB_FILE);
f = uae_tfopen (n, mode);
- xfree (n);
- return f;
+ xfree (n);
+ return f;
}
static void kill_fsdb (a_inode *dir)
{
if (!dir->nname)
return;
- TCHAR *n = build_nname (dir->nname, FSDB_FILE);
- _wunlink (n);
- xfree (n);
+ TCHAR *n = build_nname (dir->nname, FSDB_FILE);
+ _wunlink (n);
+ xfree (n);
}
static void fsdb_fixup (FILE *f, uae_u8 *buf, int size, a_inode *base)
{
- TCHAR *nname;
- int ret;
+ TCHAR *nname;
+ int ret;
- if (buf[0] == 0)
- return;
+ if (buf[0] == 0)
+ return;
TCHAR *fnname = au ((char*)buf + 5 + 257);
nname = build_nname (base->nname, fnname);
xfree (fnname);
- ret = fsdb_exists (nname);
- if (ret) {
- xfree (nname);
- return;
- }
- /* someone deleted this file/dir outside of emulation.. */
- buf[0] = 0;
- xfree (nname);
+ ret = fsdb_exists (nname);
+ if (ret) {
+ xfree (nname);
+ return;
+ }
+ /* someone deleted this file/dir outside of emulation.. */
+ buf[0] = 0;
+ xfree (nname);
}
/* Prune the db file the first time this directory is opened in a session. */
void fsdb_clean_dir (a_inode *dir)
{
uae_u8 buf[1 + 4 + 257 + 257 + 81];
- TCHAR *n;
- FILE *f;
- off_t pos1 = 0, pos2;
+ TCHAR *n;
+ FILE *f;
+ off_t pos1 = 0, pos2;
if (!dir->nname)
return;
- n = build_nname (dir->nname, FSDB_FILE);
+ n = build_nname (dir->nname, FSDB_FILE);
f = uae_tfopen (n, _T("r+b"));
- if (f == 0) {
- xfree (n);
- return;
- }
- for (;;) {
- pos2 = ftell (f);
- if (fread (buf, 1, sizeof buf, f) < sizeof buf)
- break;
- fsdb_fixup (f, buf, sizeof buf, dir);
- if (buf[0] == 0)
- continue;
- if (pos1 != pos2) {
- fseek (f, pos1, SEEK_SET);
- fwrite (buf, 1, sizeof buf, f);
- fseek (f, pos2 + sizeof buf, SEEK_SET);
- }
- pos1 += sizeof buf;
- }
- fclose (f);
+ if (f == 0) {
+ xfree (n);
+ return;
+ }
+ for (;;) {
+ pos2 = ftell (f);
+ if (fread (buf, 1, sizeof buf, f) < sizeof buf)
+ break;
+ fsdb_fixup (f, buf, sizeof buf, dir);
+ if (buf[0] == 0)
+ continue;
+ if (pos1 != pos2) {
+ fseek (f, pos1, SEEK_SET);
+ fwrite (buf, 1, sizeof buf, f);
+ fseek (f, pos2 + sizeof buf, SEEK_SET);
+ }
+ pos1 += sizeof buf;
+ }
+ fclose (f);
if (pos1 == 0) {
kill_fsdb (dir);
} else {
- my_truncate (n, pos1);
+ my_truncate (n, pos1);
}
- xfree (n);
+ xfree (n);
}
static a_inode *aino_from_buf (a_inode *base, uae_u8 *buf, long off)
{
- uae_u32 mode;
- a_inode *aino = xcalloc (a_inode, 1);
+ uae_u32 mode;
+ a_inode *aino = xcalloc (a_inode, 1);
TCHAR *s;
- mode = do_get_mem_long ((uae_u32 *)(buf + 1));
- buf += 5;
+ mode = do_get_mem_long ((uae_u32 *)(buf + 1));
+ buf += 5;
aino->aname = au ((char*)buf);
- buf += 257;
+ buf += 257;
s = au ((char*)buf);
aino->nname = build_nname (base->nname, s);
xfree (s);
- buf += 257;
+ buf += 257;
aino->comment = *buf != '\0' ? au ((char*)buf) : 0;
- fsdb_fill_file_attrs (base, aino);
- aino->amigaos_mode = mode;
- aino->has_dbentry = 1;
- aino->dirty = 0;
- aino->db_offset = off;
- return aino;
+ fsdb_fill_file_attrs (base, aino);
+ aino->amigaos_mode = mode;
+ aino->has_dbentry = 1;
+ aino->dirty = 0;
+ aino->db_offset = off;
+ return aino;
}
a_inode *fsdb_lookup_aino_aname (a_inode *base, const TCHAR *aname)
@@ -178,24 +174,24 @@ a_inode *fsdb_lookup_aino_aname (a_inode *base, const TCHAR *aname)
for (;;) {
uae_u8 buf[1 + 4 + 257 + 257 + 81];
TCHAR *s;
- if (fread (buf, 1, sizeof buf, f) < sizeof buf)
- break;
+ if (fread (buf, 1, sizeof buf, f) < sizeof buf)
+ break;
s = au ((char*)buf + 5);
if (buf[0] != 0 && same_aname (s, aname)) {
- long pos = ftell (f) - sizeof buf;
- fclose (f);
+ long pos = ftell (f) - sizeof buf;
+ fclose (f);
xfree (s);
- return aino_from_buf (base, buf, pos);
- }
+ return aino_from_buf (base, buf, pos);
+ }
xfree (s);
- }
- fclose (f);
- return 0;
+ }
+ fclose (f);
+ return 0;
}
a_inode *fsdb_lookup_aino_nname (a_inode *base, const TCHAR *nname)
{
- FILE *f;
+ FILE *f;
char *s;
f = get_fsdb (base, _T("r+b"));
@@ -203,26 +199,26 @@ a_inode *fsdb_lookup_aino_nname (a_inode *base, const TCHAR *nname)
return 0;
}
s = ua (nname);
- for (;;) {
- uae_u8 buf[1 + 4 + 257 + 257 + 81];
- if (fread (buf, 1, sizeof buf, f) < sizeof buf)
- break;
+ for (;;) {
+ uae_u8 buf[1 + 4 + 257 + 257 + 81];
+ if (fread (buf, 1, sizeof buf, f) < sizeof buf)
+ break;
if (buf[0] != 0 && strcmp ((char*)buf + 5 + 257, s) == 0) {
- long pos = ftell (f) - sizeof buf;
- fclose (f);
+ long pos = ftell (f) - sizeof buf;
+ fclose (f);
xfree (s);
- return aino_from_buf (base, buf, pos);
- }
- }
+ return aino_from_buf (base, buf, pos);
+ }
+ }
xfree (s);
- fclose (f);
- return 0;
+ fclose (f);
+ return 0;
}
int fsdb_used_as_nname (a_inode *base, const TCHAR *nname)
{
- FILE *f;
- uae_u8 buf[1 + 4 + 257 + 257 + 81];
+ FILE *f;
+ uae_u8 buf[1 + 4 + 257 + 257 + 81];
f = get_fsdb (base, _T("r+b"));
if (f == 0) {
@@ -230,128 +226,128 @@ int fsdb_used_as_nname (a_inode *base, const TCHAR *nname)
}
for (;;) {
TCHAR *s;
- if (fread (buf, 1, sizeof buf, f) < sizeof buf)
- break;
- if (buf[0] == 0)
- continue;
+ if (fread (buf, 1, sizeof buf, f) < sizeof buf)
+ break;
+ if (buf[0] == 0)
+ continue;
s = au ((char*)buf + 5 + 257);
if (_tcscmp (s, nname) == 0) {
xfree (s);
- fclose (f);
- return 1;
- }
+ fclose (f);
+ return 1;
+ }
xfree (s);
- }
- fclose (f);
- return 0;
+ }
+ fclose (f);
+ return 0;
}
static int needs_dbentry (a_inode *aino)
{
- const TCHAR *nn_begin;
+ const TCHAR *nn_begin;
- if (aino->deleted)
- return 0;
-
- if (! fsdb_mode_representable_p (aino, aino->amigaos_mode) || aino->comment != 0)
- return 1;
+ if (aino->deleted)
+ return 0;
- nn_begin = nname_begin (aino->nname);
- return _tcscmp (nn_begin, aino->aname) != 0;
+ if (! fsdb_mode_representable_p (aino, aino->amigaos_mode) || aino->comment != 0)
+ return 1;
+
+ nn_begin = nname_begin (aino->nname);
+ return _tcscmp (nn_begin, aino->aname) != 0;
}
static void write_aino (FILE *f, a_inode *aino)
{
- uae_u8 buf[1 + 4 + 257 + 257 + 81] = { 0 };
+ uae_u8 buf[1 + 4 + 257 + 257 + 81] = { 0 };
buf[0] = aino->needs_dbentry ? 1 : 0;
- do_put_mem_long ((uae_u32 *)(buf + 1), aino->amigaos_mode);
+ do_put_mem_long ((uae_u32 *)(buf + 1), aino->amigaos_mode);
ua_copy ((char*)buf + 5, 256, aino->aname);
- buf[5 + 256] = '\0';
+ buf[5 + 256] = '\0';
ua_copy ((char*)buf + 5 + 257, 256, nname_begin (aino->nname));
- buf[5 + 257 + 256] = '\0';
+ buf[5 + 257 + 256] = '\0';
ua_copy ((char*)buf + 5 + 2 * 257, 80, aino->comment ? aino->comment : _T(""));
- buf[5 + 2 * 257 + 80] = '\0';
- aino->db_offset = ftell (f);
- fwrite (buf, 1, sizeof buf, f);
- aino->has_dbentry = aino->needs_dbentry;
+ buf[5 + 2 * 257 + 80] = '\0';
+ aino->db_offset = ftell (f);
+ fwrite (buf, 1, sizeof buf, f);
+ aino->has_dbentry = aino->needs_dbentry;
}
/* Write back the db file for a directory. */
void fsdb_dir_writeback (a_inode *dir)
{
- FILE *f;
- int changes_needed = 0;
- int entries_needed = 0;
- a_inode *aino;
- uae_u8 *tmpbuf;
- int size, i;
+ FILE *f;
+ int changes_needed = 0;
+ int entries_needed = 0;
+ a_inode *aino;
+ uae_u8 *tmpbuf;
+ int size, i;
- /* First pass: clear dirty bits where unnecessary, and see if any work
- * needs to be done. */
- for (aino = dir->child; aino; aino = aino->sibling) {
- int old_needs_dbentry = aino->has_dbentry;
- int need = needs_dbentry (aino);
- aino->needs_dbentry = need;
- entries_needed |= need;
- if (! aino->dirty)
- continue;
- if (! aino->needs_dbentry && ! old_needs_dbentry)
- aino->dirty = 0;
- else
- changes_needed = 1;
- }
- if (! entries_needed) {
- kill_fsdb (dir);
- return;
- }
+ /* First pass: clear dirty bits where unnecessary, and see if any work
+ * needs to be done. */
+ for (aino = dir->child; aino; aino = aino->sibling) {
+ int old_needs_dbentry = aino->has_dbentry;
+ int need = needs_dbentry (aino);
+ aino->needs_dbentry = need;
+ entries_needed |= need;
+ if (! aino->dirty)
+ continue;
+ if (! aino->needs_dbentry && ! old_needs_dbentry)
+ aino->dirty = 0;
+ else
+ changes_needed = 1;
+ }
+ if (! entries_needed) {
+ kill_fsdb (dir);
+ return;
+ }
- if (! changes_needed) {
- return;
- }
+ if (! changes_needed) {
+ return;
+ }
f = get_fsdb (dir, _T("r+b"));
- if (f == 0) {
- f = get_fsdb (dir, _T("w+b"));
- if (f == 0) {
- /* This shouldn't happen... */
- return;
- }
- }
- fseek (f, 0, SEEK_END);
- size = ftell (f);
- fseek (f, 0, SEEK_SET);
- tmpbuf = 0;
- if (size > 0) {
- tmpbuf = (uae_u8 *)malloc (size);
- fread (tmpbuf, 1, size, f);
- }
+ if (f == 0) {
+ f = get_fsdb (dir, _T("w+b"));
+ if (f == 0) {
+ /* This shouldn't happen... */
+ return;
+ }
+ }
+ fseek (f, 0, SEEK_END);
+ size = ftell (f);
+ fseek (f, 0, SEEK_SET);
+ tmpbuf = 0;
+ if (size > 0) {
+ tmpbuf = (uae_u8*)malloc (size);
+ fread (tmpbuf, 1, size, f);
+ }
- for (aino = dir->child; aino; aino = aino->sibling) {
- if (! aino->dirty)
- continue;
- aino->dirty = 0;
+ for (aino = dir->child; aino; aino = aino->sibling) {
+ if (! aino->dirty)
+ continue;
+ aino->dirty = 0;
- i = 0;
- while (!aino->has_dbentry && i < size) {
+ i = 0;
+ while (!aino->has_dbentry && i < size) {
TCHAR *s = au ((char*)tmpbuf + i + 5);
if (!_tcscmp (s, aino->aname)) {
- aino->has_dbentry = 1;
- aino->db_offset = i;
- }
+ aino->has_dbentry = 1;
+ aino->db_offset = i;
+ }
xfree (s);
- i += 1 + 4 + 257 + 257 + 81;
- }
+ i += 1 + 4 + 257 + 257 + 81;
+ }
- if (! aino->has_dbentry) {
- fseek (f, 0, SEEK_END);
- aino->has_dbentry = 1;
- } else {
- fseek (f, aino->db_offset, SEEK_SET);
- }
- write_aino (f, aino);
- }
- fclose (f);
- xfree (tmpbuf);
+ if (! aino->has_dbentry) {
+ fseek (f, 0, SEEK_END);
+ aino->has_dbentry = 1;
+ } else {
+ fseek (f, aino->db_offset, SEEK_SET);
+ }
+ write_aino (f, aino);
+ }
+ fclose (f);
+ xfree (tmpbuf);
}
diff --git a/src/fsdb_unix.cpp b/src/fsdb_unix.cpp
index a71651d2..796a792c 100644
--- a/src/fsdb_unix.cpp
+++ b/src/fsdb_unix.cpp
@@ -8,11 +8,7 @@
* Copyright 1999 Bernd Schmidt
*/
-#include
-#include
-#include
-#include
-
+#include "sysconfig.h"
#include "sysdeps.h"
#include "fsdb.h"
@@ -27,12 +23,12 @@ static TCHAR evilchars[NUM_EVILCHARS] = { '\\', '*', '?', '\"', '<', '>', '|' };
/* Return nonzero for any name we can't create on the native filesystem. */
static int fsdb_name_invalid_2 (a_inode *aino, const TCHAR *n, int dir)
{
- int i;
+ int i;
int l = _tcslen (n);
- /* the reserved fsdb filename */
- if (_tcscmp (n, FSDB_FILE) == 0)
- return -1;
+ /* the reserved fsdb filename */
+ if (_tcscmp (n, FSDB_FILE) == 0)
+ return -1;
if (dir) {
if (n[0] == '.' && l == 1)
@@ -41,11 +37,11 @@ static int fsdb_name_invalid_2 (a_inode *aino, const TCHAR *n, int dir)
return -1;
}
- /* these characters are *never* allowed */
- for (i = 0; i < NUM_EVILCHARS; i++) {
- if (_tcschr (n, evilchars[i]) != 0)
- return 1;
- }
+ /* these characters are *never* allowed */
+ for (i = 0; i < NUM_EVILCHARS; i++) {
+ if (_tcschr (n, evilchars[i]) != 0)
+ return 1;
+ }
return 0; /* the filename passed all checks, now it should be ok */
}
diff --git a/src/fsusage.cpp b/src/fsusage.cpp
index 472ae548..e18a984e 100644
--- a/src/fsusage.cpp
+++ b/src/fsusage.cpp
@@ -1,27 +1,25 @@
/* fsusage.c -- return space usage of mounted filesystems
- Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc.
+Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
#include
#include
-#include
-#include
-#include
-
-#include "sysconfig.h"
#if defined(STAT_STATVFS) && !defined(__ANDROID__)
#include
@@ -32,22 +30,22 @@
#include "fsusage.h"
/* Return the number of TOSIZE-byte blocks used by
- BLOCKS FROMSIZE-byte blocks, rounding away from zero.
- TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
+BLOCKS FROMSIZE-byte blocks, rounding away from zero.
+TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
-static long adjust_blocks(long blocks, int fromsize, int tosize)
+static long adjust_blocks (long blocks, int fromsize, int tosize)
{
- if (tosize <= 0)
- abort ();
- if (fromsize <= 0)
- return -1;
+ if (tosize <= 0)
+ abort ();
+ if (fromsize <= 0)
+ return -1;
- if (fromsize == tosize) /* e.g., from 512 to 512 */
- return blocks;
- else if (fromsize > tosize) /* e.g., from 2048 to 512 */
- return blocks * (fromsize / tosize);
- else /* e.g., from 256 to 512 */
- return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
+ if (fromsize == tosize) /* e.g., from 512 to 512 */
+ return blocks;
+ else if (fromsize > tosize) /* e.g., from 2048 to 512 */
+ return blocks * (fromsize / tosize);
+ else /* e.g., from 256 to 512 */
+ return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
}
#ifdef WINDOWS
@@ -132,61 +130,61 @@ int statvfs ();
#endif
/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
- Return the actual number of bytes read, zero for EOF, or negative
- for an error. */
+Return the actual number of bytes read, zero for EOF, or negative
+for an error. */
static int safe_read (int desc, TCHAR *ptr, int len)
{
- int n_chars;
+ int n_chars;
- if (len <= 0)
- return len;
+ if (len <= 0)
+ return len;
#ifdef EINTR
- do
- {
- n_chars = read (desc, ptr, len);
- }
- while (n_chars < 0 && errno == EINTR);
+ do
+ {
+ n_chars = read (desc, ptr, len);
+ }
+ while (n_chars < 0 && errno == EINTR);
#else
- n_chars = read (desc, ptr, len);
+ n_chars = read (desc, ptr, len);
#endif
- return n_chars;
+ return n_chars;
}
/* Fill in the fields of FSP with information about space usage for
- the filesystem on which PATH resides.
- DISK is the device on which PATH is mounted, for space-getting
- methods that need to know it.
- Return 0 if successful, -1 if not. When returning -1, ensure that
- ERRNO is either a system error value, or zero if DISK is NULL
- on a system that requires a non-NULL value. */
+the filesystem on which PATH resides.
+DISK is the device on which PATH is mounted, for space-getting
+methods that need to know it.
+Return 0 if successful, -1 if not. When returning -1, ensure that
+ERRNO is either a system error value, or zero if DISK is NULL
+on a system that requires a non-NULL value. */
#ifndef WINDOWS
int get_fs_usage (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp)
{
#ifdef STAT_STATFS3_OSF1
# define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
- struct statfs fsd;
+ struct statfs fsd;
- if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
- return -1;
+ if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
+ return -1;
#endif /* STAT_STATFS3_OSF1 */
#ifdef STAT_STATFS2_FS_DATA /* Ultrix */
# define CONVERT_BLOCKS(B) adjust_blocks ((B), 1024, 512)
- struct fs_data fsd;
+ struct fs_data fsd;
- if (statfs (path, &fsd) != 1)
- return -1;
- fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
- fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
- fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
- fsp->fsu_files = fsd.fd_req.gtot;
- fsp->fsu_ffree = fsd.fd_req.gfree;
+ if (statfs (path, &fsd) != 1)
+ return -1;
+ fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
+ fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
+ fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
+ fsp->fsu_files = fsd.fd_req.gtot;
+ fsp->fsu_ffree = fsd.fd_req.gfree;
#endif /* STAT_STATFS2_FS_DATA */
@@ -195,56 +193,56 @@ int get_fs_usage (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp)
# define SUPERBOFF (SUPERB * 512)
# endif
# define CONVERT_BLOCKS(B) \
- adjust_blocks ((B), (fsd.s_type == Fs2b ? 1024 : 512), 512)
+ adjust_blocks ((B), (fsd.s_type == Fs2b ? 1024 : 512), 512)
- struct filsys fsd;
- int fd;
+ struct filsys fsd;
+ int fd;
- if (! disk)
- {
- errno = 0;
- return -1;
- }
+ if (! disk)
+ {
+ errno = 0;
+ return -1;
+ }
- fd = open (disk, O_RDONLY);
- if (fd < 0)
- return -1;
- lseek (fd, (long) SUPERBOFF, 0);
- if (safe_read (fd, (TCHAR *) &fsd, sizeof fsd) != sizeof fsd)
- {
- close (fd);
- return -1;
- }
- close (fd);
- fsp->fsu_blocks = CONVERT_BLOCKS (fsd.s_fsize);
- fsp->fsu_bfree = CONVERT_BLOCKS (fsd.s_tfree);
- fsp->fsu_bavail = CONVERT_BLOCKS (fsd.s_tfree);
- fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
- fsp->fsu_ffree = fsd.s_tinode;
+ fd = open (disk, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ lseek (fd, (long) SUPERBOFF, 0);
+ if (safe_read (fd, (TCHAR *) &fsd, sizeof fsd) != sizeof fsd)
+ {
+ close (fd);
+ return -1;
+ }
+ close (fd);
+ fsp->fsu_blocks = CONVERT_BLOCKS (fsd.s_fsize);
+ fsp->fsu_bfree = CONVERT_BLOCKS (fsd.s_tfree);
+ fsp->fsu_bavail = CONVERT_BLOCKS (fsd.s_tfree);
+ fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
+ fsp->fsu_ffree = fsd.s_tinode;
#endif /* STAT_READ_FILSYS */
#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */
# define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512)
- struct statfs fsd;
+ struct statfs fsd;
- if (statfs (path, &fsd) < 0)
- return -1;
+ if (statfs (path, &fsd) < 0)
+ return -1;
# ifdef STATFS_TRUNCATES_BLOCK_COUNTS
- /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
- struct statfs are truncated to 2GB. These conditions detect that
- truncation, presumably without botching the 4.1.1 case, in which
- the values are not truncated. The correct counts are stored in
- undocumented spare fields. */
- if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0)
- {
- fsd.f_blocks = fsd.f_spare[0];
- fsd.f_bfree = fsd.f_spare[1];
- fsd.f_bavail = fsd.f_spare[2];
- }
+ /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
+ struct statfs are truncated to 2GB. These conditions detect that
+ truncation, presumably without botching the 4.1.1 case, in which
+ the values are not truncated. The correct counts are stored in
+ undocumented spare fields. */
+ if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0)
+ {
+ fsd.f_blocks = fsd.f_spare[0];
+ fsd.f_bfree = fsd.f_spare[1];
+ fsd.f_bavail = fsd.f_spare[2];
+ }
# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
#endif /* STAT_STATFS2_BSIZE */
@@ -252,10 +250,10 @@ int get_fs_usage (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp)
#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */
# define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
- struct statfs fsd;
+ struct statfs fsd;
- if (statfs (path, &fsd) < 0)
- return -1;
+ if (statfs (path, &fsd) < 0)
+ return -1;
#endif /* STAT_STATFS2_FSIZE */
@@ -274,42 +272,42 @@ int get_fs_usage (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp)
# endif
# endif
- struct statfs fsd;
+ struct statfs fsd;
- if (statfs (path, &fsd, sizeof fsd, 0) < 0)
- return -1;
- /* Empirically, the block counts on most SVR3 and SVR3-derived
- systems seem to always be in terms of 512-byte blocks,
- no matter what value f_bsize has. */
+ if (statfs (path, &fsd, sizeof fsd, 0) < 0)
+ return -1;
+ /* Empirically, the block counts on most SVR3 and SVR3-derived
+ systems seem to always be in terms of 512-byte blocks,
+ no matter what value f_bsize has. */
#endif /* STAT_STATFS4 */
#ifdef STAT_STATVFS /* SVR4 */
# define CONVERT_BLOCKS(B) \
- adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
+ adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
#ifdef ANDROID
- struct statfs fsd;
+ struct statfs fsd;
- if (statfs (path, &fsd) < 0)
+ if (statfs (path, &fsd) < 0)
#else
- struct statvfs fsd;
+ struct statvfs fsd;
- if (statvfs (path, &fsd) < 0)
+ if (statvfs (path, &fsd) < 0)
#endif
- return -1;
- /* f_frsize isn't guaranteed to be supported. */
+ return -1;
+ /* f_frsize isn't guaranteed to be supported. */
#endif /* STAT_STATVFS */
#if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS)
- /* !Ultrix && !SVR2 */
+ /* !Ultrix && !SVR2 */
fsp->total = (uae_s64)fsd.f_bsize * (uae_s64)fsd.f_blocks;
fsp->avail = (uae_s64)fsd.f_bsize * (uae_s64)fsd.f_bavail;
#endif /* not STAT_STATFS2_FS_DATA && not STAT_READ_FILSYS */
- return 0;
+ return 0;
}
#endif
diff --git a/src/gayle.cpp b/src/gayle.cpp
index c0061f37..ecc12132 100644
--- a/src/gayle.cpp
+++ b/src/gayle.cpp
@@ -25,10 +25,14 @@
#include "threaddep/thread.h"
#include "ide.h"
#include "autoconf.h"
+#include "rommgr.h"
#include "devices.h"
#define PCMCIA_SRAM 1
#define PCMCIA_IDE 2
+#define PCMCIA_NE2000 3
+#define PCMCIA_ARCHOSHD 4
+#define PCMCIA_SURFSQUIRREL 5
/*
600000 to 9FFFFF 4 MB Credit Card memory if CC present
@@ -241,7 +245,7 @@ static void gayle_cs_change (uae_u8 mask, int onoff)
}
if (changed) {
gayle_irq |= mask;
- rethink_gayle ();
+ devices_rethink_all(rethink_gayle);
if ((mask & GAYLE_CS_CCDET) && (gayle_irq & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)) != (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)) {
if (gayle_irq & GAYLE_IRQ_RESET)
uae_reset (0, 0);
@@ -1154,8 +1158,7 @@ static int initpcmcia (const TCHAR *path, int readonly, int type, int reset, str
hdf_read(&pcmcia_disk->hfd, pcmcia_attrs, pcmcia_common_size, extrasize);
write_log(_T("PCMCIA SRAM: Attribute data read %ld bytes\n"), extrasize);
pcmcia_attrs_full = 1;
- }
- else {
+ } else {
initsramattr(pcmcia_common_size, readonly);
}
write_log(_T("PCMCIA SRAM: '%s' open, size=%d\n"), path, pcmcia_common_size);
@@ -1366,13 +1369,12 @@ static void gayle_map_pcmcia (void)
while (!pcmcia_override) {
int cnt = 0;
for (int i = 0; i < 8; i++) {
- struct autoconfig_info* aci = expansion_get_autoconfig_by_address(&currprefs, 6 * 1024 * 1024 + i * 512 * 1024, idx);
+ struct autoconfig_info *aci = expansion_get_autoconfig_by_address(&currprefs, 6 * 1024 * 1024 + i * 512 * 1024, idx);
if (aci) {
if (aci->zorro > 0) {
pcmcia_override = true;
}
- }
- else {
+ } else {
cnt++;
}
}
@@ -1440,7 +1442,7 @@ bool gayle_init_pcmcia(struct autoconfig_info *aci)
static void gayle_hsync(void)
{
if (ide_interrupt_hsync(idedrive[0]) || ide_interrupt_hsync(idedrive[2]) || ide_interrupt_hsync(idedrive[4]))
- rethink_gayle();
+ devices_rethink_all(rethink_gayle);
}
static void initide (void)
diff --git a/src/include/akiko.h b/src/include/akiko.h
index 891fcd90..502d6e36 100644
--- a/src/include/akiko.h
+++ b/src/include/akiko.h
@@ -2,7 +2,7 @@
#define UAE_AKIKO_H
#define AKIKO_BASE 0xb80000
-#define AKIKO_BASE_END 0xb80040 /* ?? */
+#define AKIKO_BASE_END 0xb80040
extern int akiko_init (void);
extern void akiko_mute (int);
diff --git a/src/include/autoconf.h b/src/include/autoconf.h
index 2a310c4d..720f01d3 100644
--- a/src/include/autoconf.h
+++ b/src/include/autoconf.h
@@ -94,9 +94,9 @@ extern uaecptr ROM_hardfile_resname, ROM_hardfile_resid;
extern uaecptr ROM_hardfile_init;
extern uaecptr filesys_initcode, filesys_initcode_ptr, filesys_initcode_real;
-extern int is_hardfile (int unit_no);
-extern int nr_units (void);
-extern int nr_directory_units (struct uae_prefs*);
+extern int is_hardfile(int unit_no);
+extern int nr_units(void);
+extern int nr_directory_units(struct uae_prefs*);
extern uaecptr need_uae_boot_rom(struct uae_prefs*);
struct mountedinfo
@@ -115,9 +115,10 @@ extern int move_filesys_unitconfig (struct uae_prefs *p, int nr, int to);
extern TCHAR *validatedevicename (TCHAR *s, const TCHAR *def);
extern TCHAR *validatevolumename (TCHAR *s, const TCHAR *def);
-int filesys_insert (int nr, const TCHAR *volume, const TCHAR *rootdir, bool readonly, int flags);
+int filesys_insert(int nr, const TCHAR *volume, const TCHAR *rootdir, bool readonly, int flags);
int filesys_eject(int nr);
-int filesys_media_change (const TCHAR *rootdir, int inserted, struct uaedev_config_data *uci);
+int filesys_media_change(const TCHAR *rootdir, int inserted, struct uaedev_config_data *uci);
+int filesys_media_change_queue(const TCHAR *rootdir, int total);
extern TCHAR *filesys_createvolname (const TCHAR *volname, const TCHAR *rootdir, struct zvolume *zv, const TCHAR *def);
extern int target_get_volume_name (struct uaedev_mount_info *mtinf, struct uaedev_config_info *ci, bool inserted, bool fullcheck, int cnt);
@@ -129,25 +130,39 @@ extern void filesys_cleanup (void);
extern void filesys_prepare_reset (void);
extern void filesys_start_threads (void);
extern void filesys_flush_cache (void);
-//extern void filesys_free_handles (void);
+extern void filesys_free_handles (void);
extern void filesys_vsync (void);
+extern bool filesys_heartbeat(void);
extern void filesys_install (void);
extern void filesys_install_code (void);
extern void create_ks12_boot(void);
+extern void create_68060_nofpu(void);
extern uaecptr filesys_get_entry(int);
extern void filesys_store_devinfo (uae_u8 *);
extern void hardfile_install (void);
extern void hardfile_reset (void);
extern void emulib_install (void);
+extern uae_u32 uaeboard_demux (uae_u32*);
extern void expansion_init (void);
extern void expansion_cleanup (void);
extern void expansion_clear (void);
extern uaecptr expansion_startaddress(struct uae_prefs*, uaecptr addr, uae_u32 size);
+extern bool expansion_is_next_board_fastram(void);
+extern uaecptr uaeboard_alloc_ram(uae_u32);
+extern uae_u8 *uaeboard_map_ram(uaecptr);
extern void expansion_scan_autoconfig(struct uae_prefs*, bool);
extern void expansion_generate_autoconfig_info(struct uae_prefs *p);
-extern struct autoconfig_info* expansion_get_autoconfig_by_address(struct uae_prefs* p, uaecptr addr, int index);
+extern struct autoconfig_info *expansion_get_autoconfig_info(struct uae_prefs*, int romtype, int devnum);
+extern struct autoconfig_info *expansion_get_autoconfig_data(struct uae_prefs *p, int index);
+extern struct autoconfig_info *expansion_get_autoconfig_by_address(struct uae_prefs *p, uaecptr addr, int index);
+extern void expansion_set_autoconfig_sort(struct uae_prefs *p);
+extern int expansion_autoconfig_move(struct uae_prefs *p, int index, int direction, bool test);
+extern bool expansion_can_move(struct uae_prefs *p, int index);
+extern bool alloc_expansion_bank(addrbank *bank, struct autoconfig_info *aci);
+extern void free_expansion_bank(addrbank *bank);
extern void expansion_map(void);
+extern uae_u32 expansion_board_size(addrbank *ab);
extern void uaegfx_install_code (uaecptr);
@@ -173,24 +188,99 @@ typedef void(*DEVICE_MEMORY_CALLBACK)(struct romconfig*, uae_u8*, int);
#define EXPANSIONTYPE_INTERNAL 0x4000
#define EXPANSIONTYPE_FALLBACK_DISABLE 0x8000
#define EXPANSIONTYPE_HAS_FALLBACK 0x10000
+#define EXPANSIONTYPE_X86_EXPANSION 0x20000
+#define EXPANSIONTYPE_PCMCIA 0x40000
+#define EXPANSIONTYPE_CUSTOMDISK 0x80000
#define EXPANSIONBOARD_CHECKBOX 0
#define EXPANSIONBOARD_MULTI 1
#define EXPANSIONBOARD_STRING 2
+struct expansionboardsettings
+{
+ const TCHAR *name;
+ const TCHAR *configname;
+ int type;
+ bool invert;
+ int bitshift;
+};
+struct expansionsubromtype
+{
+ const TCHAR *name;
+ const TCHAR *configname;
+ uae_u32 romtype;
+ int memory_mid, memory_pid;
+ uae_u32 memory_serial;
+ bool memory_after;
+ uae_u8 autoconfig[16];
+};
struct expansionromtype
{
const TCHAR *name;
const TCHAR *friendlyname;
const TCHAR *friendlymanufacturer;
- DEVICE_INIT init;
+ DEVICE_INIT preinit, init, init2;
DEVICE_ADD add;
uae_u32 romtype;
+ uae_u32 romtype_extra;
+ uae_u32 parentromtype;
int zorro;
+ bool singleonly;
+ const struct expansionsubromtype *subtypes;
+ int defaultsubtype;
+ bool autoboot_jumper;
int deviceflags;
+ int memory_mid, memory_pid;
+ uae_u32 memory_serial;
+ bool memory_after;
+ DEVICE_MEMORY_CALLBACK memory_callback;
+ bool id_jumper;
+ int extrahdports;
+ const struct expansionboardsettings *settings;
uae_u8 autoconfig[16];
};
extern const struct expansionromtype expansionroms[];
+struct cpuboardsubtype
+{
+ const TCHAR *name;
+ const TCHAR *configname;
+ int romtype, romtype_extra;
+ int cputype;
+ DEVICE_ADD add;
+ int deviceflags;
+ int memorytype;
+ int maxmemory;
+ int z3extra;
+ DEVICE_INIT init, init2;
+ int initzorro;
+ int initflag;
+ const struct expansionboardsettings *settings;
+ E8ACCESS e8;
+ // if includes Z2 or Z3 RAM
+ int memory_mid, memory_pid;
+ uae_u32 memory_serial;
+ bool memory_after;
+ uae_u8 autoconfig[16];
+};
+struct cpuboardtype
+{
+ int id;
+ const TCHAR *name;
+ const struct cpuboardsubtype *subtypes;
+ int defaultsubtype;
+};
+extern const struct cpuboardtype cpuboards[];
+struct memoryboardtype
+{
+ const TCHAR *man;
+ const TCHAR *name;
+ uae_u8 z;
+ uae_u32 address;
+ uae_u16 manufacturer;
+ uae_u8 product;
+ uae_u8 autoconfig[16];
+};
+extern const struct memoryboardtype memoryboards[];
#endif /* UAE_AUTOCONF_H */
diff --git a/src/include/blkdev.h b/src/include/blkdev.h
index 39bdedb6..d27456dd 100644
--- a/src/include/blkdev.h
+++ b/src/include/blkdev.h
@@ -8,6 +8,11 @@
#define SCSI_UNIT_DISABLED -1
#define SCSI_UNIT_DEFAULT 0
#define SCSI_UNIT_IMAGE 1
+#define SCSI_UNIT_IOCTL 2
+#define SCSI_UNIT_SPTI 3
+
+//#define device_debug write_log
+#define device_debug
#define INQ_DASD 0x00 /* Direct-access device (disk) */
#define INQ_SEQD 0x01 /* Sequential-access device (tape) */
@@ -61,15 +66,25 @@ struct cd_toc_head
#define AUDIO_STATUS_PLAY_ERROR 0x14
#define AUDIO_STATUS_NO_STATUS 0x15
-struct device_info
-{
+struct device_info {
bool open;
- int type;
- int media_inserted;
+ int type;
+ int media_inserted;
int audio_playing;
- int unitnum;
- TCHAR label[MAX_DPATH];
+ int removable;
+ int write_protected;
+ int cylinders;
+ int trackspercylinder;
+ int sectorspertrack;
+ int bytespersector;
+ int bus, target, lun;
+ int unitnum;
+ TCHAR label[MAX_DPATH];
TCHAR mediapath[MAX_DPATH];
+ TCHAR vendorid[10];
+ TCHAR productid[18];
+ TCHAR revision[6];
+ const TCHAR *backend;
struct cd_toc_head toc;
TCHAR system_id[33];
TCHAR volume_id[33];
@@ -77,17 +92,17 @@ struct device_info
struct amigascsi
{
- uae_u8* data;
- uae_s32 len;
- uae_u8 cmd[16];
- uae_s32 cmd_len;
- uae_u8 flags;
- uae_u8 sensedata[256];
- uae_u16 sense_len;
- uae_u16 cmdactual;
- uae_u8 status;
- uae_u16 actual;
- uae_u16 sactual;
+ uae_u8 *data;
+ uae_s32 len;
+ uae_u8 cmd[16];
+ uae_s32 cmd_len;
+ uae_u8 flags;
+ uae_u8 sensedata[256];
+ uae_u16 sense_len;
+ uae_u16 cmdactual;
+ uae_u8 status;
+ uae_u16 actual;
+ uae_u16 sactual;
};
typedef int (*check_bus_func)(int flags);
@@ -96,6 +111,9 @@ typedef void (*close_bus_func)(void);
typedef int (*open_device_func)(int, const TCHAR*, int);
typedef void (*close_device_func)(int);
typedef struct device_info* (*info_device_func)(int, struct device_info*, int, int);
+typedef uae_u8* (*execscsicmd_out_func)(int, uae_u8*, int);
+typedef uae_u8* (*execscsicmd_in_func)(int, uae_u8*, int, int*);
+typedef int (*execscsicmd_direct_func)(int, struct amigascsi*);
typedef void (*play_subchannel_callback)(uae_u8*, int);
typedef int (*play_status_callback)(int, int);
@@ -113,14 +131,16 @@ typedef int (*isatapi_func)(int);
typedef int (*ismedia_func)(int, int);
typedef int (*scsiemu_func)(int, uae_u8*);
-struct device_functions
-{
- const TCHAR* name;
+struct device_functions {
+ const TCHAR *name;
open_bus_func openbus;
close_bus_func closebus;
open_device_func opendev;
close_device_func closedev;
info_device_func info;
+ execscsicmd_out_func exec_out;
+ execscsicmd_in_func exec_in;
+ execscsicmd_direct_func exec_direct;
pause_func pause;
stop_func stop;
@@ -130,55 +150,84 @@ struct device_functions
toc_func toc;
read_func read;
rawread_func rawread;
+ write_func write;
+ isatapi_func isatapi;
ismedia_func ismedia;
+
+ scsiemu_func scsiemu;
+
};
-static int device_func_init(int flags);
+extern int device_func_init(int flags);
extern void device_func_free(void);
extern void device_func_reset(void);
-extern int sys_command_open(int unitnum);
+extern int sys_command_open (int unitnum);
+extern int sys_command_open_tape (int unitnum, const TCHAR *tape_directory, bool readonly);
extern void sys_command_close (int unitnum);
+extern int sys_command_isopen (int unitnum);
extern struct device_info *sys_command_info (int unitnum, struct device_info *di, int);
extern int sys_command_cd_pause (int unitnum, int paused);
extern void sys_command_cd_stop (int unitnum);
+extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int);
extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc);
extern uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right);
extern int sys_command_cd_qcode (int unitnum, uae_u8*, int lsn, bool all);
extern int sys_command_cd_toc (int unitnum, struct cd_toc_head*);
+extern int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size);
extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize);
+int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u8 sectortype, uae_u8 scsicmd9, uae_u8 subs);
+extern int sys_command_read (int unitnum, uae_u8 *data, int block, int size);
+extern int sys_command_write (int unitnum, uae_u8 *data, int block, int size);
+extern int sys_command_scsi_direct_native (int unitnum, int type, struct amigascsi *as);
+extern int sys_command_scsi_direct(TrapContext *ctx, int unitnum, int type, uaecptr request);
extern int sys_command_ismedia (int unitnum, int quick);
-extern bool blkdev_get_info(struct uae_prefs* p, int unitnum, struct device_info* di);
+extern struct device_info *sys_command_info_session (int unitnum, struct device_info *di, int, int);
+extern bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di);
-extern void blkdev_vsync(void);
+extern void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **data, int *datalen, int *parm);
+extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalen, int parm);
+
+extern void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen);
+extern void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen);
+
+extern int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
+ uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len, bool atapi);
+
+extern void blkdev_vsync (void);
extern void restore_blkdev_start(void);
-extern int msf2lsn(int msf);
-extern int lsn2msf(int lsn);
-extern uae_u8 frombcd(uae_u8 v);
-extern uae_u8 tobcd(uae_u8 v);
-extern int fromlongbcd(uae_u8 * p);
-extern void tolongbcd(uae_u8* p, int v);
+extern int msf2lsn (int msf);
+extern int lsn2msf (int lsn);
+extern uae_u8 frombcd (uae_u8 v);
+extern uae_u8 tobcd (uae_u8 v);
+extern int fromlongbcd (uae_u8 *p);
+extern void tolongbcd (uae_u8 *p, int v);
extern void blkdev_default_prefs (struct uae_prefs *p);
extern void blkdev_fix_prefs (struct uae_prefs *p);
extern int isaudiotrack (struct cd_toc_head*, int block);
+extern int isdatatrack (struct cd_toc_head*, int block);
+extern int cdtracknumber(struct cd_toc_head *th, int block);
void sub_to_interleaved (const uae_u8 *s, uae_u8 *d);
+void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d);
-enum cd_standard_unit
-{
- CD_STANDARD_UNIT_DEFAULT,
- CD_STANDARD_UNIT_AUDIO,
- CD_STANDARD_UNIT_CDTV,
- CD_STANDARD_UNIT_CD32
-};
+enum cd_standard_unit { CD_STANDARD_UNIT_DEFAULT, CD_STANDARD_UNIT_AUDIO, CD_STANDARD_UNIT_CDTV, CD_STANDARD_UNIT_CD32 };
-extern int get_standard_cd_unit(enum cd_standard_unit csu);
-extern void blkdev_cd_change(int unitnum, const TCHAR* name);
+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);
+extern void blkdev_entergui (void);
+extern void blkdev_exitgui (void);
+bool filesys_do_disk_change (int, bool);
+
+extern struct device_functions devicefunc_scsi_ioctl;
+extern struct device_functions devicefunc_scsi_spti;
extern struct device_functions devicefunc_cdimage;
+int blkdev_is_audio_command(uae_u8 cmd);
+int blkdev_execute_audio_command(int unitnum, uae_u8 *cdb, int cdblen, uae_u8 *inbuf, int inlen, uae_u8 *sense, int *senselen);
+
#endif /* UAE_BLKDEV_H */
diff --git a/src/include/cdtv.h b/src/include/cdtv.h
new file mode 100644
index 00000000..a9212c5f
--- /dev/null
+++ b/src/include/cdtv.h
@@ -0,0 +1,26 @@
+#ifndef UAE_CDTV_H
+#define UAE_CDTV_H
+
+#include "uae/types.h"
+
+#ifdef CDTV
+
+extern bool cdtv_init (struct autoconfig_info *aci);
+
+void cdtv_battram_write (int addr, int v);
+uae_u8 cdtv_battram_read (int addr);
+
+extern void cdtv_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+extern bool cdtvscsi_init(struct autoconfig_info *aci);
+extern bool cdtvsram_init(struct autoconfig_info *aci);
+
+extern void cdtv_getdmadata (uae_u32*);
+
+extern void cdtv_scsi_int (void);
+extern void cdtv_scsi_clear_int (void);
+
+extern bool cdtv_front_panel (int);
+
+#endif /* CDTV */
+
+#endif /* UAE_CDTV_H */
diff --git a/src/include/cdtvcr.h b/src/include/cdtvcr.h
new file mode 100644
index 00000000..8220a599
--- /dev/null
+++ b/src/include/cdtvcr.h
@@ -0,0 +1,6 @@
+#ifndef UAE_CDTVCR_H
+#define UAE_CDTVCR_H
+
+bool cdtvcr_init(struct autoconfig_info*);
+
+#endif /* UAE_CDTVCR_H */
diff --git a/src/include/cia.h b/src/include/cia.h
index 1ba6989b..7c623ae4 100644
--- a/src/include/cia.h
+++ b/src/include/cia.h
@@ -18,12 +18,23 @@ extern void CIA_handler (void);
extern void CIAA_tod_inc (int);
extern void CIAB_tod_handler (int);
+extern void diskindex_handler (void);
+extern void cia_parallelack (void);
extern void cia_diskindex (void);
+extern void dumpcia (void);
extern void rethink_cias (void);
extern int resetwarning_do (int);
extern void cia_set_overlay (bool);
+void cia_heartbeat (void);
-extern void rtc_hardreset(void);
+extern int parallel_direct_write_data (uae_u8, uae_u8);
+extern int parallel_direct_read_data (uae_u8*);
+extern int parallel_direct_write_status (uae_u8, uae_u8);
+extern int parallel_direct_read_status (uae_u8*);
+
+extern void rtc_hardreset (void);
+
+extern void keyboard_connected(bool);
#endif /* UAE_CIA_H */
diff --git a/src/include/commpipe.h b/src/include/commpipe.h
index 227a730d..8b267ce5 100644
--- a/src/include/commpipe.h
+++ b/src/include/commpipe.h
@@ -53,15 +53,15 @@ STATIC_INLINE void destroy_comm_pipe (smp_comm_pipe *p)
uae_sem_destroy (&p->lock);
uae_sem_destroy (&p->reader_wait);
uae_sem_destroy (&p->writer_wait);
- p->lock = 0;
- p->reader_wait = 0;
- p->writer_wait = 0;
- if(p->size > 0 && p->data != NULL)
- {
- free(p->data);
- p->size = 0;
- p->data = NULL;
- }
+ p->lock = 0;
+ p->reader_wait = 0;
+ p->writer_wait = 0;
+ if(p->size > 0 && p->data != NULL)
+ {
+ free(p->data);
+ p->size = 0;
+ p->data = NULL;
+ }
}
STATIC_INLINE void maybe_wake_reader (smp_comm_pipe *p, int no_buffer)
diff --git a/src/include/cpu_prefetch.h b/src/include/cpu_prefetch.h
index f4fe28cb..6f2fc024 100644
--- a/src/include/cpu_prefetch.h
+++ b/src/include/cpu_prefetch.h
@@ -3,7 +3,341 @@
#include "uae/types.h"
-STATIC_INLINE uae_u32 get_word_000_prefetch (int o)
+#ifdef CPUEMU_20
+
+extern uae_u32 get_word_020_prefetch (int);
+extern void continue_020_prefetch(void);
+
+STATIC_INLINE uae_u32 next_iword_020_prefetch (void)
+{
+ uae_u32 r = get_word_020_prefetch (0);
+ m68k_incpci (2);
+ return r;
+}
+STATIC_INLINE uae_u32 next_ilong_020_prefetch (void)
+{
+ uae_u32 r = next_iword_020_prefetch () << 16;
+ r |= next_iword_020_prefetch ();
+ return r;
+}
+
+STATIC_INLINE uae_u32 get_long_020_prefetch (int o)
+{
+ uae_u32 r = get_word_020_prefetch (o) << 16;
+ r |= get_word_020_prefetch (o + 2);
+ return r;
+}
+
+#endif
+
+#ifdef CPUEMU_21
+
+STATIC_INLINE void limit_cycles_ce020(int clocks)
+{
+#if 0
+ int cycs = clocks * cpucycleunit;
+ int diff = regs.ce020endcycle - regs.ce020startcycle;
+ if (diff <= cycs)
+ return;
+ regs.ce020startcycle = regs.ce020endcycle - cycs;
+#endif
+}
+
+STATIC_INLINE void limit_all_cycles_ce020(void)
+{
+#if 0
+ regs.ce020startcycle = regs.ce020endcycle;
+#endif
+}
+
+// only for CPU internal cycles
+STATIC_INLINE void do_cycles_ce020_internal(int clocks)
+{
+ if (currprefs.m68k_speed < 0) {
+ regs.ce020extracycles += clocks;
+ return;
+ }
+ int cycs = clocks * cpucycleunit;
+ int diff = regs.ce020endcycle - regs.ce020startcycle;
+ if (diff > 0) {
+ if (diff >= cycs) {
+ regs.ce020startcycle += cycs;
+ return;
+ }
+ regs.ce020startcycle = regs.ce020endcycle;
+ cycs -= diff;
+ }
+#if 0
+ if (regs.ce020memcycles > 0) {
+ if (regs.ce020memcycles >= cycs) {
+ regs.ce020memcycles -= cycs;
+ return;
+ }
+ cycs = cycs - regs.ce020memcycles;
+ }
+ regs.ce020memcycles = 0;
+#endif
+ x_do_cycles (cycs);
+}
+
+STATIC_INLINE void do_cycles_020_internal(int clocks)
+{
+ if (currprefs.m68k_speed < 0)
+ return;
+ x_do_cycles(clocks * cpucycleunit);
+}
+
+STATIC_INLINE void do_cycles_ce020_mem (int clocks, uae_u32 val)
+{
+ x_do_cycles_post (clocks * cpucycleunit, val);
+}
+
+#if 0
+STATIC_INLINE void do_head_cycles_ce020 (int h)
+{
+ if (regs.ce020_tail) {
+ int cycs = regs.ce020_tail_cycles - get_cycles ();
+ if (cycs < 0)
+ cycs = 0;
+ cycs -= h * cpucycleunit;
+ if (cycs)
+ x_do_cycles (cycs < 0 ? -cycs : cycs);
+ } else if (h > 0) {
+ do_cycles_ce020 (h);
+ }
+}
+#endif
+
+STATIC_INLINE uae_u32 get_long_ce020 (uaecptr addr)
+{
+ return mem_access_delay_long_read_ce020 (addr);
+}
+STATIC_INLINE uae_u32 get_word_ce020 (uaecptr addr)
+{
+ return mem_access_delay_word_read_ce020 (addr);
+}
+STATIC_INLINE uae_u32 get_byte_ce020 (uaecptr addr)
+{
+ return mem_access_delay_byte_read_ce020 (addr);
+}
+
+STATIC_INLINE void put_long_ce020 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_long_write_ce020 (addr, v);
+}
+STATIC_INLINE void put_word_ce020 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_word_write_ce020 (addr, v);
+}
+STATIC_INLINE void put_byte_ce020 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_byte_write_ce020 (addr, v);
+}
+
+extern void continue_ce020_prefetch(void);
+extern uae_u32 get_word_ce020_prefetch(int);
+extern uae_u32 get_word_ce020_prefetch_opcode(int);
+
+STATIC_INLINE uae_u32 get_long_ce020_prefetch (int o)
+{
+ uae_u32 v;
+ uae_u16 tmp;
+ v = get_word_ce020_prefetch (o) << 16;
+ tmp = regs.db;
+ v |= get_word_ce020_prefetch (o + 2);
+ regs.db = tmp;
+ return v;
+}
+
+STATIC_INLINE uae_u32 next_iword_020ce (void)
+{
+ uae_u32 r = get_word_ce020_prefetch (0);
+ m68k_incpci (2);
+ return r;
+}
+STATIC_INLINE uae_u32 next_ilong_020ce (void)
+{
+ uae_u32 r = get_long_ce020_prefetch (0);
+ m68k_incpci (4);
+ return r;
+}
+
+STATIC_INLINE void m68k_do_bsr_ce020 (uaecptr oldpc, uae_s32 offset)
+{
+ m68k_areg (regs, 7) -= 4;
+ x_put_long (m68k_areg (regs, 7), oldpc);
+ m68k_incpci (offset);
+}
+STATIC_INLINE void m68k_do_rts_ce020 (void)
+{
+ m68k_setpci (x_get_long (m68k_areg (regs, 7)));
+ m68k_areg (regs, 7) += 4;
+}
+
+
+#endif
+
+#ifdef CPUEMU_22
+
+extern void continue_030_prefetch(void);
+extern uae_u32 get_word_030_prefetch(int);
+
+STATIC_INLINE void put_long_030(uaecptr addr, uae_u32 v)
+{
+ write_data_030_lput(addr, v);
+}
+STATIC_INLINE void put_word_030(uaecptr addr, uae_u32 v)
+{
+ write_data_030_wput(addr, v);
+}
+STATIC_INLINE void put_byte_030(uaecptr addr, uae_u32 v)
+{
+ write_data_030_bput(addr, v);
+}
+STATIC_INLINE uae_u32 get_long_030(uaecptr addr)
+{
+ return read_data_030_lget(addr);
+}
+STATIC_INLINE uae_u32 get_word_030(uaecptr addr)
+{
+ return read_data_030_wget(addr);
+}
+STATIC_INLINE uae_u32 get_byte_030(uaecptr addr)
+{
+ return read_data_030_bget(addr);
+}
+
+STATIC_INLINE uae_u32 get_long_030_prefetch(int o)
+{
+ uae_u32 v;
+ v = get_word_030_prefetch(o) << 16;
+ v |= get_word_030_prefetch(o + 2);
+ return v;
+}
+
+STATIC_INLINE uae_u32 next_iword_030_prefetch(void)
+{
+ uae_u32 r = get_word_030_prefetch(0);
+ m68k_incpci(2);
+ return r;
+}
+STATIC_INLINE uae_u32 next_ilong_030_prefetch(void)
+{
+ uae_u32 r = get_long_030_prefetch(0);
+ m68k_incpci(4);
+ return r;
+}
+
+STATIC_INLINE void m68k_do_bsr_030(uaecptr oldpc, uae_s32 offset)
+{
+ m68k_areg(regs, 7) -= 4;
+ put_long_030(m68k_areg(regs, 7), oldpc);
+ m68k_incpci(offset);
+}
+STATIC_INLINE void m68k_do_rts_030(void)
+{
+ m68k_setpc(get_long_030(m68k_areg(regs, 7)));
+ m68k_areg(regs, 7) += 4;
+}
+
+#endif
+
+#ifdef CPUEMU_23
+
+extern void continue_ce030_prefetch(void);
+extern uae_u32 get_word_ce030_prefetch(int);
+extern uae_u32 get_word_ce030_prefetch_opcode(int);
+
+STATIC_INLINE uae_u32 get_long_ce030 (uaecptr addr)
+{
+ return mem_access_delay_long_read_ce020 (addr);
+}
+STATIC_INLINE uae_u32 get_word_ce030 (uaecptr addr)
+{
+ return mem_access_delay_word_read_ce020 (addr);
+}
+STATIC_INLINE uae_u32 get_byte_ce030 (uaecptr addr)
+{
+ return mem_access_delay_byte_read_ce020 (addr);
+}
+
+STATIC_INLINE void put_long_ce030 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_long_write_ce020 (addr, v);
+}
+STATIC_INLINE void put_word_ce030 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_word_write_ce020 (addr, v);
+}
+STATIC_INLINE void put_byte_ce030 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_byte_write_ce020 (addr, v);
+}
+
+
+STATIC_INLINE void put_long_dc030 (uaecptr addr, uae_u32 v)
+{
+ write_dcache030_lput(addr, v, (regs.s ? 4 : 0) | 1);
+}
+STATIC_INLINE void put_word_dc030 (uaecptr addr, uae_u32 v)
+{
+ write_dcache030_wput(addr, v, (regs.s ? 4 : 0) | 1);
+}
+STATIC_INLINE void put_byte_dc030 (uaecptr addr, uae_u32 v)
+{
+ write_dcache030_bput(addr, v, (regs.s ? 4 : 0) | 1);
+}
+STATIC_INLINE uae_u32 get_long_dc030 (uaecptr addr)
+{
+ return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
+}
+STATIC_INLINE uae_u32 get_word_dc030 (uaecptr addr)
+{
+ return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
+}
+STATIC_INLINE uae_u32 get_byte_dc030 (uaecptr addr)
+{
+ return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
+}
+
+STATIC_INLINE uae_u32 get_long_ce030_prefetch (int o)
+{
+ uae_u32 v;
+ v = get_word_ce030_prefetch (o) << 16;
+ v |= get_word_ce030_prefetch (o + 2);
+ return v;
+}
+
+STATIC_INLINE uae_u32 next_iword_030ce (void)
+{
+ uae_u32 r = get_word_ce030_prefetch (0);
+ m68k_incpci (2);
+ return r;
+}
+STATIC_INLINE uae_u32 next_ilong_030ce (void)
+{
+ uae_u32 r = get_long_ce030_prefetch (0);
+ m68k_incpci (4);
+ return r;
+}
+
+STATIC_INLINE void m68k_do_bsr_ce030 (uaecptr oldpc, uae_s32 offset)
+{
+ m68k_areg (regs, 7) -= 4;
+ x_put_long (m68k_areg (regs, 7), oldpc);
+ m68k_incpci (offset);
+}
+STATIC_INLINE void m68k_do_rts_ce030 (void)
+{
+ m68k_setpc (x_get_long (m68k_areg (regs, 7)));
+ m68k_areg (regs, 7) += 4;
+}
+
+#endif
+
+#ifdef CPUEMU_11
+
+STATIC_INLINE uae_u32 get_word_000_prefetch(int o)
{
uae_u32 v = regs.irc;
regs.irc = regs.db = get_wordi (m68k_getpci () + o);
@@ -31,6 +365,72 @@ STATIC_INLINE void put_word_000(uaecptr addr, uae_u32 v)
regs.db = v;
put_word (addr, v);
}
+#endif
+
+#ifdef CPUEMU_13
+
+STATIC_INLINE void do_cycles_ce000_internal(int clocks)
+{
+ if (currprefs.m68k_speed < 0)
+ return;
+ x_do_cycles (clocks * cpucycleunit);
+}
+STATIC_INLINE void do_cycles_ce000 (int clocks)
+{
+ x_do_cycles (clocks * cpucycleunit);
+}
+
+STATIC_INLINE void ipl_fetch (void)
+{
+ regs.ipl = regs.ipl_pin;
+}
+
+uae_u32 mem_access_delay_word_read (uaecptr addr);
+uae_u32 mem_access_delay_wordi_read (uaecptr addr);
+uae_u32 mem_access_delay_byte_read (uaecptr addr);
+void mem_access_delay_byte_write (uaecptr addr, uae_u32 v);
+void mem_access_delay_word_write (uaecptr addr, uae_u32 v);
+
+STATIC_INLINE uae_u32 get_long_ce000 (uaecptr addr)
+{
+ uae_u32 v = mem_access_delay_word_read (addr) << 16;
+ v |= mem_access_delay_word_read (addr + 2);
+ return v;
+}
+STATIC_INLINE uae_u32 get_word_ce000 (uaecptr addr)
+{
+ return mem_access_delay_word_read (addr);
+}
+STATIC_INLINE uae_u32 get_wordi_ce000 (int offset)
+{
+ return mem_access_delay_wordi_read (m68k_getpci () + offset);
+}
+STATIC_INLINE uae_u32 get_byte_ce000 (uaecptr addr)
+{
+ return mem_access_delay_byte_read (addr);
+}
+STATIC_INLINE uae_u32 get_word_ce000_prefetch (int o)
+{
+ uae_u32 v = regs.irc;
+ regs.irc = regs.read_buffer = regs.db = x_get_iword (o);
+ return v;
+}
+
+STATIC_INLINE void put_long_ce000 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_word_write (addr, v >> 16);
+ mem_access_delay_word_write (addr + 2, v);
+}
+STATIC_INLINE void put_word_ce000 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_word_write (addr, v);
+}
+STATIC_INLINE void put_byte_ce000 (uaecptr addr, uae_u32 v)
+{
+ mem_access_delay_byte_write (addr, v);
+}
+
+#endif
STATIC_INLINE uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
{
diff --git a/src/include/custom.h b/src/include/custom.h
index 67c02812..d8dca017 100644
--- a/src/include/custom.h
+++ b/src/include/custom.h
@@ -83,9 +83,9 @@ STATIC_INLINE void send_interrupt (int num)
INTREQ_0 (0x8000 | (1 << num));
}
extern void rethink_uae_int(void);
-STATIC_INLINE uae_u16 INTREQR (void)
+STATIC_INLINE uae_u16 INTREQR(void)
{
- return intreq;
+ return intreq;
}
STATIC_INLINE void safe_interrupt_set(bool i6)
@@ -93,7 +93,7 @@ STATIC_INLINE void safe_interrupt_set(bool i6)
uae_u16 v = i6 ? 0x2000 : 0x0008;
if (!(intreq & v)) {
INTREQ_0(0x8000 | v);
- }
+ }
}
/* maximums for statically allocated tables */
diff --git a/src/include/isofs.h b/src/include/isofs.h
new file mode 100644
index 00000000..0dc1c48a
--- /dev/null
+++ b/src/include/isofs.h
@@ -0,0 +1,387 @@
+#ifndef UAE_ISOFS_H
+#define UAE_ISOFS_H
+
+#include "uae/types.h"
+
+typedef int isofs_gid_t;
+typedef int isofs_uid_t;
+typedef int isofs_mode_t;
+typedef uae_s64 isofs_off_t;
+
+#define ISO_SYSTEM_ID_CDTV "CDTV"
+
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_SUPPLEMENTARY 2
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char unused1 [ISODCL ( 8, 8)];
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char unused3 [ISODCL ( 89, 120)];
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+/* Almost the same as the primary descriptor but two fields are specified */
+struct iso_supplementary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char flags [ISODCL ( 8, 8)]; /* 853 */
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char escape [ISODCL ( 89, 120)]; /* 856 */
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+
+#define HS_STANDARD_ID "CDROM"
+
+struct hs_volume_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char unused1 [ISODCL ( 16, 16)]; /* 711 */
+ char system_id [ISODCL ( 17, 48)]; /* achars */
+ char volume_id [ISODCL ( 49, 80)]; /* dchars */
+ char unused2 [ISODCL ( 81, 88)]; /* 733 */
+ char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
+ char unused3 [ISODCL ( 97, 128)]; /* 733 */
+ char volume_set_size [ISODCL (129, 132)]; /* 723 */
+ char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
+ char logical_block_size [ISODCL (137, 140)]; /* 723 */
+ char path_table_size [ISODCL (141, 148)]; /* 733 */
+ char type_l_path_table [ISODCL (149, 152)]; /* 731 */
+ char unused4 [ISODCL (153, 180)]; /* 733 */
+ char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+# pragma pack (1)
+struct iso_path_table{
+ unsigned char name_len[2]; /* 721 */
+ char extent[4]; /* 731 */
+ char parent[2]; /* 721 */
+ char name[0];
+};
+# pragma pack ()
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+ there is an extra reserved byte after the flags */
+
+# pragma pack (1)
+struct iso_directory_record {
+ char length [ISODCL (1, 1)]; /* 711 */
+ char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ char extent [ISODCL (3, 10)]; /* 733 */
+ char size [ISODCL (11, 18)]; /* 733 */
+ char date [ISODCL (19, 25)]; /* 7 by 711 */
+ char flags [ISODCL (26, 26)];
+ char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ char interleave [ISODCL (28, 28)]; /* 711 */
+ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ char name [0];
+};
+# pragma pack ()
+
+#define ISOFS_BLOCK_BITS 0
+#define ISOFS_BLOCK_SIZE 2048
+
+#define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
+#define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
+
+enum isofs_file_format {
+ isofs_file_normal = 0,
+ isofs_file_sparse = 1,
+ isofs_file_compressed = 2,
+};
+
+/*
+ * iso fs inode data in memory
+ */
+struct iso_inode_info {
+ unsigned long i_iget5_block;
+ unsigned long i_iget5_offset;
+ unsigned int i_first_extent;
+ unsigned char i_file_format;
+ unsigned char i_format_parm[3];
+ unsigned long i_next_section_block;
+ unsigned long i_next_section_offset;
+ isofs_off_t i_section_size;
+ //struct inode vfs_inode;
+};
+
+/*
+ * iso9660 super-block data in memory
+ */
+struct isofs_sb_info {
+ unsigned long s_ninodes;
+ unsigned long s_nzones;
+ unsigned long s_firstdatazone;
+ unsigned long s_log_zone_size;
+ unsigned long s_max_size;
+
+ int s_rock_offset; /* offset of SUSP fields within SU area */
+ unsigned char s_joliet_level;
+ unsigned char s_mapping;
+ unsigned int s_high_sierra:1;
+ unsigned int s_rock:2;
+ unsigned int s_utf8:1;
+ unsigned int s_cruft:1; /* Broken disks with high byte of length
+ * containing junk */
+ unsigned int s_nocompress:1;
+ unsigned int s_hide:1;
+ unsigned int s_showassoc:1;
+ unsigned int s_overriderockperm:1;
+ unsigned int s_uid_set:1;
+ unsigned int s_gid_set:1;
+
+ isofs_mode_t s_fmode;
+ isofs_mode_t s_dmode;
+ isofs_gid_t s_gid;
+ isofs_uid_t s_uid;
+ //struct nls_table *s_nls_iocharset; /* Native language support table */
+ unsigned int s_cdtv:1;
+};
+
+
+struct iso9660_options{
+ unsigned int rock:1;
+ unsigned int joliet:1;
+ unsigned int cruft:1;
+ unsigned int hide:1;
+ unsigned int showassoc:1;
+ unsigned int nocompress:1;
+ unsigned int overriderockperm:1;
+ unsigned int uid_set:1;
+ unsigned int gid_set:1;
+ unsigned int utf8:1;
+ unsigned char map;
+ unsigned char check;
+ unsigned int blocksize;
+ isofs_mode_t fmode;
+ isofs_mode_t dmode;
+ isofs_gid_t gid;
+ isofs_uid_t uid;
+ char *iocharset;
+ /* LVE */
+ uae_s32 session;
+ uae_s32 sbsector;
+};
+
+
+/*
+ * These structs are used by the system-use-sharing protocol, in which the
+ * Rock Ridge extensions are embedded. It is quite possible that other
+ * extensions are present on the disk, and this is fine as long as they
+ * all use SUSP
+ */
+
+# pragma pack (1)
+
+struct SU_SP_s {
+ unsigned char magic[2];
+ unsigned char skip;
+};
+
+struct SU_CE_s {
+ char extent[8];
+ char offset[8];
+ char size[8];
+};
+
+struct SU_ER_s {
+ unsigned char len_id;
+ unsigned char len_des;
+ unsigned char len_src;
+ unsigned char ext_ver;
+ char data[1];
+};
+
+struct RR_RR_s {
+ char flags[1];
+};
+
+struct RR_PX_s {
+ char mode[8];
+ char n_links[8];
+ char uid[8];
+ char gid[8];
+};
+
+struct RR_PN_s {
+ char dev_high[8];
+ char dev_low[8];
+};
+
+struct SL_component {
+ unsigned char flags;
+ unsigned char len;
+ char text[1];
+};
+
+struct RR_SL_s {
+ unsigned char flags;
+ struct SL_component link;
+};
+
+struct RR_NM_s {
+ unsigned char flags;
+ char name[1];
+};
+
+struct RR_CL_s {
+ char location[8];
+};
+
+struct RR_PL_s {
+ char location[8];
+};
+
+struct stamp {
+ char time[7];
+};
+
+struct RR_TF_s {
+ char flags;
+ struct stamp times[1]; /* Variable number of these beasts */
+};
+
+/* Linux-specific extension for transparent decompression */
+struct RR_ZF_s {
+ char algorithm[2];
+ char parms[2];
+ char real_size[8];
+};
+
+/* Amiga RR extension */
+struct RR_AS_s {
+ char flags;
+ char data[1];
+};
+/*
+ * These are the bits and their meanings for flags in the TF structure.
+ */
+#define TF_CREATE 1
+#define TF_MODIFY 2
+#define TF_ACCESS 4
+#define TF_ATTRIBUTES 8
+#define TF_BACKUP 16
+#define TF_EXPIRATION 32
+#define TF_EFFECTIVE 64
+#define TF_LONG_FORM 128
+
+struct rock_ridge {
+ char signature[2];
+ unsigned char len;
+ unsigned char version;
+ union {
+ struct SU_SP_s SP;
+ struct SU_CE_s CE;
+ struct SU_ER_s ER;
+ struct RR_RR_s RR;
+ struct RR_PX_s PX;
+ struct RR_PN_s PN;
+ struct RR_SL_s SL;
+ struct RR_NM_s NM;
+ struct RR_CL_s CL;
+ struct RR_PL_s PL;
+ struct RR_TF_s TF;
+ struct RR_ZF_s ZF;
+ struct RR_AS_s AS;
+ } u;
+};
+
+#define RR_PX 1 /* POSIX attributes */
+#define RR_PN 2 /* POSIX devices */
+#define RR_SL 4 /* Symbolic link */
+#define RR_NM 8 /* Alternate Name */
+#define RR_CL 16 /* Child link */
+#define RR_PL 32 /* Parent link */
+#define RR_RE 64 /* Relocation directory */
+#define RR_TF 128 /* Timestamps */
+
+# pragma pack ()
+
+#endif /* UAE_ISOFS_H */
diff --git a/src/include/isofs_api.h b/src/include/isofs_api.h
new file mode 100644
index 00000000..843afcdf
--- /dev/null
+++ b/src/include/isofs_api.h
@@ -0,0 +1,38 @@
+#ifndef UAE_ISOFS_API_H
+#define UAE_ISOFS_API_H
+
+#include "uae/types.h"
+
+struct cd_opendir_s;
+struct cd_openfile_s;
+
+struct isofs_info
+{
+ bool media;
+ bool unknown_media;
+ TCHAR volumename[256];
+ TCHAR devname[256];
+ uae_u32 blocks;
+ uae_u32 totalblocks;
+ uae_u32 blocksize;
+ time_t creation;
+};
+
+void *isofs_mount(int unitnum, uae_u64 *uniq);
+void isofs_unmount(void *sb);
+bool isofs_mediainfo(void *sb, struct isofs_info*);
+struct cd_opendir_s *isofs_opendir(void *sb, uae_u64 uniq);
+void isofs_closedir(struct cd_opendir_s*);
+bool isofs_readdir(struct cd_opendir_s*, TCHAR*, uae_u64 *uniq);
+bool isofs_stat(void *sb, uae_u64, struct mystat*);
+void isofss_fill_file_attrs(void *sb, uae_u64, int*, int*, TCHAR**, uae_u64);
+bool isofs_exists(void *sb, uae_u64, const TCHAR*, uae_u64*);
+void isofs_dispose_inode(void *sb, uae_u64);
+
+struct cd_openfile_s *isofs_openfile(void*,uae_u64, int);
+void isofs_closefile(struct cd_openfile_s*);
+uae_s64 isofs_lseek(struct cd_openfile_s*, uae_s64, int);
+uae_s64 isofs_fsize(struct cd_openfile_s*);
+uae_s64 isofs_read(struct cd_openfile_s*, void*, unsigned int);
+
+#endif /* UAE_ISOFS_API_H */
diff --git a/src/include/memory.h b/src/include/memory.h
index faf61632..2731a69f 100644
--- a/src/include/memory.h
+++ b/src/include/memory.h
@@ -22,6 +22,9 @@ extern int special_mem;
bool init_shm (void);
void free_shm (void);
+bool preinit_shm (void);
+extern bool canbang;
+extern bool jit_direct_compatible_memory;
#define Z3BASE_UAE 0x10000000
#define Z3BASE_REAL 0x40000000
@@ -32,8 +35,10 @@ void free_shm (void);
#ifdef ADDRESS_SPACE_24BIT
#define MEMORY_BANKS 256
+#define MEMORY_RANGE_MASK ((1<<24)-1)
#else
#define MEMORY_BANKS 65536
+#define MEMORY_RANGE_MASK (~0)
#endif
typedef uae_u32 (REGPARAM3 *mem_get_func)(uaecptr) REGPARAM;
@@ -43,6 +48,12 @@ typedef int (REGPARAM3 *check_func)(uaecptr, uae_u32) REGPARAM;
extern uae_u32 max_z3fastmem;
+extern uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode);
+extern void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v);
+extern uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode);
+extern void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v);
+
+#undef DIRECT_MEMFUNCS_SUCCESSFUL
#include "machdep/maccess.h"
#define chipmem_start_addr 0x00000000
@@ -54,19 +65,45 @@ extern uae_u32 max_z3fastmem;
#define ROM_SIZE_256 262144
#define ROM_SIZE_128 131072
+extern bool ersatzkickfile;
extern bool cloanto_rom, kickstart_rom;
extern uae_u16 kickstart_version;
extern int uae_boot_rom_type;
extern int uae_boot_rom_size;
extern uaecptr rtarea_base;
+extern uaecptr uaeboard_base;
+extern uae_u8* baseaddr[];
+
+#define CACHE_ENABLE_DATA 0x01
+#define CACHE_ENABLE_DATA_BURST 0x02
+#define CACHE_ENABLE_COPYBACK 0x020
+#define CACHE_ENABLE_INS 0x80
+#define CACHE_ENABLE_INS_BURST 0x40
+#define CACHE_ENABLE_BOTH (CACHE_ENABLE_DATA | CACHE_ENABLE_INS)
+#define CACHE_ENABLE_ALL (CACHE_ENABLE_BOTH | CACHE_ENABLE_INS_BURST | CACHE_ENABLE_DATA_BURST)
+#define CACHE_DISABLE_ALLOCATE 0x08
+#define CACHE_DISABLE_MMU 0x10
+extern uae_u8 ce_banktype[65536], ce_cachable[65536];
+
+#define ABFLAG_CACHE_SHIFT 24
enum
{
ABFLAG_UNK = 0, ABFLAG_RAM = 1, ABFLAG_ROM = 2, ABFLAG_ROMIN = 4, ABFLAG_IO = 8,
ABFLAG_NONE = 16, ABFLAG_SAFE = 32, ABFLAG_INDIRECT = 64, ABFLAG_NOALLOC = 128,
ABFLAG_RTG = 256, ABFLAG_THREADSAFE = 512, ABFLAG_DIRECTMAP = 1024, ABFLAG_ALLOCINDIRECT = 2048,
- ABFLAG_CHIPRAM = 4096, ABFLAG_CIA = 8192, ABFLAG_PPCIOSPACE = 16384
+ ABFLAG_CHIPRAM = 4096, ABFLAG_CIA = 8192, ABFLAG_PPCIOSPACE = 16384,
+ ABFLAG_MAPPED = 32768,
+ ABFLAG_DIRECTACCESS = 65536,
+ ABFLAG_CACHE_ENABLE_DATA = CACHE_ENABLE_DATA << ABFLAG_CACHE_SHIFT,
+ ABFLAG_CACHE_ENABLE_DATA_BURST = CACHE_ENABLE_DATA_BURST << ABFLAG_CACHE_SHIFT,
+ ABFLAG_CACHE_ENABLE_INS = CACHE_ENABLE_INS << ABFLAG_CACHE_SHIFT,
+ ABFLAG_CACHE_ENABLE_INS_BURST = CACHE_ENABLE_INS_BURST << ABFLAG_CACHE_SHIFT,
};
+
+#define ABFLAG_CACHE_ENABLE_BOTH (ABFLAG_CACHE_ENABLE_DATA | ABFLAG_CACHE_ENABLE_INS)
+#define ABFLAG_CACHE_ENABLE_ALL (ABFLAG_CACHE_ENABLE_BOTH | ABFLAG_CACHE_ENABLE_INS_BURST | ABFLAG_CACHE_ENABLE_DATA_BURST)
+
typedef struct {
/* These ones should be self-explanatory... */
mem_get_func lget, wget, bget;
@@ -87,18 +124,23 @@ typedef struct {
for this particular bank. */
uae_u8 *baseaddr;
const TCHAR *label;
- const TCHAR *name;
- /* for instruction opcode/operand fetches */
- mem_get_func wgeti;
- int flags;
+ const TCHAR *name;
+ /* for instruction opcode/operand fetches */
+ mem_get_func wgeti;
+ int flags;
int jit_read_flag, jit_write_flag;
struct addrbank_sub *sub_banks;
uae_u32 mask;
+ uae_u32 startmask;
uae_u32 start;
// if RAM: size of allocated RAM. Zero if failed.
uae_u32 allocated_size;
// size of bank (if IO or before RAM allocation)
uae_u32 reserved_size;
+ /* non-NULL if xget/xput can be bypassed */
+ uae_u8 *baseaddr_direct_r;
+ uae_u8 *baseaddr_direct_w;
+ uae_u32 startaccessmask;
} addrbank;
#define MEMORY_MIN_SUBBANK 1024
@@ -115,22 +157,62 @@ struct autoconfig_info
{
struct uae_prefs *prefs;
bool doinit;
+ bool postinit;
int devnum;
uae_u8 autoconfig_raw[128];
uae_u8 autoconfig_bytes[16];
TCHAR name[128];
const uae_u8 *autoconfigp;
+ bool autoconfig_automatic;
uae_u32 start;
uae_u32 size;
int zorro;
const TCHAR *label;
addrbank *addrbankp;
struct romconfig *rc;
+ uae_u32 last_high_ram;
+ const struct cpuboardsubtype *cst;
const struct expansionromtype *ert;
+ struct autoconfig_info *parent;
+ const int *parent_romtype;
+ bool parent_of_previous;
+ bool parent_address_space;
bool direct_vram;
+ const TCHAR *parent_name;
+ bool can_sort;
+ bool hardwired;
bool (*get_params)(struct uae_prefs*, struct expansion_params*);
+ bool (*set_params)(struct uae_prefs*, struct expansion_params*);
+ void *userdata;
};
+#define CE_MEMBANK_FAST32 0
+#define CE_MEMBANK_CHIP16 1
+#define CE_MEMBANK_CHIP32 2
+#define CE_MEMBANK_CIA 3
+#define CE_MEMBANK_FAST16 4
+//#define CE_MEMBANK_FAST16_EXTRA_ACCURACY 5
+
+#define MEMORY_LGETI(name) \
+static uae_u32 REGPARAM3 name ## _lgeti (uaecptr) REGPARAM; \
+static uae_u32 REGPARAM2 name ## _lgeti (uaecptr addr) \
+{ \
+ uae_u8 *m; \
+ addr -= name ## _bank.startaccessmask; \
+ addr &= name ## _bank.mask; \
+ m = name ## _bank.baseaddr + addr; \
+ return do_get_mem_long ((uae_u32 *)m); \
+}
+#define MEMORY_WGETI(name) \
+static uae_u32 REGPARAM3 name ## _wgeti (uaecptr) REGPARAM; \
+static uae_u32 REGPARAM2 name ## _wgeti (uaecptr addr) \
+{ \
+ uae_u8 *m; \
+ addr -= name ## _bank.startaccessmask; \
+ addr &= name ## _bank.mask; \
+ m = name ## _bank.baseaddr + addr; \
+ return do_get_mem_word ((uae_u16 *)m); \
+}
#define MEMORY_LGET(name) \
static uae_u32 REGPARAM3 name ## _lget (uaecptr) REGPARAM; \
static uae_u32 REGPARAM2 name ## _lget (uaecptr addr) \
@@ -225,6 +307,7 @@ MEMORY_BPUT(name); \
MEMORY_CHECK(name); \
MEMORY_XLATE(name);
+
#define MEMORY_ARRAY_LGET(name, index) \
static uae_u32 REGPARAM3 name ## index ## _lget (uaecptr) REGPARAM; \
static uae_u32 REGPARAM2 name ## index ## _lget (uaecptr addr) \
@@ -309,6 +392,8 @@ MEMORY_ARRAY_CHECK(name, index); \
MEMORY_ARRAY_XLATE(name, index);
extern addrbank chipmem_bank;
+extern addrbank chipmem_agnus_bank;
+extern addrbank chipmem_bank_ce2;
extern addrbank kickmem_bank;
extern addrbank custom_bank;
extern addrbank clock_bank;
@@ -317,28 +402,41 @@ extern addrbank rtarea_bank;
extern addrbank filesys_bank;
extern addrbank uaeboard_bank;
extern addrbank expamem_bank;
-extern addrbank expamem_null;
+extern addrbank expamem_null, expamem_none;
extern addrbank fastmem_bank[MAX_RAM_BOARDS];
+extern addrbank fastmem_nojit_bank[MAX_RAM_BOARDS];
extern addrbank *gfxmem_banks[MAX_RTG_BOARDS];
extern addrbank gayle_bank;
extern addrbank gayle2_bank;
extern addrbank mbres_bank;
extern addrbank akiko_bank;
+extern addrbank cardmem_bank;
extern addrbank bogomem_bank;
extern addrbank z3fastmem_bank[MAX_RAM_BOARDS];
+extern addrbank z3chipmem_bank;
+extern addrbank mem25bit_bank;
+extern addrbank debugmem_bank;
extern addrbank a3000lmem_bank;
extern addrbank a3000hmem_bank;
extern addrbank extendedkickmem_bank;
extern addrbank extendedkickmem2_bank;
extern addrbank custmem1_bank;
extern addrbank custmem2_bank;
+extern addrbank romboardmem_bank[MAX_ROM_BOARDS];
extern void rtarea_init(void);
extern void rtarea_free(void);
-extern void rtarea_setup (void);
+extern void rtarea_init_mem(void);
+extern void rtarea_setup(void);
extern void expamem_reset(int);
+extern void expamem_next(addrbank *mapped, addrbank *next);
+extern void expamem_shutup(addrbank *mapped);
+extern bool expamem_z3hack(struct uae_prefs*);
+extern void expansion_cpu_fallback(void);
extern void set_expamem_z3_hack_mode(int);
-extern uaecptr expamem_board_pointer;
+extern uaecptr expamem_board_pointer, expamem_highmem_pointer;
+extern uaecptr expamem_z3_pointer_real, expamem_z3_pointer_uae;
+extern uae_u32 expamem_z3_highram_real, expamem_z3_highram_uae;
extern uae_u32 expamem_board_size;
extern uae_u32 last_custom_value1;
@@ -470,17 +568,21 @@ STATIC_INLINE uae_u32 get_byte_jit(uaecptr addr)
# if SIZEOF_VOID_P == 8
STATIC_INLINE void *get_pointer (uaecptr addr)
{
- const unsigned int n = SIZEOF_VOID_P / 4;
- union {
- void *ptr;
- uae_u32 longs[SIZEOF_VOID_P / 4];
- } p;
- unsigned int i;
+ const unsigned int n = SIZEOF_VOID_P / 4;
+ union {
+ void *ptr;
+ uae_u32 longs[SIZEOF_VOID_P / 4];
+ } p;
+ unsigned int i;
- for (i = 0; i < n; i++) {
- p.longs[n - 1 - i] = get_long (addr + i * 4);
- }
- return p.ptr;
+ for (i = 0; i < n; i++) {
+#ifdef WORDS_BIGENDIAN
+ p.longs[i] = get_long (addr + i * 4);
+#else
+ p.longs[n - 1 - i] = get_long (addr + i * 4);
+#endif
+ }
+ return p.ptr;
}
# else
# error "Unknown or unsupported pointer size."
@@ -574,11 +676,15 @@ STATIC_INLINE void put_pointer (uaecptr addr, void *v)
} p;
unsigned int i;
- p.ptr = v;
+ p.ptr = v;
- for (i = 0; i < n; i++) {
- put_long (addr + i * 4, p.longs[n - 1 - i]);
- }
+ for (i = 0; i < n; i++) {
+#ifdef WORDS_BIGENDIAN
+ put_long (addr + i * 4, p.longs[i]);
+#else
+ put_long (addr + i * 4, p.longs[n - 1 - i]);
+#endif
+ }
}
# endif
#endif
@@ -631,6 +737,7 @@ extern void REGPARAM3 chipmem_lput (uaecptr, uae_u32) REGPARAM;
extern void REGPARAM3 chipmem_wput (uaecptr, uae_u32) REGPARAM;
extern void REGPARAM3 chipmem_bput (uaecptr, uae_u32) REGPARAM;
+extern uae_u32 REGPARAM3 chipmem_agnus_wget (uaecptr) REGPARAM;
extern void REGPARAM3 chipmem_agnus_wput (uaecptr, uae_u32) REGPARAM;
extern uae_u32 chipmem_full_mask;
@@ -647,6 +754,7 @@ STATIC_INLINE uae_u32 chipmem_wget_indirect (uae_u32 PT) {
extern bool mapped_malloc (addrbank*);
extern void mapped_free (addrbank*);
+extern void a3000_fakekick (int);
extern uaecptr strcpyha_safe (uaecptr dst, const uae_char *src);
extern void memcpyha_safe (uaecptr dst, const uae_u8 *src, int size);
@@ -654,4 +762,30 @@ extern void memcpyha (uaecptr dst, const uae_u8 *src, int size);
extern void memcpyah_safe (uae_u8 *dst, uaecptr src, int size);
extern void memcpyah (uae_u8 *dst, uaecptr src, int size);
+#define UAE_MEMORY_REGIONS_MAX 64
+#define UAE_MEMORY_REGION_NAME_LENGTH 64
+
+#define UAE_MEMORY_REGION_RAM (1 << 0)
+#define UAE_MEMORY_REGION_ALIAS (1 << 1)
+#define UAE_MEMORY_REGION_MIRROR (1 << 2)
+
+/* Get a list of memory regions in the Amiga address space */
+
+typedef struct UaeMemoryRegion {
+ uaecptr start;
+ uae_u32 size;
+ TCHAR name[UAE_MEMORY_REGION_NAME_LENGTH];
+ TCHAR rom_name[UAE_MEMORY_REGION_NAME_LENGTH];
+ uaecptr alias;
+ int flags;
+ uae_u8 *memory;
+} UaeMemoryRegion;
+
+typedef struct UaeMemoryMap {
+ UaeMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
+ int num_regions;
+} UaeMemoryMap;
+
+void uae_memory_map(UaeMemoryMap *map);
+
#endif /* UAE_MEMORY_H */
diff --git a/src/include/newcpu.h b/src/include/newcpu.h
index 393481c8..b7432194 100644
--- a/src/include/newcpu.h
+++ b/src/include/newcpu.h
@@ -1,10 +1,10 @@
/*
- * UAE - The Un*x Amiga Emulator
- *
- * MC68000 emulation
- *
- * Copyright 1995 Bernd Schmidt
- */
+* UAE - The Un*x Amiga Emulator
+*
+* MC68000 emulation
+*
+* Copyright 1995 Bernd Schmidt
+*/
#ifndef UAE_NEWCPU_H
#define UAE_NEWCPU_H
@@ -35,7 +35,7 @@ struct cputbl
#ifdef JIT
#define MIN_JIT_CACHE 128
#define MAX_JIT_CACHE 16384
-typedef uae_u32 REGPARAM3 compop_func(uae_u32) REGPARAM;
+typedef uae_u32 REGPARAM3 compop_func (uae_u32) REGPARAM;
#define COMP_OPCODE_ISJUMP 0x0001
#define COMP_OPCODE_LONG_OPCODE 0x0002
@@ -64,10 +64,47 @@ typedef uae_u8 flagtype;
typedef double fptype;
#endif
+#define MAX68020CYCLES 4
+
+#define CPU_PIPELINE_MAX 4
+#define CPU000_MEM_CYCLE 4
+#define CPU000_CLOCK_MULT 2
+#define CPU020_MEM_CYCLE 3
+#define CPU020_CLOCK_MULT 4
+
+#define CACHELINES020 64
+struct cache020
+{
+ uae_u32 data;
+ uae_u32 tag;
+ bool valid;
+};
+
+#define CACHELINES030 16
+struct cache030
+{
+ uae_u32 data[4];
+ bool valid[4];
+ uae_u32 tag;
+ uae_u8 fc;
+};
+
+#define CACHESETS040 64
+#define CACHESETS060 128
+#define CACHELINES040 4
+struct cache040
+{
+ uae_u32 data[CACHELINES040][4];
+ bool dirty[CACHELINES040][4];
+ bool gdirty[CACHELINES040];
+ bool valid[CACHELINES040];
+ uae_u32 tag[CACHELINES040];
+};
+
struct mmufixup
{
- int reg;
- uae_u32 value;
+ int reg;
+ uae_u32 value;
};
extern struct mmufixup mmufixup[1];
@@ -88,8 +125,8 @@ struct regstruct
struct flag_struct ccrflags;
uae_u32 pc;
- uae_u8* pc_p;
- uae_u8* pc_oldp;
+ uae_u8 *pc_p;
+ uae_u8 *pc_oldp;
uae_u16 opcode;
uae_u32 instruction_pc;
@@ -446,11 +483,19 @@ extern void compemu_reset(void);
#endif
bool check_prefs_changed_comp(bool);
+#define CPU_HALT_PPC_ONLY -1
#define CPU_HALT_BUS_ERROR_DOUBLE_FAULT 1
#define CPU_HALT_DOUBLE_FAULT 2
#define CPU_HALT_OPCODE_FETCH_FROM_NON_EXISTING_ADDRESS 3
+#define CPU_HALT_ACCELERATOR_CPU_FALLBACK 4
+#define CPU_HALT_ALL_CPUS_STOPPED 5
+#define CPU_HALT_FAKE_DMA 6
#define CPU_HALT_AUTOCONFIG_CONFLICT 7
+#define CPU_HALT_PCI_CONFLICT 8
+#define CPU_HALT_CPU_STUCK 9
#define CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS 10
#define CPU_HALT_INVALID_START_ADDRESS 11
+#define CPU_HALT_68060_HALT 12
+#define CPU_HALT_BKPT 13
#endif /* UAE_NEWCPU_H */
diff --git a/src/include/rommgr.h b/src/include/rommgr.h
index a206df9a..f946cbbf 100644
--- a/src/include/rommgr.h
+++ b/src/include/rommgr.h
@@ -192,6 +192,7 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
#define ROMTYPE_PCMCIAIDE 0x00100081
#define ROMTYPE_SSQUIRREL 0x00100082
#define ROMTYPE_MASTERCARD 0x00100083
+#define ROMTYPE_DOTTO 0x00100084
#define ROMTYPE_NOT 0x00800000
#define ROMTYPE_QUAD 0x01000000
diff --git a/src/include/scsi.h b/src/include/scsi.h
index 50f966fa..80952214 100644
--- a/src/include/scsi.h
+++ b/src/include/scsi.h
@@ -71,6 +71,7 @@ extern int scsi_send_data(struct scsi_data*, uae_u8);
extern int scsi_receive_data(struct scsi_data*, uae_u8*, bool next);
extern void scsi_emulate_cmd(struct scsi_data *sd);
extern void scsi_illegal_lun(struct scsi_data *sd);
+extern void scsi_clear_sense(struct scsi_data *sd);
extern bool scsi_cmd_is_safe(uae_u8 cmd);
extern int scsi_hd_emulate(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
diff --git a/src/include/scsidev.h b/src/include/scsidev.h
new file mode 100644
index 00000000..073334f8
--- /dev/null
+++ b/src/include/scsidev.h
@@ -0,0 +1,35 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * a SCSI device
+ *
+ * (c) 1995 Bernd Schmidt (hardfile.c)
+ * (c) 1999 Patrick Ohly
+ * (c) 2001-2005 Toni Wilen
+ */
+
+#ifndef UAE_SCSIDEV_H
+#define UAE_SCSIDEV_H
+
+#include "uae/types.h"
+
+uaecptr scsidev_startup(TrapContext*, uaecptr resaddr);
+void scsidev_install (void);
+void scsidev_reset (void);
+void scsidev_start_threads (void);
+int scsi_do_disk_change (int unitnum, int insert, int *pollmode);
+int scsi_do_disk_device_change (void);
+uae_u32 scsi_get_cd_drive_mask (void);
+uae_u32 scsi_get_cd_drive_media_mask (void);
+int scsi_add_tape (struct uaedev_config_info *uci);
+
+extern int log_scsi;
+
+#ifdef _WIN32
+#define UAESCSI_CDEMU 0
+#define UAESCSI_SPTI 1
+#define UAESCSI_SPTISCAN 2
+#define UAESCSI_LAST 2
+#endif
+
+#endif /* UAE_SCSIDEV_H */
diff --git a/src/inputdevice.cpp b/src/inputdevice.cpp
index 46b2b952..fdf4e640 100644
--- a/src/inputdevice.cpp
+++ b/src/inputdevice.cpp
@@ -37,6 +37,7 @@
#include "sounddep/sound.h"
#include "disk.h"
#include "amiberry_gfx.h"
+#include "cdtv.h"
#include "statusline.h"
#include "cia.h"
diff --git a/src/isofs.cpp b/src/isofs.cpp
new file mode 100644
index 00000000..ffab58e7
--- /dev/null
+++ b/src/isofs.cpp
@@ -0,0 +1,2710 @@
+/*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Linux isofs/UAE filesystem wrapper
+ *
+ * Copyright 2012 Toni Wilen
+ *
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "blkdev.h"
+#include "isofs_api.h"
+#include "uae/string.h"
+#include "zfile.h"
+
+#include "isofs.h"
+
+#define MAX_CACHED_BH_COUNT 100
+//#define MAX_CACHE_INODE_COUNT 10
+#define HASH_SIZE 65536
+
+#define CD_BLOCK_SIZE 2048
+#define ISOFS_INVALID_MODE ((isofs_mode_t) -1)
+
+#define ISOFS_I(x) (&x->ei)
+#define ISOFS_SB(x) (&x->ei)
+#define IS_ERR(x) (x == NULL)
+
+#define XS_IFDIR 0x4000
+#define XS_IFCHR 0x2000
+#define XS_IFIFO 0x1000
+#define XS_IFREG 0x8000
+
+#define XS_ISDIR(x) (x & XS_IFDIR)
+
+struct buffer_head
+{
+ struct buffer_head *next;
+ uae_u8 *b_data;
+ uae_u32 b_blocknr;
+ bool linked;
+ int usecnt;
+ struct super_block *sb;
+};
+
+struct inode
+{
+ struct inode *next;
+ uae_u32 i_mode;
+ isofs_uid_t i_uid;
+ isofs_gid_t i_gid;
+ uae_u32 i_ino;
+ uae_u32 i_size;
+ uae_u32 i_blocks;
+ struct super_block *i_sb;
+ timeval i_mtime;
+ timeval i_atime;
+ timeval i_ctime;
+ iso_inode_info ei;
+ TCHAR *name;
+ int i_blkbits;
+ bool linked;
+ int usecnt;
+ int lockcnt;
+ bool i_isaflags;
+ uae_u8 i_aflags;
+ TCHAR *i_comment;
+};
+
+
+struct super_block
+{
+ int s_high_sierra;
+ int s_blocksize;
+ int s_blocksize_bits;
+ isofs_sb_info ei;
+ int unitnum;
+ struct inode *inodes, *root;
+ int inode_cnt;
+ struct buffer_head *buffer_heads;
+ int bh_count;
+ bool unknown_media;
+ struct inode *hash[HASH_SIZE];
+ int hash_miss, hash_hit;
+};
+
+static int gethashindex(struct inode *inode)
+{
+ return inode->i_ino & (HASH_SIZE - 1);
+}
+
+static void free_inode(struct inode *inode)
+{
+ if (!inode)
+ return;
+ inode->i_sb->hash[gethashindex(inode)] = NULL;
+ inode->i_sb->inode_cnt--;
+ xfree(inode->name);
+ xfree(inode->i_comment);
+ xfree(inode);
+}
+
+static void free_bh(struct buffer_head *bh)
+{
+ if (!bh)
+ return;
+ bh->sb->bh_count--;
+ xfree(bh->b_data);
+ xfree(bh);
+}
+
+static void lock_inode(struct inode *inode)
+{
+ inode->lockcnt++;
+}
+static void unlock_inode(struct inode *inode)
+{
+ inode->lockcnt--;
+}
+
+
+static void iput(struct inode *inode)
+{
+ if (!inode || inode->linked)
+ return;
+
+ struct super_block *sb = inode->i_sb;
+
+#if 0
+ struct inode *in;
+ while (inode->i_sb->inode_cnt > MAX_CACHE_INODE_COUNT) {
+ /* not very fast but better than nothing.. */
+ struct inode *minin = NULL, *mininprev = NULL;
+ struct inode *prev = NULL;
+ in = sb->inodes;
+ while (in) {
+ if (!in->lockcnt && (minin == NULL || in->usecnt < minin->usecnt)) {
+ minin = in;
+ mininprev = prev;
+ }
+ prev = in;
+ in = in->next;
+ }
+ if (!minin)
+ break;
+ if (mininprev)
+ mininprev->next = minin->next;
+ else
+ sb->inodes = minin->next;
+ free_inode(minin);
+ }
+#endif
+ inode->next = sb->inodes;
+ sb->inodes = inode;
+ inode->linked = true;
+ sb->inode_cnt++;
+ sb->hash[gethashindex(inode)] = inode;
+}
+
+static struct inode *find_inode(struct super_block *sb, uae_u64 uniq)
+{
+ struct inode *inode;
+
+ inode = sb->hash[uniq & (HASH_SIZE - 1)];
+ if (inode && inode->i_ino == uniq) {
+ sb->hash_hit++;
+ return inode;
+ }
+ sb->hash_miss++;
+
+ inode = sb->inodes;
+ while (inode) {
+ if (inode->i_ino == uniq) {
+ inode->usecnt++;
+ return inode;
+ }
+ inode = inode->next;
+ }
+ return NULL;
+}
+
+static buffer_head *sb_bread(struct super_block *sb, uae_u32 block)
+{
+ struct buffer_head *bh;
+
+ bh = sb->buffer_heads;
+ while (bh) {
+ if (bh->b_blocknr == block) {
+ bh->usecnt++;
+ return bh;
+ }
+ bh = bh->next;
+ }
+ // simple LRU block cache. Should be in blkdev, not here..
+ while (sb->bh_count > MAX_CACHED_BH_COUNT) {
+ struct buffer_head *minbh = NULL, *minbhprev = NULL;
+ struct buffer_head *prev = NULL;
+ bh = sb->buffer_heads;
+ while (bh) {
+ if (minbh == NULL || bh->usecnt < minbh->usecnt) {
+ minbh = bh;
+ minbhprev = prev;
+ }
+ prev = bh;
+ bh = bh->next;
+ }
+ if (minbh) {
+ if (minbhprev)
+ minbhprev->next = minbh->next;
+ else
+ sb->buffer_heads = minbh->next;
+ free_bh(minbh);
+ }
+ }
+ bh = xcalloc (struct buffer_head, 1);
+ bh->sb = sb;
+ bh->b_data = xmalloc (uae_u8, CD_BLOCK_SIZE);
+ bh->b_blocknr = block;
+ if (sys_command_cd_read (sb->unitnum, bh->b_data, block, 1)) {
+ bh->next = sb->buffer_heads;
+ sb->buffer_heads = bh;
+ bh->linked = true;
+ sb->bh_count++;
+ return bh;
+ }
+ xfree (bh);
+ return NULL;
+}
+
+static void brelse(struct buffer_head *sh)
+{
+}
+
+static TCHAR *getname(char *name, int len)
+{
+ TCHAR *s;
+ char old;
+
+ old = name[len];
+ while (len > 0 && name[len - 1] == ' ')
+ len--;
+ name[len] = 0;
+ s = au (name);
+ name[len] = old;
+ return s;
+}
+
+static inline uae_u32 isofs_get_ino(unsigned long block, unsigned long offset, unsigned long bufbits)
+{
+ return (block << (bufbits - 5)) | (offset >> 5);
+}
+
+static inline int isonum_711(char *p)
+{
+ return *(uae_u8*)p;
+}
+static inline int isonum_712(char *p)
+{
+ return *(uae_u8*)p;
+}
+static inline unsigned int isonum_721(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ return p[0] | (p[1] << 8);
+}
+static inline unsigned int isonum_722(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ return p[1] | (p[0] << 8);
+}
+static inline unsigned int isonum_723(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ /* Ignore bigendian datum due to broken mastering programs */
+ return p[0] | (p[1] << 8);
+}
+static inline unsigned int isonum_731(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
+}
+static inline unsigned int isonum_732(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0);
+}
+static inline unsigned int isonum_733(char *pp)
+{
+ uae_u8 *p = (uae_u8*)pp;
+ /* Ignore bigendian datum due to broken mastering programs */
+ return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0);
+}
+
+static void isofs_normalize_block_and_offset(struct iso_directory_record* de, unsigned long *block, unsigned long *offset)
+{
+#if 0
+ /* Only directories are normalized. */
+ if (de->flags[0] & 2) {
+ *offset = 0;
+ *block = (unsigned long)isonum_733(de->extent)
+ + (unsigned long)isonum_711(de->ext_attr_length);
+ }
+#endif
+}
+
+static int make_date(int year, int month, int day, int hour, int minute, int second, int tz)
+{
+ int crtime, days, i;
+
+ if (year < 0) {
+ crtime = 0;
+ } else {
+ int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+ days = year * 365;
+ if (year > 2)
+ days += (year+1) / 4;
+ for (i = 1; i < month; i++)
+ days += monlen[i-1];
+ if (((year+2) % 4) == 0 && month > 2)
+ days++;
+ days += day - 1;
+ crtime = ((((days * 24) + hour) * 60 + minute) * 60)
+ + second;
+
+ /* sign extend */
+ if (tz & 0x80)
+ tz |= (-1 << 8);
+
+ /*
+ * The timezone offset is unreliable on some disks,
+ * so we make a sanity check. In no case is it ever
+ * more than 13 hours from GMT, which is 52*15min.
+ * The time is always stored in localtime with the
+ * timezone offset being what get added to GMT to
+ * get to localtime. Thus we need to subtract the offset
+ * to get to true GMT, which is what we store the time
+ * as internally. On the local system, the user may set
+ * their timezone any way they wish, of course, so GMT
+ * gets converted back to localtime on the receiving
+ * system.
+ *
+ * NOTE: mkisofs in versions prior to mkisofs-1.10 had
+ * the sign wrong on the timezone offset. This has now
+ * been corrected there too, but if you are getting screwy
+ * results this may be the explanation. If enough people
+ * complain, a user configuration option could be added
+ * to add the timezone offset in with the wrong sign
+ * for 'compatibility' with older discs, but I cannot see how
+ * it will matter that much.
+ *
+ * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
+ * for pointing out the sign error.
+ */
+ if (-52 <= tz && tz <= 52)
+ crtime -= tz * 15 * 60;
+ }
+ return crtime;
+}
+
+/*
+ * We have to convert from a MM/DD/YY format to the Unix ctime format.
+ * We have to take into account leap years and all of that good stuff.
+ * Unfortunately, the kernel does not have the information on hand to
+ * take into account daylight savings time, but it shouldn't matter.
+ * The time stored should be localtime (with or without DST in effect),
+ * and the timezone offset should hold the offset required to get back
+ * to GMT. Thus we should always be correct.
+ */
+
+static int iso_date(char * p, int flag)
+{
+ int year, month, day, hour, minute, second, tz;
+
+ year = p[0] - 70;
+ month = p[1];
+ day = p[2];
+ hour = p[3];
+ minute = p[4];
+ second = p[5];
+ if (flag == 0) tz = p[6]; /* High sierra has no time zone */
+ else tz = 0;
+
+ return make_date(year, month, day, hour, minute, second, tz);
+}
+
+static int iso_ltime(char *p)
+{
+ int year, month, day, hour, minute, second;
+ char t;
+
+ t = p[4];
+ p[4] = 0;
+ year = atol(p);
+ p[4] = t;
+ t = p[6];
+ p[6] = 0;
+ month = atol(p + 4);
+ p[6] = t;
+ t = p[8];
+ p[8] = 0;
+ day = atol(p + 6);
+ p[8] = t;
+ t = p[10];
+ p[10] = 0;
+ hour = atol(p + 8);
+ p[10] = t;
+ t = p[12];
+ p[12] = 0;
+ minute = atol(p + 10);
+ p[12] = t;
+ t = p[14];
+ p[14] = 0;
+ second = atol(p + 12);
+ p[14] = t;
+
+ return make_date(year - 1970, month, day, hour, minute, second, 0);
+}
+
+static int isofs_read_level3_size(struct inode *inode)
+{
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
+ struct buffer_head *bh = NULL;
+ unsigned long block, offset, block_saved, offset_saved;
+ int i = 0;
+ int more_entries = 0;
+ struct iso_directory_record *tmpde = NULL;
+ struct iso_inode_info *ei = ISOFS_I(inode);
+
+ inode->i_size = 0;
+
+ /* The first 16 blocks are reserved as the System Area. Thus,
+ * no inodes can appear in block 0. We use this to flag that
+ * this is the last section. */
+ ei->i_next_section_block = 0;
+ ei->i_next_section_offset = 0;
+
+ block = ei->i_iget5_block;
+ offset = ei->i_iget5_offset;
+
+ do {
+ struct iso_directory_record *de;
+ unsigned int de_len;
+
+ if (!bh) {
+ bh = sb_bread(inode->i_sb, block);
+ if (!bh)
+ goto out_noread;
+ }
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+ de_len = *(unsigned char *) de;
+
+ if (de_len == 0) {
+ brelse(bh);
+ bh = NULL;
+ ++block;
+ offset = 0;
+ continue;
+ }
+
+ block_saved = block;
+ offset_saved = offset;
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= bufsize) {
+ int slop = bufsize - offset + de_len;
+ if (!tmpde) {
+ tmpde = (struct iso_directory_record*)xmalloc(uae_u8, 256);
+ if (!tmpde)
+ goto out_nomem;
+ }
+ memcpy(tmpde, de, slop);
+ offset &= bufsize - 1;
+ block++;
+ brelse(bh);
+ bh = NULL;
+ if (offset) {
+ bh = sb_bread(inode->i_sb, block);
+ if (!bh)
+ goto out_noread;
+ memcpy((uae_u8*)tmpde+slop, bh->b_data, offset);
+ }
+ de = tmpde;
+ }
+
+ inode->i_size += isonum_733(de->size);
+ if (i == 1) {
+ ei->i_next_section_block = block_saved;
+ ei->i_next_section_offset = offset_saved;
+ }
+
+ more_entries = de->flags[-high_sierra] & 0x80;
+
+ i++;
+ if (i > 100)
+ goto out_toomany;
+ } while (more_entries);
+out:
+ xfree(tmpde);
+ if (bh)
+ brelse(bh);
+ return 0;
+
+out_nomem:
+ if (bh)
+ brelse(bh);
+ return -ENOMEM;
+
+out_noread:
+ write_log (_T("ISOFS: unable to read i-node block %lu\n"), block);
+ xfree(tmpde);
+ return -EIO;
+
+out_toomany:
+ write_log (_T("ISOFS: More than 100 file sections ?!?, aborting... isofs_read_level3_size: inode=%u\n"), inode->i_ino);
+ goto out;
+}
+
+static int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode);
+
+static int isofs_read_inode(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct isofs_sb_info *sbi = ISOFS_SB(sb);
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ unsigned long block;
+ int high_sierra = sbi->s_high_sierra;
+ struct buffer_head *bh = NULL;
+ struct iso_directory_record *de;
+ struct iso_directory_record *tmpde = NULL;
+ unsigned int de_len;
+ unsigned long offset;
+ struct iso_inode_info *ei = ISOFS_I(inode);
+ int ret = -EIO;
+
+ block = ei->i_iget5_block;
+ bh = sb_bread(inode->i_sb, block);
+ if (!bh)
+ goto out_badread;
+
+ offset = ei->i_iget5_offset;
+
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+ de_len = *(unsigned char *) de;
+
+ if (offset + de_len > bufsize) {
+ int frag1 = bufsize - offset;
+
+ tmpde = (struct iso_directory_record*)xmalloc (uae_u8, de_len);
+ if (tmpde == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ memcpy(tmpde, bh->b_data + offset, frag1);
+ brelse(bh);
+ bh = sb_bread(inode->i_sb, ++block);
+ if (!bh)
+ goto out_badread;
+ memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
+ de = tmpde;
+ }
+
+ inode->i_ino = isofs_get_ino(ei->i_iget5_block, ei->i_iget5_offset, ISOFS_BUFFER_BITS(inode));
+
+ /* Assume it is a normal-format file unless told otherwise */
+ ei->i_file_format = isofs_file_normal;
+
+ if (de->flags[-high_sierra] & 2) {
+ if (sbi->s_dmode != ISOFS_INVALID_MODE)
+ inode->i_mode = XS_IFDIR | sbi->s_dmode;
+ else
+ inode->i_mode = XS_IFDIR; // | S_IRUGO | S_IXUGO;
+ } else {
+ if (sbi->s_fmode != ISOFS_INVALID_MODE) {
+ inode->i_mode = XS_IFREG | sbi->s_fmode;
+ } else {
+ /*
+ * Set default permissions: r-x for all. The disc
+ * could be shared with DOS machines so virtually
+ * anything could be a valid executable.
+ */
+ inode->i_mode = XS_IFREG; // | S_IRUGO | S_IXUGO;
+ }
+ }
+
+ inode->i_uid = sbi->s_uid;
+ inode->i_gid = sbi->s_gid;
+ inode->i_blocks = 0;
+
+ ei->i_format_parm[0] = 0;
+ ei->i_format_parm[1] = 0;
+ ei->i_format_parm[2] = 0;
+
+ ei->i_section_size = isonum_733(de->size);
+ if (de->flags[-high_sierra] & 0x80) {
+ ret = isofs_read_level3_size(inode);
+ if (ret < 0)
+ goto fail;
+ // FIXME: this value is never used (?), because it is overwritten
+ // with ret = 0 further down.
+ ret = -EIO;
+ } else {
+ ei->i_next_section_block = 0;
+ ei->i_next_section_offset = 0;
+ inode->i_size = isonum_733(de->size);
+ }
+
+ /*
+ * Some dipshit decided to store some other bit of information
+ * in the high byte of the file length. Truncate size in case
+ * this CDROM was mounted with the cruft option.
+ */
+
+ if (sbi->s_cruft)
+ inode->i_size &= 0x00ffffff;
+
+ if (de->interleave[0]) {
+ write_log (_T("ISOFS: Interleaved files not (yet) supported.\n"));
+ inode->i_size = 0;
+ }
+
+ /* I have no idea what file_unit_size is used for, so
+ we will flag it for now */
+ if (de->file_unit_size[0] != 0) {
+ write_log (_T("ISOFS: File unit size != 0 for ISO file (%d).\n"), inode->i_ino);
+ }
+
+ /* I have no idea what other flag bits are used for, so
+ we will flag it for now */
+ if((de->flags[-high_sierra] & ~2)!= 0){
+ write_log (_T("ISOFS: Unusual flag settings for ISO file (%d %x).\n"), inode->i_ino, de->flags[-high_sierra]);
+ }
+
+ inode->i_mtime.tv_sec =
+ inode->i_atime.tv_sec =
+ inode->i_ctime.tv_sec = iso_date(de->date, high_sierra);
+ inode->i_mtime.tv_usec =
+ inode->i_atime.tv_usec =
+ inode->i_ctime.tv_usec = 0;
+
+ ei->i_first_extent = (isonum_733(de->extent) +
+ isonum_711(de->ext_attr_length));
+
+ /* Set the number of blocks for stat() - should be done before RR */
+ inode->i_blocks = (inode->i_size + 511) >> 9;
+
+ /*
+ * Now test for possible Rock Ridge extensions which will override
+ * some of these numbers in the inode structure.
+ */
+ if (!high_sierra) {
+ parse_rock_ridge_inode(de, inode);
+ /* if we want uid/gid set, override the rock ridge setting */
+ if (sbi->s_uid_set)
+ inode->i_uid = sbi->s_uid;
+ if (sbi->s_gid_set)
+ inode->i_gid = sbi->s_gid;
+ }
+
+#if 0
+ /* Now set final access rights if overriding rock ridge setting */
+ if (XS_ISDIR(inode->i_mode) && sbi->s_overriderockperm &&
+ sbi->s_dmode != ISOFS_INVALID_MODE)
+ inode->i_mode = XS_IFDIR | sbi->s_dmode;
+ if (XS_ISREG(inode->i_mode) && sbi->s_overriderockperm &&
+ sbi->s_fmode != ISOFS_INVALID_MODE)
+ inode->i_mode = XS_IFREG | sbi->s_fmode;
+ /* Install the inode operations vector */
+ if (XS_ISREG(inode->i_mode)) {
+ inode->i_fop = &generic_ro_fops;
+ switch (ei->i_file_format) {
+#ifdef CONFIG_ZISOFS
+ case isofs_file_compressed:
+ inode->i_data.a_ops = &zisofs_aops;
+ break;
+#endif
+ default:
+ inode->i_data.a_ops = &isofs_aops;
+ break;
+ }
+ } else if (XS_ISDIR(inode->i_mode)) {
+ inode->i_op = &isofs_dir_inode_operations;
+ inode->i_fop = &isofs_dir_operations;
+ } else if (XS_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &isofs_symlink_aops;
+ } else
+ /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
+#endif
+
+ ret = 0;
+out:
+ xfree(tmpde);
+ if (bh)
+ brelse(bh);
+ return ret;
+
+out_badread:
+ write_log(_T("ISOFS: unable to read i-node block\n"));
+fail:
+ goto out;
+}
+
+
+static struct inode *isofs_iget(struct super_block *sb, unsigned long block, unsigned long offset, const TCHAR *name)
+{
+ struct inode *inode;
+ uae_u32 id;
+
+ if (offset >= 1ul << sb->s_blocksize_bits)
+ return NULL;
+ if (sb->root) {
+ unsigned char bufbits = ISOFS_BUFFER_BITS(sb->root);
+ id = isofs_get_ino(block, offset, bufbits);
+ inode = find_inode (sb, id);
+ if (inode)
+ return inode;
+ }
+ inode = xcalloc(struct inode, 1);
+ inode->name = name ? my_strdup(name) : NULL;
+ inode->i_sb = sb;
+ inode->ei.i_iget5_block = block;
+ inode->ei.i_iget5_offset = offset;
+ inode->i_blkbits = sb->s_blocksize_bits;
+ isofs_read_inode(inode);
+ return inode;
+}
+
+
+/**************************************************************
+
+ ROCK RIDGE
+
+ **************************************************************/
+
+
+#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
+
+struct rock_state {
+ void *buffer;
+ unsigned char *chr;
+ int len;
+ int cont_size;
+ int cont_extent;
+ int cont_offset;
+ struct inode *inode;
+};
+
+/*
+ * This is a way of ensuring that we have something in the system
+ * use fields that is compatible with Rock Ridge. Return zero on success.
+ */
+
+static int check_sp(struct rock_ridge *rr, struct inode *inode)
+{
+ if (rr->u.SP.magic[0] != 0xbe)
+ return -1;
+ if (rr->u.SP.magic[1] != 0xef)
+ return -1;
+ ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
+ return 0;
+}
+
+static void setup_rock_ridge(struct iso_directory_record *de, struct inode *inode, struct rock_state *rs)
+{
+ rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
+ if (rs->len & 1)
+ (rs->len)++;
+ rs->chr = (unsigned char *)de + rs->len;
+ rs->len = *((unsigned char *)de) - rs->len;
+ if (rs->len < 0)
+ rs->len = 0;
+
+ if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
+ rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
+ rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
+ if (rs->len < 0)
+ rs->len = 0;
+ }
+}
+
+static void init_rock_state(struct rock_state *rs, struct inode *inode)
+{
+ memset(rs, 0, sizeof(*rs));
+ rs->inode = inode;
+}
+
+/*
+ * Returns 0 if the caller should continue scanning, 1 if the scan must end
+ * and -ve on error.
+ */
+static int rock_continue(struct rock_state *rs)
+{
+ int ret = 1;
+ int blocksize = 1 << rs->inode->i_blkbits;
+ const int min_de_size = offsetof(struct rock_ridge, u);
+
+ xfree(rs->buffer);
+ rs->buffer = NULL;
+
+ if ((unsigned)rs->cont_offset > blocksize - min_de_size || (unsigned)rs->cont_size > blocksize || (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
+ write_log (_T("rock: corrupted directory entry. extent=%d, offset=%d, size=%d\n"), rs->cont_extent, rs->cont_offset, rs->cont_size);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (rs->cont_extent) {
+ struct buffer_head *bh;
+
+ rs->buffer = xmalloc(uae_u8, rs->cont_size);
+ if (!rs->buffer) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = -EIO;
+ bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
+ if (bh) {
+ memcpy(rs->buffer, bh->b_data + rs->cont_offset, rs->cont_size);
+ brelse(bh);
+ rs->chr = (unsigned char*)rs->buffer;
+ rs->len = rs->cont_size;
+ rs->cont_extent = 0;
+ rs->cont_size = 0;
+ rs->cont_offset = 0;
+ return 0;
+ }
+ write_log (_T("Unable to read rock-ridge attributes\n"));
+ }
+out:
+ xfree(rs->buffer);
+ rs->buffer = NULL;
+ return ret;
+}
+
+/*
+ * We think there's a record of type `sig' at rs->chr. Parse the signature
+ * and make sure that there's really room for a record of that type.
+ */
+static int rock_check_overflow(struct rock_state *rs, int sig)
+{
+ int len;
+
+ switch (sig) {
+ case SIG('S', 'P'):
+ len = sizeof(struct SU_SP_s);
+ break;
+ case SIG('C', 'E'):
+ len = sizeof(struct SU_CE_s);
+ break;
+ case SIG('E', 'R'):
+ len = sizeof(struct SU_ER_s);
+ break;
+ case SIG('R', 'R'):
+ len = sizeof(struct RR_RR_s);
+ break;
+ case SIG('P', 'X'):
+ len = sizeof(struct RR_PX_s);
+ break;
+ case SIG('P', 'N'):
+ len = sizeof(struct RR_PN_s);
+ break;
+ case SIG('S', 'L'):
+ len = sizeof(struct RR_SL_s);
+ break;
+ case SIG('N', 'M'):
+ len = sizeof(struct RR_NM_s);
+ break;
+ case SIG('C', 'L'):
+ len = sizeof(struct RR_CL_s);
+ break;
+ case SIG('P', 'L'):
+ len = sizeof(struct RR_PL_s);
+ break;
+ case SIG('T', 'F'):
+ len = sizeof(struct RR_TF_s);
+ break;
+ case SIG('Z', 'F'):
+ len = sizeof(struct RR_ZF_s);
+ break;
+ case SIG('A', 'S'):
+ len = sizeof(struct RR_AS_s);
+ break;
+ default:
+ len = 0;
+ break;
+ }
+ len += offsetof(struct rock_ridge, u);
+ if (len > rs->len) {
+ write_log(_T("rock: directory entry would overflow storage\n"));
+ write_log(_T("rock: sig=0x%02x, size=%d, remaining=%d\n"), sig, len, rs->len);
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * return length of name field; 0: not found, -1: to be ignored
+ */
+static int get_rock_ridge_filename(struct iso_directory_record *de,
+ char *retname, struct inode *inode)
+{
+ struct rock_state rs;
+ struct rock_ridge *rr;
+ int sig;
+ int retnamlen = 0;
+ int truncate = 0;
+ int ret = 0;
+
+ if (!ISOFS_SB(inode->i_sb)->s_rock)
+ return 0;
+ *retname = 0;
+
+ init_rock_state(&rs, inode);
+ setup_rock_ridge(de, inode, &rs);
+repeat:
+
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
+ /*
+ * Ignore rock ridge info if rr->len is out of range, but
+ * don't return -EIO because that would make the file
+ * invisible.
+ */
+ if (rr->len < 3)
+ goto out; /* Something got screwed up here */
+ sig = isonum_721((char*)rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto eio;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ /*
+ * As above, just ignore the rock ridge info if rr->len
+ * is bogus.
+ */
+ if (rs.len < 0)
+ goto out; /* Something got screwed up here */
+
+ switch (sig) {
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] & RR_NM) == 0)
+ goto out;
+ break;
+ case SIG('S', 'P'):
+ if (check_sp(rr, inode))
+ goto out;
+ break;
+ case SIG('C', 'E'):
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
+ break;
+ case SIG('N', 'M'):
+ if (truncate)
+ break;
+ if (rr->len < 5)
+ break;
+ /*
+ * If the flags are 2 or 4, this indicates '.' or '..'.
+ * We don't want to do anything with this, because it
+ * screws up the code that calls us. We don't really
+ * care anyways, since we can just use the non-RR
+ * name.
+ */
+ if (rr->u.NM.flags & 6)
+ break;
+
+ if (rr->u.NM.flags & ~1) {
+ write_log(_T("Unsupported NM flag settings (%d)\n"), rr->u.NM.flags);
+ break;
+ }
+ if ((strlen(retname) + rr->len - 5) >= 254) {
+ truncate = 1;
+ break;
+ }
+ strncat(retname, rr->u.NM.name, rr->len - 5);
+ retnamlen += rr->len - 5;
+ break;
+ case SIG('R', 'E'):
+ xfree(rs.buffer);
+ return -1;
+ default:
+ break;
+ }
+ }
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret == 1)
+ return retnamlen; /* If 0, this file did not have a NM field */
+out:
+ xfree(rs.buffer);
+ return ret;
+eio:
+ ret = -EIO;
+ goto out;
+}
+
+static int parse_rock_ridge_inode_internal(struct iso_directory_record *de, struct inode *inode, int regard_xa)
+{
+ int symlink_len = 0;
+ int cnt, sig;
+ struct inode *reloc;
+ struct rock_ridge *rr;
+ int rootflag;
+ struct rock_state rs;
+ int ret = 0;
+
+ if (!ISOFS_SB(inode->i_sb)->s_rock)
+ return 0;
+
+ init_rock_state(&rs, inode);
+ setup_rock_ridge(de, inode, &rs);
+ if (regard_xa) {
+ rs.chr += 14;
+ rs.len -= 14;
+ if (rs.len < 0)
+ rs.len = 0;
+ }
+
+repeat:
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
+ /*
+ * Ignore rock ridge info if rr->len is out of range, but
+ * don't return -EIO because that would make the file
+ * invisible.
+ */
+ if (rr->len < 3)
+ goto out; /* Something got screwed up here */
+ sig = isonum_721((char*)rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto eio;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ /*
+ * As above, just ignore the rock ridge info if rr->len
+ * is bogus.
+ */
+ if (rs.len < 0)
+ goto out; /* Something got screwed up here */
+
+ switch (sig) {
+ case SIG('A', 'S'):
+ {
+ char *p = &rr->u.AS.data[0];
+ if (rr->u.AS.flags & 1) { // PROTECTION
+ inode->i_isaflags = true;
+ inode->i_aflags = p[3];
+ p += 4;
+ }
+ if (rr->u.AS.flags & 2) { // COMMENT
+ const int maxcomment = 80;
+ if (!inode->i_comment)
+ inode->i_comment = xcalloc (TCHAR, maxcomment + 1);
+ int l = p[0];
+ char t = p[l];
+ p[l] = 0;
+ au_copy (inode->i_comment + _tcslen (inode->i_comment), maxcomment + 1 - _tcslen (inode->i_comment), p + 1);
+ p[l] = t;
+ }
+ break;
+ }
+ case SIG('S', 'P'):
+ if (check_sp(rr, inode))
+ goto out;
+ break;
+ case SIG('C', 'E'):
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
+ break;
+ case SIG('E', 'R'):
+ ISOFS_SB(inode->i_sb)->s_rock = 1;
+ write_log(_T("ISO 9660 Extensions: "));
+ {
+ int p;
+ for (p = 0; p < rr->u.ER.len_id; p++)
+ write_log(_T("%c"), rr->u.ER.data[p]);
+ }
+ write_log(_T("\n"));
+ break;
+ case SIG('P', 'X'):
+ inode->i_mode = isonum_733(rr->u.PX.mode);
+ //set_nlink(inode, isonum_733(rr->u.PX.n_links));
+ inode->i_uid = isonum_733(rr->u.PX.uid);
+ inode->i_gid = isonum_733(rr->u.PX.gid);
+ break;
+ case SIG('P', 'N'):
+ {
+ int high, low;
+ high = isonum_733(rr->u.PN.dev_high);
+ low = isonum_733(rr->u.PN.dev_low);
+ /*
+ * The Rock Ridge standard specifies that if
+ * sizeof(dev_t) <= 4, then the high field is
+ * unused, and the device number is completely
+ * stored in the low field. Some writers may
+ * ignore this subtlety,
+ * and as a result we test to see if the entire
+ * device number is
+ * stored in the low field, and use that.
+ */
+#if 0
+ if ((low & ~0xff) && high == 0) {
+ inode->i_rdev =
+ MKDEV(low >> 8, low & 0xff);
+ } else {
+ inode->i_rdev =
+ MKDEV(high, low);
+ }
+#endif
+ }
+ break;
+ case SIG('T', 'F'):
+ /*
+ * Some RRIP writers incorrectly place ctime in the
+ * TF_CREATE field. Try to handle this correctly for
+ * either case.
+ */
+ /* Rock ridge never appears on a High Sierra disk */
+ cnt = 0;
+ if (rr->u.TF.flags & TF_CREATE) {
+ inode->i_ctime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_ctime.tv_usec = 0;
+ }
+ if (rr->u.TF.flags & TF_MODIFY) {
+ inode->i_mtime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_mtime.tv_usec = 0;
+ }
+ if (rr->u.TF.flags & TF_ACCESS) {
+ inode->i_atime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_atime.tv_usec = 0;
+ }
+ if (rr->u.TF.flags & TF_ATTRIBUTES) {
+ inode->i_ctime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_ctime.tv_usec = 0;
+ }
+ break;
+ case SIG('S', 'L'):
+ {
+ int slen;
+ struct SL_component *slp;
+ struct SL_component *oldslp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ inode->i_size = symlink_len;
+ while (slen > 1) {
+ rootflag = 0;
+ switch (slp->flags & ~1) {
+ case 0:
+ inode->i_size +=
+ slp->len;
+ break;
+ case 2:
+ inode->i_size += 1;
+ break;
+ case 4:
+ inode->i_size += 2;
+ break;
+ case 8:
+ rootflag = 1;
+ inode->i_size += 1;
+ break;
+ default:
+ write_log(_T("Symlink component flag not implemented\n"));
+ }
+ slen -= slp->len + 2;
+ oldslp = slp;
+ slp = (struct SL_component *)
+ (((char *)slp) + slp->len + 2);
+
+ if (slen < 2) {
+ if (((rr->u.SL.
+ flags & 1) != 0)
+ &&
+ ((oldslp->
+ flags & 1) == 0))
+ inode->i_size +=
+ 1;
+ break;
+ }
+
+ /*
+ * If this component record isn't
+ * continued, then append a '/'.
+ */
+ if (!rootflag
+ && (oldslp->flags & 1) == 0)
+ inode->i_size += 1;
+ }
+ }
+ symlink_len = inode->i_size;
+ break;
+ case SIG('R', 'E'):
+ write_log(_T("Attempt to read inode for relocated directory\n"));
+ goto out;
+ case SIG('C', 'L'):
+ ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
+ reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0, NULL);
+ if (IS_ERR(reloc)) {
+ ret = -1; //PTR_ERR(reloc);
+ goto out;
+ }
+ inode->i_mode = reloc->i_mode;
+ //set_nlink(inode, reloc->i_nlink);
+ inode->i_uid = reloc->i_uid;
+ inode->i_gid = reloc->i_gid;
+ //inode->i_rdev = reloc->i_rdev;
+ inode->i_size = reloc->i_size;
+ inode->i_blocks = reloc->i_blocks;
+ inode->i_atime = reloc->i_atime;
+ inode->i_ctime = reloc->i_ctime;
+ inode->i_mtime = reloc->i_mtime;
+ iput(reloc);
+ break;
+#ifdef CONFIG_ZISOFS
+ case SIG('Z', 'F'): {
+ int algo;
+
+ if (ISOFS_SB(inode->i_sb)->s_nocompress)
+ break;
+ algo = isonum_721(rr->u.ZF.algorithm);
+ if (algo == SIG('p', 'z')) {
+ int block_shift =
+ isonum_711(&rr->u.ZF.parms[1]);
+ if (block_shift > 17) {
+ printk(KERN_WARNING "isofs: "
+ "Can't handle ZF block "
+ "size of 2^%d\n",
+ block_shift);
+ } else {
+ /*
+ * Note: we don't change
+ * i_blocks here
+ */
+ ISOFS_I(inode)->i_file_format =
+ isofs_file_compressed;
+ /*
+ * Parameters to compression
+ * algorithm (header size,
+ * block size)
+ */
+ ISOFS_I(inode)->i_format_parm[0] =
+ isonum_711(&rr->u.ZF.parms[0]);
+ ISOFS_I(inode)->i_format_parm[1] =
+ isonum_711(&rr->u.ZF.parms[1]);
+ inode->i_size =
+ isonum_733(rr->u.ZF.
+ real_size);
+ }
+ } else {
+ printk(KERN_WARNING
+ "isofs: Unknown ZF compression "
+ "algorithm: %c%c\n",
+ rr->u.ZF.algorithm[0],
+ rr->u.ZF.algorithm[1]);
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret == 1)
+ ret = 0;
+out:
+ xfree(rs.buffer);
+ return ret;
+eio:
+ ret = -EIO;
+ goto out;
+}
+
+static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
+{
+ int slen;
+ int rootflag;
+ struct SL_component *oldslp;
+ struct SL_component *slp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ while (slen > 1) {
+ rootflag = 0;
+ switch (slp->flags & ~1) {
+ case 0:
+ if (slp->len > plimit - rpnt)
+ return NULL;
+ memcpy(rpnt, slp->text, slp->len);
+ rpnt += slp->len;
+ break;
+ case 2:
+ if (rpnt >= plimit)
+ return NULL;
+ *rpnt++ = '.';
+ break;
+ case 4:
+ if (2 > plimit - rpnt)
+ return NULL;
+ *rpnt++ = '.';
+ *rpnt++ = '.';
+ break;
+ case 8:
+ if (rpnt >= plimit)
+ return NULL;
+ rootflag = 1;
+ *rpnt++ = '/';
+ break;
+ default:
+ write_log(_T("Symlink component flag not implemented (%d)\n"), slp->flags);
+ }
+ slen -= slp->len + 2;
+ oldslp = slp;
+ slp = (struct SL_component *)((char *)slp + slp->len + 2);
+
+ if (slen < 2) {
+ /*
+ * If there is another SL record, and this component
+ * record isn't continued, then add a slash.
+ */
+ if ((!rootflag) && (rr->u.SL.flags & 1) &&
+ !(oldslp->flags & 1)) {
+ if (rpnt >= plimit)
+ return NULL;
+ *rpnt++ = '/';
+ }
+ break;
+ }
+
+ /*
+ * If this component record isn't continued, then append a '/'.
+ */
+ if (!rootflag && !(oldslp->flags & 1)) {
+ if (rpnt >= plimit)
+ return NULL;
+ *rpnt++ = '/';
+ }
+ }
+ return rpnt;
+}
+
+static int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
+{
+ int result = parse_rock_ridge_inode_internal(de, inode, 0);
+
+ /*
+ * if rockridge flag was reset and we didn't look for attributes
+ * behind eventual XA attributes, have a look there
+ */
+ if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
+ && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
+ result = parse_rock_ridge_inode_internal(de, inode, 14);
+ }
+ return result;
+}
+
+#if 0
+/*
+ * readpage() for symlinks: reads symlink contents into the page and either
+ * makes it uptodate and returns 0 or returns error (-EIO)
+ */
+static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ struct iso_inode_info *ei = ISOFS_I(inode);
+ struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
+ char *link = kmap(page);
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ struct buffer_head *bh;
+ char *rpnt = link;
+ unsigned char *pnt;
+ struct iso_directory_record *raw_de;
+ unsigned long block, offset;
+ int sig;
+ struct rock_ridge *rr;
+ struct rock_state rs;
+ int ret;
+
+ if (!sbi->s_rock)
+ goto error;
+
+ init_rock_state(&rs, inode);
+ block = ei->i_iget5_block;
+ bh = sb_bread(inode->i_sb, block);
+ if (!bh)
+ goto out_noread;
+
+ offset = ei->i_iget5_offset;
+ pnt = (unsigned char *)bh->b_data + offset;
+
+ raw_de = (struct iso_directory_record *)pnt;
+
+ /*
+ * If we go past the end of the buffer, there is some sort of error.
+ */
+ if (offset + *pnt > bufsize)
+ goto out_bad_span;
+
+ /*
+ * Now test for possible Rock Ridge extensions which will override
+ * some of these numbers in the inode structure.
+ */
+
+ setup_rock_ridge(raw_de, inode, &rs);
+
+repeat:
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
+ if (rr->len < 3)
+ goto out; /* Something got screwed up here */
+ sig = isonum_721(rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto out;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ if (rs.len < 0)
+ goto out; /* corrupted isofs */
+
+ switch (sig) {
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] & RR_SL) == 0)
+ goto out;
+ break;
+ case SIG('S', 'P'):
+ if (check_sp(rr, inode))
+ goto out;
+ break;
+ case SIG('S', 'L'):
+ rpnt = get_symlink_chunk(rpnt, rr,
+ link + (PAGE_SIZE - 1));
+ if (rpnt == NULL)
+ goto out;
+ break;
+ case SIG('C', 'E'):
+ /* This tells is if there is a continuation record */
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
+ default:
+ break;
+ }
+ }
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret < 0)
+ goto fail;
+
+ if (rpnt == link)
+ goto fail;
+ brelse(bh);
+ *rpnt = '\0';
+ SetPageUptodate(page);
+ kunmap(page);
+ unlock_page(page);
+ return 0;
+
+ /* error exit from macro */
+out:
+ kfree(rs.buffer);
+ goto fail;
+out_noread:
+ printk("unable to read i-node block");
+ goto fail;
+out_bad_span:
+ printk("symlink spans iso9660 blocks\n");
+fail:
+ brelse(bh);
+error:
+ SetPageError(page);
+ kunmap(page);
+ unlock_page(page);
+ return -EIO;
+}
+
+#endif
+
+
+static TCHAR *get_joliet_name(char *name, unsigned char len, bool utf8)
+{
+ TCHAR *out;
+
+ if (utf8) {
+ /* probably never used */
+ uae_char *o = xmalloc(uae_char, len + 1);
+ for (int i = 0; i < len; i++)
+ o[i] = name[i];
+ o[len] = 0;
+ out = utf8u(o);
+ xfree(o);
+ } else {
+ len /= 2;
+ out = xmalloc(TCHAR, len + 1);
+ for (int i = 0; i < len; i++)
+ out[i] = isonum_722(name + i * 2);
+ out[len] = 0;
+ }
+
+ if ((len > 2) && (out[len - 2] == ';') && (out[len - 1] == '1')) {
+ len -= 2;
+ out[len] = 0;
+ }
+
+ /*
+ * Windows doesn't like periods at the end of a name,
+ * so neither do we
+ */
+ while (len >= 2 && (out[len - 1] == '.')) {
+ len--;
+ out[len] = 0;
+ }
+ return out;
+}
+
+static TCHAR *get_joliet_filename(struct iso_directory_record * de, struct inode * inode)
+{
+ unsigned char utf8;
+ //struct nls_table *nls;
+ TCHAR *out;
+
+ utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
+ //nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
+
+ out = get_joliet_name(de->name, de->name_len[0], utf8 != 0);
+ return out;
+}
+
+
+/************************************************************ */
+
+
+
+/*
+ * Get a set of blocks; filling in buffer_heads if already allocated
+ * or getblk() if they are not. Returns the number of blocks inserted
+ * (-ve == error.)
+ */
+static int isofs_get_blocks(struct inode *inode, uae_u32 iblock, struct buffer_head *bh, unsigned long nblocks)
+{
+ unsigned int b_off = iblock;
+ unsigned offset, sect_size;
+ unsigned int firstext;
+ unsigned int nextblk, nextoff;
+ int section, rv, error;
+ struct iso_inode_info *ei = ISOFS_I(inode);
+
+ error = -1;
+ rv = 0;
+#if 0
+ if (iblock != b_off) {
+ write(KERN_DEBUG "%s: block number too large\n", __func__);
+ goto abort;
+ }
+#endif
+
+ offset = 0;
+ firstext = ei->i_first_extent;
+ sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
+ nextblk = ei->i_next_section_block;
+ nextoff = ei->i_next_section_offset;
+ section = 0;
+
+ while (nblocks) {
+ /* If we are *way* beyond the end of the file, print a message.
+ * Access beyond the end of the file up to the next page boundary
+ * is normal, however because of the way the page cache works.
+ * In this case, we just return 0 so that we can properly fill
+ * the page with useless information without generating any
+ * I/O errors.
+ */
+ if (b_off > ((inode->i_size) >> ISOFS_BUFFER_BITS(inode))) {
+ write_log (_T("ISOFS: block >= EOF (%u, %llu)\n"), b_off, (unsigned long long)inode->i_size);
+ goto abort;
+ }
+
+ /* On the last section, nextblk == 0, section size is likely to
+ * exceed sect_size by a partial block, and access beyond the
+ * end of the file will reach beyond the section size, too.
+ */
+ while (nextblk && (b_off >= (offset + sect_size))) {
+ struct inode *ninode;
+
+ offset += sect_size;
+ ninode = isofs_iget(inode->i_sb, nextblk, nextoff, NULL);
+ if (IS_ERR(ninode)) {
+ //error = PTR_ERR(ninode);
+ goto abort;
+ }
+ firstext = ISOFS_I(ninode)->i_first_extent;
+ sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
+ nextblk = ISOFS_I(ninode)->i_next_section_block;
+ nextoff = ISOFS_I(ninode)->i_next_section_offset;
+ iput(ninode);
+
+ if (++section > 100) {
+ write_log (_T("ISOFS: More than 100 file sections ?!? aborting...\n"));
+ goto abort;
+ }
+ }
+
+ if (bh) {
+ bh->b_blocknr = firstext + b_off - offset;
+ }
+ bh++; /* Next buffer head */
+ b_off++; /* Next buffer offset */
+ nblocks--;
+ rv++;
+ }
+
+ error = 0;
+abort:
+ return rv != 0 ? rv : -1;
+}
+
+static struct buffer_head *isofs_bread(struct inode *inode, uae_u32 block)
+{
+ struct buffer_head dummy[1];
+ int error;
+
+ error = isofs_get_blocks(inode, block, dummy, 1);
+ if (error < 0)
+ return NULL;
+ return sb_bread(inode->i_sb, dummy[0].b_blocknr);
+}
+
+
+/*
+ * Check if root directory is empty (has less than 3 files).
+ *
+ * Used to detect broken CDs where ISO root directory is empty but Joliet root
+ * directory is OK. If such CD has Rock Ridge extensions, they will be disabled
+ * (and Joliet used instead) or else no files would be visible.
+ */
+static bool rootdir_empty(struct super_block *sb, unsigned long block)
+{
+ int offset = 0, files = 0, de_len;
+ struct iso_directory_record *de;
+ struct buffer_head *bh;
+
+ bh = sb_bread(sb, block);
+ if (!bh)
+ return true;
+ while (files < 3) {
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+ de_len = *(unsigned char *) de;
+ if (de_len == 0)
+ break;
+ files++;
+ offset += de_len;
+ }
+ brelse(bh);
+ return files < 3;
+}
+
+/*
+ * Initialize the superblock and read the root inode.
+ *
+ * Note: a check_disk_change() has been done immediately prior
+ * to this call, so we don't need to check again.
+ */
+static int isofs_fill_super(struct super_block *s, void *data, int silent, uae_u64 *uniq)
+{
+ struct buffer_head *bh = NULL, *pri_bh = NULL;
+ struct hs_primary_descriptor *h_pri = NULL;
+ struct iso_primary_descriptor *pri = NULL;
+ struct iso_supplementary_descriptor *sec = NULL;
+ struct iso_directory_record *rootp;
+ struct inode *inode;
+ struct iso9660_options opt;
+ struct isofs_sb_info *sbi;
+ unsigned long first_data_zone;
+ int joliet_level = 0;
+ int iso_blknum, block;
+ int orig_zonesize;
+ int table, error = -EINVAL;
+ unsigned int vol_desc_start;
+ TCHAR *volume_name = NULL, *ch;
+ uae_u32 volume_date;
+
+ //save_mount_options(s, data);
+
+ sbi = &s->ei;
+
+ memset (&opt, 0, sizeof opt);
+ //if (!parse_options((char *)data, &opt))
+ // goto out_freesbi;
+
+ opt.blocksize = 2048;
+ opt.map = 'n';
+ opt.rock = 1;
+ opt.joliet = 1;
+
+ sbi->s_high_sierra = 0; /* default is iso9660 */
+
+ vol_desc_start = 0;
+#if 0
+ struct device_info di;
+ if (sys_command_info (s->unitnum, &di, true)) {
+ vol_desc_start = di.toc.firstaddress;
+ }
+#endif
+
+ for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) {
+ struct hs_volume_descriptor *hdp;
+ struct iso_volume_descriptor *vdp;
+
+ block = iso_blknum << ISOFS_BLOCK_BITS;
+ if (!(bh = sb_bread(s, block)))
+ goto out_no_read;
+
+ vdp = (struct iso_volume_descriptor *)bh->b_data;
+ hdp = (struct hs_volume_descriptor *)bh->b_data;
+
+ /*
+ * Due to the overlapping physical location of the descriptors,
+ * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
+ * proper identification in this case, we first check for ISO.
+ */
+ if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+ if (isonum_711(vdp->type) == ISO_VD_END)
+ break;
+ if (isonum_711(vdp->type) == ISO_VD_PRIMARY) {
+ if (pri == NULL) {
+ pri = (struct iso_primary_descriptor *)vdp;
+ /* Save the buffer in case we need it ... */
+ pri_bh = bh;
+ bh = NULL;
+ }
+ }
+ else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
+ sec = (struct iso_supplementary_descriptor *)vdp;
+ if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
+ if (opt.joliet) {
+ if (sec->escape[2] == 0x40)
+ joliet_level = 1;
+ else if (sec->escape[2] == 0x43)
+ joliet_level = 2;
+ else if (sec->escape[2] == 0x45)
+ joliet_level = 3;
+
+ write_log (_T("ISO 9660 Extensions: Microsoft Joliet Level %d\n"), joliet_level);
+ }
+ goto root_found;
+ } else {
+ /* Unknown supplementary volume descriptor */
+ sec = NULL;
+ }
+ }
+ } else {
+ if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+ if (isonum_711(hdp->type) != ISO_VD_PRIMARY)
+ goto out_freebh;
+
+ sbi->s_high_sierra = 1;
+ opt.rock = 0;
+ h_pri = (struct hs_primary_descriptor *)vdp;
+ goto root_found;
+ }
+ }
+
+ /* Just skip any volume descriptors we don't recognize */
+
+ brelse(bh);
+ bh = NULL;
+ }
+ /*
+ * If we fall through, either no volume descriptor was found,
+ * or else we passed a primary descriptor looking for others.
+ */
+ if (!pri)
+ goto out_unknown_format;
+ brelse(bh);
+ bh = pri_bh;
+ pri_bh = NULL;
+
+root_found:
+
+ if (joliet_level && (pri == NULL || !opt.rock)) {
+ /* This is the case of Joliet with the norock mount flag.
+ * A disc with both Joliet and Rock Ridge is handled later
+ */
+ pri = (struct iso_primary_descriptor *) sec;
+ }
+
+ if(sbi->s_high_sierra){
+ rootp = (struct iso_directory_record *) h_pri->root_directory_record;
+ sbi->s_nzones = isonum_733(h_pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723(h_pri->logical_block_size);
+ sbi->s_max_size = isonum_733(h_pri->volume_space_size);
+ } else {
+ if (!pri)
+ goto out_freebh;
+ rootp = (struct iso_directory_record *) pri->root_directory_record;
+ sbi->s_nzones = isonum_733(pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723(pri->logical_block_size);
+ sbi->s_max_size = isonum_733(pri->volume_space_size);
+ }
+
+ sbi->s_ninodes = 0; /* No way to figure this out easily */
+
+ orig_zonesize = sbi->s_log_zone_size;
+ /*
+ * If the zone size is smaller than the hardware sector size,
+ * this is a fatal error. This would occur if the disc drive
+ * had sectors that were 2048 bytes, but the filesystem had
+ * blocks that were 512 bytes (which should only very rarely
+ * happen.)
+ */
+ if (orig_zonesize < opt.blocksize)
+ goto out_bad_size;
+
+ /* RDE: convert log zone size to bit shift */
+ switch (sbi->s_log_zone_size) {
+ case 512: sbi->s_log_zone_size = 9; break;
+ case 1024: sbi->s_log_zone_size = 10; break;
+ case 2048: sbi->s_log_zone_size = 11; break;
+
+ default:
+ goto out_bad_zone_size;
+ }
+
+ //s->s_magic = ISOFS_SUPER_MAGIC;
+
+ /*
+ * With multi-extent files, file size is only limited by the maximum
+ * size of a file system, which is 8 TB.
+ */
+ //s->s_maxbytes = 0x80000000000LL;
+
+ /*
+ * The CDROM is read-only, has no nodes (devices) on it, and since
+ * all of the files appear to be owned by root, we really do not want
+ * to allow suid. (suid or devices will not show up unless we have
+ * Rock Ridge extensions)
+ */
+
+ //s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
+
+ /* Set this for reference. Its not currently used except on write
+ which we don't have .. */
+
+ first_data_zone = isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length);
+ sbi->s_firstdatazone = first_data_zone;
+
+ write_log (_T("ISOFS: Max size:%ld Log zone size:%ld\n"), sbi->s_max_size, 1UL << sbi->s_log_zone_size);
+ write_log (_T("ISOFS: First datazone:%ld\n"), sbi->s_firstdatazone);
+ if(sbi->s_high_sierra)
+ write_log(_T("ISOFS: Disc in High Sierra format.\n"));
+ ch = getname(pri->system_id, 4);
+ write_log (_T("ISOFS: System ID: %s"), ch);
+ xfree(ch);
+ volume_name = getname(pri->volume_id, 32);
+ volume_date = iso_ltime(pri->creation_date);
+ write_log (_T(" Volume ID: '%s'\n"), volume_name);
+ if (!strncmp(pri->system_id, ISO_SYSTEM_ID_CDTV, strlen(ISO_SYSTEM_ID_CDTV)))
+ sbi->s_cdtv = 1;
+
+ /*
+ * If the Joliet level is set, we _may_ decide to use the
+ * secondary descriptor, but can't be sure until after we
+ * read the root inode. But before reading the root inode
+ * we may need to change the device blocksize, and would
+ * rather release the old buffer first. So, we cache the
+ * first_data_zone value from the secondary descriptor.
+ */
+ if (joliet_level) {
+ pri = (struct iso_primary_descriptor *) sec;
+ rootp = (struct iso_directory_record *)pri->root_directory_record;
+ first_data_zone = isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length);
+ }
+
+
+ /*
+ * We're all done using the volume descriptor, and may need
+ * to change the device blocksize, so release the buffer now.
+ */
+ brelse(pri_bh);
+ brelse(bh);
+
+#if 0
+ if (joliet_level && opt.utf8 == 0) {
+ char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
+ sbi->s_nls_iocharset = load_nls(p);
+ if (! sbi->s_nls_iocharset) {
+ /* Fail only if explicit charset specified */
+ if (opt.iocharset)
+ goto out_freesbi;
+ sbi->s_nls_iocharset = load_nls_default();
+ }
+ }
+#endif
+ //s->s_op = &isofs_sops;
+ //s->s_export_op = &isofs_export_ops;
+
+ sbi->s_mapping = opt.map;
+ sbi->s_rock = (opt.rock ? 2 : 0);
+ sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
+ sbi->s_cruft = opt.cruft;
+ sbi->s_hide = opt.hide;
+ sbi->s_showassoc = opt.showassoc;
+ sbi->s_uid = opt.uid;
+ sbi->s_gid = opt.gid;
+ sbi->s_uid_set = opt.uid_set;
+ sbi->s_gid_set = opt.gid_set;
+ sbi->s_utf8 = opt.utf8;
+ sbi->s_nocompress = opt.nocompress;
+ sbi->s_overriderockperm = opt.overriderockperm;
+
+ /*
+ * Read the root inode, which _may_ result in changing
+ * the s_rock flag. Once we have the final s_rock value,
+ * we then decide whether to use the Joliet descriptor.
+ */
+ inode = isofs_iget(s, sbi->s_firstdatazone, 0, NULL);
+ if (IS_ERR(inode))
+ goto out_no_root;
+
+
+ /*
+ * Fix for broken CDs with Rock Ridge and empty ISO root directory but
+ * correct Joliet root directory.
+ */
+ if (sbi->s_rock == 1 && joliet_level && rootdir_empty(s, sbi->s_firstdatazone)) {
+ write_log(_T("ISOFS: primary root directory is empty. Disabling Rock Ridge and switching to Joliet.\n"));
+ sbi->s_rock = 0;
+ }
+
+ /*
+ * If this disk has both Rock Ridge and Joliet on it, then we
+ * want to use Rock Ridge by default. This can be overridden
+ * by using the norock mount option. There is still one other
+ * possibility that is not taken into account: a Rock Ridge
+ * CD with Unicode names. Until someone sees such a beast, it
+ * will not be supported.
+ */
+ if (sbi->s_rock == 1) {
+ joliet_level = 0;
+ sbi->s_cdtv = 1; /* only convert if plain iso9660 */
+ } else if (joliet_level) {
+ sbi->s_rock = 0;
+ sbi->s_cdtv = 1; /* only convert if plain iso9660 */
+ if (sbi->s_firstdatazone != first_data_zone) {
+ sbi->s_firstdatazone = first_data_zone;
+ write_log (_T("ISOFS: changing to secondary root\n"));
+ iput(inode);
+ inode = isofs_iget(s, sbi->s_firstdatazone, 0, NULL);
+ if (IS_ERR(inode))
+ goto out_no_root;
+ TCHAR *volname = get_joliet_name(pri->volume_id, 28, sbi->s_utf8);
+ if (volname && _tcslen(volname) > 0) {
+ xfree(volume_name);
+ volume_name = volname;
+ write_log(_T("ISOFS: Joliet Volume ID: '%s'\n"), volume_name);
+ } else {
+ xfree(volname);
+ }
+ }
+ }
+
+ if (opt.check == 'u') {
+ /* Only Joliet is case insensitive by default */
+ if (joliet_level)
+ opt.check = 'r';
+ else
+ opt.check = 's';
+ }
+ sbi->s_joliet_level = joliet_level;
+
+ /* Make sure the root inode is a directory */
+ if (!XS_ISDIR(inode->i_mode)) {
+ write_log (_T("isofs_fill_super: root inode is not a directory. Corrupted media?\n"));
+ goto out_iput;
+ }
+
+ table = 0;
+ if (joliet_level)
+ table += 2;
+ if (opt.check == 'r')
+ table++;
+
+ //s->s_d_op = &isofs_dentry_ops[table];
+
+ /* get the root dentry */
+ //s->s_root = d_alloc_root(inode);
+ //if (!(s->s_root))
+ // goto out_no_root;
+
+ //kfree(opt.iocharset);
+
+ iput(inode);
+ s->root = inode;
+ inode->name = volume_name;
+ inode->i_ctime.tv_sec = volume_date;
+ *uniq = inode->i_ino;
+ return 0;
+
+ /*
+ * Display error messages and free resources.
+ */
+out_iput:
+ iput(inode);
+ goto out_no_inode;
+out_no_root:
+ write_log (_T("ISOFS: get root inode failed\n"));
+out_no_inode:
+#ifdef CONFIG_JOLIET
+ unload_nls(sbi->s_nls_iocharset);
+#endif
+ goto out_freesbi;
+out_no_read:
+ write_log (_T("ISOFS: bread failed, dev=%d, iso_blknum=%d, block=%d\n"), s->unitnum, iso_blknum, block);
+ goto out_freebh;
+out_bad_zone_size:
+ write_log(_T("ISOFS: Bad logical zone size %ld\n"), sbi->s_log_zone_size);
+ goto out_freebh;
+out_bad_size:
+ write_log (_T("ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n"), orig_zonesize, opt.blocksize);
+ goto out_freebh;
+out_unknown_format:
+ if (!silent)
+ write_log (_T("ISOFS: Unable to identify CD-ROM format.\n"));
+out_freebh:
+ brelse(bh);
+ brelse(pri_bh);
+out_freesbi:
+ xfree(volume_name);
+ return error;
+}
+
+static int isofs_name_translate(struct iso_directory_record *de, char *newn, struct inode *inode)
+{
+ char * old = de->name;
+ int len = de->name_len[0];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ unsigned char c = old[i];
+ if (!c)
+ break;
+
+ if (!inode->i_sb->ei.s_cdtv) { /* keep case if Amiga/CDTV/CD32 */
+ /* convert from second character (same as CacheCDFS default) */
+ if (i > 0 && c >= 'A' && c <= 'Z')
+ c |= 0x20; /* lower case */
+ }
+
+ /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
+ if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
+ break;
+
+ /* Drop trailing ';1' */
+ if (c == ';' && i == len - 2 && old[i + 1] == '1')
+ break;
+
+ /* Convert remaining ';' to '.' */
+ /* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
+ if (c == ';' || c == '/')
+ c = '.';
+
+ newn[i] = c;
+ }
+ return i;
+}
+
+static int isofs_cmp(const char *name, char *compare, int dlen)
+{
+ if (!compare)
+ return 1;
+ /* we don't care about special "." and ".." files */
+ if (dlen == 1) {
+ /* "." */
+ if (compare[0] == 0) {
+ return 1;
+ } else if (compare[0] == 1) {
+ return 1;
+ }
+ }
+ char tmp = compare[dlen];
+ compare[dlen] = 0;
+ int c = stricmp(name, compare);
+ compare[dlen] = tmp;
+ return c;
+}
+
+static struct inode *isofs_find_entry(struct inode *dir, char *tmpname, TCHAR *tmpname2, struct iso_directory_record *tmpde, const char *name, const TCHAR *nameu)
+{
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
+ unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
+ unsigned long block, f_pos, offset, block_saved, offset_saved;
+ struct buffer_head *bh = NULL;
+ struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
+ int i;
+ TCHAR *jname;
+
+ if (!ISOFS_I(dir)->i_first_extent)
+ return 0;
+
+ f_pos = 0;
+ offset = 0;
+ block = 0;
+
+ while (f_pos < dir->i_size) {
+ struct iso_directory_record *de;
+ int de_len, match, dlen;
+ char *dpnt;
+
+ if (!bh) {
+ bh = isofs_bread(dir, block);
+ if (!bh)
+ return 0;
+ }
+
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+
+ de_len = *(unsigned char *) de;
+ if (!de_len) {
+ brelse(bh);
+ bh = NULL;
+ f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
+ block = f_pos >> bufbits;
+ offset = 0;
+ continue;
+ }
+
+ block_saved = bh->b_blocknr;
+ offset_saved = offset;
+ offset += de_len;
+ f_pos += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= bufsize) {
+ int slop = bufsize - offset + de_len;
+ memcpy((uae_u8*)tmpde, de, slop);
+ offset &= bufsize - 1;
+ block++;
+ brelse(bh);
+ bh = NULL;
+ if (offset) {
+ bh = isofs_bread(dir, block);
+ if (!bh)
+ return 0;
+ memcpy((uae_u8*)tmpde + slop, bh->b_data, offset);
+ }
+ de = tmpde;
+ }
+
+ dlen = de->name_len[0];
+ dpnt = de->name;
+ /* Basic sanity check, whether name doesn't exceed dir entry */
+ if (de_len < dlen + sizeof(struct iso_directory_record)) {
+ write_log (_T("iso9660: Corrupted directory entry in block %lu of inode %u\n"), block, dir->i_ino);
+ return 0;
+ }
+
+ jname = NULL;
+ if (sbi->s_rock && ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
+ dlen = i; /* possibly -1 */
+ dpnt = tmpname;
+ } else if (sbi->s_joliet_level) {
+ jname = get_joliet_filename(de, dir);
+ } else if (sbi->s_mapping == 'n') {
+ dlen = isofs_name_translate(de, tmpname, dir);
+ dpnt = tmpname;
+ }
+
+ /*
+ * Skip hidden or associated files unless hide or showassoc,
+ * respectively, is set
+ */
+ match = 0;
+ if (dlen > 0 && (!sbi->s_hide || (!(de->flags[-sbi->s_high_sierra] & 1))) && (sbi->s_showassoc || (!(de->flags[-sbi->s_high_sierra] & 4)))) {
+ if (jname)
+ match = _tcsicmp(jname, nameu) == 0;
+ else
+ match = isofs_cmp(name, dpnt, dlen) == 0;
+ }
+ xfree (jname);
+ if (match) {
+ isofs_normalize_block_and_offset(de, &block_saved, &offset_saved);
+ struct inode *dinode = isofs_iget(dir->i_sb, block_saved, offset_saved, nameu);
+ iput(dinode);
+ brelse(bh);
+ return dinode;
+ }
+
+ }
+ brelse(bh);
+ return 0;
+}
+
+/* Acorn extensions written by Matthew Wilcox 1998 */
+static int get_acorn_filename(struct iso_directory_record *de, char *retname, struct inode *inode)
+{
+ int std;
+ unsigned char *chr;
+ int retnamlen = isofs_name_translate(de, retname, inode);
+
+ if (retnamlen == 0)
+ return 0;
+ std = sizeof(struct iso_directory_record) + de->name_len[0];
+ if (std & 1)
+ std++;
+ if ((*((unsigned char *) de) - std) != 32)
+ return retnamlen;
+ chr = ((unsigned char *) de) + std;
+ if (strncmp((char*)chr, "ARCHIMEDES", 10))
+ return retnamlen;
+ if ((*retname == '_') && ((chr[19] & 1) == 1))
+ *retname = '!';
+ if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff) && ((chr[12] & 0xf0) == 0xf0)) {
+ retname[retnamlen] = ',';
+ sprintf(retname+retnamlen+1, "%3.3x",
+ ((chr[12] & 0xf) << 8) | chr[11]);
+ retnamlen += 4;
+ }
+ return retnamlen;
+}
+
+struct file
+{
+ uae_u32 f_pos;
+};
+
+static int do_isofs_readdir(struct inode *inode, struct file *filp, char *tmpname, struct iso_directory_record *tmpde, TCHAR *outname, uae_u64 *uniq)
+{
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
+ unsigned long block, offset, block_saved, offset_saved;
+ unsigned long inode_number = 0; /* Quiet GCC */
+ struct buffer_head *bh = NULL;
+ int len;
+ int map;
+ int first_de = 1;
+ char *p = NULL; /* Quiet GCC */
+ struct iso_directory_record *de;
+ struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
+ struct inode *dinode = NULL;
+ int bh_block = 0;
+
+ offset = filp->f_pos & (bufsize - 1);
+ block = filp->f_pos >> bufbits;
+
+ while (filp->f_pos < inode->i_size) {
+ int de_len;
+
+ if (!bh) {
+ bh = isofs_bread(inode, block);
+ if (!bh)
+ return 0;
+ bh_block = bh->b_blocknr;
+ }
+
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+
+ de_len = *(unsigned char *) de;
+
+ /*
+ * If the length byte is zero, we should move on to the next
+ * CDROM sector. If we are at the end of the directory, we
+ * kick out of the while loop.
+ */
+
+ if (de_len == 0) {
+ brelse(bh);
+ bh = NULL;
+ filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
+ block = filp->f_pos >> bufbits;
+ offset = 0;
+ continue;
+ }
+
+ block_saved = block;
+ offset_saved = offset;
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= bufsize) {
+ int slop = bufsize - offset + de_len;
+ memcpy(tmpde, de, slop);
+ offset &= bufsize - 1;
+ block++;
+ brelse(bh);
+ bh = NULL;
+ if (offset) {
+ bh = isofs_bread(inode, block);
+ if (!bh)
+ return 0;
+ memcpy((uae_u8*)tmpde + slop, bh->b_data, offset);
+ }
+ de = tmpde;
+ }
+ /* Basic sanity check, whether name doesn't exceed dir entry */
+ if (de_len < de->name_len[0] + sizeof(struct iso_directory_record)) {
+ write_log (_T("iso9660: Corrupted directory entry in block %lu of inode %u\n"), block, inode->i_ino);
+ return 0;
+ }
+
+ if (first_de) {
+ isofs_normalize_block_and_offset(de, &block_saved, &offset_saved);
+ inode_number = isofs_get_ino(block_saved, offset_saved, bufbits);
+ }
+
+ if (de->flags[-sbi->s_high_sierra] & 0x80) {
+ first_de = 0;
+ filp->f_pos += de_len;
+ continue;
+ }
+ first_de = 1;
+
+ /* Handle the case of the '.' directory */
+ if (de->name_len[0] == 1 && de->name[0] == 0) {
+ filp->f_pos += de_len;
+ continue;
+ }
+ len = 0;
+ /* Handle the case of the '..' directory */
+ if (de->name_len[0] == 1 && de->name[0] == 1) {
+ filp->f_pos += de_len;
+ continue;
+ }
+ /* Handle everything else. Do name translation if there
+ is no Rock Ridge NM field. */
+
+ /*
+ * Do not report hidden files if so instructed, or associated
+ * files unless instructed to do so
+ */
+ if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) || (!sbi->s_showassoc && (de->flags[-sbi->s_high_sierra] & 4))) {
+ filp->f_pos += de_len;
+ continue;
+ }
+
+ map = 1;
+#if 1
+ if (sbi->s_rock) {
+ len = get_rock_ridge_filename(de, tmpname, inode);
+ if (len != 0) { /* may be -1 */
+ p = tmpname;
+ map = 0;
+ }
+ }
+#endif
+ TCHAR *jname = NULL;
+ if (map) {
+ if (sbi->s_joliet_level) {
+ jname = get_joliet_filename(de, inode);
+ len = 1;
+ } else
+ if (sbi->s_mapping == 'a') {
+ len = get_acorn_filename(de, tmpname, inode);
+ p = tmpname;
+ } else
+ if (sbi->s_mapping == 'n') {
+ len = isofs_name_translate(de, tmpname, inode);
+ p = tmpname;
+ } else {
+ p = de->name;
+ len = de->name_len[0];
+ }
+ }
+
+ filp->f_pos += de_len;
+ if (len > 0) {
+ if (jname == NULL) {
+ if (p == NULL) {
+ write_log(_T("ISOFS: no name copied (p == NULL)\n"));
+ outname[0] = _T('\0');
+ }
+ else {
+ char t = p[len];
+ p[len] = 0;
+ au_copy (outname, MAX_DPATH, p);
+ p[len] = t;
+ }
+ } else {
+ uae_tcslcpy (outname, jname, MAX_DPATH);
+ xfree (jname);
+ }
+ dinode = isofs_iget(inode->i_sb, bh_block, offset_saved, outname);
+ iput(dinode);
+ *uniq = dinode->i_ino;
+ brelse(bh);
+ return 1;
+ }
+
+ continue;
+ }
+ brelse(bh);
+ return 0;
+}
+
+
+void *isofs_mount(int unitnum, uae_u64 *uniq)
+{
+ struct super_block *sb;
+
+ sb = xcalloc(struct super_block, 1);
+ sb->s_blocksize = 2048;
+ sb->s_blocksize_bits = 11;
+ sb->unitnum = unitnum;
+ if (sys_command_ismedia (unitnum, true)) {
+ if (isofs_fill_super(sb, NULL, 0, uniq)) {
+ sb->unknown_media = true;
+ }
+ }
+ return sb;
+}
+void isofs_unmount(void *sbp)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode;
+ struct buffer_head *bh;
+
+ if (!sb)
+ return;
+ write_log (_T("miss: %d hit: %d\n"), sb->hash_miss, sb->hash_hit);
+ inode = sb->inodes;
+ while (inode) {
+ struct inode *next = inode->next;
+ free_inode(inode);
+ inode = next;
+ }
+ bh = sb->buffer_heads;
+ while (bh) {
+ struct buffer_head *next = bh->next;
+ free_bh(bh);
+ bh = next;
+ }
+ xfree (sb);
+}
+
+bool isofs_mediainfo(void *sbp, struct isofs_info *ii)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+
+ memset (ii, 0, sizeof (struct isofs_info));
+
+ if (!sb)
+ return true;
+ struct isofs_sb_info *sbi = ISOFS_SB(sb);
+ ii->blocksize = 2048;
+ if (sys_command_ismedia (sb->unitnum, true)) {
+ struct device_info di;
+ uae_u32 totalblocks = 0;
+ ii->media = true;
+ di.cylinders = 0;
+ _stprintf (ii->devname, _T("CD%d"), sb->unitnum);
+ if (sys_command_info (sb->unitnum, &di, true)) {
+ totalblocks = di.cylinders * di.sectorspertrack * di.trackspercylinder;
+ uae_tcslcpy (ii->devname, di.label, sizeof (ii->devname));
+ }
+ ii->unknown_media = sb->unknown_media;
+ if (sb->root) {
+ if (_tcslen(sb->root->name) == 0) {
+ uae_tcslcpy(ii->volumename, _T("NO_LABEL"), sizeof(ii->volumename));
+ } else {
+ uae_tcslcpy (ii->volumename, sb->root->name, sizeof(ii->volumename));
+ }
+ ii->blocks = sbi->s_max_size;
+ ii->totalblocks = totalblocks ? totalblocks : ii->blocks;
+ ii->creation = sb->root->i_ctime.tv_sec;
+ }
+ if (!ii->volumename[0] || !ii->blocks)
+ ii->unknown_media = true;
+ }
+ return true;
+}
+
+struct cd_opendir_s
+{
+ struct super_block *sb;
+ struct inode *inode;
+ struct file f;
+ char tmp1[1024];
+ char tmp2[1024];
+};
+
+struct cd_opendir_s *isofs_opendir(void *sb, uae_u64 uniq)
+{
+ struct cd_opendir_s *od = xcalloc(struct cd_opendir_s, 1);
+ od->sb = (struct super_block*)sb;
+ od->inode = find_inode(od->sb, uniq);
+ if (od->inode) {
+ lock_inode(od->inode);
+ od->f.f_pos = 0;
+ return od;
+ }
+ xfree(od);
+ return NULL;
+}
+void isofs_closedir(struct cd_opendir_s *od)
+{
+ unlock_inode(od->inode);
+ xfree (od);
+}
+bool isofs_readdir(struct cd_opendir_s *od, TCHAR *name, uae_u64 *uniq)
+{
+ return do_isofs_readdir(od->inode, &od->f, od->tmp1, (struct iso_directory_record*)od->tmp2, name, uniq) != 0;
+}
+
+void isofss_fill_file_attrs(void *sbp, uae_u64 parent, int *dir, int *flags, TCHAR **comment, uae_u64 uniq)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode = find_inode(sb, uniq);
+ if (!inode)
+ return;
+
+ *comment = NULL;
+ *dir = XS_ISDIR(inode->i_mode) ? 1 : 0;
+ if (inode->i_isaflags)
+ *flags = inode->i_aflags;
+ else
+ *flags = 0;
+ if (inode->i_comment)
+ *comment = my_strdup(inode->i_comment);
+}
+
+bool isofs_stat(void *sbp, uae_u64 uniq, struct mystat *statbuf)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode = find_inode(sb, uniq);
+
+ if (!inode)
+ return false;
+
+ statbuf->mtime.tv_sec = inode->i_mtime.tv_sec;
+ statbuf->mtime.tv_usec = 0;
+ if (!XS_ISDIR(inode->i_mode)) {
+ statbuf->size = inode->i_size;
+ }
+ return true;
+}
+
+bool isofs_exists(void *sbp, uae_u64 parent, const TCHAR *name, uae_u64 *uniq)
+{
+ char tmp1[1024];
+ TCHAR tmp1x[1024];
+ char tmp2[1024];
+ char tmp3[1024];
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode = find_inode(sb, parent);
+
+ if (!inode)
+ return false;
+ ua_copy(tmp3, sizeof tmp3, name);
+ inode = isofs_find_entry(inode, tmp1, tmp1x, (struct iso_directory_record*)tmp2, tmp3, name);
+ if (inode) {
+ *uniq = inode->i_ino;
+ return true;
+ }
+ return false;
+}
+
+void isofs_dispose_inode(void *sbp, uae_u64 uniq)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode;
+ struct inode *old = NULL, *prev = NULL;
+
+ if (!sb)
+ return;
+ inode = sb->inodes;
+ while (inode) {
+ if (inode->i_ino == uniq) {
+ old = inode;
+ break;
+ }
+ prev = inode;
+ inode = inode->next;
+ }
+ if (!old)
+ return;
+
+ if (prev)
+ prev->next = old->next;
+ else
+ sb->inodes = old->next;
+ free_inode(old);
+}
+
+struct cd_openfile_s
+{
+ struct super_block *sb;
+ struct inode *inode;
+ uae_s64 seek;
+};
+
+struct cd_openfile_s *isofs_openfile(void *sbp, uae_u64 uniq, int flags)
+{
+ struct super_block *sb = (struct super_block*)sbp;
+ struct inode *inode = find_inode(sb, uniq);
+ if (!inode)
+ return NULL;
+ struct cd_openfile_s *of = xcalloc(struct cd_openfile_s, 1);
+ of->sb = sb;
+ of->inode = inode;
+ return of;
+}
+
+void isofs_closefile(struct cd_openfile_s *of)
+{
+ xfree(of);
+}
+
+uae_s64 isofs_lseek(struct cd_openfile_s *of, uae_s64 offset, int mode)
+{
+ struct inode *inode = of->inode;
+ int ret = -1;
+ switch (mode)
+ {
+ case SEEK_SET:
+ of->seek = offset;
+ break;
+ case SEEK_CUR:
+ of->seek += offset;
+ break;
+ case SEEK_END:
+ of->seek = inode->i_size + offset;
+ break;
+ }
+ if (of->seek < 0) {
+ of->seek = 0;
+ ret = -1;
+ } else if (of->seek > inode->i_size) {
+ of->seek = inode->i_size;
+ ret = -1;
+ } else {
+ ret = of->seek;
+ }
+ return ret;
+}
+uae_s64 isofs_fsize(struct cd_openfile_s *of)
+{
+ struct inode *inode = of->inode;
+ return inode->i_size;
+}
+
+uae_s64 isofs_read(struct cd_openfile_s *of, void *bp, unsigned int size)
+{
+ struct inode *inode = of->inode;
+ uae_u32 bufsize = ISOFS_BUFFER_SIZE(inode);
+ uae_u32 bufmask = bufsize - 1;
+ uae_s64 offset = of->seek;
+ struct buffer_head *bh;
+ uae_u64 totalread = 0;
+ uae_u32 read;
+ uae_u8 *b = (uae_u8*)bp;
+
+ if (size + of->seek > inode->i_size)
+ size = inode->i_size - of->seek;
+
+ // first partial sector
+ if (offset & bufmask) {
+ bh = isofs_bread(inode, offset / bufsize);
+ if (!bh)
+ return 0;
+ read = size < (bufsize - (offset & bufmask)) ? size : (bufsize - (offset & bufmask));
+ memcpy (b, bh->b_data + (offset & bufmask), read);
+ offset += read;
+ size -= read;
+ totalread += read;
+ b += read;
+ of->seek += read;
+ brelse(bh);
+ }
+ // complete sector(s)
+ while (size >= bufsize) {
+ bh = isofs_bread(inode, offset / bufsize);
+ if (!bh)
+ return totalread;
+ read = size < bufsize ? size : bufsize;
+ memcpy (b, bh->b_data, read);
+ offset += read;
+ size -= read;
+ totalread += read;
+ b += read;
+ of->seek += read;
+ brelse(bh);
+ }
+ // and finally last partial sector
+ if (size > 0) {
+ bh = isofs_bread(inode, offset / bufsize);
+ if (!bh)
+ return totalread;
+ read = size;
+ memcpy (b, bh->b_data, size);
+ totalread += read;
+ of->seek += read;
+ brelse(bh);
+ }
+
+ return totalread;
+}
diff --git a/src/memory.cpp b/src/memory.cpp
index 52f1152e..d4074802 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -21,10 +21,12 @@
#include "ar.h"
#include "crc32.h"
#include "gui.h"
+#include "cdtv.h"
#include "akiko.h"
#include "gayle.h"
#include "devices.h"
+static bool rom_write_enabled;
#ifdef JIT
/* Set by each memory handler that does not simply access real memory. */
int special_mem;
@@ -328,6 +330,38 @@ MEMORY_FUNCTIONS(a3000hmem);
uae_u16 kickstart_version;
+/*
+* A1000 kickstart RAM handling
+*
+* RESET instruction unhides boot ROM and disables write protection
+* write access to boot ROM hides boot ROM and enables write protection
+*
+*/
+static int a1000_kickstart_mode;
+static uae_u8 *a1000_bootrom;
+static void a1000_handle_kickstart (int mode)
+{
+ if (!a1000_bootrom)
+ return;
+ protect_roms (false);
+ if (mode == 0) {
+ a1000_kickstart_mode = 0;
+ memcpy (kickmem_bank.baseaddr, kickmem_bank.baseaddr + ROM_SIZE_256, ROM_SIZE_256);
+ kickstart_version = (kickmem_bank.baseaddr[ROM_SIZE_256 + 12] << 8) | kickmem_bank.baseaddr[ROM_SIZE_256 + 13];
+ } else {
+ a1000_kickstart_mode = 1;
+ memcpy (kickmem_bank.baseaddr, a1000_bootrom, ROM_SIZE_256);
+ kickstart_version = 0;
+ }
+ if (kickstart_version == 0xffff)
+ kickstart_version = 0;
+}
+
+void a1000_reset (void)
+{
+ a1000_handle_kickstart (1);
+}
+
static void REGPARAM3 kickmem_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 kickmem_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 kickmem_bput (uaecptr, uae_u32) REGPARAM;
@@ -340,14 +374,81 @@ MEMORY_XLATE(kickmem);
static void REGPARAM2 kickmem_lput (uaecptr addr, uae_u32 b)
{
+ uae_u32 *m;
+ if (currprefs.rom_readwrite && rom_write_enabled) {
+ addr &= kickmem_bank.mask;
+ m = (uae_u32 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_long (m, b);
+ } else if (a1000_kickstart_mode) {
+ if (addr >= 0xfc0000) {
+ addr &= kickmem_bank.mask;
+ m = (uae_u32 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_long (m, b);
+ return;
+ } else
+ a1000_handle_kickstart (0);
+ } else if (currprefs.illegal_mem) {
+ write_log (_T("Illegal kickmem lput at %08x PC=%08x\n"), addr, M68K_GETPC);
+ }
}
static void REGPARAM2 kickmem_wput (uaecptr addr, uae_u32 b)
{
+ uae_u16 *m;
+ if (currprefs.rom_readwrite && rom_write_enabled) {
+ addr &= kickmem_bank.mask;
+ m = (uae_u16 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_word (m, b);
+ } else if (a1000_kickstart_mode) {
+ if (addr >= 0xfc0000) {
+ addr &= kickmem_bank.mask;
+ m = (uae_u16 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_word (m, b);
+ return;
+ } else
+ a1000_handle_kickstart (0);
+ } else if (currprefs.illegal_mem) {
+ write_log (_T("Illegal kickmem wput at %08x PC=%08x\n"), addr, M68K_GETPC);
+ }
}
static void REGPARAM2 kickmem_bput (uaecptr addr, uae_u32 b)
{
+ if (currprefs.rom_readwrite && rom_write_enabled) {
+ addr &= kickmem_bank.mask;
+ kickmem_bank.baseaddr[addr] = b;
+ } else if (a1000_kickstart_mode) {
+ if (addr >= 0xfc0000) {
+ addr &= kickmem_bank.mask;
+ kickmem_bank.baseaddr[addr] = b;
+ return;
+ } else
+ a1000_handle_kickstart (0);
+ } else if (currprefs.illegal_mem) {
+ write_log (_T("Illegal kickmem bput at %08x PC=%08x\n"), addr, M68K_GETPC);
+ }
+}
+
+static void REGPARAM2 kickmem2_lput (uaecptr addr, uae_u32 l)
+{
+ uae_u32 *m;
+ addr &= kickmem_bank.mask;
+ m = (uae_u32 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_long (m, l);
+}
+
+static void REGPARAM2 kickmem2_wput (uaecptr addr, uae_u32 w)
+{
+ uae_u16 *m;
+ addr &= kickmem_bank.mask;
+ m = (uae_u16 *)(kickmem_bank.baseaddr + addr);
+ do_put_mem_word (m, w);
+}
+
+static void REGPARAM2 kickmem2_bput (uaecptr addr, uae_u32 b)
+{
+ addr &= kickmem_bank.mask;
+ kickmem_bank.baseaddr[addr] = b;
}
/* CD32/CDTV extended kick memory */
@@ -355,7 +456,10 @@ static void REGPARAM2 kickmem_bput (uaecptr addr, uae_u32 b)
static int extendedkickmem_type;
#define EXTENDED_ROM_CD32 1
+#define EXTENDED_ROM_CDTV 2
#define EXTENDED_ROM_KS 3
+#define EXTENDED_ROM_ARCADIA 4
+#define EXTENDED_ROM_ALG 5
static void REGPARAM3 extendedkickmem_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 extendedkickmem_wput (uaecptr, uae_u32) REGPARAM;
@@ -402,15 +506,14 @@ static void REGPARAM2 extendedkickmem2_bput (uaecptr addr, uae_u32 b)
int REGPARAM2 default_check (uaecptr a, uae_u32 b)
{
- return 0;
+ return 0;
}
static int be_cnt, be_recursive;
uae_u8 *REGPARAM2 default_xlate(uaecptr addr)
{
- if (be_recursive)
- {
+ if (be_recursive) {
cpu_halt(CPU_HALT_OPCODE_FETCH_FROM_NON_EXISTING_ADDRESS);
return kickmem_xlate(2);
}
@@ -523,7 +626,7 @@ addrbank custmem2_bank = {
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
-static bool singlebit (uae_u32 v)
+static bool singlebit(uae_u32 v)
{
while (v && !(v & 1))
v >>= 1;
@@ -533,103 +636,194 @@ static bool singlebit (uae_u32 v)
static void allocate_memory_custombanks(void)
{
if (custmem1_bank.reserved_size != currprefs.custom_memory_sizes[0]) {
- mapped_free (&custmem1_bank);
+ mapped_free(&custmem1_bank);
custmem1_bank.reserved_size = currprefs.custom_memory_sizes[0];
// custmem1 and 2 can have non-power of 2 size so only set correct mask if size is power of 2.
- custmem1_bank.mask = singlebit (custmem1_bank.reserved_size) ? custmem1_bank.reserved_size - 1 : -1;
+ custmem1_bank.mask = singlebit(custmem1_bank.reserved_size) ? custmem1_bank.reserved_size - 1 : -1;
custmem1_bank.start = currprefs.custom_memory_addrs[0];
if (custmem1_bank.reserved_size) {
- if (!mapped_malloc (&custmem1_bank))
+ if (!mapped_malloc(&custmem1_bank))
custmem1_bank.reserved_size = 0;
}
}
if (custmem2_bank.reserved_size != currprefs.custom_memory_sizes[1]) {
- mapped_free (&custmem2_bank);
+ mapped_free(&custmem2_bank);
custmem2_bank.reserved_size = currprefs.custom_memory_sizes[1];
- custmem2_bank.mask = singlebit (custmem2_bank.reserved_size) ? custmem2_bank.reserved_size - 1 : -1;
+ custmem2_bank.mask = singlebit(custmem2_bank.reserved_size) ? custmem2_bank.reserved_size - 1 : -1;
custmem2_bank.start = currprefs.custom_memory_addrs[1];
if (custmem2_bank.reserved_size) {
- if (!mapped_malloc (&custmem2_bank))
+ if (!mapped_malloc(&custmem2_bank))
custmem2_bank.reserved_size = 0;
}
}
}
+#define fkickmem_size ROM_SIZE_512
+static int a3000_f0;
+void a3000_fakekick (int map)
+{
+ static uae_u8 *kickstore;
+
+ protect_roms (false);
+ if (map) {
+ uae_u8 *fkickmemory = a3000lmem_bank.baseaddr + a3000lmem_bank.reserved_size - fkickmem_size;
+ if (fkickmemory[2] == 0x4e && fkickmemory[3] == 0xf9 && fkickmemory[4] == 0x00) {
+ if (!kickstore)
+ kickstore = xmalloc (uae_u8, fkickmem_size);
+ memcpy (kickstore, kickmem_bank.baseaddr, fkickmem_size);
+ if (fkickmemory[5] == 0xfc) {
+ memcpy (kickmem_bank.baseaddr, fkickmemory, fkickmem_size / 2);
+ memcpy (kickmem_bank.baseaddr + fkickmem_size / 2, fkickmemory, fkickmem_size / 2);
+ extendedkickmem_bank.reserved_size = 65536;
+ extendedkickmem_bank.label = _T("rom_f0");
+ extendedkickmem_bank.mask = extendedkickmem_bank.reserved_size - 1;
+ mapped_malloc (&extendedkickmem_bank);
+ memcpy (extendedkickmem_bank.baseaddr, fkickmemory + fkickmem_size / 2, 65536);
+ map_banks (&extendedkickmem_bank, 0xf0, 1, 1);
+ a3000_f0 = 1;
+ } else {
+ memcpy (kickmem_bank.baseaddr, fkickmemory, fkickmem_size);
+ }
+ }
+ } else {
+ if (a3000_f0) {
+ map_banks (&dummy_bank, 0xf0, 1, 1);
+ mapped_free (&extendedkickmem_bank);
+ a3000_f0 = 0;
+ }
+ if (kickstore)
+ memcpy (kickmem_bank.baseaddr, kickstore, fkickmem_size);
+ xfree (kickstore);
+ kickstore = NULL;
+ }
+ protect_roms (true);
+}
+
+static bool is_alg_rom(const TCHAR *name)
+{
+ struct romdata *rd = getromdatabypath(name);
+ if (!rd)
+ return false;
+ return (rd->type & ROMTYPE_ALG) != 0;
+}
+
+static void descramble_alg(uae_u8 *data, int size)
+{
+ uae_u8 *tbuf = xmalloc(uae_u8, size);
+ memcpy(tbuf, data, size);
+ for (int mode = 0; mode < 3; mode++) {
+ if ((data[8] == 0x4a && data[9] == 0xfc))
+ break;
+ for (int s = 0; s < size; s++) {
+ int d = s;
+ if (mode == 0) {
+ if (s & 0x2000)
+ d ^= 0x1000;
+ if (s & 0x8000)
+ d ^= 0x4000;
+ } else if (mode == 1) {
+ if (s & 0x2000)
+ d ^= 0x1000;
+ } else {
+ if ((~s) & 0x2000)
+ d ^= 0x1000;
+ if (s & 0x8000)
+ d ^= 0x4000;
+ d ^= 0x20000;
+ }
+ data[d] = tbuf[s];
+ }
+ }
+ xfree(tbuf);
+}
+
static const uae_char *kickstring = "exec.library";
-static int read_kickstart(struct zfile *f, uae_u8 *mem, int size, int dochecksum, int noalias)
+static int read_kickstart (struct zfile *f, uae_u8 *mem, int size, int dochecksum, int noalias)
{
uae_char buffer[20];
int i, j, oldpos;
int cr = 0, kickdisk = 0;
if (size < 0) {
- zfile_fseek(f, 0, SEEK_END);
- size = zfile_ftell(f) & ~0x3ff;
- zfile_fseek(f, 0, SEEK_SET);
+ zfile_fseek (f, 0, SEEK_END);
+ size = zfile_ftell (f) & ~0x3ff;
+ zfile_fseek (f, 0, SEEK_SET);
}
- oldpos = zfile_ftell(f);
- i = zfile_fread (buffer, 1, sizeof(buffer), f);
+ oldpos = zfile_ftell (f);
+ i = zfile_fread (buffer, 1, sizeof(buffer), f);
if (i < sizeof(buffer))
return 0;
- if (!memcmp(buffer, "KICK", 4)) {
- zfile_fseek(f, 512, SEEK_SET);
+ if (!memcmp (buffer, "KICK", 4)) {
+ zfile_fseek (f, 512, SEEK_SET);
kickdisk = 1;
- }
- else if (memcmp((uae_char*)buffer, "AMIROMTYPE1", 11) != 0) {
- zfile_fseek(f, oldpos, SEEK_SET);
- }
- else {
+ } else if (memcmp ((uae_char*)buffer, "AMIROMTYPE1", 11) != 0) {
+ zfile_fseek (f, oldpos, SEEK_SET);
+ } else {
cloanto_rom = 1;
cr = 1;
}
- memset(mem, 0, size);
+ memset (mem, 0, size);
if (size >= 131072) {
for (i = 0; i < 8; i++) {
mem[size - 16 + i * 2 + 1] = 0x18 + i;
}
mem[size - 20] = size >> 24;
mem[size - 19] = size >> 16;
- mem[size - 18] = size >> 8;
- mem[size - 17] = size >> 0;
+ mem[size - 18] = size >> 8;
+ mem[size - 17] = size >> 0;
}
- i = zfile_fread(mem, 1, size, f);
+ i = zfile_fread (mem, 1, size, f);
if (kickdisk && i > ROM_SIZE_256)
i = ROM_SIZE_256;
if (i < size - 20)
- kickstart_fix_checksum(mem, size);
+ kickstart_fix_checksum (mem, size);
j = 1;
while (j < i)
j <<= 1;
i = j;
if (!noalias && i == size / 2)
- memcpy(mem + size / 2, mem, size / 2);
+ memcpy (mem + size / 2, mem, size / 2);
if (cr) {
- if (!decode_rom(mem, size, cr, i))
+ if (!decode_rom (mem, size, cr, i))
return 0;
}
if (size <= 256)
return size;
+ if (currprefs.cs_a1000ram && i < ROM_SIZE_256) {
+ int off = 0;
+ if (!a1000_bootrom)
+ a1000_bootrom = xcalloc (uae_u8, ROM_SIZE_256);
+ while (off + i < ROM_SIZE_256) {
+ memcpy (a1000_bootrom + off, kickmem_bank.baseaddr, i);
+ off += i;
+ }
+ memset (kickmem_bank.baseaddr, 0, kickmem_bank.allocated_size);
+ a1000_handle_kickstart (1);
+ dochecksum = 0;
+ i = ROM_SIZE_512;
+ }
+
for (j = 0; j < 256 && i >= ROM_SIZE_256; j++) {
- if (!memcmp(mem + j, kickstring, strlen(kickstring) + 1))
+ if (!memcmp (mem + j, kickstring, strlen (kickstring) + 1))
break;
}
if (j == 256 || i < ROM_SIZE_256)
dochecksum = 0;
if (dochecksum)
- kickstart_checksum(mem, size);
+ kickstart_checksum (mem, size);
return i;
}
-static bool load_extendedkickstart(const TCHAR *romextfile, int type)
+static bool load_extendedkickstart (const TCHAR *romextfile, int type)
{
struct zfile *f;
int size, off;
@@ -637,50 +831,63 @@ static bool load_extendedkickstart(const TCHAR *romextfile, int type)
if (_tcslen(romextfile) == 0)
return false;
- f = read_rom_name(romextfile);
- if (!f)
- {
+ f = read_rom_name (romextfile);
+ if (!f) {
notify_user(NUMSG_NOEXTROM);
return false;
}
- zfile_fseek(f, 0, SEEK_END);
- size = zfile_ftell(f);
+ zfile_fseek (f, 0, SEEK_END);
+ size = zfile_ftell (f);
extendedkickmem_bank.reserved_size = ROM_SIZE_512;
off = 0;
- if (type == 0)
- {
- if (currprefs.cs_cd32cd)
- {
+ if (type == 0) {
+ if (currprefs.cs_cd32cd) {
extendedkickmem_type = EXTENDED_ROM_CD32;
- }
- else if (size > 300000)
- {
- extendedkickmem_type = EXTENDED_ROM_CD32;
- }
- }
- else
- {
+ } else if (currprefs.cs_cdtvcd || currprefs.cs_cdtvram) {
+ extendedkickmem_type = EXTENDED_ROM_CDTV;
+ } else if (size > 300000) {
+ uae_u8 data[2] = { 0 };
+ zfile_fseek(f, off, SEEK_SET);
+ zfile_fread(data, sizeof(data), 1, f);
+ if (data[0] == 0x11 && data[1] == 0x11) {
+ if (need_uae_boot_rom(&currprefs) != 0xf00000)
+ extendedkickmem_type = EXTENDED_ROM_CDTV;
+ } else {
+ extendedkickmem_type = EXTENDED_ROM_CD32;
+ }
+ } else if (need_uae_boot_rom (&currprefs) != 0xf00000) {
+ extendedkickmem_type = EXTENDED_ROM_CDTV;
+ }
+ } else {
extendedkickmem_type = type;
}
- if (extendedkickmem_type)
- {
- zfile_fseek(f, off, SEEK_SET);
- switch (extendedkickmem_type)
- {
+ if (extendedkickmem_type) {
+ zfile_fseek (f, off, SEEK_SET);
+ switch (extendedkickmem_type) {
+ case EXTENDED_ROM_CDTV:
+ extendedkickmem_bank.label = _T("rom_f0");
+ mapped_malloc (&extendedkickmem_bank);
+ extendedkickmem_bank.start = 0xf00000;
+ break;
case EXTENDED_ROM_CD32:
extendedkickmem_bank.label = _T("rom_e0");
- mapped_malloc(&extendedkickmem_bank);
+ mapped_malloc (&extendedkickmem_bank);
extendedkickmem_bank.start = 0xe00000;
break;
+ //case EXTENDED_ROM_ALG:
+ // extendedkickmem_bank.label = _T("rom_f0");
+ // mapped_malloc(&extendedkickmem_bank);
+ // extendedkickmem_bank.start = 0xf00000;
+ // break;
}
if (extendedkickmem_bank.baseaddr)
{
- read_kickstart(f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
+ read_kickstart (f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
ret = true;
}
}
- zfile_fclose(f);
+ zfile_fclose (f);
return ret;
}
@@ -732,10 +939,10 @@ static bool load_kickstart_replacement(void)
/* disable incompatible drivers */
static int patch_residents (uae_u8 *kickmemory, int size)
{
- int i, j, patched = 0;
- const uae_char *residents[] = { "NCR scsi.device", NULL };
- // "scsi.device", "carddisk.device", "card.resource" };
- uaecptr base = size == ROM_SIZE_512 ? 0xf80000 : 0xfc0000;
+ int i, j, patched = 0;
+ const uae_char *residents[] = { "NCR scsi.device", NULL };
+ // "scsi.device", "carddisk.device", "card.resource" };
+ uaecptr base = size == ROM_SIZE_512 ? 0xf80000 : 0xfc0000;
for (i = 0; i < size - 100; i++) {
if (kickmemory[i] == 0x4a && kickmemory[i + 1] == 0xfc) {
@@ -765,15 +972,15 @@ static int patch_residents (uae_u8 *kickmemory, int size)
static void patch_kick(void)
{
- int patched = 0;
- patched += patch_residents (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
- if (extendedkickmem_bank.baseaddr) {
- patched += patch_residents (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
- if (patched)
- kickstart_fix_checksum (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
- }
- if (patched)
- kickstart_fix_checksum (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
+ int patched = 0;
+ patched += patch_residents (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
+ if (extendedkickmem_bank.baseaddr) {
+ patched += patch_residents (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
+ if (patched)
+ kickstart_fix_checksum (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
+ }
+ if (patched)
+ kickstart_fix_checksum (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
}
static struct zfile *get_kickstart_filehandle(struct uae_prefs *p)
@@ -784,114 +991,127 @@ static struct zfile *get_kickstart_filehandle(struct uae_prefs *p)
f = read_rom_name(p->romfile);
_tcscpy(tmprom, p->romfile);
_tcscpy(tmprom2, p->romfile);
- if (f == NULL) {
+ if (f == NULL) {
_stprintf(tmprom2, _T("%s%s"), start_path_data, p->romfile);
f = rom_fopen(tmprom2, _T("rb"), ZFD_NORMAL);
- if (f == NULL) {
- _stprintf (tmprom2, _T("%sroms/kick.rom"), start_path_data);
- f = rom_fopen (tmprom2, _T("rb"), ZFD_NORMAL);
- if (f == NULL) {
- _stprintf (tmprom2, _T("%skick.rom"), start_path_data);
- f = rom_fopen(tmprom2, _T("rb"), ZFD_NORMAL);
+ if (f == NULL) {
+ _stprintf(tmprom2, _T("%sroms/kick.rom"), start_path_data);
+ f = rom_fopen(tmprom2, _T("rb"), ZFD_NORMAL);
+ if (f == NULL) {
+ _stprintf(tmprom2, _T("%skick.rom"), start_path_data);
+ f = rom_fopen(tmprom2, _T("rb"), ZFD_NORMAL);
if (f == NULL) {
f = read_rom_name_guess (tmprom, tmprom2);
+ }
}
}
- }
}
if (f) {
- _tcscpy (p->romfile, tmprom2);
- }
+ _tcscpy(p->romfile, tmprom2);
+ }
return f;
}
-static int load_kickstart(void)
+extern struct zfile *read_executable_rom(struct zfile*, int size, int blocks);
+static const uae_u8 romend[20] = {
+ 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f
+};
+
+static int load_kickstart (void)
{
TCHAR tmprom[MAX_DPATH];
cloanto_rom = 0;
- if (!_tcscmp(currprefs.romfile, _T(":AROS")))
- {
+ if (!_tcscmp(currprefs.romfile, _T(":AROS"))) {
return load_kickstart_replacement();
}
_tcscpy(tmprom, currprefs.romfile);
struct zfile *f = get_kickstart_filehandle(&currprefs);
- addkeydir(currprefs.romfile);
+ addkeydir (currprefs.romfile);
if (f == NULL) /* still no luck */
goto err;
- if (f != NULL)
- {
+ if (f != NULL) {
int filesize, size, maxsize;
int kspos = ROM_SIZE_512;
int extpos = 0;
+ bool singlebigrom = false;
+
+ uae_u8 tmp[8] = { 0 };
+ zfile_fread(tmp, sizeof tmp, 1, f);
maxsize = ROM_SIZE_512;
- zfile_fseek(f, 0, SEEK_END);
- filesize = zfile_ftell(f);
- zfile_fseek(f, 0, SEEK_SET);
- if (filesize == 1760 * 512)
- {
- filesize = ROM_SIZE_256;
- maxsize = ROM_SIZE_256;
- }
- if (filesize == ROM_SIZE_512 + 8)
- {
- /* GVP 0xf0 kickstart */
- zfile_fseek(f, 8, SEEK_SET);
- }
- if (filesize >= ROM_SIZE_512 * 2)
- {
- struct romdata *rd = getromdatabyzfile(f);
- zfile_fseek(f, kspos, SEEK_SET);
- }
- if (filesize >= ROM_SIZE_512 * 4)
- {
- kspos = ROM_SIZE_512 * 3;
- extpos = 0;
- zfile_fseek(f, kspos, SEEK_SET);
- }
- size = read_kickstart(f, kickmem_bank.baseaddr, maxsize, 1, 0);
- if (size == 0)
- goto err;
- kickmem_bank.mask = size - 1;
- kickmem_bank.reserved_size = size;
- if (filesize >= ROM_SIZE_512 * 2 && !extendedkickmem_type)
- {
- extendedkickmem_bank.reserved_size = ROM_SIZE_512;
- extendedkickmem_type = EXTENDED_ROM_KS;
- extendedkickmem_bank.label = _T("rom_e0");
- extendedkickmem_bank.start = 0xe00000;
- mapped_malloc(&extendedkickmem_bank);
- zfile_fseek(f, extpos, SEEK_SET);
- read_kickstart(f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
- extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
- }
- if (filesize > ROM_SIZE_512 * 2)
- {
- extendedkickmem2_bank.reserved_size = ROM_SIZE_512 * 2;
- mapped_malloc(&extendedkickmem2_bank);
- zfile_fseek(f, extpos + ROM_SIZE_512, SEEK_SET);
- read_kickstart(f, extendedkickmem2_bank.baseaddr, ROM_SIZE_512, 0, 1);
- zfile_fseek(f, extpos + ROM_SIZE_512 * 2, SEEK_SET);
- read_kickstart(f, extendedkickmem2_bank.baseaddr + ROM_SIZE_512, ROM_SIZE_512, 0, 1);
- extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
- extendedkickmem2_bank.start = 0xa80000;
+
+ if (!singlebigrom) {
+ zfile_fseek(f, 0, SEEK_END);
+ filesize = zfile_ftell(f);
+ zfile_fseek(f, 0, SEEK_SET);
+ if (!singlebigrom) {
+ if (filesize == 1760 * 512) {
+ filesize = ROM_SIZE_256;
+ maxsize = ROM_SIZE_256;
+ }
+ if (filesize == ROM_SIZE_512 + 8) {
+ /* GVP 0xf0 kickstart */
+ zfile_fseek(f, 8, SEEK_SET);
+ }
+ if (filesize >= ROM_SIZE_512 * 2) {
+ struct romdata *rd = getromdatabyzfile(f);
+ zfile_fseek(f, kspos, SEEK_SET);
+ }
+ if (filesize >= ROM_SIZE_512 * 4) {
+ kspos = ROM_SIZE_512 * 3;
+ extpos = 0;
+ zfile_fseek(f, kspos, SEEK_SET);
+ }
+ }
+ size = read_kickstart(f, kickmem_bank.baseaddr, maxsize, 1, 0);
+ if (size == 0)
+ goto err;
+ kickmem_bank.mask = size - 1;
+ kickmem_bank.reserved_size = size;
+ if (filesize >= ROM_SIZE_512 * 2 && !extendedkickmem_type) {
+ extendedkickmem_bank.reserved_size = ROM_SIZE_512;
+ if (currprefs.cs_cdtvcd || currprefs.cs_cdtvram) {
+ extendedkickmem_type = EXTENDED_ROM_CDTV;
+ extendedkickmem_bank.reserved_size *= 2;
+ extendedkickmem_bank.label = _T("rom_f0");
+ extendedkickmem_bank.start = 0xf00000;
+ } else {
+ extendedkickmem_type = EXTENDED_ROM_KS;
+ extendedkickmem_bank.label = _T("rom_e0");
+ extendedkickmem_bank.start = 0xe00000;
+ }
+ mapped_malloc(&extendedkickmem_bank);
+ zfile_fseek(f, extpos, SEEK_SET);
+ read_kickstart(f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
+ extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
+ }
+ if (filesize > ROM_SIZE_512 * 2) {
+ extendedkickmem2_bank.reserved_size = ROM_SIZE_512 * 2;
+ mapped_malloc(&extendedkickmem2_bank);
+ zfile_fseek(f, extpos + ROM_SIZE_512, SEEK_SET);
+ read_kickstart(f, extendedkickmem2_bank.baseaddr, ROM_SIZE_512, 0, 1);
+ zfile_fseek(f, extpos + ROM_SIZE_512 * 2, SEEK_SET);
+ read_kickstart(f, extendedkickmem2_bank.baseaddr + ROM_SIZE_512, ROM_SIZE_512, 0, 1);
+ extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
+ extendedkickmem2_bank.start = 0xa80000;
+ }
}
}
kickstart_version = (kickmem_bank.baseaddr[12] << 8) | kickmem_bank.baseaddr[13];
- if (kickstart_version == 0xffff)
- {
+ if (kickstart_version == 0xffff) {
// 1.0-1.1 and older
kickstart_version = (kickmem_bank.baseaddr[16] << 8) | kickmem_bank.baseaddr[17];
if (kickstart_version > 33)
kickstart_version = 0;
}
- zfile_fclose(f);
+ zfile_fclose (f);
return 1;
err:
- _tcscpy(currprefs.romfile, tmprom);
- zfile_fclose(f);
+ _tcscpy (currprefs.romfile, tmprom);
+ zfile_fclose (f);
return 0;
}
@@ -1080,6 +1300,7 @@ static void restore_roms(void)
extendedkickmem2_bank.reserved_size = 0;
extendedkickmem_type = 0;
load_extendedkickstart(currprefs.romextfile, 0);
+ load_extendedkickstart(currprefs.romextfile2, EXTENDED_ROM_CDTV);
kickmem_bank.mask = ROM_SIZE_512 - 1;
if (!load_kickstart())
{
@@ -1169,6 +1390,7 @@ void memory_reset(void)
int bnk, bnk_end;
bool gayleorfatgary;
+ rom_write_enabled = true;
/* Use changed_prefs, as m68k_reset is called later. */
last_address_space_24 = changed_prefs.address_space_24;
@@ -1183,6 +1405,8 @@ void memory_reset(void)
currprefs.cs_ksmirror_e0 = changed_prefs.cs_ksmirror_e0;
currprefs.cs_ksmirror_a8 = changed_prefs.cs_ksmirror_a8;
currprefs.cs_ciaoverlay = changed_prefs.cs_ciaoverlay;
+ currprefs.cs_cdtvram = changed_prefs.cs_cdtvram;
+ currprefs.cs_a1000ram = changed_prefs.cs_a1000ram;
currprefs.cs_ide = changed_prefs.cs_ide;
currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev;
currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev;
@@ -1212,20 +1436,21 @@ void memory_reset(void)
bnk = 0x20 + (currprefs.fastmem[0].size >> 16);
bnk_end = currprefs.cs_cd32cd ? 0xBE : (gayleorfatgary ? 0xBF : 0xA0);
map_banks(&dummy_bank, bnk, bnk_end - bnk, 0);
- if (gayleorfatgary) {
+ if (gayleorfatgary) {
// a4000 = custom chips from 0xc0 to 0xd0
if (currprefs.cs_ide == IDE_A4000)
map_banks(&dummy_bank, 0xd0, 8, 0);
else
map_banks(&dummy_bank, 0xc0, 0xd8 - 0xc0, 0);
- } else if (currprefs.cs_cd32cd) {
+ }
+ else if (currprefs.cs_cd32cd) {
// CD32: 0xc0 to 0xd0
map_banks(&dummy_bank, 0xd0, 8, 0);
// strange 64k custom mirror
map_banks(&custom_bank, 0xb9, 1, 0);
}
- if (bogomem_bank.baseaddr) {
+ if (bogomem_bank.baseaddr) {
int t = currprefs.bogomem_size >> 16;
if (t > 0x1C)
t = 0x1C;
@@ -1249,7 +1474,7 @@ void memory_reset(void)
}
if (currprefs.cs_rtc == 3) // A2000 clock
map_banks(&clock_bank, 0xD8, 4, 0);
- if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 2)
+ if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 2 || currprefs.cs_cdtvram)
map_banks(&clock_bank, 0xDC, 1, 0);
else if (currprefs.cs_ksmirror_a8 || currprefs.cs_ide > 0 || currprefs.cs_pcmcia)
map_banks(&clock_bank, 0xDC, 1, 0); /* none clock */
@@ -1267,7 +1492,7 @@ void memory_reset(void)
map_banks(&a3000hmem_bank, a3000hmem_bank.start >> 16, a3000hmem_bank.allocated_size >> 16, 0);
map_banks_set(&kickmem_bank, 0xF8, 8, 0);
/* map beta Kickstarts at 0x200000/0xC00000/0xF00000 */
- if (kickmem_bank.baseaddr[0] == 0x11 && kickmem_bank.baseaddr[2] == 0x4e && kickmem_bank.baseaddr[3] == 0xf9 && kickmem_bank.baseaddr[4] == 0x00) {
+ if (kickmem_bank.baseaddr[0] == 0x11 && kickmem_bank.baseaddr[2] == 0x4e && kickmem_bank.baseaddr[3] == 0xf9 && kickmem_bank.baseaddr[4] == 0x00) {
uae_u32 addr = kickmem_bank.baseaddr[5];
if (addr == 0x20 && currprefs.chipmem_size <= 0x200000 && currprefs.fastmem[0].size == 0)
map_banks_set(&kickmem_bank, addr, 8, 0);
@@ -1284,10 +1509,15 @@ void memory_reset(void)
/* Map the chipmem into all of the lower 8MB */
map_overlay(1);
- switch (extendedkickmem_type) {
+ switch (extendedkickmem_type) {
case EXTENDED_ROM_KS:
map_banks_set(&extendedkickmem_bank, 0xE0, 8, 0);
break;
+#ifdef CDTV
+ case EXTENDED_ROM_CDTV:
+ map_banks_set(&extendedkickmem_bank, 0xF0, extendedkickmem_bank.allocated_size == 2 * ROM_SIZE_512 ? 16 : 8, 0);
+ break;
+#endif
#ifdef CD32
case EXTENDED_ROM_CD32:
map_banks_set(&extendedkickmem_bank, 0xE0, 8, 0);
@@ -1306,9 +1536,10 @@ void memory_reset(void)
if (currprefs.cs_ksmirror_a8) {
if (extendedkickmem2_bank.allocated_size) {
map_banks_set(&extendedkickmem2_bank, extendedkickmem2_bank.start >> 16, extendedkickmem2_bank.allocated_size >> 16, 0);
- } else {
- struct romdata *rd = getromdatabypath(currprefs.cartfile);
- if (!rd || rd->id != 63) {
+ }
+ else {
+ struct romdata* rd = getromdatabypath(currprefs.cartfile);
+ if (!rd || rd->id != 63) {
if (extendedkickmem_type == EXTENDED_ROM_CD32 || extendedkickmem_type == EXTENDED_ROM_KS)
map_banks(&extendedkickmem_bank, 0xb0, 8, 0);
else
@@ -1316,7 +1547,8 @@ void memory_reset(void)
map_banks(&kickmem_bank, 0xa8, 8, 0);
}
}
- } else if (extendedkickmem2_bank.allocated_size && extendedkickmem2_bank.baseaddr) {
+ }
+ else if (extendedkickmem2_bank.allocated_size && extendedkickmem2_bank.baseaddr) {
map_banks_set(&extendedkickmem2_bank, extendedkickmem2_bank.start >> 16, extendedkickmem2_bank.allocated_size >> 16, 0);
}
@@ -1426,7 +1658,7 @@ void map_banks_cond(addrbank *bank, int start, int size, int realsize)
map_banks(bank, start, size, realsize);
}
-static void map_banks2 (addrbank *bank, int start, int size, int realsize)
+static void map_banks2(addrbank* bank, int start, int size, int realsize)
{
int bnr;
unsigned long int hioffs = 0, endhioffs = 0x100;
@@ -1437,14 +1669,14 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize)
if (!realsize)
realsize = size << 16;
- if ((size << 16) < realsize) {
+ if ((size << 16) < realsize) {
write_log(_T("Broken mapping, size=%x, realsize=%x\nStart is %x\n"),
- size, realsize, start);
+ size, realsize, start);
}
#ifndef ADDRESS_SPACE_24BIT
- if (start >= 0x100) {
- for (bnr = start; bnr < start + size; bnr++) {
+ if (start >= 0x100) {
+ for (bnr = start; bnr < start + size; bnr++) {
mem_banks[bnr] = bank;
}
return;
@@ -1455,14 +1687,14 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize)
#ifdef ADDRESS_SPACE_24BIT
endhioffs = 0x100;
#endif
- for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) {
- for (bnr = start; bnr < start + size; bnr++) {
+ for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) {
+ for (bnr = start; bnr < start + size; bnr++) {
mem_banks[bnr + hioffs] = bank;
}
}
}
-void map_banks(addrbank *bank, int start, int size, int realsize)
+void map_banks (addrbank *bank, int start, int size, int realsize)
{
if (start == 0xffffffff)
return;
@@ -1541,14 +1773,14 @@ void map_banks_z2(addrbank *bank, int start, int size)
{
if (!validate_banks_z2(bank, start, size))
return;
- map_banks(bank, start, size, 0);
+ map_banks (bank, start, size, 0);
}
#ifdef SAVESTATE
/* memory save/restore code */
-uae_u8 *save_bootrom(int *len)
+uae_u8 *save_bootrom (int *len)
{
if (!uae_boot_rom_type)
return 0;
@@ -1556,13 +1788,13 @@ uae_u8 *save_bootrom(int *len)
return rtarea_bank.baseaddr;
}
-uae_u8 *save_cram(int *len)
+uae_u8 *save_cram (int *len)
{
*len = chipmem_bank.allocated_size;
return chipmem_bank.baseaddr;
}
-uae_u8 *save_bram(int *len)
+uae_u8 *save_bram (int *len)
{
*len = bogomem_bank.allocated_size;
return bogomem_bank.baseaddr;
@@ -1574,100 +1806,100 @@ uae_u8 *save_a3000lram(int *len)
return a3000lmem_bank.baseaddr;
}
-uae_u8 *save_a3000hram(int *len)
+uae_u8 *save_a3000hram (int *len)
{
*len = a3000hmem_bank.allocated_size;
return a3000hmem_bank.baseaddr;
}
-void restore_bootrom(int len, size_t filepos)
+void restore_bootrom (int len, size_t filepos)
{
bootrom_filepos = filepos;
}
-void restore_cram(int len, size_t filepos)
+void restore_cram (int len, size_t filepos)
{
chip_filepos = filepos;
changed_prefs.chipmem_size = len;
}
-void restore_bram(int len, size_t filepos)
+void restore_bram (int len, size_t filepos)
{
bogo_filepos = filepos;
changed_prefs.bogomem_size = len;
}
-void restore_a3000lram(int len, size_t filepos)
+void restore_a3000lram (int len, size_t filepos)
{
a3000lmem_filepos = filepos;
changed_prefs.mbresmem_low_size = len;
}
-void restore_a3000hram(int len, size_t filepos)
+void restore_a3000hram (int len, size_t filepos)
{
a3000hmem_filepos = filepos;
changed_prefs.mbresmem_high_size = len;
}
-uae_u8 *restore_rom(uae_u8 *src)
+uae_u8 *restore_rom (uae_u8 *src)
{
uae_u32 crc32, mem_start, mem_size, mem_type, version;
TCHAR *s, *romn;
int i, crcdet;
- struct romlist *rl = romlist_getit();
+ struct romlist *rl = romlist_getit ();
- mem_start = restore_u32();
- mem_size = restore_u32();
- mem_type = restore_u32();
- version = restore_u32();
- crc32 = restore_u32();
- romn = restore_string();
+ mem_start = restore_u32 ();
+ mem_size = restore_u32 ();
+ mem_type = restore_u32 ();
+ version = restore_u32 ();
+ crc32 = restore_u32 ();
+ romn = restore_string ();
crcdet = 0;
- for (i = 0; i < romlist_count (); i++) {
- if (rl[i].rd->crc32 == crc32 && crc32) {
- if (zfile_exists (rl[i].path)) {
+ for (i = 0; i < romlist_count (); i++) {
+ if (rl[i].rd->crc32 == crc32 && crc32) {
+ if (zfile_exists (rl[i].path)) {
switch (mem_type)
{
case 0:
- _tcsncpy(changed_prefs.romfile, rl[i].path, 255);
+ _tcsncpy (changed_prefs.romfile, rl[i].path, 255);
break;
case 1:
- _tcsncpy(changed_prefs.romextfile, rl[i].path, 255);
+ _tcsncpy (changed_prefs.romextfile, rl[i].path, 255);
break;
}
- write_log(_T("ROM '%s' = '%s'\n"), romn, rl[i].path);
+ write_log (_T("ROM '%s' = '%s'\n"), romn, rl[i].path);
crcdet = 1;
- } else {
- write_log(_T("ROM '%s' = '%s' invalid rom scanner path!"), romn, rl[i].path);
+ } else {
+ write_log (_T("ROM '%s' = '%s' invalid rom scanner path!"), romn, rl[i].path);
}
break;
}
}
- s = restore_string();
- if (!crcdet) {
- if(zfile_exists (s)) {
+ s = restore_string ();
+ if (!crcdet) {
+ if (zfile_exists (s)) {
switch (mem_type)
{
case 0:
- _tcsncpy(changed_prefs.romfile, s, 255);
+ _tcsncpy (changed_prefs.romfile, s, 255);
break;
case 1:
- _tcsncpy(changed_prefs.romextfile, s, 255);
+ _tcsncpy (changed_prefs.romextfile, s, 255);
break;
}
- write_log(_T("ROM detected (path) as '%s'\n"), s);
+ write_log (_T("ROM detected (path) as '%s'\n"), s);
crcdet = 1;
}
}
- xfree(s);
+ xfree (s);
if (!crcdet)
- write_log(_T("WARNING: ROM '%s' %d.%d (CRC32=%08x %08x-%08x) not found!\n"),
- romn, version >> 16, version & 0xffff, crc32, mem_start, mem_start + mem_size - 1);
- xfree(romn);
+ write_log (_T("WARNING: ROM '%s' %d.%d (CRC32=%08x %08x-%08x) not found!\n"),
+ romn, version >> 16, version & 0xffff, crc32, mem_start, mem_start + mem_size - 1);
+ xfree (romn);
return src;
}
-uae_u8 *save_rom(int first, int *len, uae_u8 *dstptr)
+uae_u8 *save_rom (int first, int *len, uae_u8 *dstptr)
{
static int count;
uae_u8 *dst, *dstbak;
@@ -1682,26 +1914,26 @@ uae_u8 *save_rom(int first, int *len, uae_u8 *dstptr)
saverom = 0;
if (first)
count = 0;
- for (;;) {
+ for (;;) {
mem_type = count;
mem_size = 0;
- switch (count) {
+ switch (count) {
case 0: /* Kickstart ROM */
mem_start = 0xf80000;
mem_real_start = kickmem_bank.baseaddr;
mem_size = kickmem_bank.allocated_size;
path = currprefs.romfile;
/* 256KB or 512KB ROM? */
- for (i = 0; i < mem_size / 2 - 4; i++) {
- if (get_long (i + mem_start) != get_long (i + mem_start + mem_size / 2))
+ for (i = 0; i < mem_size / 2 - 4; i++) {
+ if (get_long(i + mem_start) != get_long(i + mem_start + mem_size / 2))
break;
}
- if (i == mem_size / 2 - 4) {
+ if (i == mem_size / 2 - 4) {
mem_size /= 2;
mem_start += ROM_SIZE_256;
}
- version = get_long (mem_start + 12); /* version+revision */
- _stprintf (tmpname, _T("Kickstart %d.%d"), get_word (mem_start + 12), get_word (mem_start + 14));
+ version = get_long(mem_start + 12); /* version+revision */
+ _stprintf (tmpname, _T("Kickstart %d.%d"), get_word(mem_start + 12), get_word(mem_start + 14));
break;
case 1: /* Extended ROM */
if (!extendedkickmem_type)
@@ -1710,10 +1942,10 @@ uae_u8 *save_rom(int first, int *len, uae_u8 *dstptr)
mem_real_start = extendedkickmem_bank.baseaddr;
mem_size = extendedkickmem_bank.allocated_size;
path = currprefs.romextfile;
- version = get_long (mem_start + 12); /* version+revision */
+ version = get_long(mem_start + 12); /* version+revision */
if (version == 0xffffffff)
- version = get_long (mem_start + 16);
- _stprintf(tmpname, _T("Extended"));
+ version = get_long(mem_start + 16);
+ _stprintf (tmpname, _T("Extended"));
break;
default:
return 0;
@@ -1725,17 +1957,17 @@ uae_u8 *save_rom(int first, int *len, uae_u8 *dstptr)
if (dstptr)
dstbak = dst = dstptr;
else
- dstbak = dst = xmalloc(uae_u8, 4 + 4 + 4 + 4 + 4 + 256 + 256 + mem_size);
- save_u32(mem_start);
- save_u32(mem_size);
- save_u32(mem_type);
- save_u32(version);
- save_u32(get_crc32(mem_real_start, mem_size));
- save_string(tmpname);
- save_string(path);
- if (saverom) {
+ dstbak = dst = xmalloc (uae_u8, 4 + 4 + 4 + 4 + 4 + 256 + 256 + mem_size);
+ save_u32 (mem_start);
+ save_u32 (mem_size);
+ save_u32 (mem_type);
+ save_u32 (version);
+ save_u32 (get_crc32 (mem_real_start, mem_size));
+ save_string (tmpname);
+ save_string (path);
+ if (saverom) {
for (i = 0; i < mem_size; i++)
- *dst++ = get_byte (mem_start + i);
+ *dst++ = get_byte(mem_start + i);
}
*len = dst - dstbak;
return dstbak;
@@ -1747,15 +1979,15 @@ uae_u8 *save_rom(int first, int *len, uae_u8 *dstptr)
void memcpyha_safe(uaecptr dst, const uae_u8 *src, int size)
{
- if (!addr_valid(_T("memcpyha"), dst, size))
+ if (!addr_valid (_T("memcpyha"), dst, size))
return;
while (size--)
- put_byte(dst++, *src++);
+ put_byte (dst++, *src++);
}
void memcpyha(uaecptr dst, const uae_u8 *src, int size)
{
while (size--)
- put_byte(dst++, *src++);
+ put_byte (dst++, *src++);
}
void memcpyah_safe(uae_u8 *dst, uaecptr src, int size)
{
@@ -1773,11 +2005,11 @@ uaecptr strcpyha_safe(uaecptr dst, const uae_char *src)
{
uaecptr res = dst;
uae_u8 b;
- do {
- if (!addr_valid(_T("_tcscpyha"), dst, 1))
+ do {
+ if (!addr_valid (_T("_tcscpyha"), dst, 1))
return res;
b = *src++;
- put_byte(dst++, b);
+ put_byte (dst++, b);
} while (b);
return res;
}
diff --git a/src/osdep/amiberry.cpp b/src/osdep/amiberry.cpp
index 7c460be3..b0a79139 100644
--- a/src/osdep/amiberry.cpp
+++ b/src/osdep/amiberry.cpp
@@ -298,6 +298,14 @@ void fix_apmodes(struct uae_prefs* p)
void target_fixup_options(struct uae_prefs* p)
{
+ // If we have a CD inserted, but not emulating a CDTV or CD32, enable SCSI
+ if (p->cdslots[0].inuse
+ && (!p->cs_cd32cd && !p->cs_cd32nvram)
+ && (!p->cs_cdtvcd && !p->cs_cdtvram))
+ {
+ p->scsi = 1;
+ }
+
p->rtgboards[0].rtgmem_type = GFXBOARD_UAE_Z3;
if (z3_base_adr == Z3BASE_REAL)
diff --git a/src/osdep/sysconfig.h b/src/osdep/sysconfig.h
index 9af7cc03..eddd973a 100644
--- a/src/osdep/sysconfig.h
+++ b/src/osdep/sysconfig.h
@@ -31,12 +31,12 @@
#ifndef ANDROID
#define CD32 /* CD32 emulation */
#endif
-/* #define CDTV */ /* CDTV emulation */
+#define CDTV /* CDTV emulation */
/* #define PARALLEL_PORT */ /* parallel port emulation */
/* #define PARALLEL_DIRECT */ /* direct parallel port emulation */
/* #define SERIAL_PORT */ /* serial port emulation */
/* #define SERIAL_ENET */ /* serial port UDP transport */
-/* #define SCSIEMU */ /* uaescsi.device emulation */
+#define SCSIEMU /* uaescsi.device emulation */
/* #define UAESERIAL */ /* uaeserial.device emulation */
#define FPUEMU /* FPU emulation */
/* #define FPU_UAE */
diff --git a/src/osdep/target.h b/src/osdep/target.h
index ace4e0a2..db751788 100644
--- a/src/osdep/target.h
+++ b/src/osdep/target.h
@@ -22,8 +22,8 @@
#define GETBDM(x) (((x) - (((x) / 10000) * 10000)) / 100)
#define GETBDD(x) ((x) % 100)
-#define AMIBERRYVERSION _T("Amiberry v3.2 beta (2020-06-16)")
-#define AMIBERRYDATE MAKEBD(2020, 6, 16)
+#define AMIBERRYVERSION _T("Amiberry v3.2 beta (2020-06-17)")
+#define AMIBERRYDATE MAKEBD(2020, 6, 17)
extern std::string get_version_string();
diff --git a/src/rommgr.cpp b/src/rommgr.cpp
index 6938dd9d..ee4365bb 100644
--- a/src/rommgr.cpp
+++ b/src/rommgr.cpp
@@ -5,9 +5,7 @@
*
*/
-#include
-#include
-
+#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
@@ -34,28 +32,26 @@ int romlist_count (void)
return romlist_cnt;
}
-TCHAR *romlist_get(const struct romdata *rd)
+TCHAR *romlist_get (const struct romdata *rd)
{
int i;
if (!rd)
return 0;
- for (i = 0; i < romlist_cnt; i++)
- {
+ for (i = 0; i < romlist_cnt; i++) {
if (rl[i].rd->id == rd->id)
return rl[i].path;
}
return 0;
}
-static struct romlist *romlist_getrl(const struct romdata *rd)
+static struct romlist *romlist_getrl (const struct romdata *rd)
{
int i;
if (!rd)
return 0;
- for (i = 0; i < romlist_cnt; i++)
- {
+ for (i = 0; i < romlist_cnt; i++) {
if (rl[i].rd == rd)
return &rl[i];
}
@@ -63,33 +59,31 @@ static struct romlist *romlist_getrl(const struct romdata *rd)
}
static void romlist_cleanup (void);
-void romlist_add(const TCHAR *path, struct romdata *rd)
+void romlist_add (const TCHAR *path, struct romdata *rd)
{
struct romlist *rl2;
- if (path == NULL || rd == NULL)
- {
- romlist_cleanup();
+ if (path == NULL || rd == NULL) {
+ romlist_cleanup ();
return;
}
romlist_cnt++;
- rl = xrealloc(struct romlist, rl, romlist_cnt);
+ rl = xrealloc (struct romlist, rl, romlist_cnt);
rl2 = rl + romlist_cnt - 1;
- rl2->path = my_strdup(path);
+ rl2->path = my_strdup (path);
rl2->rd = rd;
- struct romdata *rd2 = getromdatabyid(rd->id);
+ struct romdata *rd2 = getromdatabyid (rd->id);
if (rd2 != rd && rd2) // replace "X" with parent name
rd->name = rd2->name;
}
-struct romdata *getromdatabypath(const TCHAR *path)
+
+struct romdata *getromdatabypath (const TCHAR *path)
{
int i;
- for (i = 0; i < romlist_cnt; i++)
- {
+ for (i = 0; i < romlist_cnt; i++) {
struct romdata *rd = rl[i].rd;
- if (rd->configname && path[0] == ':')
- {
+ if (rd->configname && path[0] == ':') {
if (!_tcscmp(path + 1, rd->configname))
return rd;
}
@@ -834,7 +828,7 @@ static struct romdata roms[] = {
ALTROMPN(198, 1, 1, 65536, ROMTYPE_EVEN | ROMTYPE_8BIT, NULL, 0xf59cfc4a, 0x9fadf7f1,0xe23d6b4e,0x828bf2b3,0xde919d08,0x7c690a3f)
ALTROMPN(198, 1, 2, 65536, ROMTYPE_ODD | ROMTYPE_8BIT, NULL, 0x938b25cb, 0xd0114bbc,0x588dcfce,0x6a469013,0xd0e35afb,0x93e38af5)
- { NULL }
+ { NULL }
};
@@ -853,75 +847,75 @@ void dumpromlist(void)
void romlist_clear (void)
{
- int i;
- int mask = 0;
- struct romdata *parent;
+ int i;
+ int mask = 0;
+ struct romdata *parent;
const TCHAR *pn;
- xfree (rl);
- rl = 0;
- romlist_cnt = 0;
- parent = 0;
- pn = NULL;
- for (i = 0; roms[i].name; i++) {
- struct romdata *rd = &roms[i];
- if (rd->group == 0) {
- parent = rd;
- mask = rd->type;
- pn = parent->partnumber;
- } else {
- rd->type &= ~ROMTYPE_MASK;
- rd->type |= mask & ROMTYPE_MASK;
- if (rd->partnumber && !pn) {
- TCHAR *newpn;
- if (parent->partnumber == NULL)
+ xfree (rl);
+ rl = 0;
+ romlist_cnt = 0;
+ parent = 0;
+ pn = NULL;
+ for (i = 0; roms[i].name; i++) {
+ struct romdata *rd = &roms[i];
+ if (rd->group == 0) {
+ parent = rd;
+ mask = rd->type;
+ pn = parent->partnumber;
+ } else {
+ rd->type &= ~ROMTYPE_MASK;
+ rd->type |= mask & ROMTYPE_MASK;
+ if (rd->partnumber && !pn) {
+ TCHAR *newpn;
+ if (parent->partnumber == NULL)
parent->partnumber = my_strdup (_T(""));
- newpn = xcalloc (TCHAR, _tcslen (parent->partnumber) + 1 + _tcslen (rd->partnumber) + 1);
- if (_tcslen (parent->partnumber) > 0) {
- _tcscpy (newpn, parent->partnumber);
+ newpn = xcalloc (TCHAR, _tcslen (parent->partnumber) + 1 + _tcslen (rd->partnumber) + 1);
+ if (_tcslen (parent->partnumber) > 0) {
+ _tcscpy (newpn, parent->partnumber);
_tcscat (newpn, _T("/"));
- }
- _tcscat (newpn, rd->partnumber);
+ }
+ _tcscat (newpn, rd->partnumber);
xfree ((char *) parent->partnumber);
- parent->partnumber = newpn;
- }
- }
- }
+ parent->partnumber = newpn;
+ }
+ }
+ }
}
/* remove rom entries that need 2 or more roms but not everything required is present */
static void romlist_cleanup (void)
{
- int i = 0;
- while (roms[i].name) {
- struct romdata *rd = &roms[i];
- int grp = rd->group >> 16;
- int ok = 1;
- int j = i;
- int k = i;
- while (rd->name && (rd->group >> 16) == grp && grp > 0) {
- struct romlist *rl = romlist_getrl (rd);
- if (!rl)
- ok = 0;
- rd++;
- j++;
- }
- if (ok == 0) {
- while (i < j) {
- struct romlist *rl2 = romlist_getrl (&roms[i]);
- if (rl2) {
- int cnt = romlist_cnt - (rl2 - rl) - 1;
+ int i = 0;
+ while (roms[i].name) {
+ struct romdata *rd = &roms[i];
+ int grp = rd->group >> 16;
+ int ok = 1;
+ int j = i;
+ int k = i;
+ while (rd->name && (rd->group >> 16) == grp && grp > 0) {
+ struct romlist *rl = romlist_getrl (rd);
+ if (!rl)
+ ok = 0;
+ rd++;
+ j++;
+ }
+ if (ok == 0) {
+ while (i < j) {
+ struct romlist *rl2 = romlist_getrl (&roms[i]);
+ if (rl2) {
+ int cnt = romlist_cnt - (rl2 - rl) - 1;
write_log (_T("%s '%s' removed from romlist\n"), roms[k].name, rl2->path);
- xfree (rl2->path);
- if (cnt > 0)
- memmove (rl2, rl2 + 1, cnt * sizeof (struct romlist));
- romlist_cnt--;
- }
- i++;
- }
- }
- i++;
- }
+ xfree (rl2->path);
+ if (cnt > 0)
+ memmove (rl2, rl2 + 1, cnt * sizeof (struct romlist));
+ romlist_cnt--;
+ }
+ i++;
+ }
+ }
+ i++;
+ }
}
struct romlist **getromlistbyident (int ver, int rev, int subver, int subrev, const TCHAR *model, int romflags, bool all)
@@ -1050,16 +1044,16 @@ struct romlist **getarcadiaroms (void)
static int kickstart_checksum_do (uae_u8 *mem, int size)
{
- uae_u32 cksum = 0, prevck = 0;
- int i;
- for (i = 0; i < size; i+=4) {
- uae_u32 data = mem[i]*65536*256 + mem[i+1]*65536 + mem[i+2]*256 + mem[i+3];
- cksum += data;
- if (cksum < prevck)
- cksum++;
- prevck = cksum;
- }
- return cksum == 0xffffffff;
+ uae_u32 cksum = 0, prevck = 0;
+ int i;
+ for (i = 0; i < size; i += 4) {
+ uae_u32 data = mem[i] * 65536 * 256 + mem[i + 1] * 65536 + mem[i + 2] * 256 + mem[i + 3];
+ cksum += data;
+ if (cksum < prevck)
+ cksum++;
+ prevck = cksum;
+ }
+ return cksum == 0xffffffff;
}
static int kickstart_checksum_more_do (uae_u8 *mem, int size)
@@ -1082,186 +1076,186 @@ static int kickstart_checksum_more_do (uae_u8 *mem, int size)
#define ROM_KEY_NUM 4
struct rom_key {
- uae_u8 *key;
- int size;
+ uae_u8 *key;
+ int size;
};
static struct rom_key keyring[ROM_KEY_NUM];
static void addkey (uae_u8 *key, int size, const TCHAR *name)
{
- int i;
+ int i;
//write_log (_T("addkey(%08x,%d,'%s')\n"), key, size, name);
- if (key == NULL || size == 0) {
- xfree (key);
- return;
- }
- for (i = 0; i < ROM_KEY_NUM; i++) {
- if (keyring[i].key && keyring[i].size == size && !memcmp (keyring[i].key, key, size)) {
- xfree (key);
+ if (key == NULL || size == 0) {
+ xfree (key);
+ return;
+ }
+ for (i = 0; i < ROM_KEY_NUM; i++) {
+ if (keyring[i].key && keyring[i].size == size && !memcmp (keyring[i].key, key, size)) {
+ xfree (key);
//write_log (_T("key already in keyring\n"));
- return;
- }
- }
- for (i = 0; i < ROM_KEY_NUM; i++) {
- if (keyring[i].key == NULL)
- break;
- }
- if (i == ROM_KEY_NUM) {
- xfree (key);
+ return;
+ }
+ }
+ for (i = 0; i < ROM_KEY_NUM; i++) {
+ if (keyring[i].key == NULL)
+ break;
+ }
+ if (i == ROM_KEY_NUM) {
+ xfree (key);
//write_log (_T("keyring full\n"));
- return;
- }
- keyring[i].key = key;
- keyring[i].size = size;
+ return;
+ }
+ keyring[i].key = key;
+ keyring[i].size = size;
}
void addkeyfile (const TCHAR *path)
{
- struct zfile *f;
- int keysize;
- uae_u8 *keybuf;
+ struct zfile *f;
+ int keysize;
+ uae_u8 *keybuf;
f = zfile_fopen (path, _T("rb"), ZFD_NORMAL);
- if (!f)
- return;
- zfile_fseek (f, 0, SEEK_END);
- keysize = zfile_ftell (f);
- if (keysize > 0) {
- zfile_fseek (f, 0, SEEK_SET);
- keybuf = xmalloc (uae_u8, keysize);
- zfile_fread (keybuf, 1, keysize, f);
- addkey (keybuf, keysize, path);
- }
- zfile_fclose (f);
+ if (!f)
+ return;
+ zfile_fseek (f, 0, SEEK_END);
+ keysize = zfile_ftell (f);
+ if (keysize > 0) {
+ zfile_fseek (f, 0, SEEK_SET);
+ keybuf = xmalloc (uae_u8, keysize);
+ zfile_fread (keybuf, 1, keysize, f);
+ addkey (keybuf, keysize, path);
+ }
+ zfile_fclose (f);
}
void addkeydir (const TCHAR *path)
{
- TCHAR tmp[MAX_DPATH];
+ TCHAR tmp[MAX_DPATH];
- _tcscpy (tmp, path);
- if (zfile_exists (tmp)) {
- int i;
- for (i = _tcslen (tmp) - 1; i > 0; i--) {
- if (tmp[i] == '\\' || tmp[i] == '/')
- break;
- }
- tmp[i] = 0;
- }
+ _tcscpy (tmp, path);
+ if (zfile_exists (tmp)) {
+ int i;
+ for (i = _tcslen (tmp) - 1; i > 0; i--) {
+ if (tmp[i] == '\\' || tmp[i] == '/')
+ break;
+ }
+ tmp[i] = 0;
+ }
_tcscat (tmp, _T("/"));
_tcscat (tmp, _T("rom.key"));
- addkeyfile (tmp);
+ addkeyfile (tmp);
}
int get_keyring (void)
{
- int i, num = 0;
- for (i = 0; i < ROM_KEY_NUM; i++) {
- if (keyring[i].key)
- num++;
- }
- return num;
+ int i, num = 0;
+ for (i = 0; i < ROM_KEY_NUM; i++) {
+ if (keyring[i].key)
+ num++;
+ }
+ return num;
}
int load_keyring (struct uae_prefs *p, const TCHAR *path)
{
- uae_u8 *keybuf;
- int keysize;
- TCHAR tmp[MAX_DPATH], *d;
- int keyids[] = { 0, 48, 73, -1 };
- int cnt, i;
+ uae_u8 *keybuf;
+ int keysize;
+ TCHAR tmp[MAX_DPATH], *d;
+ int keyids[] = { 0, 48, 73, -1 };
+ int cnt, i;
- free_keyring();
- keybuf = target_load_keyfile(p, path, &keysize, tmp);
- addkey (keybuf, keysize, tmp);
- for (i = 0; keyids[i] >= 0; i++) {
- struct romdata *rd = getromdatabyid (keyids[i]);
- TCHAR *s;
- if (rd) {
- s = romlist_get (rd);
- if (s)
- addkeyfile (s);
- }
- }
+ free_keyring ();
+ keybuf = target_load_keyfile (p, path, &keysize, tmp);
+ addkey (keybuf, keysize, tmp);
+ for (i = 0; keyids[i] >= 0; i++) {
+ struct romdata *rd = getromdatabyid (keyids[i]);
+ TCHAR *s;
+ if (rd) {
+ s = romlist_get (rd);
+ if (s)
+ addkeyfile (s);
+ }
+ }
- cnt = 0;
- for (;;) {
- keybuf = NULL;
- keysize = 0;
- tmp[0] = 0;
- switch (cnt)
- {
+ cnt = 0;
+ for (;;) {
+ keybuf = NULL;
+ keysize = 0;
+ tmp[0] = 0;
+ switch (cnt)
+ {
case 0:
if (path)
- {
_tcscpy (tmp, path);
- _tcscat (tmp, _T("rom.key"));
- }
break;
case 1:
- if (p) {
- _tcscpy (tmp, p->path_rom.path[0]);
- _tcscat (tmp, _T("rom.key"));
- }
- break;
- case 2:
- _tcscpy (tmp, _T("roms/rom.key"));
- break;
- case 3:
- _tcscpy (tmp, start_path_data);
- _tcscat (tmp, _T("rom.key"));
- break;
- case 4:
- _stprintf (tmp, _T("%s../shared/rom/rom.key"), start_path_data);
- break;
- case 5:
- if (p) {
- for (i = 0; uae_archive_extensions[i]; i++) {
- if (_tcsstr (p->romfile, uae_archive_extensions[i]))
- break;
- }
- if (!uae_archive_extensions[i]) {
- _tcscpy (tmp, p->romfile);
- d = _tcsrchr (tmp, '/');
- if (!d)
- d = _tcsrchr (tmp, '\\');
- if (d)
- _tcscpy (d + 1, _T("rom.key"));
- }
- }
- break;
- case 6:
- return get_keyring ();
- }
- cnt++;
- if (!tmp[0])
- continue;
- addkeyfile (tmp);
- }
+ _tcscat (tmp, _T("rom.key"));
+ break;
+ case 2:
+ if (p) {
+ _tcscpy (tmp, p->path_rom.path[0]);
+ _tcscat (tmp, _T("rom.key"));
+ }
+ break;
+ case 3:
+ _tcscpy (tmp, _T("roms/rom.key"));
+ break;
+ case 4:
+ _tcscpy (tmp, start_path_data);
+ _tcscat (tmp, _T("rom.key"));
+ break;
+ case 5:
+ _stprintf (tmp, _T("%s../shared/rom/rom.key"), start_path_data);
+ break;
+ case 6:
+ if (p) {
+ for (i = 0; uae_archive_extensions[i]; i++) {
+ if (_tcsstr (p->romfile, uae_archive_extensions[i]))
+ break;
+ }
+ if (!uae_archive_extensions[i]) {
+ _tcscpy (tmp, p->romfile);
+ d = _tcsrchr (tmp, '/');
+ if (!d)
+ d = _tcsrchr (tmp, '\\');
+ if (d)
+ _tcscpy (d + 1, _T("rom.key"));
+ }
+ }
+ break;
+ case 7:
+ return get_keyring ();
+ }
+ cnt++;
+ if (!tmp[0])
+ continue;
+ addkeyfile (tmp);
+ }
}
void free_keyring (void)
{
- int i;
- for (i = 0; i < ROM_KEY_NUM; i++)
- xfree (keyring[i].key);
- memset(keyring, 0, sizeof (struct rom_key) * ROM_KEY_NUM);
+ int i;
+ for (i = 0; i < ROM_KEY_NUM; i++)
+ xfree (keyring[i].key);
+ memset (keyring, 0, sizeof (struct rom_key) * ROM_KEY_NUM);
}
struct romdata *getromdatabyname (const TCHAR *name)
{
- TCHAR tmp[MAX_DPATH];
- int i = 0;
- while (roms[i].name) {
- if (!roms[i].group) {
- getromname (&roms[i], tmp);
- if (!_tcscmp (tmp, name) || !_tcscmp (roms[i].name, name))
- return &roms[i];
- }
- i++;
- }
- return 0;
+ TCHAR tmp[MAX_DPATH];
+ int i = 0;
+ while (roms[i].name) {
+ if (!roms[i].group) {
+ getromname (&roms[i], tmp);
+ if (!_tcscmp (tmp, name) || !_tcscmp (roms[i].name, name))
+ return &roms[i];
+ }
+ i++;
+ }
+ return 0;
}
struct romdata *getromdatabytype (int romtype)
@@ -1277,41 +1271,41 @@ struct romdata *getromdatabytype (int romtype)
struct romdata *getromdatabyid (int id)
{
- int i = 0;
- while (roms[i].name) {
- if (id == roms[i].id && roms[i].group == 0)
- return &roms[i];
- i++;
- }
- return 0;
+ int i = 0;
+ while (roms[i].name) {
+ if (id == roms[i].id && roms[i].group == 0)
+ return &roms[i];
+ i++;
+ }
+ return 0;
}
struct romdata *getromdatabyidgroup (int id, int group, int subitem)
{
- int i = 0;
- group = (group << 16) | subitem;
- while (roms[i].name) {
- if (id == roms[i].id && roms[i].group == group)
- return &roms[i];
- i++;
- }
- return 0;
+ int i = 0;
+ group = (group << 16) | subitem;
+ while (roms[i].name) {
+ if (id == roms[i].id && roms[i].group == group)
+ return &roms[i];
+ i++;
+ }
+ return 0;
}
-STATIC_INLINE int notcrc32(uae_u32 crc32)
+STATIC_INLINE int notcrc32 (uae_u32 crc32)
{
- if (crc32 == 0xffffffff || crc32 == 0x00000000)
- return 1;
- return 0;
+ if (crc32 == 0xffffffff || crc32 == 0x00000000)
+ return 1;
+ return 0;
}
struct romdata *getromdatabycrc (uae_u32 crc32, bool allowgroup)
{
- int i = 0;
- while (roms[i].name) {
- if (roms[i].group == 0 && crc32 == roms[i].crc32 && !notcrc32(crc32))
- return &roms[i];
- i++;
+ int i = 0;
+ while (roms[i].name) {
+ if (roms[i].group == 0 && crc32 == roms[i].crc32 && !notcrc32(crc32))
+ return &roms[i];
+ i++;
}
if (allowgroup) {
i = 0;
@@ -1320,8 +1314,8 @@ struct romdata *getromdatabycrc (uae_u32 crc32, bool allowgroup)
return &roms[i];
i++;
}
- }
- return 0;
+ }
+ return 0;
}
struct romdata *getromdatabycrc (uae_u32 crc32)
{
@@ -1330,16 +1324,16 @@ struct romdata *getromdatabycrc (uae_u32 crc32)
static int cmpsha1 (const uae_u8 *s1, const struct romdata *rd)
{
- int i;
+ int i;
- for (i = 0; i < SHA1_SIZE / 4; i++) {
- uae_u32 v1 = (s1[0] << 24) | (s1[1] << 16) | (s1[2] << 8) | (s1[3] << 0);
- uae_u32 v2 = rd->sha1[i];
- if (v1 != v2)
- return -1;
- s1 += 4;
- }
- return 0;
+ for (i = 0; i < SHA1_SIZE / 4; i++) {
+ uae_u32 v1 = (s1[0] << 24) | (s1[1] << 16) | (s1[2] << 8) | (s1[3] << 0);
+ uae_u32 v2 = rd->sha1[i];
+ if (v1 != v2)
+ return -1;
+ s1 += 4;
+ }
+ return 0;
}
struct romdata *getfrombydefaultname(const TCHAR *name, int size)
@@ -1356,163 +1350,163 @@ struct romdata *getfrombydefaultname(const TCHAR *name, int size)
static struct romdata *checkromdata (const uae_u8 *sha1, int size, uae_u32 mask)
{
- int i = 0;
- while (roms[i].name) {
- if (!notcrc32(roms[i].crc32) && roms[i].size >= size) {
- if (roms[i].type & mask) {
- if (!cmpsha1(sha1, &roms[i]))
- return &roms[i];
- }
- }
- i++;
- }
- return NULL;
+ int i = 0;
+ while (roms[i].name) {
+ if (!notcrc32(roms[i].crc32) && roms[i].size >= size) {
+ if (roms[i].type & mask) {
+ if (!cmpsha1 (sha1, &roms[i]))
+ return &roms[i];
+ }
+ }
+ i++;
+ }
+ return NULL;
}
int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size)
{
- int cnt, t, i;
+ int cnt, t, i;
- for (i = ROM_KEY_NUM - 1; i >= 0; i--) {
- uae_u8 sha1[SHA1_SIZE];
- struct romdata *rd;
- int keysize = keyring[i].size;
- uae_u8 *key = keyring[i].key;
- if (!key)
- continue;
- for (t = cnt = 0; cnt < size; cnt++, t = (t + 1) % keysize) {
- mem[cnt] ^= key[t];
- if (real_size == cnt + 1)
- t = keysize - 1;
- }
- if ((mem[2] == 0x4e && mem[3] == 0xf9) || (mem[0] == 0x11 && (mem[1] == 0x11 || mem[1] == 0x14))) {
- cloanto_rom = 1;
- return 1;
- }
- get_sha1 (mem, size, sha1);
- rd = checkromdata (sha1, size, -1);
- if (rd) {
- if (rd->cloanto)
- cloanto_rom = 1;
- return 1;
- }
- if (i == 0)
- break;
- for (t = cnt = 0; cnt < size; cnt++, t = (t + 1) % keysize) {
- mem[cnt] ^= key[t];
- if (real_size == cnt + 1)
- t = keysize - 1;
- }
- }
- return 0;
+ for (i = ROM_KEY_NUM - 1; i >= 0; i--) {
+ uae_u8 sha1[SHA1_SIZE];
+ struct romdata *rd;
+ int keysize = keyring[i].size;
+ uae_u8 *key = keyring[i].key;
+ if (!key)
+ continue;
+ for (t = cnt = 0; cnt < size; cnt++, t = (t + 1) % keysize) {
+ mem[cnt] ^= key[t];
+ if (real_size == cnt + 1)
+ t = keysize - 1;
+ }
+ if ((mem[2] == 0x4e && mem[3] == 0xf9) || (mem[0] == 0x11 && (mem[1] == 0x11 || mem[1] == 0x14))) {
+ cloanto_rom = 1;
+ return 1;
+ }
+ get_sha1 (mem, size, sha1);
+ rd = checkromdata (sha1, size, -1);
+ if (rd) {
+ if (rd->cloanto)
+ cloanto_rom = 1;
+ return 1;
+ }
+ if (i == 0)
+ break;
+ for (t = cnt = 0; cnt < size; cnt++, t = (t + 1) % keysize) {
+ mem[cnt] ^= key[t];
+ if (real_size == cnt + 1)
+ t = keysize - 1;
+ }
+ }
+ return 0;
}
static int decode_rekick_rom_do (uae_u8 *mem, int size, int real_size)
{
- uae_u32 d1 = 0xdeadfeed, d0;
- int i;
+ uae_u32 d1 = 0xdeadfeed, d0;
+ int i;
- for (i = 0; i < size / 8; i++) {
- d0 = ((mem[i * 8 + 0] << 24) | (mem[i * 8 + 1] << 16) | (mem[i * 8 + 2] << 8) | mem[i * 8 + 3]);
- d1 = d1 ^ d0;
- mem[i * 8 + 0] = d1 >> 24;
- mem[i * 8 + 1] = d1 >> 16;
- mem[i * 8 + 2] = d1 >> 8;
- mem[i * 8 + 3] = d1;
- d1 = ((mem[i * 8 + 4] << 24) | (mem[i * 8 + 5] << 16) | (mem[i * 8 + 6] << 8) | mem[i * 8 + 7]);
- d0 = d0 ^ d1;
- mem[i * 8 + 4] = d0 >> 24;
- mem[i * 8 + 5] = d0 >> 16;
- mem[i * 8 + 6] = d0 >> 8;
- mem[i * 8 + 7] = d0;
- }
- return 1;
+ for (i = 0; i < size / 8; i++) {
+ d0 = ((mem[i * 8 + 0] << 24) | (mem[i * 8 + 1] << 16) | (mem[i * 8 + 2] << 8) | mem[i * 8 + 3]);
+ d1 = d1 ^ d0;
+ mem[i * 8 + 0] = d1 >> 24;
+ mem[i * 8 + 1] = d1 >> 16;
+ mem[i * 8 + 2] = d1 >> 8;
+ mem[i * 8 + 3] = d1;
+ d1 = ((mem[i * 8 + 4] << 24) | (mem[i * 8 + 5] << 16) | (mem[i * 8 + 6] << 8) | mem[i * 8 + 7]);
+ d0 = d0 ^ d1;
+ mem[i * 8 + 4] = d0 >> 24;
+ mem[i * 8 + 5] = d0 >> 16;
+ mem[i * 8 + 6] = d0 >> 8;
+ mem[i * 8 + 7] = d0;
+ }
+ return 1;
}
int decode_rom (uae_u8 *mem, int size, int mode, int real_size)
{
- if (mode == 1) {
- if (!decode_cloanto_rom_do (mem, size, real_size)) {
- notify_user (NUMSG_NOROMKEY);
- return 0;
- }
- return 1;
- } else if (mode == 2) {
- decode_rekick_rom_do (mem, size, real_size);
- return 1;
- }
- return 0;
+ if (mode == 1) {
+ if (!decode_cloanto_rom_do (mem, size, real_size)) {
+ notify_user (NUMSG_NOROMKEY);
+ return 0;
+ }
+ return 1;
+ } else if (mode == 2) {
+ decode_rekick_rom_do (mem, size, real_size);
+ return 1;
+ }
+ return 0;
}
struct romdata *getromdatabydata (uae_u8 *rom, int size)
{
- uae_u8 sha1[SHA1_SIZE];
- uae_u8 tmp[4];
- uae_u8 *tmpbuf = NULL;
- struct romdata *ret = NULL;
+ uae_u8 sha1[SHA1_SIZE];
+ uae_u8 tmp[4];
+ uae_u8 *tmpbuf = NULL;
+ struct romdata *ret = NULL;
- if (size > 11 && !memcmp (rom, "AMIROMTYPE1", 11)) {
- uae_u8 *tmpbuf = xmalloc (uae_u8, size);
- int tmpsize = size - 11;
- memcpy (tmpbuf, rom + 11, tmpsize);
- decode_rom (tmpbuf, tmpsize, 1, tmpsize);
- rom = tmpbuf;
- size = tmpsize;
- }
- get_sha1 (rom, size, sha1);
- ret = checkromdata(sha1, size, -1);
- if (!ret) {
- get_sha1 (rom, size / 2, sha1);
- ret = checkromdata (sha1, size / 2, -1);
- if (!ret) {
+ if (size > 11 && !memcmp (rom, "AMIROMTYPE1", 11)) {
+ uae_u8 *tmpbuf = xmalloc (uae_u8, size);
+ int tmpsize = size - 11;
+ memcpy (tmpbuf, rom + 11, tmpsize);
+ decode_rom (tmpbuf, tmpsize, 1, tmpsize);
+ rom = tmpbuf;
+ size = tmpsize;
+ }
+ get_sha1 (rom, size, sha1);
+ ret = checkromdata(sha1, size, -1);
+ if (!ret) {
+ get_sha1 (rom, size / 2, sha1);
+ ret = checkromdata (sha1, size / 2, -1);
+ if (!ret) {
/* ignore AR2/3 IO-port range until we have full dump */
- memcpy (tmp, rom, 4);
- memset (rom, 0, 4);
- get_sha1 (rom, size, sha1);
+ memcpy (tmp, rom, 4);
+ memset (rom, 0, 4);
+ get_sha1 (rom, size, sha1);
ret = checkromdata (sha1, size, ROMTYPE_AR2);
- memcpy (rom, tmp, 4);
- }
+ memcpy (rom, tmp, 4);
+ }
}//9
- xfree (tmpbuf);
- return ret;
+ xfree (tmpbuf);
+ return ret;
}
struct romdata *getromdatabyzfile (struct zfile *f)
{
- int pos, size;
- uae_u8 *p;
- struct romdata *rd;
+ int pos, size;
+ uae_u8 *p;
+ struct romdata *rd;
- pos = zfile_ftell (f);
- zfile_fseek (f, 0, SEEK_END);
- size = zfile_ftell (f);
+ pos = zfile_ftell (f);
+ zfile_fseek (f, 0, SEEK_END);
+ size = zfile_ftell (f);
if (size > 2048 * 1024)
return NULL;
- p = xmalloc (uae_u8, size);
- if (!p)
- return NULL;
- memset (p, 0, size);
- zfile_fseek (f, 0, SEEK_SET);
- zfile_fread (p, 1, size, f);
- zfile_fseek (f, pos, SEEK_SET);
- rd = getromdatabydata (p, size);
- xfree (p);
- return rd;
+ p = xmalloc (uae_u8, size);
+ if (!p)
+ return NULL;
+ memset (p, 0, size);
+ zfile_fseek (f, 0, SEEK_SET);
+ zfile_fread (p, 1, size, f);
+ zfile_fseek (f, pos, SEEK_SET);
+ rd = getromdatabydata (p, size);
+ xfree (p);
+ return rd;
}
void getromname (const struct romdata *rd, TCHAR *name)
{
- name[0] = 0;
- if (!rd)
- return;
- while (rd->group)
- rd--;
- _tcscat (name, rd->name);
- if ((rd->subrev || rd->subver) && rd->subver != rd->ver)
+ name[0] = 0;
+ if (!rd)
+ return;
+ while (rd->group)
+ rd--;
+ _tcscat (name, rd->name);
+ if ((rd->subrev || rd->subver) && rd->subver != rd->ver)
_stprintf (name + _tcslen (name), _T(" rev %d.%d"), rd->subver, rd->subrev);
- if (rd->size > 0)
+ if (rd->size > 0)
_stprintf (name + _tcslen (name), _T(" (%dk)"), (rd->size + 1023) / 1024);
- if (rd->partnumber && _tcslen (rd->partnumber) > 0)
+ if (rd->partnumber && _tcslen (rd->partnumber) > 0)
_stprintf (name + _tcslen (name), _T(" [%s]"), rd->partnumber);
}
@@ -1520,9 +1514,9 @@ static struct romlist *getromlistbyids (const int *ids, const TCHAR *romname);
struct romlist *getromlistbyromdata (const struct romdata *rd)
{
- int ids[2];
-
- ids[0] = rd->id;
+ int ids[2];
+
+ ids[0] = rd->id;
ids[1] = -1;
return getromlistbyids(ids, NULL);
}
@@ -1537,7 +1531,7 @@ static struct romlist *getromlistbyromtype(uae_u32 romtype, const TCHAR *romname
if (rl[j].rd->id == rd->id) {
if (romname) {
if (my_issamepath(rl[j].path, romname))
- return &rl[j];
+ return &rl[j];
} else {
return &rl[j];
}
@@ -1551,8 +1545,8 @@ static struct romlist *getromlistbyromtype(uae_u32 romtype, const TCHAR *romname
static struct romlist *getromlistbyids (const int *ids, const TCHAR *romname)
{
- struct romdata *rd;
- int i, j;
+ struct romdata *rd;
+ int i, j;
i = 0;
if (romname) {
@@ -1569,18 +1563,18 @@ static struct romlist *getromlistbyids (const int *ids, const TCHAR *romname)
i++;
}
}
- i = 0;
- while (ids[i] >= 0) {
- rd = getromdatabyid (ids[i]);
- if (rd) {
- for (j = 0; j < romlist_cnt; j++) {
- if (rl[j].rd->id == rd->id)
- return &rl[j];
- }
- }
- i++;
- }
- return NULL;
+ i = 0;
+ while (ids[i] >= 0) {
+ rd = getromdatabyid (ids[i]);
+ if (rd) {
+ for (j = 0; j < romlist_cnt; j++) {
+ if (rl[j].rd->id == rd->id)
+ return &rl[j];
+ }
+ }
+ i++;
+ }
+ return NULL;
}
struct romdata *getromdatabyids (const int *ids)
@@ -1639,54 +1633,55 @@ void romwarning (const int *ids)
while (ids[i] >= 0) {
struct romdata *rd = getromdatabyid (ids[i]);
if (!(rd->type & ROMTYPE_NONE)) {
- getromname (rd, tmp1);
- _tcscat (tmp2, _T("- "));
- _tcscat (tmp2, tmp1);
- _tcscat (tmp2, _T("\n"));
+ getromname (rd, tmp1);
+ _tcscat (tmp2, _T("- "));
+ _tcscat (tmp2, tmp1);
+ _tcscat (tmp2, _T("\n"));
if (rd->type & (ROMTYPE_SCSI | ROMTYPE_CPUBOARD | ROMTYPE_CD32CART))
- exp++;
+ exp++;
}
i++;
- }
+ }
translate_message (exp ? NUMSG_EXPROMNEED : NUMSG_ROMNEED, tmp3);
gui_message (tmp3, tmp2);
}
+
static void byteswap (uae_u8 *buf, int size)
{
- int i;
- for (i = 0; i < size; i += 2) {
- uae_u8 t = buf[i];
- buf[i] = buf[i + 1];
- buf[i + 1] = t;
- }
+ int i;
+ for (i = 0; i < size; i += 2) {
+ uae_u8 t = buf[i];
+ buf[i] = buf[i + 1];
+ buf[i + 1] = t;
+ }
}
static void wordbyteswap (uae_u8 *buf, int size)
{
- int i;
- for (i = 0; i < size; i += 4) {
- uae_u8 t;
- t = buf[i + 0];
- buf[i + 0] = buf[i + 2];
- buf[i + 2] = t;
- t = buf[i + 1];
- buf[i + 1] = buf[i + 3];
- buf[i + 3] = t;
- }
+ int i;
+ for (i = 0; i < size; i += 4) {
+ uae_u8 t;
+ t = buf[i + 0];
+ buf[i + 0] = buf[i + 2];
+ buf[i + 2] = t;
+ t = buf[i + 1];
+ buf[i + 1] = buf[i + 3];
+ buf[i + 3] = t;
+ }
}
static void mergecd32 (uae_u8 *dst, uae_u8 *src, int size)
{
- int i, k;
- k = 0;
- for (i = 0; i < size / 2; i += 2) {
- int j = i + size / 2;
- dst[k + 1] = src[i + 0];
- dst[k + 0] = src[i + 1];
- dst[k + 3] = src[j + 0];
- dst[k + 2] = src[j + 1];
- k += 4;
- }
+ int i, k;
+ k = 0;
+ for (i = 0; i < size / 2; i += 2) {
+ int j = i + size / 2;
+ dst[k + 1] = src[i + 0];
+ dst[k + 0] = src[i + 1];
+ dst[k + 3] = src[j + 0];
+ dst[k + 2] = src[j + 1];
+ k += 4;
+ }
}
static void descramble (const struct romdata *rd, uae_u8 *data, int size, int odd)
@@ -1699,26 +1694,26 @@ static void descramble (const struct romdata *rd, uae_u8 *data, int size, int od
static int read_rom_file (uae_u8 *buf, const struct romdata *rd)
{
- struct zfile *zf;
- struct romlist *rl = romlist_getrl (rd);
- uae_char tmp[11];
+ struct zfile *zf;
+ struct romlist *rl = romlist_getrl (rd);
+ uae_char tmp[11];
- if (!rl || _tcslen (rl->path) == 0)
- return 0;
+ if (!rl || _tcslen (rl->path) == 0)
+ return 0;
zf = zfile_fopen (rl->path, _T("rb"), ZFD_NORMAL);
- if (!zf)
- return 0;
- addkeydir (rl->path);
- zfile_fread (tmp, sizeof tmp, 1, zf);
- if (!memcmp (tmp, "AMIROMTYPE1", sizeof tmp)) {
- zfile_fread (buf, rd->size, 1, zf);
- decode_cloanto_rom_do (buf, rd->size, rd->size);
- } else {
- memcpy (buf, tmp, sizeof tmp);
- zfile_fread (buf + sizeof tmp, rd->size - sizeof (tmp), 1, zf);
- }
- zfile_fclose (zf);
- return 1;
+ if (!zf)
+ return 0;
+ addkeydir (rl->path);
+ zfile_fread (tmp, sizeof tmp, 1, zf);
+ if (!memcmp (tmp, "AMIROMTYPE1", sizeof tmp)) {
+ zfile_fread (buf, rd->size, 1, zf);
+ decode_cloanto_rom_do (buf, rd->size, rd->size);
+ } else {
+ memcpy (buf, tmp, sizeof tmp);
+ zfile_fread (buf + sizeof tmp, rd->size - sizeof (tmp), 1, zf);
+ }
+ zfile_fclose (zf);
+ return 1;
}
static struct zfile *read_rom (struct romdata *prd)
@@ -1727,45 +1722,45 @@ static struct zfile *read_rom (struct romdata *prd)
struct romdata *rd = prd;
struct romdata *rdpair = NULL;
const TCHAR *name;
- int id = rd->id;
- uae_u32 crc32;
- int size;
- uae_u8 *buf, *buf2;
+ int id = rd->id;
+ uae_u32 crc32;
+ int size;
+ uae_u8 *buf, *buf2;
- /* find parent node */
- for (;;) {
- if (rd2 == &roms[0])
- break;
- if (rd2[-1].id != id)
- break;
- rd2--;
- }
+ /* find parent node */
+ for (;;) {
+ if (rd2 == &roms[0])
+ break;
+ if (rd2[-1].id != id)
+ break;
+ rd2--;
+ }
- size = rd2->size;
- crc32 = rd2->crc32;
- name = rd->name;
- buf = xmalloc (uae_u8, size * 2);
- memset (buf, 0xff, size * 2);
- if (!buf)
- return NULL;
- buf2 = buf + size;
- while (rd->id == id) {
- int i, j, add;
- int ok = 0;
- uae_u32 flags = rd->type;
- int odd = (flags & ROMTYPE_ODD) ? 1 : 0;
+ size = rd2->size;
+ crc32 = rd2->crc32;
+ name = rd->name;
+ buf = xmalloc (uae_u8, size * 2);
+ memset (buf, 0xff, size * 2);
+ if (!buf)
+ return NULL;
+ buf2 = buf + size;
+ while (rd->id == id) {
+ int i, j, add;
+ int ok = 0;
+ uae_u32 flags = rd->type;
+ int odd = (flags & ROMTYPE_ODD) ? 1 : 0;
- add = 0;
- for (i = 0; i < 2; i++) {
- memset (buf, 0, size);
- if (!(flags & (ROMTYPE_EVEN | ROMTYPE_ODD))) {
- read_rom_file (buf, rd);
- if (flags & ROMTYPE_CD32) {
- memcpy (buf2, buf, size);
- mergecd32 (buf, buf2, size);
- }
- add = 1;
- i++;
+ add = 0;
+ for (i = 0; i < 2; i++) {
+ memset (buf, 0, size);
+ if (!(flags & (ROMTYPE_EVEN | ROMTYPE_ODD))) {
+ read_rom_file (buf, rd);
+ if (flags & ROMTYPE_CD32) {
+ memcpy (buf2, buf, size);
+ mergecd32 (buf, buf2, size);
+ }
+ add = 1;
+ i++;
} else if (flags & ROMTYPE_QUAD) {
if (i == 0) {
for (int k = 0; k < 4; k++) {
@@ -1784,93 +1779,93 @@ static struct zfile *read_rom (struct romdata *prd)
}
}
add = 4;
- } else {
- int romsize = size / 2;
- if (i)
- odd = !odd;
+ } else {
+ int romsize = size / 2;
+ if (i)
+ odd = !odd;
if (rd->id == rd[1].id)
rdpair = &rd[1];
else if (rd != roms)
rdpair = &rd[-1];
else
rdpair = rd;
- if (flags & ROMTYPE_8BIT) {
- read_rom_file (buf2, rd);
- if (flags & ROMTYPE_BYTESWAP)
- byteswap (buf2, romsize);
- if (flags & ROMTYPE_SCRAMBLED)
- descramble (rd, buf2, romsize, odd);
- for (j = 0; j < size; j += 2)
- buf[j + odd] = buf2[j / 2];
+ if (flags & ROMTYPE_8BIT) {
+ read_rom_file (buf2, rd);
+ if (flags & ROMTYPE_BYTESWAP)
+ byteswap (buf2, romsize);
+ if (flags & ROMTYPE_SCRAMBLED)
+ descramble (rd, buf2, romsize, odd);
+ for (j = 0; j < size; j += 2)
+ buf[j + odd] = buf2[j / 2];
read_rom_file (buf2, rdpair);
- if (flags & ROMTYPE_BYTESWAP)
- byteswap (buf2, romsize);
- if (flags & ROMTYPE_SCRAMBLED)
- descramble (rd + 1, buf2, romsize, !odd);
- for (j = 0; j < size; j += 2)
- buf[j + (1 - odd)] = buf2[j / 2];
- } else {
- read_rom_file (buf2, rd);
- if (flags & ROMTYPE_BYTESWAP)
- byteswap (buf2, romsize);
- if (flags & ROMTYPE_SCRAMBLED)
- descramble (rd, buf2, romsize, odd);
- for (j = 0; j < size; j += 4) {
- buf[j + 2 * odd + 0] = buf2[j / 2 + 0];
- buf[j + 2 * odd + 1] = buf2[j / 2 + 1];
- }
+ if (flags & ROMTYPE_BYTESWAP)
+ byteswap (buf2, romsize);
+ if (flags & ROMTYPE_SCRAMBLED)
+ descramble (rd + 1, buf2, romsize, !odd);
+ for (j = 0; j < size; j += 2)
+ buf[j + (1 - odd)] = buf2[j / 2];
+ } else {
+ read_rom_file (buf2, rd);
+ if (flags & ROMTYPE_BYTESWAP)
+ byteswap (buf2, romsize);
+ if (flags & ROMTYPE_SCRAMBLED)
+ descramble (rd, buf2, romsize, odd);
+ for (j = 0; j < size; j += 4) {
+ buf[j + 2 * odd + 0] = buf2[j / 2 + 0];
+ buf[j + 2 * odd + 1] = buf2[j / 2 + 1];
+ }
read_rom_file (buf2, rdpair);
- if (flags & ROMTYPE_BYTESWAP)
- byteswap (buf2, romsize);
- if (flags & ROMTYPE_SCRAMBLED)
- descramble (rd + 1, buf2, romsize, !odd);
- for (j = 0; j < size; j += 4) {
- buf[j + 2 * (1 - odd) + 0] = buf2[j / 2 + 0];
- buf[j + 2 * (1 - odd) + 1] = buf2[j / 2 + 1];
- }
- }
- add = 2;
- }
+ if (flags & ROMTYPE_BYTESWAP)
+ byteswap (buf2, romsize);
+ if (flags & ROMTYPE_SCRAMBLED)
+ descramble (rd + 1, buf2, romsize, !odd);
+ for (j = 0; j < size; j += 4) {
+ buf[j + 2 * (1 - odd) + 0] = buf2[j / 2 + 0];
+ buf[j + 2 * (1 - odd) + 1] = buf2[j / 2 + 1];
+ }
+ }
+ add = 2;
+ }
if (notcrc32(crc32) || get_crc32(buf, size) == crc32) {
- ok = 1;
- }
- if (!ok && (rd->type & ROMTYPE_AR)) {
- uae_u8 tmp[2];
- tmp[0] = buf[0];
- tmp[1] = buf[1];
- buf[0] = buf[1] = 0;
- if (get_crc32 (buf, size) == crc32)
- ok = 1;
- buf[0] = tmp[0];
- buf[1] = tmp[1];
- }
- if (!ok) {
- /* perhaps it is byteswapped without byteswap entry? */
- byteswap (buf, size);
- if (get_crc32 (buf, size) == crc32)
- ok = 1;
+ ok = 1;
+ }
+ if (!ok && (rd->type & ROMTYPE_AR)) {
+ uae_u8 tmp[2];
+ tmp[0] = buf[0];
+ tmp[1] = buf[1];
+ buf[0] = buf[1] = 0;
+ if (get_crc32 (buf, size) == crc32)
+ ok = 1;
+ buf[0] = tmp[0];
+ buf[1] = tmp[1];
+ }
+ if (!ok) {
+ /* perhaps it is byteswapped without byteswap entry? */
+ byteswap (buf, size);
+ if (get_crc32 (buf, size) == crc32)
+ ok = 1;
if (!ok)
byteswap(buf, size);
- }
- if (ok) {
- struct zfile *zf = zfile_fopen_empty (NULL, name, size);
- if (zf) {
- zfile_fwrite (buf, size, 1, zf);
- zfile_fseek (zf, 0, SEEK_SET);
- }
- xfree (buf);
- return zf;
- }
- }
- rd += add;
+ }
+ if (ok) {
+ struct zfile *zf = zfile_fopen_empty (NULL, name, size);
+ if (zf) {
+ zfile_fwrite (buf, size, 1, zf);
+ zfile_fseek (zf, 0, SEEK_SET);
+ }
+ xfree (buf);
+ return zf;
+ }
+ }
+ rd += add;
- }
- xfree (buf);
- return NULL;
+ }
+ xfree (buf);
+ return NULL;
}
-struct zfile *rom_fopen (const TCHAR *name, const TCHAR *mode, int mask)
+struct zfile *rom_fopen(const TCHAR *name, const TCHAR *mode, int mask)
{
return zfile_fopen (name, mode, mask);
}
@@ -1944,42 +1939,42 @@ static struct zfile *rom_fopen2(const TCHAR *name, const TCHAR *mode, int mask)
struct zfile *read_rom_name (const TCHAR *filename)
{
- struct zfile *f;
+ struct zfile *f;
- for (int i = 0; i < romlist_cnt; i++) {
+ for (int i = 0; i < romlist_cnt; i++) {
if (my_issamepath(filename, rl[i].path)) {
- struct romdata *rd = rl[i].rd;
+ struct romdata *rd = rl[i].rd;
f = read_rom (rd);
- if (f)
- return f;
- }
- }
+ if (f)
+ return f;
+ }
+ }
f = rom_fopen2(filename, _T("rb"), ZFD_NORMAL);
- if (f) {
+ if (f) {
uae_u8 tmp[11] = { 0 };
- zfile_fread (tmp, sizeof tmp, 1, f);
- if (!memcmp (tmp, "AMIROMTYPE1", sizeof tmp)) {
- struct zfile *df;
- int size;
- uae_u8 *buf;
- addkeydir (filename);
- zfile_fseek (f, 0, SEEK_END);
- size = zfile_ftell (f) - sizeof tmp;
- zfile_fseek (f, sizeof tmp, SEEK_SET);
- buf = xmalloc (uae_u8, size);
- zfile_fread (buf, size, 1, f);
- df = zfile_fopen_empty (f, _T("tmp.rom"), size);
- decode_cloanto_rom_do (buf, size, size);
- zfile_fwrite (buf, size, 1, df);
- zfile_fclose (f);
- xfree (buf);
- zfile_fseek (df, 0, SEEK_SET);
- f = df;
- } else {
- zfile_fseek (f, -((int)sizeof tmp), SEEK_CUR);
- }
- }
- return f;
+ zfile_fread(tmp, sizeof tmp, 1, f);
+ if (!memcmp(tmp, "AMIROMTYPE1", sizeof tmp)) {
+ struct zfile *df;
+ int size;
+ uae_u8 *buf;
+ addkeydir(filename);
+ zfile_fseek(f, 0, SEEK_END);
+ size = zfile_ftell(f) - sizeof tmp;
+ zfile_fseek(f, sizeof tmp, SEEK_SET);
+ buf = xmalloc(uae_u8, size);
+ zfile_fread(buf, size, 1, f);
+ df = zfile_fopen_empty(f, _T("tmp.rom"), size);
+ decode_cloanto_rom_do(buf, size, size);
+ zfile_fwrite(buf, size, 1, df);
+ zfile_fclose(f);
+ xfree(buf);
+ zfile_fseek(df, 0, SEEK_SET);
+ f = df;
+ } else {
+ zfile_fseek (f, -((int)sizeof tmp), SEEK_CUR);
+ }
+ }
+ return f;
}
struct zfile *read_rom_name_guess (const TCHAR *filename, TCHAR *out)
@@ -2019,34 +2014,34 @@ struct zfile *read_rom_name_guess (const TCHAR *filename, TCHAR *out)
void kickstart_fix_checksum (uae_u8 *mem, int size)
{
- uae_u32 cksum = 0, prevck = 0;
- int i, ch = size == 524288 ? 0x7ffe8 : (size == 262144 ? 0x3ffe8 : 0x3e);
+ uae_u32 cksum = 0, prevck = 0;
+ int i, ch = size == 524288 ? 0x7ffe8 : (size == 262144 ? 0x3ffe8 : 0x3e);
- mem[ch] = 0;
- mem[ch + 1] = 0;
- mem[ch + 2] = 0;
- mem[ch + 3] = 0;
- for (i = 0; i < size; i+=4) {
- uae_u32 data = (mem[i] << 24) | (mem[i + 1] << 16) | (mem[i + 2] << 8) | mem[i + 3];
- cksum += data;
- if (cksum < prevck)
- cksum++;
- prevck = cksum;
- }
- cksum ^= 0xffffffff;
- mem[ch++] = cksum >> 24;
- mem[ch++] = cksum >> 16;
- mem[ch++] = cksum >> 8;
- mem[ch++] = cksum >> 0;
+ mem[ch] = 0;
+ mem[ch + 1] = 0;
+ mem[ch + 2] = 0;
+ mem[ch + 3] = 0;
+ for (i = 0; i < size; i+=4) {
+ uae_u32 data = (mem[i] << 24) | (mem[i + 1] << 16) | (mem[i + 2] << 8) | mem[i + 3];
+ cksum += data;
+ if (cksum < prevck)
+ cksum++;
+ prevck = cksum;
+ }
+ cksum ^= 0xffffffff;
+ mem[ch++] = cksum >> 24;
+ mem[ch++] = cksum >> 16;
+ mem[ch++] = cksum >> 8;
+ mem[ch++] = cksum >> 0;
}
int kickstart_checksum (uae_u8 *mem, int size)
{
- if (!kickstart_checksum_do (mem, size)) {
- notify_user (NUMSG_KSROMCRCERROR);
- return 0;
- }
- return 1;
+ if (!kickstart_checksum_do (mem, size)) {
+ notify_user (NUMSG_KSROMCRCERROR);
+ return 0;
+ }
+ return 1;
}
int configure_rom (struct uae_prefs *p, const int *rom, int msg)
@@ -2114,6 +2109,8 @@ const struct expansionromtype *get_unit_expansion_rom(int hdunit)
return &expansionroms[hdunit - HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST];
if (hdunit >= HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST && hdunit <= HD_CONTROLLER_TYPE_IDE_LAST)
return &expansionroms[hdunit - HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST];
+ if (hdunit >= HD_CONTROLLER_TYPE_CUSTOM_FIRST && hdunit <= HD_CONTROLLER_TYPE_CUSTOM_LAST)
+ return &expansionroms[hdunit - HD_CONTROLLER_TYPE_CUSTOM_FIRST];
return NULL;
}
@@ -2165,8 +2162,8 @@ struct boardromconfig *get_device_rom_new(struct uae_prefs *p, int romtype, int
return &fake;
}
if (index)
- *index = 0;
- struct boardromconfig *brc = get_device_rom(p, romtype, devnum, &idx2);
+ *index = ert->parentromtype ? 1 : 0;
+ struct boardromconfig *brc = get_device_rom(p, ert->parentromtype ? ert->parentromtype : romtype, devnum, &idx2);
if (!brc) {
for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) {
brc = &p->expansionboard[i];
@@ -2210,12 +2207,12 @@ struct boardromconfig *get_device_rom(struct uae_prefs *p, int romtype, int devn
const struct expansionromtype *ert = get_device_expansion_rom(romtype);
if (!ert) {
if (index)
- *index = 0;
+ *index = 0;
return NULL;
}
- int parentrom = romtype;
+ int parentrom = ert->parentromtype ? ert->parentromtype : romtype;
if (index)
- *index = 0;
+ *index = ert->parentromtype ? 1 : 0;
for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) {
struct boardromconfig *brc = &p->expansionboard[i];
if (!brc->device_type)
@@ -2363,6 +2360,7 @@ bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fil
struct zfile *f = read_device_from_romconfig(rc, romtype);
if (!f)
return false;
+ TCHAR *ext = _tcsrchr(zfile_getname(f), '.');
zfile_fseek(f, fileoffset, SEEK_SET);
int cnt = 0;
int pos = 0;
diff --git a/src/savestate.cpp b/src/savestate.cpp
index 29bc7d85..db005c10 100644
--- a/src/savestate.cpp
+++ b/src/savestate.cpp
@@ -481,200 +481,215 @@ static void restore_header (uae_u8 *src)
/* restore all subsystems */
-void restore_state (const TCHAR *filename)
+void restore_state(const TCHAR* filename)
{
- struct zfile *f;
- uae_u8 *chunk,*end;
- TCHAR name[5];
+ struct zfile* f;
+ uae_u8* chunk, * end;
+ TCHAR name[5];
unsigned int len, totallen;
- size_t filepos, filesize;
+ size_t filepos, filesize;
int z3num, z2num;
- chunk = 0;
- f = zfile_fopen (filename, _T("rb"), ZFD_NORMAL);
- if (!f)
- goto error;
- zfile_fseek (f, 0, SEEK_END);
- filesize = zfile_ftell (f);
- zfile_fseek (f, 0, SEEK_SET);
- savestate_state = STATE_RESTORE;
+ chunk = 0;
+ f = zfile_fopen(filename, _T("rb"), ZFD_NORMAL);
+ if (!f)
+ goto error;
+ zfile_fseek(f, 0, SEEK_END);
+ filesize = zfile_ftell(f);
+ zfile_fseek(f, 0, SEEK_SET);
+ savestate_state = STATE_RESTORE;
- chunk = restore_chunk (f, name, &len, &totallen, &filepos);
- if (!chunk || _tcsncmp (name, _T("ASF "), 4)) {
- write_log (_T("%s is not an AmigaStateFile\n"), filename);
- goto error;
- }
- write_log (_T("STATERESTORE: '%s'\n"), filename);
- set_config_changed ();
- savestate_file = f;
- restore_header (chunk);
- xfree (chunk);
+ chunk = restore_chunk(f, name, &len, &totallen, &filepos);
+ if (!chunk || _tcsncmp(name, _T("ASF "), 4)) {
+ write_log(_T("%s is not an AmigaStateFile\n"), filename);
+ goto error;
+ }
+ write_log(_T("STATERESTORE: '%s'\n"), filename);
+ set_config_changed();
+ savestate_file = f;
+ restore_header(chunk);
+ xfree(chunk);
devices_restore_start();
z2num = z3num = 0;
- for (;;) {
- name[0] = 0;
- chunk = end = restore_chunk (f, name, &len, &totallen, &filepos);
- write_log (_T("Chunk '%s' size %u (%u)\n"), name, len, totallen);
- if (!_tcscmp (name, _T("END "))) {
- break;
- }
- if (!_tcscmp (name, _T("CRAM"))) {
- restore_cram (totallen, filepos);
- continue;
- } else if (!_tcscmp (name, _T("BRAM"))) {
- restore_bram (totallen, filepos);
- continue;
- } else if (!_tcscmp (name, _T("A3K1"))) {
- restore_a3000lram (totallen, filepos);
+ for (;;) {
+ name[0] = 0;
+ chunk = end = restore_chunk(f, name, &len, &totallen, &filepos);
+ write_log(_T("Chunk '%s' size %u (%u)\n"), name, len, totallen);
+ if (!_tcscmp(name, _T("END "))) {
+ break;
+ }
+ if (!_tcscmp(name, _T("CRAM"))) {
+ restore_cram(totallen, filepos);
continue;
- } else if (!_tcscmp (name, _T("A3K2"))) {
- restore_a3000hram (totallen, filepos);
+ }
+ else if (!_tcscmp(name, _T("BRAM"))) {
+ restore_bram(totallen, filepos);
+ continue;
+ }
+ else if (!_tcscmp(name, _T("A3K1"))) {
+ restore_a3000lram(totallen, filepos);
+ continue;
+ }
+ else if (!_tcscmp(name, _T("A3K2"))) {
+ restore_a3000hram(totallen, filepos);
continue;
#ifdef AUTOCONFIG
- } else if (!_tcscmp (name, _T("FRAM"))) {
- restore_fram (totallen, filepos, z2num++);
- continue;
- } else if (!_tcscmp (name, _T("ZRAM"))) {
- restore_zram (totallen, filepos, z3num++);
- continue;
- } else if (!_tcscmp (name, _T("BORO"))) {
- restore_bootrom (totallen, filepos);
- continue;
+ }
+ else if (!_tcscmp(name, _T("FRAM"))) {
+ restore_fram(totallen, filepos, z2num++);
+ continue;
+ }
+ else if (!_tcscmp(name, _T("ZRAM"))) {
+ restore_zram(totallen, filepos, z3num++);
+ continue;
+ }
+ else if (!_tcscmp(name, _T("BORO"))) {
+ restore_bootrom(totallen, filepos);
+ continue;
#endif
#ifdef PICASSO96
- } else if (!_tcscmp (name, _T("PRAM"))) {
- restore_pram (totallen, filepos);
- continue;
+ }
+ else if (!_tcscmp(name, _T("PRAM"))) {
+ restore_pram(totallen, filepos);
+ continue;
#endif
- } else if (!_tcscmp (name, _T("CPU "))) {
- end = restore_cpu (chunk);
- } else if (!_tcscmp (name, _T("CPUX")))
- end = restore_cpu_extra (chunk);
+ }
+ else if (!_tcscmp(name, _T("CPU "))) {
+ end = restore_cpu(chunk);
+ }
+ else if (!_tcscmp(name, _T("CPUX")))
+ end = restore_cpu_extra(chunk);
#ifdef FPUEMU
- else if (!_tcscmp (name, _T("FPU ")))
- end = restore_fpu (chunk);
+ else if (!_tcscmp(name, _T("FPU ")))
+ end = restore_fpu(chunk);
#endif
- else if (!_tcscmp (name, _T("AGAC")))
- end = restore_custom_agacolors (chunk);
- else if (!_tcscmp (name, _T("SPR0")))
- end = restore_custom_sprite (0, chunk);
- else if (!_tcscmp (name, _T("SPR1")))
- end = restore_custom_sprite (1, chunk);
- else if (!_tcscmp (name, _T("SPR2")))
- end = restore_custom_sprite (2, chunk);
- else if (!_tcscmp (name, _T("SPR3")))
- end = restore_custom_sprite (3, chunk);
- else if (!_tcscmp (name, _T("SPR4")))
- end = restore_custom_sprite (4, chunk);
- else if (!_tcscmp (name, _T("SPR5")))
- end = restore_custom_sprite (5, chunk);
- else if (!_tcscmp (name, _T("SPR6")))
- end = restore_custom_sprite (6, chunk);
- else if (!_tcscmp (name, _T("SPR7")))
- end = restore_custom_sprite (7, chunk);
- else if (!_tcscmp (name, _T("CIAA")))
- end = restore_cia (0, chunk);
- else if (!_tcscmp (name, _T("CIAB")))
- end = restore_cia (1, chunk);
- else if (!_tcscmp (name, _T("CHIP")))
- end = restore_custom (chunk);
- else if (!_tcscmp (name, _T("CINP")))
- end = restore_input (chunk);
- else if (!_tcscmp (name, _T("CHPX")))
- end = restore_custom_extra (chunk);
- else if (!_tcscmp (name, _T("AUD0")))
- end = restore_audio (0, chunk);
- else if (!_tcscmp (name, _T("AUD1")))
- end = restore_audio (1, chunk);
- else if (!_tcscmp (name, _T("AUD2")))
- end = restore_audio (2, chunk);
- else if (!_tcscmp (name, _T("AUD3")))
- end = restore_audio (3, chunk);
- else if (!_tcscmp (name, _T("BLIT")))
- end = restore_blitter (chunk);
- else if (!_tcscmp (name, _T("BLTX")))
- end = restore_blitter_new (chunk);
- else if (!_tcscmp (name, _T("DISK")))
- end = restore_floppy (chunk);
- else if (!_tcscmp (name, _T("DSK0")))
- end = restore_disk (0, chunk);
- else if (!_tcscmp (name, _T("DSK1")))
- end = restore_disk (1, chunk);
- else if (!_tcscmp (name, _T("DSK2")))
- end = restore_disk (2, chunk);
- else if (!_tcscmp (name, _T("DSK3")))
- end = restore_disk (3, chunk);
- else if (!_tcscmp (name, _T("DSD0")))
- end = restore_disk2 (0, chunk);
- else if (!_tcscmp (name, _T("DSD1")))
- end = restore_disk2 (1, chunk);
- else if (!_tcscmp (name, _T("DSD2")))
- end = restore_disk2 (2, chunk);
- else if (!_tcscmp (name, _T("DSD3")))
- end = restore_disk2 (3, chunk);
- else if (!_tcscmp (name, _T("KEYB")))
- end = restore_keyboard (chunk);
+ else if (!_tcscmp(name, _T("AGAC")))
+ end = restore_custom_agacolors(chunk);
+ else if (!_tcscmp(name, _T("SPR0")))
+ end = restore_custom_sprite(0, chunk);
+ else if (!_tcscmp(name, _T("SPR1")))
+ end = restore_custom_sprite(1, chunk);
+ else if (!_tcscmp(name, _T("SPR2")))
+ end = restore_custom_sprite(2, chunk);
+ else if (!_tcscmp(name, _T("SPR3")))
+ end = restore_custom_sprite(3, chunk);
+ else if (!_tcscmp(name, _T("SPR4")))
+ end = restore_custom_sprite(4, chunk);
+ else if (!_tcscmp(name, _T("SPR5")))
+ end = restore_custom_sprite(5, chunk);
+ else if (!_tcscmp(name, _T("SPR6")))
+ end = restore_custom_sprite(6, chunk);
+ else if (!_tcscmp(name, _T("SPR7")))
+ end = restore_custom_sprite(7, chunk);
+ else if (!_tcscmp(name, _T("CIAA")))
+ end = restore_cia(0, chunk);
+ else if (!_tcscmp(name, _T("CIAB")))
+ end = restore_cia(1, chunk);
+ else if (!_tcscmp(name, _T("CHIP")))
+ end = restore_custom(chunk);
+ else if (!_tcscmp(name, _T("CINP")))
+ end = restore_input(chunk);
+ else if (!_tcscmp(name, _T("CHPX")))
+ end = restore_custom_extra(chunk);
+ else if (!_tcscmp(name, _T("AUD0")))
+ end = restore_audio(0, chunk);
+ else if (!_tcscmp(name, _T("AUD1")))
+ end = restore_audio(1, chunk);
+ else if (!_tcscmp(name, _T("AUD2")))
+ end = restore_audio(2, chunk);
+ else if (!_tcscmp(name, _T("AUD3")))
+ end = restore_audio(3, chunk);
+ else if (!_tcscmp(name, _T("BLIT")))
+ end = restore_blitter(chunk);
+ else if (!_tcscmp(name, _T("BLTX")))
+ end = restore_blitter_new(chunk);
+ else if (!_tcscmp(name, _T("DISK")))
+ end = restore_floppy(chunk);
+ else if (!_tcscmp(name, _T("DSK0")))
+ end = restore_disk(0, chunk);
+ else if (!_tcscmp(name, _T("DSK1")))
+ end = restore_disk(1, chunk);
+ else if (!_tcscmp(name, _T("DSK2")))
+ end = restore_disk(2, chunk);
+ else if (!_tcscmp(name, _T("DSK3")))
+ end = restore_disk(3, chunk);
+ else if (!_tcscmp(name, _T("DSD0")))
+ end = restore_disk2(0, chunk);
+ else if (!_tcscmp(name, _T("DSD1")))
+ end = restore_disk2(1, chunk);
+ else if (!_tcscmp(name, _T("DSD2")))
+ end = restore_disk2(2, chunk);
+ else if (!_tcscmp(name, _T("DSD3")))
+ end = restore_disk2(3, chunk);
+ else if (!_tcscmp(name, _T("KEYB")))
+ end = restore_keyboard(chunk);
#ifdef AUTOCONFIG
- else if (!_tcscmp (name, _T("EXPA")))
- end = restore_expansion (chunk);
+ else if (!_tcscmp(name, _T("EXPA")))
+ end = restore_expansion(chunk);
#endif
- else if (!_tcscmp (name, _T("ROM ")))
- end = restore_rom (chunk);
+ else if (!_tcscmp(name, _T("ROM ")))
+ end = restore_rom(chunk);
#ifdef PICASSO96
- else if (!_tcscmp (name, _T("P96 ")))
- end = restore_p96 (chunk);
+ else if (!_tcscmp(name, _T("P96 ")))
+ end = restore_p96(chunk);
#endif
#ifdef ACTION_REPLAY
- else if (!_tcscmp (name, _T("ACTR")))
- end = restore_action_replay (chunk);
- else if (!_tcscmp (name, _T("HRTM")))
- end = restore_hrtmon (chunk);
+ else if (!_tcscmp(name, _T("ACTR")))
+ end = restore_action_replay(chunk);
+ else if (!_tcscmp(name, _T("HRTM")))
+ end = restore_hrtmon(chunk);
#endif
#ifdef FILESYS
else if (!_tcscmp(name, _T("FSYP")))
end = restore_filesys_paths(chunk);
- else if (!_tcscmp (name, _T("FSYS")))
- end = restore_filesys (chunk);
- else if (!_tcscmp (name, _T("FSYC")))
- end = restore_filesys_common (chunk);
+ else if (!_tcscmp(name, _T("FSYS")))
+ end = restore_filesys(chunk);
+ else if (!_tcscmp(name, _T("FSYC")))
+ end = restore_filesys_common(chunk);
#endif
#ifdef CD32
- else if (!_tcscmp (name, _T("CD32")))
- end = restore_akiko (chunk);
+ else if (!_tcscmp(name, _T("CD32")))
+ end = restore_akiko(chunk);
#endif
- else if (!_tcscmp (name, _T("GAYL")))
- end = restore_gayle (chunk);
- else if (!_tcscmp (name, _T("IDE ")))
- end = restore_gayle_ide (chunk);
- else if (!_tcsncmp (name, _T("CDU"), 3))
- end = restore_cd (name[3] - '0', chunk);
- else if (!_tcsncmp (name, _T("EXPB"), 4))
+#ifdef CDTV
+ else if (!_tcscmp(name, _T("CDTV")))
+ end = restore_cdtv(chunk);
+ else if (!_tcscmp(name, _T("DMAC")))
+ end = restore_cdtv_dmac(chunk);
+#endif
+ else if (!_tcscmp(name, _T("GAYL")))
+ end = restore_gayle(chunk);
+ else if (!_tcscmp(name, _T("IDE ")))
+ end = restore_gayle_ide(chunk);
+ else if (!_tcsncmp(name, _T("CDU"), 3))
+ end = restore_cd(name[3] - '0', chunk);
+ else if (!_tcsncmp(name, _T("EXPB"), 4))
end = restore_expansion_boards(chunk);
- else {
- end = chunk + len;
- write_log (_T("unknown chunk '%s' size %d bytes\n"), name, len);
- }
- if (end == NULL)
- write_log (_T("Chunk '%s', size %d bytes was not accepted!\n"),
- name, len);
- else if (totallen != end - chunk)
- write_log (_T("Chunk '%s' total size %d bytes but read %ld bytes!\n"),
- name, totallen, end - chunk);
- xfree (chunk);
+ else {
+ end = chunk + len;
+ write_log(_T("unknown chunk '%s' size %d bytes\n"), name, len);
+ }
+ if (end == NULL)
+ write_log(_T("Chunk '%s', size %d bytes was not accepted!\n"),
+ name, len);
+ else if (totallen != end - chunk)
+ write_log(_T("Chunk '%s' total size %d bytes but read %ld bytes!\n"),
+ name, totallen, end - chunk);
+ xfree(chunk);
if (name[0] == 0)
break;
- }
- target_addtorecent (filename, 0);
- return;
+ }
+ target_addtorecent(filename, 0);
+ return;
error:
- savestate_state = 0;
- savestate_file = 0;
- if (chunk)
- xfree (chunk);
- if (f)
- zfile_fclose (f);
+ savestate_state = 0;
+ savestate_file = 0;
+ if (chunk)
+ xfree(chunk);
+ if (f)
+ zfile_fclose(f);
}
bool savestate_restore_finish(void)
@@ -689,6 +704,9 @@ bool savestate_restore_finish(void)
restore_blitter_finish ();
restore_expansion_finish();
restore_akiko_finish ();
+#ifdef CDTV
+ restore_cdtv_finish();
+#endif
#ifdef PICASSO96
restore_p96_finish ();
#endif
@@ -745,113 +763,113 @@ static void save_rams (struct zfile *f, int comp)
/* Save all subsystems */
-static int save_state_internal (struct zfile *f, const TCHAR *description, int comp, bool savepath)
+static int save_state_internal(struct zfile* f, const TCHAR* description, int comp, bool savepath)
{
- uae_u8 endhunk[] = { 'E', 'N', 'D', ' ', 0, 0, 0, 8 };
- uae_u8 header[1000];
- TCHAR tmp[100];
- uae_u8 *dst;
- TCHAR name[5];
+ uae_u8 endhunk[] = { 'E', 'N', 'D', ' ', 0, 0, 0, 8 };
+ uae_u8 header[1000];
+ TCHAR tmp[100];
+ uae_u8* dst;
+ TCHAR name[5];
int i, len;
- write_log (_T("STATESAVE (%s):\n"), f ? zfile_getname (f) : _T(""));
- dst = header;
- save_u32 (0);
- save_string(_T("UAE"));
- _stprintf (tmp, _T("%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV);
- save_string (tmp);
- save_string (description);
- save_chunk (f, header, dst-header, _T("ASF "), 0);
+ write_log(_T("STATESAVE (%s):\n"), f ? zfile_getname(f) : _T(""));
+ dst = header;
+ save_u32(0);
+ save_string(_T("UAE"));
+ _stprintf(tmp, _T("%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV);
+ save_string(tmp);
+ save_string(description);
+ save_chunk(f, header, dst - header, _T("ASF "), 0);
- dst = save_cpu (&len, 0);
- save_chunk (f, dst, len, _T("CPU "), 0);
- xfree (dst);
+ dst = save_cpu(&len, 0);
+ save_chunk(f, dst, len, _T("CPU "), 0);
+ xfree(dst);
- dst = save_cpu_extra (&len, 0);
- save_chunk (f, dst, len, _T("CPUX"), 0);
- xfree (dst);
+ dst = save_cpu_extra(&len, 0);
+ save_chunk(f, dst, len, _T("CPUX"), 0);
+ xfree(dst);
#ifdef FPUEMU
- dst = save_fpu (&len, 0);
- save_chunk (f, dst, len, _T("FPU "), 0);
- xfree (dst);
+ dst = save_fpu(&len, 0);
+ save_chunk(f, dst, len, _T("FPU "), 0);
+ xfree(dst);
#endif
- _tcscpy(name, _T("DSKx"));
- for (i = 0; i < 4; i++) {
- dst = save_disk (i, &len, 0, savepath);
- if (dst) {
- name[3] = i + '0';
- save_chunk (f, dst, len, name, 0);
- xfree (dst);
- }
- }
- _tcscpy(name, _T("DSDx"));
+ _tcscpy(name, _T("DSKx"));
for (i = 0; i < 4; i++) {
- dst = save_disk2 (i, &len, 0);
+ dst = save_disk(i, &len, 0, savepath);
if (dst) {
name[3] = i + '0';
- save_chunk (f, dst, len, name, comp);
- xfree (dst);
+ save_chunk(f, dst, len, name, 0);
+ xfree(dst);
+ }
+ }
+ _tcscpy(name, _T("DSDx"));
+ for (i = 0; i < 4; i++) {
+ dst = save_disk2(i, &len, 0);
+ if (dst) {
+ name[3] = i + '0';
+ save_chunk(f, dst, len, name, comp);
+ xfree(dst);
}
}
- dst = save_floppy (&len, 0);
- save_chunk (f, dst, len, _T("DISK"), 0);
- xfree (dst);
+ dst = save_floppy(&len, 0);
+ save_chunk(f, dst, len, _T("DISK"), 0);
+ xfree(dst);
- dst = save_custom (&len, 0, 0);
- save_chunk (f, dst, len, _T("CHIP"), 0);
- xfree (dst);
+ dst = save_custom(&len, 0, 0);
+ save_chunk(f, dst, len, _T("CHIP"), 0);
+ xfree(dst);
- dst = save_custom_extra (&len, 0);
- save_chunk (f, dst, len, _T("CHPX"), 0);
- xfree (dst);
+ dst = save_custom_extra(&len, 0);
+ save_chunk(f, dst, len, _T("CHPX"), 0);
+ xfree(dst);
- dst = save_blitter_new (&len, 0);
- save_chunk (f, dst, len, _T("BLTX"), 0);
- xfree (dst);
- dst = save_blitter (&len, 0);
- save_chunk (f, dst, len, _T("BLIT"), 0);
- xfree (dst);
+ dst = save_blitter_new(&len, 0);
+ save_chunk(f, dst, len, _T("BLTX"), 0);
+ xfree(dst);
+ dst = save_blitter(&len, 0);
+ save_chunk(f, dst, len, _T("BLIT"), 0);
+ xfree(dst);
- dst = save_input (&len, 0);
- save_chunk (f, dst, len, _T("CINP"), 0);
- xfree (dst);
+ dst = save_input(&len, 0);
+ save_chunk(f, dst, len, _T("CINP"), 0);
+ xfree(dst);
- dst = save_custom_agacolors (&len, 0);
+ dst = save_custom_agacolors(&len, 0);
if (dst) {
- save_chunk (f, dst, len, _T("AGAC"), 0);
- xfree (dst);
- }
+ save_chunk(f, dst, len, _T("AGAC"), 0);
+ xfree(dst);
+ }
- _tcscpy (name, _T("SPRx"));
- for (i = 0; i < 8; i++) {
- dst = save_custom_sprite (i, &len, 0);
- name[3] = i + '0';
- save_chunk (f, dst, len, name, 0);
- xfree (dst);
- }
+ _tcscpy(name, _T("SPRx"));
+ for (i = 0; i < 8; i++) {
+ dst = save_custom_sprite(i, &len, 0);
+ name[3] = i + '0';
+ save_chunk(f, dst, len, name, 0);
+ xfree(dst);
+ }
- _tcscpy (name, _T("AUDx"));
- for (i = 0; i < 4; i++) {
- dst = save_audio (i, &len, 0);
- name[3] = i + '0';
- save_chunk (f, dst, len, name, 0);
- xfree (dst);
- }
+ _tcscpy(name, _T("AUDx"));
+ for (i = 0; i < 4; i++) {
+ dst = save_audio(i, &len, 0);
+ name[3] = i + '0';
+ save_chunk(f, dst, len, name, 0);
+ xfree(dst);
+ }
- dst = save_cia (0, &len, 0);
- save_chunk (f, dst, len, _T("CIAA"), 0);
- xfree (dst);
+ dst = save_cia(0, &len, 0);
+ save_chunk(f, dst, len, _T("CIAA"), 0);
+ xfree(dst);
- dst = save_cia (1, &len, 0);
- save_chunk (f, dst, len, _T("CIAB"), 0);
- xfree (dst);
+ dst = save_cia(1, &len, 0);
+ save_chunk(f, dst, len, _T("CIAB"), 0);
+ xfree(dst);
- dst = save_keyboard (&len, NULL);
- save_chunk (f, dst, len, _T("KEYB"), 0);
- xfree (dst);
+ dst = save_keyboard(&len, NULL);
+ save_chunk(f, dst, len, _T("KEYB"), 0);
+ xfree(dst);
#ifdef AUTOCONFIG
// new
@@ -861,80 +879,88 @@ static int save_state_internal (struct zfile *f, const TCHAR *description, int c
if (!dst)
break;
save_chunk(f, dst, len, _T("EXPB"), 0);
- xfree (dst);
+ xfree(dst);
i++;
}
- dst = save_expansion (&len, 0);
- save_chunk (f, dst, len, _T("EXPA"), 0);
- xfree (dst);
+ dst = save_expansion(&len, 0);
+ save_chunk(f, dst, len, _T("EXPA"), 0);
+ xfree(dst);
#endif
#ifdef PICASSO96
- dst = save_p96 (&len, 0);
- save_chunk (f, dst, len, _T("P96 "), 0);
+ dst = save_p96(&len, 0);
+ save_chunk(f, dst, len, _T("P96 "), 0);
#endif
- save_rams (f, comp);
+ save_rams(f, comp);
- dst = save_rom (1, &len, 0);
- do {
- if (!dst)
- break;
- save_chunk (f, dst, len, _T("ROM "), 0);
- xfree (dst);
- } while ((dst = save_rom (0, &len, 0)));
+ dst = save_rom(1, &len, 0);
+ do {
+ if (!dst)
+ break;
+ save_chunk(f, dst, len, _T("ROM "), 0);
+ xfree(dst);
+ } while ((dst = save_rom(0, &len, 0)));
#ifdef CD32
- dst = save_akiko (&len, NULL);
- save_chunk (f, dst, len, _T("CD32"), 0);
- xfree (dst);
+ dst = save_akiko(&len, NULL);
+ save_chunk(f, dst, len, _T("CD32"), 0);
+ xfree(dst);
+#endif
+#ifdef CDTV
+ dst = save_cdtv(&len, NULL);
+ save_chunk(f, dst, len, _T("CDTV"), 0);
+ xfree(dst);
+ dst = save_cdtv_dmac(&len, NULL);
+ save_chunk(f, dst, len, _T("DMAC"), 0);
+ xfree(dst);
#endif
#ifdef ACTION_REPLAY
- dst = save_action_replay (&len, NULL);
- save_chunk (f, dst, len, _T("ACTR"), comp);
- dst = save_hrtmon (&len, NULL);
- save_chunk (f, dst, len, _T("HRTM"), comp);
+ dst = save_action_replay(&len, NULL);
+ save_chunk(f, dst, len, _T("ACTR"), comp);
+ dst = save_hrtmon(&len, NULL);
+ save_chunk(f, dst, len, _T("HRTM"), comp);
#endif
#ifdef FILESYS
- dst = save_filesys_common (&len);
- if (dst) {
- save_chunk (f, dst, len, _T("FSYC"), 0);
- for (i = 0; i < nr_units (); i++) {
+ dst = save_filesys_common(&len);
+ if (dst) {
+ save_chunk(f, dst, len, _T("FSYC"), 0);
+ for (i = 0; i < nr_units(); i++) {
dst = save_filesys_paths(i, &len);
if (dst) {
save_chunk(f, dst, len, _T("FSYP"), 0);
xfree(dst);
}
- dst = save_filesys (i, &len);
- if (dst) {
- save_chunk (f, dst, len, _T("FSYS"), 0);
- xfree (dst);
- }
- }
- }
+ dst = save_filesys(i, &len);
+ if (dst) {
+ save_chunk(f, dst, len, _T("FSYS"), 0);
+ xfree(dst);
+ }
+ }
+ }
#endif
- dst = save_gayle (&len, NULL);
+ dst = save_gayle(&len, NULL);
if (dst) {
- save_chunk (f, dst, len, _T("GAYL"), 0);
+ save_chunk(f, dst, len, _T("GAYL"), 0);
xfree(dst);
}
for (i = 0; i < 4; i++) {
- dst = save_gayle_ide (i, &len, NULL);
+ dst = save_gayle_ide(i, &len, NULL);
if (dst) {
- save_chunk (f, dst, len, _T("IDE "), 0);
- xfree (dst);
+ save_chunk(f, dst, len, _T("IDE "), 0);
+ xfree(dst);
}
}
for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- dst = save_cd (i, &len);
+ dst = save_cd(i, &len);
if (dst) {
- _stprintf (name, _T("CDU%d"), i);
- save_chunk (f, dst, len, name, 0);
+ _stprintf(name, _T("CDU%d"), i);
+ save_chunk(f, dst, len, name, 0);
}
}
- zfile_fwrite (endhunk, 1, 8, f);
+ zfile_fwrite(endhunk, 1, 8, f);
- return 1;
+ return 1;
}
int save_state (const TCHAR *filename, const TCHAR *description)
diff --git a/src/scsi.cpp b/src/scsi.cpp
index 6333a5a7..8e8413b3 100644
--- a/src/scsi.cpp
+++ b/src/scsi.cpp
@@ -12,7 +12,72 @@
#include "options.h"
#include "filesys.h"
+#include "blkdev.h"
+#include "zfile.h"
+#include "memory.h"
#include "scsi.h"
+#include "autoconf.h"
+#include "rommgr.h"
+#include "newcpu.h"
+#include "custom.h"
+#include "gayle.h"
+#include "cia.h"
+#include "devices.h"
+#include "flashrom.h"
+#include "gui.h"
+
+#define SCSI_EMU_DEBUG 0
+#define RAW_SCSI_DEBUG 0
+#define NCR5380_DEBUG 0
+#define NCR5380_DEBUG_IRQ 0
+#define NCR53400_DEBUG 0
+
+#define NCR5380_SUPRA 1
+#define NONCR_GOLEM 2
+#define NCR5380_STARDRIVE 3
+#define NONCR_KOMMOS 4
+#define NONCR_VECTOR 5
+#define NONCR_APOLLO 6
+#define NCR5380_PROTAR 7
+#define NCR5380_ADD500 8
+#define NCR5380_KRONOS 9
+#define NCR5380_ADSCSI 10
+#define NCR5380_ROCHARD 11
+#define NCR5380_CLTD 12
+#define NCR5380_PTNEXUS 13
+#define NCR5380_DATAFLYER 14
+#define NONCR_TECMAR 15
+#define NCR5380_XEBEC 16
+#define NONCR_MICROFORGE 17
+#define NONCR_PARADOX 18
+#define OMTI_HDA506 19
+#define OMTI_ALF1 20
+#define OMTI_PROMIGOS 21
+#define OMTI_SYSTEM2000 22
+#define OMTI_ADAPTER 23
+#define NCR5380_X86_RT1000 24
+#define NCR5380_PHOENIXBOARD 25
+#define NCR5380_TRUMPCARDPRO 26
+#define NCR5380_IVSVECTOR 27 // nearly identical to trumpcard pro
+#define NCR5380_SCRAM 28
+#define NCR5380_OSSI 29
+#define NCR5380_DATAFLYERPLUS 30
+#define NONCR_HARDFRAME 31
+#define NCR5380_MALIBU 32
+#define NCR5380_ADDHARD 33
+#define NONCR_INMATE 34
+#define NCR5380_EMPLANT 35
+#define OMTI_HD3000 36
+#define OMTI_WEDGE 37
+#define NCR5380_EVESHAMREF 38
+#define OMTI_PROFEX 39
+#define NCR5380_FASTTRAK 40
+#define NCR5380_12GAUGE 41
+#define NCR5380_OVERDRIVE 42
+#define NCR5380_TRUMPCARD 43
+#define NCR_LAST 44
+
+extern int log_scsiemu;
static const uae_s16 outcmd[] = { 0x04, 0x0a, 0x0c, 0x11, 0x2a, 0xaa, 0x15, 0x55, 0x0f, -1 };
static const uae_s16 incmd[] = { 0x01, 0x03, 0x08, 0x0e, 0x12, 0x1a, 0x5a, 0x25, 0x28, 0x34, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, 0xb9, 0xbd, 0xd8, 0xd9, 0xbe, -1 };
@@ -72,7 +137,7 @@ static int scsi_data_dir(struct scsi_data *sd)
bool scsi_emulate_analyze (struct scsi_data *sd)
{
- int cmd_len, data_len, data_len2;
+ int cmd_len, data_len, data_len2, tmp_len;
data_len = sd->data_len;
data_len2 = 0;
@@ -83,6 +148,8 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
switch (sd->cmd[0])
{
case 0x04: // FORMAT UNIT
+ if (sd->device_type == UAEDEV_CD)
+ goto nocmd;
// FmtData set?
if (sd->cmd[1] & 0x10) {
int cl = (sd->cmd[1] & 8) != 0;
@@ -96,6 +163,8 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
break;
case 0x06: // FORMAT TRACK
case 0x07: // FORMAT BAD TRACK
+ if (sd->device_type == UAEDEV_CD)
+ goto nocmd;
sd->direction = 0;
sd->data_len = 0;
return true;
@@ -112,7 +181,7 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
if (sd->hfd && sd->hfd->ci.unit_feature_level < HD_LEVEL_SASI)
goto nocmd;
data_len = 4;
- break;
+ break;
case 0x28: // READ(10)
data_len2 = ((sd->cmd[7] << 8) | (sd->cmd[8] << 0)) * (uae_s64)sd->blocksize;
scsi_grow_buffer(sd, data_len2);
@@ -126,14 +195,20 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
scsi_grow_buffer(sd, data_len);
break;
case 0x0a: // WRITE(6)
+ if (sd->device_type == UAEDEV_CD)
+ goto nocmd;
data_len = (sd->cmd[4] == 0 ? 256 : sd->cmd[4]) * sd->blocksize;
scsi_grow_buffer(sd, data_len);
break;
case 0x2a: // WRITE(10)
+ if (sd->device_type == UAEDEV_CD)
+ goto nocmd;
data_len = ((sd->cmd[7] << 8) | (sd->cmd[8] << 0)) * (uae_s64)sd->blocksize;
scsi_grow_buffer(sd, data_len);
break;
case 0xaa: // WRITE(12)
+ if (sd->device_type == UAEDEV_CD)
+ goto nocmd;
data_len = ((sd->cmd[6] << 24) | (sd->cmd[7] << 16) | (sd->cmd[8] << 8) | (sd->cmd[9] << 0)) * (uae_s64)sd->blocksize;
scsi_grow_buffer(sd, data_len);
break;
@@ -141,7 +216,12 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
case 0xb9: // READ CD MSF
case 0xd8: // READ CD-DA
case 0xd9: // READ CD-DA MSF
- goto nocmd;
+ if (sd->device_type != UAEDEV_CD)
+ goto nocmd;
+ tmp_len = (sd->cmd[6] << 16) | (sd->cmd[7] << 8) | sd->cmd[8];
+ // max block transfer size, it is usually smaller.
+ tmp_len *= 2352 + 96;
+ scsi_grow_buffer(sd, tmp_len);
break;
case 0x2f: // VERIFY
if (sd->cmd[1] & 2) {
@@ -163,7 +243,7 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
} else {
sd->data_len = data_len;
}
- sd->direction = scsi_data_dir (sd);
+ sd->direction = scsi_data_dir(sd);
if (sd->direction > 0 && sd->data_len == 0) {
sd->direction = 0;
}
@@ -175,12 +255,35 @@ nocmd:
return false;
}
-static void scsi_clear_sense(struct scsi_data *sd)
+void scsi_illegal_lun(struct scsi_data *sd)
+{
+ uae_u8 *s = sd->sense;
+
+ memset (s, 0, sizeof (sd->sense));
+ sd->status = SCSI_STATUS_CHECK_CONDITION;
+ s[0] = 0x70;
+ s[2] = SCSI_SK_ILLEGAL_REQ;
+ s[12] = SCSI_INVALID_LUN;
+ sd->sense_len = 0x12;
+}
+
+void scsi_clear_sense(struct scsi_data *sd)
{
memset (sd->sense, 0, sizeof (sd->sense));
memset (sd->reply, 0, sizeof (sd->reply));
sd->sense[0] = 0x70;
}
+static void showsense(struct scsi_data *sd)
+{
+ //if (log_scsiemu) {
+ // for (int i = 0; i < sd->sense_len; i++) {
+ // if (i > 0)
+ // write_log (_T("."));
+ // write_log (_T("%02X"), sd->buffer[i]);
+ // }
+ // write_log (_T("\n"));
+ //}
+}
static void copysense(struct scsi_data *sd)
{
bool sasi = sd->hfd && (sd->hfd->ci.unit_feature_level >= HD_LEVEL_SASI && sd->hfd->ci.unit_feature_level <= HD_LEVEL_SASI_ENHANCED);
@@ -196,6 +299,9 @@ static void copysense(struct scsi_data *sd)
sd->buffer[0] = 0x70;
sd->sense_len = tlen;
}
+ //if (log_scsiemu)
+ // write_log(_T("REQUEST SENSE %d (%d -> %d)\n"), sd->cmd[4], sd->sense_len, tlen);
+ showsense (sd);
sd->data_len = tlen;
scsi_clear_sense(sd);
}
@@ -208,6 +314,22 @@ static void copyreply(struct scsi_data *sd)
}
}
+static void scsi_set_unit_attention(struct scsi_data *sd, uae_u8 v1, uae_u8 v2)
+{
+ sd->unit_attention = (v1 << 8) | v2;
+}
+
+static void scsi_emulate_reset_device(struct scsi_data *sd)
+{
+ if (!sd)
+ return;
+ if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
+ scsi_clear_sense(sd);
+ // SCSI bus reset occurred
+ scsi_set_unit_attention(sd, 0x29, 0x02);
+ }
+}
+
static bool handle_ca(struct scsi_data *sd)
{
bool cc = sd->sense_len > 2 && sd->sense[2] >= 2;
@@ -278,7 +400,30 @@ void scsi_emulate_cmd(struct scsi_data *sd)
sd->cmd[1] &= ~(7 << 5);
sd->cmd[1] |= lun << 5;
}
- if (sd->device_type == UAEDEV_HDF) {
+#if SCSI_EMU_DEBUG
+ write_log (_T("CMD=%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x (%d,%d)\n"),
+ sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5], sd->cmd[6], sd->cmd[7], sd->cmd[8], sd->cmd[9],
+ sd->device_type, sd->nativescsiunit);
+#endif
+ if (sd->device_type == UAEDEV_CD && sd->cd_emu_unit >= 0) {
+
+ uae_u32 ua = 0;
+ ua = scsi_cd_emulate(sd->cd_emu_unit, NULL, 0, 0, 0, 0, 0, 0, 0, sd->atapi);
+ if (ua)
+ sd->unit_attention = ua;
+ if (handle_ca(sd)) {
+ if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+ scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, 0, 0, 0, 0, 0, 0, 0, sd->atapi); /* ack request sense */
+ copysense(sd);
+ } else {
+ sd->status = scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len, sd->atapi);
+ copyreply(sd);
+ }
+ }
+ gui_flicker_led(LED_CD, sd->uae_unitnum, 1);
+
+
+ } else if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
uae_u32 ua = 0;
ua = scsi_hd_emulate(sd->hfd, sd->hdhfd, NULL, 0, 0, 0, 0, 0, 0, 0);
@@ -295,6 +440,23 @@ void scsi_emulate_cmd(struct scsi_data *sd)
}
}
+ //} else if (sd->device_type == UAEDEV_TAPE && sd->nativescsiunit < 0) {
+
+ // uae_u32 ua = 0;
+ // ua = scsi_tape_emulate(sd->tape, NULL, 0, 0, 0, 0, 0, 0, 0);
+ // if (ua)
+ // sd->unit_attention = ua;
+ // if (handle_ca(sd)) {
+ // if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+ // scsi_tape_emulate(sd->tape, sd->cmd, 0, 0, 0, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); /* get request sense extra bits */
+ // copysense(sd);
+ // } else {
+ // sd->status = scsi_tape_emulate(sd->tape,
+ // sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+ // copyreply(sd);
+ // }
+ // }
+
} else if (sd->device_type == UAEDEV_DIR) {
uae_u32 ua = 0;
@@ -321,7 +483,29 @@ void scsi_emulate_cmd(struct scsi_data *sd)
}
}
+ } else if (sd->nativescsiunit >= 0) {
+ struct amigascsi as;
+
+ memset(sd->sense, 0, 256);
+ memset(&as, 0, sizeof as);
+ memcpy (&as.cmd, sd->cmd, sd->cmd_len);
+ as.flags = 2 | 1;
+ if (sd->direction > 0)
+ as.flags &= ~1;
+ as.sense_len = 32;
+ as.cmd_len = sd->cmd_len;
+ as.data = sd->buffer;
+ as.len = sd->direction < 0 ? DEVICE_SCSI_BUFSIZE : sd->data_len;
+ sys_command_scsi_direct_native(sd->nativescsiunit, -1, &as);
+ sd->status = as.status;
+ sd->data_len = as.len;
+ if (sd->status) {
+ sd->direction = 0;
+ sd->data_len = 0;
+ memcpy(sd->sense, as.sensedata, as.sense_len);
+ }
}
+ sd->offset = 0;
}
static void allocscsibuf(struct scsi_data *sd)
@@ -335,6 +519,8 @@ struct scsi_data *scsi_alloc_generic(struct hardfiledata *hfd, int type, int uae
struct scsi_data *sd = xcalloc(struct scsi_data, 1);
sd->hfd = hfd;
sd->id = -1;
+ sd->nativescsiunit = -1;
+ sd->cd_emu_unit = -1;
sd->blocksize = hfd->ci.blocksize;
sd->device_type = type;
sd->uae_unitnum = uae_unitnum;
@@ -342,10 +528,4887 @@ struct scsi_data *scsi_alloc_generic(struct hardfiledata *hfd, int type, int uae
return sd;
}
+struct scsi_data *scsi_alloc_hd(int id, struct hd_hardfiledata *hfd, int uae_unitnum)
+{
+ struct scsi_data *sd = xcalloc (struct scsi_data, 1);
+ sd->hdhfd = hfd;
+ sd->hfd = &hfd->hfd;
+ sd->id = id;
+ sd->nativescsiunit = -1;
+ sd->cd_emu_unit = -1;
+ sd->blocksize = hfd->hfd.virtual_rdb ? 512 : hfd->hfd.ci.blocksize;
+ sd->device_type = UAEDEV_HDF;
+ sd->uae_unitnum = uae_unitnum;
+ allocscsibuf(sd);
+ return sd;
+}
+
+struct scsi_data *scsi_alloc_cd(int id, int unitnum, bool atapi, int uae_unitnum)
+{
+ struct scsi_data *sd;
+ if (!sys_command_open (unitnum)) {
+ write_log (_T("SCSI: CD EMU scsi unit %d failed to open\n"), unitnum);
+ return NULL;
+ }
+ sd = xcalloc (struct scsi_data, 1);
+ sd->id = id;
+ sd->cd_emu_unit = unitnum;
+ sd->nativescsiunit = -1;
+ sd->atapi = atapi;
+ sd->blocksize = 2048;
+ sd->device_type = UAEDEV_CD;
+ sd->uae_unitnum = uae_unitnum;
+ allocscsibuf(sd);
+ return sd;
+}
+
+struct scsi_data *scsi_alloc_tape(int id, const TCHAR *tape_directory, bool readonly, int uae_unitnum)
+{
+ struct scsi_data_tape *tape;
+ tape = tape_alloc (id, tape_directory, readonly);
+ if (!tape)
+ return NULL;
+ struct scsi_data *sd = xcalloc (struct scsi_data, 1);
+ sd->id = id;
+ sd->nativescsiunit = -1;
+ sd->cd_emu_unit = -1;
+ sd->blocksize = tape->blocksize;
+ sd->tape = tape;
+ sd->device_type = UAEDEV_TAPE;
+ sd->uae_unitnum = uae_unitnum;
+ allocscsibuf(sd);
+ return sd;
+}
+
+struct scsi_data *scsi_alloc_native(int id, int nativeunit)
+{
+ struct scsi_data *sd;
+ if (!sys_command_open (nativeunit)) {
+ write_log (_T("SCSI: native scsi unit %d failed to open\n"), nativeunit);
+ return NULL;
+ }
+ sd = xcalloc (struct scsi_data, 1);
+ sd->id = id;
+ sd->nativescsiunit = nativeunit;
+ sd->cd_emu_unit = -1;
+ sd->blocksize = 2048;
+ sd->device_type = 0;
+ allocscsibuf(sd);
+ return sd;
+}
+
+void scsi_reset(void)
+{
+ //device_func_init (DEVICE_TYPE_SCSI);
+}
+
void scsi_free(struct scsi_data *sd)
{
if (!sd)
return;
+ if (sd->nativescsiunit >= 0) {
+ sys_command_close (sd->nativescsiunit);
+ sd->nativescsiunit = -1;
+ }
+ if (sd->cd_emu_unit >= 0) {
+ sys_command_close (sd->cd_emu_unit);
+ sd->cd_emu_unit = -1;
+ }
+ //tape_free (sd->tape);
xfree(sd->buffer);
xfree(sd);
}
+
+void scsi_start_transfer(struct scsi_data *sd)
+{
+ sd->offset = 0;
+}
+
+int scsi_send_data(struct scsi_data *sd, uae_u8 b)
+{
+ if (sd->offset < 0) {
+ write_log(_T("SCSI data offset is negative!\n"));
+ return 0;
+ }
+ if (sd->direction == 1) {
+ if (sd->offset >= sd->buffer_size) {
+ write_log (_T("SCSI data buffer overflow!\n"));
+ return 0;
+ }
+ sd->buffer[sd->offset++] = b;
+ } else if (sd->direction == 2) {
+ if (sd->offset >= 16) {
+ write_log (_T("SCSI command buffer overflow!\n"));
+ return 0;
+ }
+ sd->cmd[sd->offset++] = b;
+ if (sd->offset == sd->cmd_len)
+ return 1;
+ } else {
+ write_log (_T("scsi_send_data() without direction! (%02X)\n"), sd->cmd[0]);
+ return 0;
+ }
+ if (sd->offset == sd->data_len)
+ return 1;
+ return 0;
+}
+
+int scsi_receive_data(struct scsi_data *sd, uae_u8 *b, bool next)
+{
+ if (!sd->data_len)
+ return -1;
+ *b = sd->buffer[sd->offset];
+ if (next) {
+ sd->offset++;
+ if (sd->offset == sd->data_len)
+ return 1; // requested length got
+ }
+ return 0;
+}
+
+void free_scsi (struct scsi_data *sd)
+{
+ if (!sd)
+ return;
+ hdf_hd_close(sd->hdhfd);
+ scsi_free (sd);
+}
+
+int add_scsi_hd (struct scsi_data **sd, int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci)
+{
+ free_scsi (*sd);
+ *sd = NULL;
+ if (!hfd) {
+ hfd = xcalloc (struct hd_hardfiledata, 1);
+ memcpy (&hfd->hfd.ci, ci, sizeof (struct uaedev_config_info));
+ }
+ if (!hdf_hd_open (hfd))
+ return 0;
+ hfd->ansi_version = ci->unit_feature_level + 1;
+ *sd = scsi_alloc_hd (ch, hfd, ci->uae_unitnum);
+ return *sd ? 1 : 0;
+}
+
+int add_scsi_cd (struct scsi_data **sd, int ch, int unitnum)
+{
+ device_func_init (0);
+ free_scsi (*sd);
+ *sd = scsi_alloc_cd (ch, unitnum, false, unitnum);
+ return *sd ? 1 : 0;
+}
+
+int add_scsi_tape (struct scsi_data **sd, int ch, const TCHAR *tape_directory, bool readonly)
+{
+ free_scsi (*sd);
+ *sd = scsi_alloc_tape (ch, tape_directory, readonly, ch);
+ return *sd ? 1 : 0;
+}
+
+int add_scsi_device(struct scsi_data **sd, int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ if (ci->type == UAEDEV_CD)
+ return add_scsi_cd(sd, ch, ci->device_emu_unit);
+ else if (ci->type == UAEDEV_TAPE)
+ return add_scsi_tape(sd, ch, ci->rootdir, ci->readonly);
+ else if (ci->type == UAEDEV_HDF)
+ return add_scsi_hd(sd, ch, NULL, ci);
+ return 0;
+}
+
+void scsi_freenative(struct scsi_data **sd, int max)
+{
+ for (int i = 0; i < max; i++) {
+ free_scsi (sd[i]);
+ sd[i] = NULL;
+ }
+}
+
+void scsi_addnative(struct scsi_data **sd)
+{
+ int i, j;
+ int devices[MAX_TOTAL_SCSI_DEVICES];
+ int types[MAX_TOTAL_SCSI_DEVICES];
+ struct device_info dis[MAX_TOTAL_SCSI_DEVICES];
+
+ scsi_freenative (sd, MAX_TOTAL_SCSI_DEVICES);
+ i = 0;
+ while (i < MAX_TOTAL_SCSI_DEVICES) {
+ types[i] = -1;
+ devices[i] = -1;
+ if (sys_command_open (i)) {
+ if (sys_command_info (i, &dis[i], 0)) {
+ devices[i] = i;
+ types[i] = 100 - i;
+ if (dis[i].type == INQ_ROMD)
+ types[i] = 1000 - i;
+ }
+ sys_command_close (i);
+ }
+ i++;
+ }
+ i = 0;
+ while (devices[i] >= 0) {
+ j = i + 1;
+ while (devices[j] >= 0) {
+ if (types[i] > types[j]) {
+ int tmp = types[i];
+ types[i] = types[j];
+ types[j] = tmp;
+ }
+ j++;
+ }
+ i++;
+ }
+ i = 0; j = 0;
+ while (devices[i] >= 0 && j < 7) {
+ if (sd[j] == NULL) {
+ sd[j] = scsi_alloc_native(j, devices[i]);
+ write_log (_T("SCSI: %d:'%s'\n"), j, dis[i].label);
+ i++;
+ }
+ j++;
+ }
+}
+
+// raw scsi
+
+#define SCSI_IO_BUSY 0x80
+#define SCSI_IO_ATN 0x40
+#define SCSI_IO_SEL 0x20
+#define SCSI_IO_REQ 0x10
+#define SCSI_IO_DIRECTION 0x01
+#define SCSI_IO_COMMAND 0x02
+#define SCSI_IO_MESSAGE 0x04
+
+#define SCSI_SIGNAL_PHASE_FREE -1
+#define SCSI_SIGNAL_PHASE_ARBIT -2
+#define SCSI_SIGNAL_PHASE_SELECT_1 -3
+#define SCSI_SIGNAL_PHASE_SELECT_2 -4
+
+#define SCSI_SIGNAL_PHASE_DATA_OUT 0
+#define SCSI_SIGNAL_PHASE_DATA_IN 1
+#define SCSI_SIGNAL_PHASE_COMMAND 2
+#define SCSI_SIGNAL_PHASE_STATUS 3
+#define SCSI_SIGNAL_PHASE_MESSAGE_OUT 6
+#define SCSI_SIGNAL_PHASE_MESSAGE_IN 7
+
+struct raw_scsi
+{
+ int io;
+ int bus_phase;
+ bool atn;
+ bool ack;
+ bool wait_ack;
+ uae_u8 data_write;
+ uae_u8 status;
+ bool databusoutput;
+ int initiator_id, target_id;
+ struct scsi_data *device[MAX_TOTAL_SCSI_DEVICES];
+ struct scsi_data *target;
+ int msglun;
+};
+
+struct soft_scsi
+{
+ uae_u8 regs[32];
+ uae_u16 regs_400[2];
+ uae_u8 scratch_400[64];
+ int c400_count;
+ bool c400;
+ uae_u8 aic_reg;
+ struct raw_scsi rscsi;
+ bool irq;
+ bool intena;
+ bool level6;
+ bool enabled;
+ bool delayed_irq;
+ bool configured;
+ uae_u8 acmemory[128];
+ uaecptr baseaddress;
+ uaecptr baseaddress2;
+ uae_u8 *rom;
+ int rom_size;
+ int board_mask;
+ int board_mask2;
+ int board_size;
+ addrbank *bank;
+ int type;
+ int subtype;
+ int dma_direction;
+ bool dma_active;
+ bool dma_started;
+ bool dma_controller;
+ bool dma_drq;
+ bool dma_autodack;
+ struct romconfig *rc;
+ struct soft_scsi **self_ptr;
+
+ int dmac_direction;
+ uaecptr dmac_address;
+ int dmac_length;
+ int dmac_active;
+ int chip_state;
+
+ // add500
+ uae_u16 databuffer[2];
+ bool databuffer_empty;
+
+ // kronos/xebec
+ uae_u8 *databufferptr;
+ int databuffer_size;
+ int db_read_index;
+ int db_write_index;
+ void *eeprom;
+
+ // sasi
+ bool active_select;
+ bool wait_select;
+
+ // 12 Gauge needs this (Driver has buggy BSY test)
+ bool busy_delayed_hack;
+ int busy_delayed_hack_cnt;
+};
+
+
+#define MAX_SOFT_SCSI_UNITS 10
+static struct soft_scsi *soft_scsi_devices[MAX_SOFT_SCSI_UNITS];
+static struct soft_scsi *soft_scsi_units[NCR_LAST * MAX_DUPLICATE_EXPANSION_BOARDS];
+bool parallel_port_scsi;
+static struct soft_scsi *parallel_port_scsi_data;
+static struct soft_scsi *x86_hd_data;
+
+static void soft_scsi_free_unit(struct soft_scsi *s)
+{
+ if (!s)
+ return;
+ struct raw_scsi *rs = &s->rscsi;
+ for (int j = 0; j < 8; j++) {
+ free_scsi (rs->device[j]);
+ rs->device[j] = NULL;
+ }
+ eeprom93xx_free(s->eeprom);
+ xfree(s->databufferptr);
+ xfree(s->rom);
+ if (s->self_ptr)
+ *s->self_ptr = NULL;
+ xfree(s);
+}
+
+static void freescsi(struct soft_scsi **ncr)
+{
+ if (!ncr)
+ return;
+ for (int i = 0; i < MAX_SOFT_SCSI_UNITS; i++) {
+ if (soft_scsi_devices[i] == *ncr) {
+ soft_scsi_devices[i] = NULL;
+ }
+ }
+ if (*ncr) {
+ soft_scsi_free_unit(*ncr);
+ }
+ *ncr = NULL;
+}
+
+static struct soft_scsi *allocscsi(struct soft_scsi **ncr, struct romconfig *rc, int ch)
+{
+ struct soft_scsi *scsi;
+
+ if (ch < 0) {
+ freescsi(ncr);
+ *ncr = NULL;
+ }
+ if ((*ncr) == NULL) {
+ scsi = xcalloc(struct soft_scsi, 1);
+ for (int i = 0; i < MAX_SOFT_SCSI_UNITS; i++) {
+ if (soft_scsi_devices[i] == NULL) {
+ soft_scsi_devices[i] = scsi;
+ rc->unitdata = scsi;
+ scsi->rc = rc;
+ scsi->self_ptr = ncr;
+ if (ncr)
+ *ncr = scsi;
+ return scsi;
+ }
+ }
+ }
+ return *ncr;
+}
+
+static struct soft_scsi *getscsiboard(uaecptr addr)
+{
+ for (int i = 0; soft_scsi_devices[i]; i++) {
+ struct soft_scsi *s = soft_scsi_devices[i];
+ if (s->baseaddress2 && (addr & ~s->board_mask2) == s->baseaddress2)
+ return s;
+ if (!s->baseaddress && !s->configured)
+ return s;
+ if ((addr & ~s->board_mask) == s->baseaddress)
+ return s;
+ if (s->baseaddress == AUTOCONFIG_Z2 && addr < 65536)
+ return s;
+ }
+ return NULL;
+}
+
+static void raw_scsi_reset(struct raw_scsi *rs)
+{
+ rs->target = NULL;
+ rs->io = 0;
+ rs->bus_phase = SCSI_SIGNAL_PHASE_FREE;
+}
+
+extern addrbank soft_bank_generic;
+
+static void ew(struct soft_scsi *scsi, int addr, uae_u32 value)
+{
+ addr &= 0xffff;
+ if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
+ scsi->acmemory[addr] = (value & 0xf0);
+ scsi->acmemory[addr + 2] = (value & 0x0f) << 4;
+ } else {
+ scsi->acmemory[addr] = ~(value & 0xf0);
+ scsi->acmemory[addr + 2] = ~((value & 0x0f) << 4);
+ }
+}
+
+static struct soft_scsi *generic_soft_scsi_add(int ch, struct uaedev_config_info *ci, struct romconfig *rc, int type, int boardsize, int romsize, int romtype)
+{
+ struct soft_scsi *ss = allocscsi(&soft_scsi_units[type * MAX_DUPLICATE_EXPANSION_BOARDS + ci->controller_type_unit], rc, ch);
+ ss->type = type;
+ ss->configured = 0;
+ ss->bank = &soft_bank_generic;
+ ss->subtype = rc->subtype;
+ ss->intena = false;
+ if (boardsize > 0) {
+ ss->board_size = boardsize;
+ ss->board_mask = ss->board_size - 1;
+ }
+ if (!ss->board_mask && !ss->board_size) {
+ ss->board_size = 0x10000;
+ ss->board_mask = 0xffff;
+ }
+ ss->board_mask2 = ss->board_mask;
+ if (romsize >= 0) {
+ ss->rom_size = romsize;
+ xfree(ss->rom);
+ ss->rom = NULL;
+ if (romsize > 0) {
+ ss->rom = xcalloc(uae_u8, ss->rom_size);
+ memset(ss->rom, 0xff, ss->rom_size);
+ }
+ }
+ memset(ss->acmemory, 0xff, sizeof ss->acmemory);
+ const struct expansionromtype *ert = get_device_expansion_rom(romtype);
+ if (ert) {
+ const uae_u8 *ac = NULL;
+ if (ert->subtypes)
+ ac = ert->subtypes[rc->subtype].autoconfig;
+ else
+ ac = ert->autoconfig;
+ if (ac[0]) {
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ac[i];
+ ew(ss, i * 4, b);
+ }
+ }
+ }
+ raw_scsi_reset(&ss->rscsi);
+ if (ch < 0)
+ return ss;
+ add_scsi_device(&ss->rscsi.device[ch], ch, ci, rc);
+ return ss;
+}
+
+static void raw_scsi_busfree(struct raw_scsi *rs)
+{
+ rs->target = NULL;
+ rs->io = 0;
+ rs->bus_phase = SCSI_SIGNAL_PHASE_FREE;
+}
+
+static void bus_free(struct raw_scsi *rs)
+{
+ rs->bus_phase = SCSI_SIGNAL_PHASE_FREE;
+ rs->io = 0;
+}
+
+static int getbit(uae_u8 v)
+{
+ for (int i = 7; i >= 0; i--) {
+ if ((1 << i) & v)
+ return i;
+ }
+ return -1;
+}
+static int countbits(uae_u8 v)
+{
+ int cnt = 0;
+ for (int i = 7; i >= 0; i--) {
+ if ((1 << i) & v)
+ cnt++;
+ }
+ return cnt;
+}
+
+static void raw_scsi_reset_bus(struct soft_scsi *scsi)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+#if RAW_SCSI_DEBUG
+ write_log(_T("SCSI BUS reset\n"));
+#endif
+ raw_scsi_reset(r);
+ for (int i = 0; i < 8; i++) {
+ scsi_emulate_reset_device(r->device[i]);
+ }
+}
+
+
+static void raw_scsi_set_databus(struct raw_scsi *rs, bool databusoutput)
+{
+ rs->databusoutput = databusoutput;
+}
+
+static void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool atn)
+{
+ switch (rs->bus_phase)
+ {
+ case SCSI_SIGNAL_PHASE_FREE:
+ if (busy && !select && !rs->databusoutput) {
+ if (countbits(rs->data_write) != 1) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: invalid arbitration scsi id mask! (%02x) %08x\n"), rs->data_write, M68K_GETPC);
+#endif
+ return;
+ }
+ rs->bus_phase = SCSI_SIGNAL_PHASE_ARBIT;
+ rs->initiator_id = getbit(rs->data_write);
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: arbitration initiator id %d (%02x) %08x\n"), rs->initiator_id, rs->data_write, M68K_GETPC);
+#endif
+ } else if (!busy && select) {
+ if (countbits(rs->data_write) > 2 || rs->data_write == 0) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: invalid scsi id selected mask (%02x) %08x\n"), rs->data_write, M68K_GETPC);
+#endif
+ return;
+ }
+ rs->initiator_id = -1;
+ rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1;
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: selected scsi id mask (%02x) %08x\n"), rs->data_write, M68K_GETPC);
+#endif
+ raw_scsi_set_signal_phase(rs, busy, select, atn);
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_ARBIT:
+ rs->target_id = -1;
+ rs->target = NULL;
+ if (busy && select) {
+ rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1;
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_SELECT_1:
+ rs->atn = atn;
+ rs->msglun = -1;
+ rs->target_id = -1;
+ if (!busy) {
+ for (int i = 0; i < 8; i++) {
+ if (i == rs->initiator_id)
+ continue;
+ if ((rs->data_write & (1 << i)) && rs->device[i]) {
+ rs->target_id = i;
+ rs->target = rs->device[rs->target_id];
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: selected id %d %08x\n"), rs->target_id, M68K_GETPC);
+#endif
+ rs->io |= SCSI_IO_BUSY;
+ }
+ }
+#if RAW_SCSI_DEBUG
+ if (rs->target_id < 0) {
+ for (int i = 0; i < 8; i++) {
+ if (i == rs->initiator_id)
+ continue;
+ if ((rs->data_write & (1 << i)) && !rs->device[i]) {
+ write_log(_T("raw_scsi: selected non-existing id %d %08x\n"), i, M68K_GETPC);
+ }
+ }
+ }
+#endif
+ if (rs->target_id >= 0) {
+ rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_2;
+ } else {
+ if (!select) {
+ rs->bus_phase = SCSI_SIGNAL_PHASE_FREE;
+ }
+ }
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_SELECT_2:
+ if (!select) {
+ scsi_start_transfer(rs->target);
+ rs->bus_phase = rs->atn ? SCSI_SIGNAL_PHASE_MESSAGE_OUT : SCSI_SIGNAL_PHASE_COMMAND;
+ rs->io = SCSI_IO_BUSY | SCSI_IO_REQ;
+ }
+ break;
+ }
+}
+
+static uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs)
+{
+ uae_u8 v = rs->io;
+ if (rs->bus_phase >= 0)
+ v |= rs->bus_phase;
+ if (rs->ack)
+ v &= ~SCSI_IO_REQ;
+ return v;
+}
+
+static uae_u8 raw_scsi_get_data_2(struct raw_scsi *rs, bool next, bool nodebug)
+{
+ struct scsi_data *sd = rs->target;
+ uae_u8 v = 0;
+
+ switch (rs->bus_phase)
+ {
+ case SCSI_SIGNAL_PHASE_FREE:
+ v = 0;
+ break;
+ case SCSI_SIGNAL_PHASE_ARBIT:
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: arbitration %08x\n"), M68K_GETPC);
+#endif
+ v = rs->data_write;
+ break;
+ case SCSI_SIGNAL_PHASE_DATA_IN:
+#if RAW_SCSI_DEBUG > 2
+ scsi_receive_data(sd, &v, false);
+ write_log(_T("raw_scsi: read data byte %02x (%d/%d) %08x\n"), v, sd->offset, sd->data_len, M68K_GETPC);
+#endif
+ if (scsi_receive_data(sd, &v, next)) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: data in finished, %d bytes: status phase\n"), sd->offset);
+#endif
+ rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS;
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_STATUS:
+#if RAW_SCSI_DEBUG
+ if (!nodebug || next)
+ write_log(_T("raw_scsi: status byte read %02x. Next=%d PC=%08x\n"), sd->status, next, M68K_GETPC);
+#endif
+ v = sd->status;
+ if (next) {
+ sd->status = 0;
+ rs->bus_phase = SCSI_SIGNAL_PHASE_MESSAGE_IN;
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_MESSAGE_IN:
+#if RAW_SCSI_DEBUG
+ if (!nodebug || next)
+ write_log(_T("raw_scsi: message byte read %02x. Next=%d PC=%08x\n"), sd->status, next, M68K_GETPC);
+#endif
+ v = sd->status;
+ rs->status = v;
+ if (next) {
+ bus_free(rs);
+ }
+ break;
+ default:
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi_get_data but bus phase is %d %08x!\n"), rs->bus_phase, M68K_GETPC);
+#endif
+ break;
+ }
+
+ return v;
+}
+
+static uae_u8 raw_scsi_get_data(struct raw_scsi *rs, bool next)
+{
+ return raw_scsi_get_data_2(rs, next, true);
+}
+
+
+static int getmsglen(uae_u8 *msgp, int len)
+{
+ uae_u8 msg = msgp[0];
+ if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) ||msg >= 0x80)
+ return 1;
+ if (msg >= 0x20 && msg <= 0x2f)
+ return 2;
+ // extended message, at least 3 bytes
+ if (len < 2)
+ return 3;
+ return msgp[1];
+}
+
+static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
+{
+ struct scsi_data *sd = rs->target;
+ int len;
+
+ switch (rs->bus_phase)
+ {
+ case SCSI_SIGNAL_PHASE_SELECT_1:
+ case SCSI_SIGNAL_PHASE_FREE:
+ break;
+ case SCSI_SIGNAL_PHASE_COMMAND:
+ sd->cmd[sd->offset++] = data;
+ len = scsicmdsizes[sd->cmd[0] >> 5];
+#if RAW_SCSI_DEBUG > 1
+ write_log(_T("raw_scsi: got command byte %02x (%d/%d) %08x\n"), data, sd->offset, len, M68K_GETPC);
+#endif
+ if (sd->offset >= len) {
+ if (rs->msglun >= 0) {
+ sd->cmd[1] &= ~(0x80 | 0x40 | 0x20);
+ sd->cmd[1] |= rs->msglun << 5;
+ }
+ scsi_emulate_analyze(rs->target);
+ if (sd->direction > 0) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: data out %d bytes required\n"), sd->data_len);
+#endif
+ scsi_start_transfer(sd);
+ rs->bus_phase = SCSI_SIGNAL_PHASE_DATA_OUT;
+ } else if (sd->direction <= 0) {
+ scsi_emulate_cmd(sd);
+ scsi_start_transfer(sd);
+#if RAW_SCSI_DEBUG
+ if (sd->status) {
+ write_log(_T("raw_scsi: status = %d len = %d\n"), sd->status, sd->data_len);
+ }
+#endif
+ if (!sd->status && sd->data_len > 0) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: data in %d bytes waiting\n"), sd->data_len);
+#endif
+ rs->bus_phase = SCSI_SIGNAL_PHASE_DATA_IN;
+ } else {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: no data, status = %d\n"), sd->status);
+#endif
+ rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS;
+ }
+ }
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_DATA_OUT:
+#if RAW_SCSI_DEBUG > 2
+ write_log(_T("raw_scsi: write data byte %02x (%d/%d) %08x\n"), data, sd->offset, sd->data_len, M68K_GETPC);
+#endif
+ if (scsi_send_data(sd, data)) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi: data out finished, %d bytes\n"), sd->data_len);
+#endif
+ scsi_emulate_cmd(sd);
+ rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS;
+ }
+ break;
+ case SCSI_SIGNAL_PHASE_MESSAGE_OUT:
+ sd->msgout[sd->offset++] = data;
+ len = getmsglen(sd->msgout, sd->offset);
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi_put_data got message %02x (%d/%d) %08x\n"), data, sd->offset, len, M68K_GETPC);
+#endif
+ if (sd->offset >= len) {
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi_put_data got message %02x (%d bytes)\n"), sd->msgout[0], len);
+#endif
+ if ((sd->msgout[0] & (0x80 | 0x20)) == 0x80)
+ rs->msglun = sd->msgout[0] & 7;
+ scsi_start_transfer(sd);
+ rs->bus_phase = SCSI_SIGNAL_PHASE_COMMAND;
+ }
+ break;
+ default:
+#if RAW_SCSI_DEBUG
+ write_log(_T("raw_scsi_put_data but bus phase is %d!\n"), rs->bus_phase);
+#endif
+ break;
+ }
+}
+
+static void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput)
+{
+ rs->data_write = data;
+ if (!databusoutput)
+ return;
+ raw_scsi_write_data(rs, data);
+}
+
+static void raw_scsi_set_ack(struct raw_scsi *rs, bool ack)
+{
+ if (rs->ack != ack) {
+ rs->ack = ack;
+ if (!ack)
+ return;
+ if (rs->bus_phase < 0)
+ return;
+ if (!(rs->bus_phase & SCSI_IO_DIRECTION)) {
+ if (rs->databusoutput) {
+ raw_scsi_write_data(rs, rs->data_write);
+ }
+ } else {
+ raw_scsi_get_data_2(rs, true, false);
+ }
+ }
+}
+
+// APOLLO SOFTSCSI
+
+void apollo_scsi_bput(uaecptr addr, uae_u8 v, uae_u32 config)
+{
+ struct soft_scsi *as = getscsiboard(addr);
+ if (!as)
+ return;
+ int bank = addr & (0x800 | 0x400);
+ struct raw_scsi *rs = &as->rscsi;
+ addr &= 0x3fff;
+ if (bank == 0) {
+ raw_scsi_put_data(rs, v, true);
+ } else if (bank == 0xc00 && !(addr & 1)) {
+ as->irq = (v & 64) != 0;
+ raw_scsi_set_signal_phase(rs,
+ (v & 128) != 0,
+ (v & 32) != 0,
+ false);
+ } else if (bank == 0x400 && (addr & 1)) {
+ raw_scsi_put_data(rs, v, true);
+ raw_scsi_set_signal_phase(rs, true, false, false);
+ }
+ //write_log(_T("apollo scsi put %04x = %02x\n"), addr, v);
+}
+
+uae_u8 apollo_scsi_bget(uaecptr addr, uae_u32 config)
+{
+ struct soft_scsi *as = getscsiboard(addr);
+ if (!as)
+ return 0;
+ int bank = addr & (0x800 | 0x400);
+ struct raw_scsi *rs = &as->rscsi;
+ uae_u8 v = 0xff;
+ addr &= 0x3fff;
+ if (bank == 0) {
+ v = raw_scsi_get_data(rs, true);
+ } else if (bank == 0x800 && (addr & 1)) {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ if (config & 1) // scsi module installed
+ v |= 1;
+ if (t & SCSI_IO_BUSY)
+ v |= 128;
+ if (t & SCSI_IO_SEL)
+ v |= 32;
+ if (t & SCSI_IO_REQ)
+ v |= 2;
+ if (t & SCSI_IO_DIRECTION)
+ v |= 8;
+ if (t & SCSI_IO_COMMAND)
+ v |= 16;
+ if (t & SCSI_IO_MESSAGE)
+ v |= 4;
+ v ^= (1 | 2 | 4 | 8 | 16 | 32 | 128);
+ //v |= apolloscsi.irq ? 64 : 0;
+ }
+ //write_log(_T("apollo scsi get %04x = %02x\n"), addr, v);
+ return v;
+}
+
+void apollo_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+void apollo_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ if (ch < 0) {
+ generic_soft_scsi_add(-1, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO);
+ // make sure IDE side is also initialized
+ struct uaedev_config_info ci2 = { 0 };
+ apollo_add_ide_unit(-1, &ci2, rc);
+ } else {
+ if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST) {
+ apollo_add_ide_unit(ch, ci, rc);
+ } else {
+ generic_soft_scsi_add(ch, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO);
+ }
+ }
+}
+
+uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg);
+void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v);
+
+static void supra_do_dma(struct soft_scsi *ncr)
+{
+ int len = ncr->dmac_length;
+ for (int i = 0; i < len; i++) {
+ if (ncr->dmac_direction < 0) {
+ x_put_byte(ncr->dmac_address, ncr5380_bget(ncr, 0));
+ } else if (ncr->dmac_direction > 0) {
+ ncr5380_bput(ncr, 0, x_get_byte(ncr->dmac_address));
+ }
+ ncr->dmac_length--;
+ ncr->dmac_address++;
+ }
+}
+
+uae_u8 aic_bget_dma(struct soft_scsi *scsi, bool *phaseerr);
+void aic_bput_dma(struct soft_scsi *scsi, uae_u8 v, bool *phaseerr);
+
+static void hardframe_do_dma(struct soft_scsi *ncr)
+{
+ int len = ncr->dmac_length;
+ for (int i = 0; i < len; i++) {
+ bool phaseerr;
+ if (ncr->dmac_direction < 0) {
+ uae_u8 v = aic_bget_dma(ncr, &phaseerr);
+ if (phaseerr)
+ break;
+ x_put_byte(ncr->dmac_address, v);
+ } else if (ncr->dmac_direction > 0) {
+ uae_u8 v = x_get_byte(ncr->dmac_address);
+ aic_bput_dma(ncr, v, &phaseerr);
+ if (phaseerr)
+ break;
+ }
+ ncr->dmac_length--;
+ ncr->dmac_address++;
+ }
+}
+
+static void xebec_do_dma(struct soft_scsi *ncr)
+{
+ struct raw_scsi *rs = &ncr->rscsi;
+ while (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+ x_put_byte(ncr->dmac_address, ncr5380_bget(ncr, 8));
+ } else if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) {
+ ncr5380_bput(ncr, 8, x_get_byte(ncr->dmac_address));
+ }
+ }
+}
+
+static void overdrive_do_dma(struct soft_scsi *ncr)
+{
+ struct raw_scsi *rs = &ncr->rscsi;
+ while ((rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) && ncr->dmac_length > 0) {
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+ x_put_byte(ncr->dmac_address, ncr5380_bget(ncr, 8));
+ ncr->dmac_address++;
+ ncr->dmac_length--;
+ } else if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) {
+ ncr5380_bput(ncr, 8, x_get_byte(ncr->dmac_address));
+ ncr->dmac_address++;
+ ncr->dmac_length--;
+ }
+ }
+}
+
+
+static void dma_check(struct soft_scsi *ncr)
+{
+ if (ncr->dmac_active && ncr->dma_direction) {
+
+ m68k_cancel_idle();
+
+ if (ncr->type == NCR5380_SUPRA && ncr->subtype == 4) {
+ if (ncr->dmac_direction != ncr->dma_direction) {
+ write_log(_T("SUPRADMA: mismatched direction\n"));
+ ncr->dmac_active = 0;
+ return;
+ }
+ supra_do_dma(ncr);
+ }
+
+ if (ncr->type == NCR5380_XEBEC) {
+
+ xebec_do_dma(ncr);
+
+ }
+
+ if (ncr->type == NONCR_HARDFRAME) {
+
+ hardframe_do_dma(ncr);
+
+ }
+
+ if (ncr->type == NCR5380_OVERDRIVE) {
+
+ overdrive_do_dma(ncr);
+
+ }
+
+ ncr->dmac_active = 0;
+ }
+}
+
+void x86_doirq(uint8_t irqnum);
+static void ncr80_rethink(void)
+{
+ for (int i = 0; soft_scsi_devices[i]; i++) {
+ struct soft_scsi *s = soft_scsi_devices[i];
+ if (s->irq && s->intena && ((s->c400 && (s->regs_400[0] & 0x10) && !s->c400_count) || !s->c400)) {
+ if (soft_scsi_devices[i] == x86_hd_data) {
+ ;// x86_doirq(5);
+ } else {
+ safe_interrupt_set(soft_scsi_devices[i]->level6);
+ }
+ }
+ }
+}
+
+// AIC-6250
+
+static void aic_int(struct soft_scsi *scsi, uae_u8 mask)
+{
+ scsi->regs[16 + 8] |= mask;
+ if ((scsi->regs[16 + 8] & scsi->regs[3]) & 0x1f) {
+ scsi->irq = true;
+ devices_rethink_all(ncr80_rethink);
+ } else {
+ scsi->irq = false;
+ }
+}
+
+static bool aic_phase_match(struct soft_scsi *scsi)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+ uae_u8 phase = r->bus_phase;
+ bool cd = (phase & SCSI_IO_COMMAND) != 0;
+ bool io = (phase & SCSI_IO_DIRECTION) != 0;
+ bool msg = (phase & SCSI_IO_MESSAGE) != 0;
+ if (phase >= 0 &&
+ ((scsi->regs[9] >> 5) & 1) == msg &&
+ ((scsi->regs[9] >> 6) & 1) == io &&
+ ((scsi->regs[9] >> 7) & 1) == cd) {
+ return true;
+ }
+ return false;
+}
+
+static void aic_reg_inc(struct soft_scsi *scsi)
+{
+ if (scsi->aic_reg >= 8)
+ return;
+ scsi->aic_reg++;
+}
+
+static uae_u8 aic_bget_reg(struct soft_scsi *scsi)
+{
+ return scsi->aic_reg & 15;
+}
+
+uae_u8 aic_bget_dma(struct soft_scsi *scsi, bool *phaseerr)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+ if (!scsi->dma_direction)
+ return 0;
+ if (!aic_phase_match(scsi)) {
+ if (phaseerr)
+ *phaseerr = true;
+ if (!scsi->dmac_active) {
+ aic_int(scsi, 0x08); // COMMAND DONE
+ }
+ scsi->dma_direction = 0;
+ return 0;
+ }
+ if (phaseerr)
+ *phaseerr = false;
+ return raw_scsi_get_data(r, true);
+}
+
+static uae_u8 aic_bget_data(struct soft_scsi *scsi)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+ int reg = scsi->aic_reg;
+ uae_u8 v = scsi->regs[reg];
+
+ aic_reg_inc(scsi);
+
+ switch (reg)
+ {
+ case 0:
+ v = (scsi->dmac_length >> 0) & 0xff;
+ break;
+ case 1:
+ v = (scsi->dmac_length >> 8) & 0xff;
+ break;
+ case 2:
+ v = (scsi->dmac_length >> 16) & 0xff;
+ break;
+ case 6: // REVISION CONTROL
+ v = 2;
+ break;
+ case 7: // STATUS 0
+ {
+ v = scsi->regs[reg + 16] & 2;
+ if (r->bus_phase == SCSI_SIGNAL_PHASE_FREE)
+ v |= 0x10; // BUS FREE
+ if (raw_scsi_get_signal_phase(r) & SCSI_IO_REQ)
+ v |= 0x04; // SCSI REQ ON
+ if (scsi->dmac_length == 0)
+ v |= 0x01; // DMA BYTE COUNT ZERO
+ if ((raw_scsi_get_signal_phase(r) & SCSI_IO_REQ) && !aic_phase_match(scsi))
+ v |= 0x20; // PHASE MISMATCH
+ }
+ break;
+ case 8: // STATUS 1
+ {
+ v = scsi->regs[reg + 16] | 0x40;
+ if (scsi->regs[8] & 2) { // SCSI RESET OUT
+ v |= 0x20; // SCSI RESET IN
+ } else {
+ v &= ~0x20;
+ }
+ scsi->regs[reg + 16] = v;
+ }
+ break;
+ case 9: // SCSI SIGNAL
+ {
+ uae_u8 t = raw_scsi_get_signal_phase(r);
+ v = 0;
+ if (t & SCSI_IO_BUSY)
+ v |= 0x04;
+ if (t & SCSI_IO_ATN)
+ v |= 0x10;
+ if (t & SCSI_IO_SEL)
+ v |= 0x08;
+ if (t & SCSI_IO_REQ)
+ v |= 0x02;
+ if (t & SCSI_IO_DIRECTION)
+ v |= 0x40;
+ if (t & SCSI_IO_COMMAND)
+ v |= 0x80;
+ if (t & SCSI_IO_MESSAGE)
+ v |= 0x20;
+ if (r->ack)
+ v |= 0x01;
+ }
+ break;
+ case 10: // SCSI ID DATA
+ v = scsi->regs[16 + 10];
+ break;
+ case 13:
+ {
+ // SCSI ID (4 to 7 only)
+ int vv = scsi->rc->device_id - 4;
+ if (vv < 0)
+ vv = 0;
+ vv ^= 3;
+ vv = (vv >> 1) | (vv << 1);
+ v = (vv & 3) << 5;
+ }
+ break;
+ }
+ return v;
+}
+
+static void aic_bput_reg(struct soft_scsi *scsi, uae_u8 v)
+{
+ scsi->aic_reg = v & 15;
+}
+
+void aic_bput_dma(struct soft_scsi *scsi, uae_u8 v, bool *phaseerr)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+ if (!scsi->dma_direction)
+ return;
+ if (!aic_phase_match(scsi)) {
+ if (phaseerr)
+ *phaseerr = true;
+ if (!scsi->dmac_active) {
+ aic_int(scsi, 0x08); // COMMAND DONE
+ }
+ scsi->dma_direction = 0;
+ return;
+ }
+ if (phaseerr)
+ *phaseerr = false;
+ raw_scsi_put_data(r, v, true);
+}
+
+static void aic_bput_data(struct soft_scsi *scsi, uae_u8 v)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+ int reg = scsi->aic_reg;
+
+ aic_reg_inc(scsi);
+
+ switch (reg)
+ {
+ case 0:
+ scsi->dmac_length &= 0xffff00;
+ scsi->dmac_length |= v << 0;
+ break;
+ case 1:
+ scsi->dmac_length &= 0xff00ff;
+ scsi->dmac_length |= v << 8;
+ break;
+ case 2:
+ scsi->dmac_length &= 0x00ffff;
+ scsi->dmac_length |= v << 16;
+ break;
+ case 3: // INT MSK
+ // cleared interrupt mask clears request
+ scsi->regs[16 + 8] &= v | ~0x1f;
+ if (v & 0x40) { // ARB/SEL START
+ raw_scsi_put_data(r, scsi->regs[10], false);
+ raw_scsi_set_signal_phase(r, false, true, (v & 0x20) != 0);
+ raw_scsi_set_signal_phase(r, true, false, false);
+ aic_int(scsi, 0x08); // COMMAND DONE
+ scsi->regs[11] = scsi->regs[10]; // SOURCE AND DESTINATION ID = DATA
+ v &= ~0x40;
+ }
+ aic_int(scsi, 0);
+ break;
+ case 5:
+ if (v & 1) { // DMA XFER EN
+ scsi->dma_direction = (v & 2) ? 1 : -1;
+ if (scsi->dmac_active) {
+ dma_check(scsi);
+ aic_int(scsi, 0x08); // COMMAND DONE
+ scsi->dma_direction = 0;
+ }
+ } else {
+ scsi->dma_direction = 0;
+ }
+ break;
+ case 8: // CONTROL
+ if (v & 2) { // SCSI RESET OUT
+ raw_scsi_reset(r);
+ }
+ if (v & 0x80) { // AUTO SCSI PIO REQ
+ if (aic_phase_match(scsi)) {
+ int phase = r->bus_phase;
+ bool io = (phase & SCSI_IO_DIRECTION) != 0;
+ scsi->regs[16 + 7] &= ~0x02;
+ if (!io) {
+ raw_scsi_put_data(r, scsi->regs[10], true);
+ } else {
+ scsi->regs[16 + 10] = raw_scsi_get_data(r, true);
+ }
+ aic_int(scsi, 0x08); // COMMAND DONE
+ if (phase != r->bus_phase)
+ scsi->regs[16 + 7] |= 0x02; // SCSI PHASE CHG/ATN
+ v &= ~0x80;
+ } else {
+ aic_int(scsi, 0x10); // ERROR
+ }
+ }
+ break;
+ case 9: // SCSI SIGNAL
+
+ break;
+ }
+ scsi->regs[reg] = v;
+}
+
+// NCR 53C80/MISC SCSI-LIKE
+
+static void ncr5380_set_irq(struct soft_scsi *scsi)
+{
+ if (scsi->irq)
+ return;
+ scsi->irq = true;
+ devices_rethink_all(ncr80_rethink);
+ if (scsi->delayed_irq)
+ x_do_cycles(2 * CYCLE_UNIT);
+#if NCR5380_DEBUG_IRQ
+ write_log(_T("IRQ\n"));
+#endif
+}
+
+static void ncr5380_databusoutput(struct soft_scsi *scsi)
+{
+ bool databusoutput = (scsi->regs[1] & 1) != 0;
+ struct raw_scsi *r = &scsi->rscsi;
+
+ if (r->bus_phase >= 0 && (r->bus_phase & SCSI_IO_DIRECTION))
+ databusoutput = false;
+ raw_scsi_set_databus(r, databusoutput);
+}
+
+static void ncr5380_check(struct soft_scsi *scsi)
+{
+ ncr5380_databusoutput(scsi);
+}
+
+static void ncr5380_check_phase(struct soft_scsi *scsi)
+{
+ if (!(scsi->regs[2] & 2))
+ return;
+ if (scsi->regs[2] & 0x40)
+ return;
+ if (scsi->rscsi.bus_phase != (scsi->regs[3] & 7)) {
+ if (scsi->dma_controller) {
+ scsi->regs[5] |= 0x80; // end of dma
+ scsi->regs[3] |= 0x80; // last byte sent
+ }
+ ncr5380_set_irq(scsi);
+ }
+}
+
+static void ncr5380_reset(struct soft_scsi *scsi, bool busreset)
+{
+ struct raw_scsi *r = &scsi->rscsi;
+
+ memset(scsi->regs, 0, sizeof scsi->regs);
+ if (busreset) {
+ raw_scsi_reset_bus(scsi);
+ scsi->regs[1] = 0x80;
+ ncr5380_set_irq(scsi);
+ }
+}
+
+uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
+{
+ if (reg > 8)
+ return 0;
+ uae_u8 v = scsi->regs[reg];
+ struct raw_scsi *r = &scsi->rscsi;
+ switch(reg)
+ {
+ case 1:
+ break;
+ case 4:
+ {
+ uae_u8 oldv = v;
+ uae_u8 t = raw_scsi_get_signal_phase(r);
+ v = 0;
+ if (t & SCSI_IO_BUSY)
+ v |= 1 << 6;
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 5;
+ if (t & SCSI_IO_SEL)
+ v |= 1 << 1;
+ if (r->bus_phase >= 0)
+ v |= r->bus_phase << 2;
+ if (scsi->regs[1] & 0x80)
+ v |= 0x80;
+
+ scsi->regs[reg] = v;
+ if (scsi->busy_delayed_hack && !(v & (1 << 6)) && (oldv & (1 << 6))) {
+ scsi->busy_delayed_hack_cnt = 2;
+ }
+ if (scsi->busy_delayed_hack_cnt > 0) {
+ scsi->busy_delayed_hack_cnt--;
+ v |= 1 << 6;
+ }
+ }
+ break;
+ case 5:
+ {
+ uae_u8 t = raw_scsi_get_signal_phase(r);
+ v &= (0x80 | 0x40 | 0x20 | 0x04);
+ if (t & SCSI_IO_ATN)
+ v |= 1 << 1;
+ if (r->bus_phase == (scsi->regs[3] & 7)) {
+ v |= 1 << 3;
+ }
+ if (scsi->irq) {
+ v |= 1 << 4;
+ }
+ if (scsi->dma_drq || (scsi->dma_active && !scsi->dma_controller && r->bus_phase == (scsi->regs[3] & 7))) {
+ scsi->dma_drq = true;
+ if (scsi->dma_autodack && r->bus_phase != (scsi->regs[3] & 7))
+ scsi->dma_drq = false;
+ if (scsi->dma_drq)
+ v |= 1 << 6;
+ }
+ if (scsi->regs[2] & 4) {
+ // monitor busy
+ if (r->bus_phase == SCSI_SIGNAL_PHASE_FREE) {
+ // any loss of busy = Busy error
+ // not just "unexpected" loss of busy
+ v |= 1 << 2;
+ scsi->dmac_active = false;
+ }
+ }
+ }
+ break;
+ case 0:
+ v = raw_scsi_get_data(r, false);
+ break;
+ case 6:
+ v = raw_scsi_get_data(r, scsi->dma_active);
+ ncr5380_check_phase(scsi);
+ break;
+ case 7:
+ scsi->irq = false;
+ break;
+ case 8: // fake dma port
+ v = raw_scsi_get_data(r, true);
+ ncr5380_check_phase(scsi);
+ break;
+ }
+ ncr5380_check(scsi);
+ return v;
+}
+
+void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+ if (reg > 8)
+ return;
+ bool dataoutput = (scsi->regs[1] & 1) != 0;
+ struct raw_scsi *r = &scsi->rscsi;
+ uae_u8 old = scsi->regs[reg];
+ scsi->regs[reg] = v;
+ switch(reg)
+ {
+ case 0:
+ {
+ r->data_write = v;
+ // assert data bus can be only active if direction is out
+ // and bus phase matches
+ if (r->databusoutput) {
+ if (((scsi->regs[2] & 2) && scsi->dma_active) || r->bus_phase < 0) {
+ raw_scsi_write_data(r, v);
+ ncr5380_check_phase(scsi);
+ }
+ }
+ }
+ break;
+ case 1:
+ {
+ scsi->regs[reg] &= ~((1 << 5) | (1 << 6));
+ scsi->regs[reg] |= old & ((1 << 5) | (1 << 6)); // AIP, LA
+ if (!(v & 0x80)) {
+ bool init = r->bus_phase < 0;
+ ncr5380_databusoutput(scsi);
+ if (init && !dataoutput && (v & 1) && (scsi->regs[2] & 1)) {
+ r->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1;
+ }
+ raw_scsi_set_signal_phase(r,
+ (v & (1 << 3)) != 0,
+ (v & (1 << 2)) != 0,
+ (v & (1 << 1)) != 0);
+ if (!(scsi->regs[2] & 2))
+ raw_scsi_set_ack(r, (v & (1 << 4)) != 0);
+ }
+ if (v & 0x80) { // RST
+ ncr5380_reset(scsi, true);
+ }
+ }
+ break;
+ case 2:
+ if ((v & 1) && !(old & 1)) { // Arbitrate
+ r->databusoutput = false;
+ raw_scsi_set_signal_phase(r, true, false, false);
+ scsi->regs[1] |= 1 << 6; // AIP
+ scsi->regs[1] &= ~(1 << 5); // LA
+ } else if (!(v & 1) && (old & 1)) {
+ scsi->regs[1] &= ~(1 << 6);
+ }
+ if (!(v & 2)) {
+ // end of dma and dma request
+ scsi->regs[5] &= ~(0x80 | 0x40);
+ scsi->dma_direction = 0;
+ scsi->dma_active = false;
+ scsi->dma_drq = false;
+ }
+ break;
+ case 5:
+ scsi->regs[reg] = old;
+ if (scsi->regs[2] & 2) {
+ scsi->dma_direction = 1;
+ scsi->dma_active = true;
+ dma_check(scsi);
+ }
+#if NCR5380_DEBUG
+ write_log(_T("DMA send PC=%08x\n"), M68K_GETPC);
+#endif
+ break;
+ case 6:
+ if (scsi->regs[2] & 2) {
+ scsi->dma_direction = 1;
+ scsi->dma_active = true;
+ scsi->dma_started = true;
+ }
+#if NCR5380_DEBUG
+ write_log(_T("DMA target recv PC=%08x\n"), M68K_GETPC);
+#endif
+ break;
+ case 7:
+ if (scsi->regs[2] & 2) {
+ scsi->dma_direction = -1;
+ scsi->dma_active = true;
+ scsi->dma_started = true;
+ dma_check(scsi);
+ }
+#if NCR5380_DEBUG
+ write_log(_T("DMA initiator recv PC=%08x\n"), M68K_GETPC);
+#endif
+ break;
+ case 8: // fake dma port
+ if (r->bus_phase == (scsi->regs[3] & 7)) {
+ raw_scsi_put_data(r, v, true);
+ }
+ ncr5380_check_phase(scsi);
+ break;
+ }
+ ncr5380_check(scsi);
+}
+
+static bool ncr53400_5380(struct soft_scsi *scsi)
+{
+ if (scsi->irq)
+ scsi->regs_400[1] = 0;
+ return !scsi->regs_400[1];
+}
+
+static void ncr53400_dmacount(struct soft_scsi *scsi)
+{
+ scsi->c400_count++;
+ if (scsi->c400_count == 128) {
+ scsi->c400_count = 0;
+ scsi->regs_400[1]--;
+ scsi->regs_400[1] &= 0xff;
+ ncr5380_check_phase(scsi);
+ scsi->regs[5] |= 0x80; // end of dma
+ scsi->regs[3] |= 0x80; // last byte sent
+ ncr5380_set_irq(scsi);
+ }
+}
+
+static uae_u8 ncr53400_bget(struct soft_scsi *scsi, int reg)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 v = 0;
+ uae_u8 csr = (uae_u8)scsi->regs_400[0];
+
+ if (ncr53400_5380(scsi) && reg < 8) {
+ v = ncr5380_bget(scsi, reg);
+#if NCR53400_DEBUG
+ static uae_u8 lastreg, lastval;
+ if (lastreg != reg || lastval != v) {
+ write_log(_T("53C80 REG GET %02x -> %02x\n"), reg, v);
+ lastreg = reg;
+ lastval = v;
+ }
+#endif
+ return v;
+ }
+ if (reg & 0x80) {
+ v = raw_scsi_get_data(rs, true);
+ ncr53400_dmacount(scsi);
+#if NCR53400_DEBUG
+ write_log(_T("53C400 DATA GET %02x %d\n"), v, scsi->c400_count);
+#endif
+ } else if (reg & 0x100) {
+ switch (reg) {
+ case 0x100:
+ if (scsi->regs_400[1]) {
+ v |= 0x02;
+ } else {
+ v |= 0x04;
+ }
+ if (ncr53400_5380(scsi))
+ v |= 0x80;
+ if (scsi->irq)
+ v |= 0x01;
+ break;
+ case 0x101:
+ v = (uae_u8)scsi->regs_400[1];
+ break;
+ }
+#if NCR53400_DEBUG
+ write_log(_T("53C400 REG GET %02x -> %02x\n"), reg, v);
+#endif
+ } else if (reg & 0x200) {
+ v = scsi->scratch_400[reg & 0x3f];
+ }
+ ncr5380_check_phase(scsi);
+ return v;
+}
+
+static void ncr53400_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 csr = (uae_u8)scsi->regs_400[0];
+
+ if (ncr53400_5380(scsi) && reg < 8) {
+ ncr5380_bput(scsi, reg, v);
+#if NCR53400_DEBUG
+ write_log(_T("53C80 REG PUT %02x -> %02x\n"), reg, v);
+#endif
+ return;
+ }
+ if (reg & 0x80) {
+ raw_scsi_put_data(rs, v, true);
+ ncr53400_dmacount(scsi);
+#if NCR53400_DEBUG
+ write_log(_T("53C400 DATA PUT %02x %d\n"), v, scsi->c400_count);
+#endif
+ } else if (reg & 0x100) {
+ switch (reg) {
+ case 0x100:
+ scsi->regs_400[0] = v;
+ if (v & 0x80) {
+ // 53C400 reset does not reset 53C80
+ scsi->regs_400[0] = 0x80;
+ scsi->regs_400[1] = 0;
+ }
+ break;
+ case 0x101:
+ scsi->regs_400[1] = v;
+ if (v == 0)
+ scsi->regs_400[1] = 256;
+ scsi->c400_count = 0;
+ break;
+ }
+#if NCR53400_DEBUG
+ write_log(_T("53C400 REG PUT %02x -> %02x\n"), reg, v);
+#endif
+ } else if (reg & 0x200) {
+ scsi->scratch_400[reg & 0x3f] = v;
+ }
+ ncr5380_check_phase(scsi);
+}
+
+/* SASI */
+
+static uae_u8 sasi_tecmar_bget(struct soft_scsi *scsi, int reg)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 v = 0;
+
+ if (reg == 1) {
+
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ switch (rs->bus_phase)
+ {
+ case SCSI_SIGNAL_PHASE_DATA_OUT:
+ v = 0;
+ break;
+ case SCSI_SIGNAL_PHASE_DATA_IN:
+ v = 1 << 2;
+ break;
+ case SCSI_SIGNAL_PHASE_COMMAND:
+ v = 1 << 3;
+ break;
+ case SCSI_SIGNAL_PHASE_STATUS:
+ v = (1 << 2) | (1 << 3);
+ break;
+ case SCSI_SIGNAL_PHASE_MESSAGE_IN:
+ v = (1 << 2) | (1 << 3) | (1 << 4);
+ break;
+ }
+ if (t & SCSI_IO_BUSY)
+ v |= 1 << 1;
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 0;
+ v = v ^ 0xff;
+
+ } else {
+
+ v = raw_scsi_get_data_2(rs, true, false);
+
+ }
+
+ //write_log(_T("SASI READ port %d: %02x\n"), reg, v);
+
+ return v;
+}
+
+static void sasi_tecmar_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+
+ //write_log(_T("SASI WRITE port %d: %02x\n"), reg, v);
+
+ if (reg == 1) {
+ if ((v & 1)) {
+ raw_scsi_busfree(rs);
+ }
+ if ((v & 2) && !scsi->active_select) {
+ // select?
+ scsi->active_select = true;
+ if (!rs->data_write)
+ scsi->wait_select = true;
+ else
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ } else if (!(v & 2) && scsi->active_select) {
+ scsi->active_select = false;
+ raw_scsi_set_signal_phase(rs, false, false, false);
+ }
+ } else {
+ raw_scsi_put_data(rs, v, true);
+ if (scsi->wait_select && scsi->active_select)
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ scsi->wait_select = false;
+ }
+}
+
+static uae_u8 sasi_microforge_bget(struct soft_scsi *scsi, int reg)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 v = 0;
+
+ if (reg == 1) {
+
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ if (rs->bus_phase >= 0) {
+ if (rs->bus_phase & SCSI_IO_MESSAGE)
+ v |= 1 << 1;
+ if (rs->bus_phase & SCSI_IO_COMMAND)
+ v |= 1 << 2;
+ if (rs->bus_phase & SCSI_IO_DIRECTION)
+ v |= 1 << 3;
+ }
+ if (t & SCSI_IO_BUSY)
+ v |= 1 << 0;
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 4;
+ v = v ^ 0xff;
+
+ } else {
+
+ v = raw_scsi_get_data_2(rs, true, false);
+
+ }
+
+ //write_log(_T("SASI READ port %d: %02x\n"), reg, v);
+
+ return v;
+}
+
+static void sasi_microforge_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+
+ //write_log(_T("SASI WRITE port %d: %02x\n"), reg, v);
+
+ if (reg == 1) {
+ if ((v & 4) && !scsi->active_select) {
+ // select?
+ scsi->active_select = true;
+ if (!rs->data_write)
+ scsi->wait_select = true;
+ else
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ } else if (!(v & 4) && scsi->active_select) {
+ scsi->active_select = false;
+ raw_scsi_set_signal_phase(rs, false, false, false);
+ }
+ } else {
+ raw_scsi_put_data(rs, v, true);
+ if (scsi->wait_select && scsi->active_select)
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ scsi->wait_select = false;
+ }
+}
+
+// OMTI 5510
+static void omti_irq(struct soft_scsi *scsi)
+{
+ if (scsi->chip_state & 2) {
+ scsi->chip_state |= 0x100;
+ if (scsi->intena)
+ ncr5380_set_irq(scsi);
+ }
+}
+static void omti_check_state(struct soft_scsi *scsi)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ if ((rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) && (scsi->chip_state & 1)) {
+ if (scsi->intena && (scsi->chip_state & 2)) {
+ ncr5380_set_irq(scsi);
+ }
+ }
+}
+
+static uae_u8 omti_bget(struct soft_scsi *scsi, int reg)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ uae_u8 v = 0;
+
+ switch (reg)
+ {
+ case 0: // DATA IN
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS) {
+ v = raw_scsi_get_data_2(rs, true, false);
+ // get message (not used in OMTI protocol)
+ raw_scsi_get_data_2(rs, true, false);
+ } else {
+ v = raw_scsi_get_data_2(rs, true, false);
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS) {
+ omti_irq(scsi); // command complete interrupt
+ }
+ }
+ break;
+ case 1: // STATUS
+ if (rs->bus_phase >= 0)
+ v |= 8; // busy
+ if (v & 8) {
+ if (t & SCSI_IO_REQ)
+ v |= 1; // req
+ if (t & SCSI_IO_DIRECTION)
+ v |= 2;
+ if (t & SCSI_IO_COMMAND)
+ v |= 4;
+ }
+ v |= 0x80 | 0x40; // always one
+ if ((rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) && (scsi->chip_state & 1))
+ v |= 0x10; // DREQ
+ if (scsi->chip_state & 0x100)
+ v |= 0x20; // IREQ
+ if (rs->bus_phase != SCSI_SIGNAL_PHASE_STATUS) {
+ scsi->chip_state &= ~0x100;
+ scsi->irq = false;
+ }
+ break;
+ case 2: // CONFIGURATION
+ v = 0xff;
+ break;
+ case 3: // -
+ break;
+ }
+ omti_check_state(scsi);
+ return v;
+}
+static void omti_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+ struct raw_scsi *rs = &scsi->rscsi;
+ switch (reg)
+ {
+ case 0: // DATA OUT
+ raw_scsi_put_data(rs, v, true);
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS)
+ omti_irq(scsi); // command complete interrupt
+ break;
+ case 1: // RESET
+ raw_scsi_busfree(rs);
+ scsi->chip_state = 0;
+ break;
+ case 2: // SELECT
+ rs->data_write = 0x01;
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ raw_scsi_set_signal_phase(rs, false, false, false);
+ break;
+ case 3: // MASK (bit 1 = interrupt enable, bit 0 = DMA enable)
+ scsi->chip_state &= ~0xff;
+ scsi->chip_state |= v;
+ break;
+ }
+ omti_check_state(scsi);
+}
+
+static int supra_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ int reg = (addr & 0x0f) >> 1;
+ if ((addr & 0x20) && ncr->subtype == 0) {
+ // "dma" data in/out space
+ reg = 8;
+ if (!(ncr->regs[2] & 2))
+ cpu_halt(CPU_HALT_FAKE_DMA);
+ }
+ return reg;
+}
+
+static int stardrive_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if ((addr & 0x0191) == 0x191) {
+ // "dma" data in/out register
+ return 8;
+ }
+ if ((addr & 0x0181) != 0x181)
+ return -1;
+ int reg = (addr >> 1) & 7;
+ return reg;
+}
+
+static int cltd_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (!(addr & 1)) {
+ return -1;
+ }
+ int reg = (addr >> 1) & 7;
+ return reg;
+}
+
+static int protar_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ int reg = -1;
+ if ((addr & 0x24) == 0x20) {
+ // "fake dma" data port
+ reg = 8;
+ } else if ((addr & 0x20) == 0x00) {
+ reg = (addr >> 2) & 7;
+ }
+ return reg;
+}
+
+static int add500_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ int reg = -1;
+ if ((addr & 0x8048) == 0x8000) {
+ reg = 8;
+ } else if ((addr & 0x8040) == 0x8040) {
+ reg = (addr >> 1) & 7;
+ }
+ return reg;
+}
+
+static int adscsi_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ int reg = -1;
+ if ((addr == 0x38 || addr == 0x39) && !write) {
+ reg = 8;
+ } else if ((addr == 0x20 || addr == 0x21) && write) {
+ reg = 8;
+ } else if (addr < 0x20) {
+ reg = (addr >> 2) & 7;
+ }
+ return reg;
+}
+
+static int ptnexus_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ int reg = -1;
+ if ((addr & 0x8ff0) == 0) {
+ reg = (addr >> 1) & 7;
+ }
+ return reg;
+}
+
+static int xebec_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (addr < 0x10000) {
+ if (addr & 1)
+ return (addr & 0xff) >> 1;
+ return -1;
+ }
+ if ((addr & 0x180000) == 0x100000) {
+
+ ncr->dmac_active = 1;
+
+ } else if ((addr & 0x180000) == 0x180000) {
+
+ ncr->dmac_active = 0;
+ ncr->dmac_address = ncr->baseaddress | 0x80000;
+
+ } else if ((addr & 0x180000) == 0x080000) {
+ ncr->dmac_address = addr | ncr->baseaddress | 1;
+ ncr->dmac_address += 2;
+ if (addr & 1)
+ return 0x80000 + (addr & 32767);
+ return -1;
+ }
+ return -1;
+}
+
+static int hd3000_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ if (!(addr & 1))
+ return -1;
+ if (!(addr & 0x4000))
+ return -1;
+ return (addr / 2) & 7;
+}
+
+static int profex_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ if (addr & 1)
+ return -1;
+ if (!(addr & 0x8000))
+ return -1;
+ return (addr / 2) & 7;
+}
+
+static int hda506_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ if ((addr & 0x7fe1) != 0x7fe0)
+ return -1;
+ addr &= 0x7;
+ addr >>= 1;
+ return addr;
+}
+
+static int alf1_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ if ((addr & 0x7ff9) != 0x0641)
+ return -1;
+ addr >>= 1;
+ addr &= 3;
+ return addr;
+}
+
+static int wedge_reg(struct soft_scsi *ncr, uaecptr addr, int size, bool write)
+{
+ if (size != 1)
+ return -1;
+ if ((addr & 0xFFF9) != 0x0641)
+ return -1;
+ addr >>= 1;
+ addr &= 3;
+ return addr;
+}
+
+static int system2000_reg(struct soft_scsi *ncr, uaecptr addr, int size, bool write)
+{
+ if (size != 1)
+ return -1;
+ if ((addr & 0xc007) != 0x4000)
+ return -1;
+ addr >>= 3;
+ addr &= 3;
+ return addr;
+}
+
+static int promigos_reg(struct soft_scsi *ncr, uaecptr addr, int size, bool write)
+{
+ if (size != 1)
+ return -1;
+ if ((addr & 0x1) != 1)
+ return -1;
+ addr &= 7;
+ if (addr == 1 && write)
+ return 3;
+ if (addr == 3 && write)
+ return 0;
+ if (addr == 5 && write)
+ return 1;
+ if (addr == 5 && !write)
+ return 0;
+ if (addr == 7 && write)
+ return 2;
+ if (addr == 7 && !write)
+ return 1;
+ return -1;
+}
+
+static int microforge_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+ int reg = -1;
+ if ((addr & 0x7000) != 0x7000)
+ return -1;
+ addr &= 0xfff;
+ if (addr == 38 && !write)
+ return 0;
+ if (addr == 40 && write)
+ return 0;
+ if (addr == 42 && !write)
+ return 1;
+ if (addr == 44 && write)
+ return 1;
+ return reg;
+}
+
+static int ossi_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ int reg = -1;
+ if (!(addr & 1))
+ return -1;
+ if ((addr & 0x8020) == 0x8020)
+ return 8;
+ if ((addr & 0x8010) != 0x8010)
+ return -1;
+ reg = (addr >> 1) & 7;
+ return reg;
+}
+
+static int phoenixboard_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (addr & 1)
+ return -1;
+ if (addr & 0xc000)
+ return -1;
+ addr >>= 1;
+ addr &= 7;
+ return addr;
+}
+
+static int trumpcardpro_reg(struct soft_scsi *ncr, uaecptr addr, bool vector)
+{
+ if (addr & 1)
+ return -1;
+ if (((addr & 0x8000) && !vector) || (vector && addr >= 0x100))
+ return -1;
+ if ((addr & 0xe0) == 0x60)
+ return 8;
+ if ((addr & 0xe0) != 0x40)
+ return -1;
+ addr >>= 1;
+ addr &= 7;
+ return addr;
+}
+
+static int dataflyerplus_reg(uaecptr addr)
+{
+ if (!(addr & 1))
+ return -1;
+ if (addr == 0x41)
+ return 8;
+ if (addr >= 0x10)
+ return -1;
+ return (addr >> 1) & 7;
+}
+
+// this is clone of trumpcardpro!
+static int addhard_reg(uaecptr addr)
+{
+ if (addr & 1)
+ return -1;
+ if (addr & 0x8000)
+ return -1;
+ if ((addr & 0xe0) == 0x60)
+ return 8;
+ if ((addr & 0xe0) != 0x40)
+ return -1;
+ addr >>= 1;
+ addr &= 7;
+ return addr;
+}
+
+static int emplant_reg(uaecptr addr)
+{
+ if (addr & 1)
+ return -1;
+ if ((addr & 0xf000) == 0x6000)
+ return 8;
+ if ((addr & 0xf000) != 0x5000)
+ return -1;
+ addr >>= 4;
+ addr &= 7;
+ return addr;
+}
+
+static int malibu_reg(uaecptr addr)
+{
+ if ((addr & 0xc000) == 0x8000)
+ return 8; // long read port
+ if ((addr & 0xc000) == 0xc000)
+ return 8; // long write port
+ if (!(addr & 1))
+ return -1;
+ if (addr & 0x4000)
+ return -1;
+ int reg = (addr & 0x0f) >> 1;
+ return reg;
+}
+
+static int eveshamref_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (!ncr->configured)
+ return -1;
+ if (addr < 0x40)
+ return (addr >> 1) & 7;
+ if (addr == 0x41)
+ return 8;
+ return -1;
+}
+
+static int fasttrak_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if ((addr & 0xc010) == 0x4000)
+ return (addr >> 1) & 7;
+ if ((addr & 0xc010) == 0x4010)
+ return 8;
+ return -1;
+}
+
+static int kronos_reg(uaecptr addr)
+{
+ if (addr >= 0x10)
+ return -1;
+ if (!(addr & 1))
+ return -1;
+ addr >>= 1;
+ return addr & 7;
+}
+
+static int twelvegauge_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (addr & 0x8000)
+ return -1;
+ if (!(addr & 0x2000))
+ return -1;
+ if (addr & 0x100)
+ return 8;
+ return (addr >> 4) & 7;
+}
+
+static int overdrive_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+ if (addr & 0x8000)
+ return -1;
+ if ((addr & 0x7000) == 0x4000)
+ return 0x100 + (addr & 0x3f);
+ if (addr & 1)
+ return -1;
+ if ((addr & 0x7000) == 0x2000)
+ return (addr >> 1) & 7;
+ if ((addr & 0x7000) == 0x6000)
+ return 8;
+ return -1;
+}
+
+static uae_u8 read_684xx_dma(struct soft_scsi *ncr, uaecptr addr)
+{
+ uae_u8 val = 0;
+
+ addr &= 0x3f;
+ switch (addr)
+ {
+ case 0:
+ val = ncr->dmac_active ? 0x00 : 0x80;
+ break;
+ case 4:
+ val = 0;
+ break;
+ }
+#if NCR5380_DEBUG > 0
+ write_log(_T("684xx DMA GET %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#endif
+ return val;
+}
+
+static void write_684xx_dma(struct soft_scsi *ncr, uaecptr addr, uae_u8 val)
+{
+#if NCR5380_DEBUG > 0
+ write_log(_T("684xx DMA PUT %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#endif
+
+ addr &= 0x3f;
+ switch (addr)
+ {
+ case 5: // OCR
+ ncr->dmac_direction = (val & 0x80) ? -1 : 1;
+ break;
+ case 7:
+ ncr->dmac_active = (val & 0x80) != 0;
+ dma_check(ncr);
+ break;
+ case 10: // MTCR
+ ncr->dmac_length &= 0x000000ff;
+ ncr->dmac_length |= val << 8;
+ break;
+ case 11: // MTCR
+ ncr->dmac_length &= 0x0000ff00;
+ ncr->dmac_length |= val << 0;
+ break;
+ case 12: // MAR
+ break;
+ case 13: // MAR
+ ncr->dmac_address &= 0x0000ffff;
+ ncr->dmac_address |= val << 16;
+ break;
+ case 14: // MAR
+ ncr->dmac_address &= 0x00ff00ff;
+ ncr->dmac_address |= val << 8;
+ break;
+ case 15: // MAR
+ ncr->dmac_address &= 0x00ffff00;
+ ncr->dmac_address |= val << 0;
+ break;
+ }
+}
+
+static void vector_scsi_status(struct raw_scsi *rs)
+{
+ // Vector Falcon 8000 FPGA seems to handle this internally
+ while (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS || rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN) {
+ raw_scsi_get_data(rs, true);
+ }
+}
+
+static int tecmar_clock_reg_select;
+static uae_u8 tecmar_clock_regs[64];
+static uae_u8 tecmar_clock_bcd(uae_u8 v)
+{
+ uae_u8 out = v;
+ if (!(tecmar_clock_regs[11] & 4)) {
+ out = ((v / 10) << 4) + (v % 10);
+ }
+ return out;
+}
+static void tecmar_clock_bput(int addr, uae_u8 v)
+{
+ if (addr == 0) {
+ tecmar_clock_reg_select = v & 63;
+ } else if (addr == 1) {
+ tecmar_clock_regs[tecmar_clock_reg_select] = v;
+ tecmar_clock_regs[12] = 0x00;
+ tecmar_clock_regs[13] = 0x80;
+ }
+}
+static uae_u8 tecmar_clock_bget(int addr)
+{
+ uae_u8 v = 0;
+ if (addr == 0) {
+ v = tecmar_clock_reg_select;
+ } else if (addr == 1) {
+ time_t t = time(0);
+ t += currprefs.cs_rtc_adjust;
+ struct tm *ct = localtime(&t);
+ switch (tecmar_clock_reg_select)
+ {
+ case 0:
+ v = tecmar_clock_bcd(ct->tm_sec);
+ break;
+ case 2:
+ v = tecmar_clock_bcd(ct->tm_min);
+ break;
+ case 4:
+ v = tecmar_clock_bcd(ct->tm_hour);
+ if (!(tecmar_clock_regs[11] & 2)) {
+ if (v >= 12) {
+ v -= 12;
+ v |= 0x80;
+ }
+ v++;
+ }
+ break;
+ case 6:
+ v = tecmar_clock_bcd(ct->tm_wday + 1);
+ break;
+ case 7:
+ v = tecmar_clock_bcd(ct->tm_mday);
+ break;
+ case 8:
+ v = tecmar_clock_bcd(ct->tm_mon + 1);
+ break;
+ case 9:
+ v = tecmar_clock_bcd(ct->tm_year % 100);
+ break;
+ default:
+ v = tecmar_clock_regs[tecmar_clock_reg_select];
+ break;
+ }
+ }
+ return v;
+}
+
+static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
+{
+ int reg = -1;
+ uae_u32 v = 0;
+ int addresstype = -1;
+ uaecptr origaddr = addr;
+
+ addr &= ncr->board_mask;
+
+ if (ncr->type == NCR5380_MALIBU) {
+
+ if ((addr & 0xc000) == 0x4000) {
+ v = ncr->rom[addr & 0x3fff];
+ } else {
+ reg = malibu_reg(addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_ADDHARD) {
+
+ if (addr & 0x8000) {
+ v = ncr->rom[addr & 0x7fff];
+ } else {
+ reg = addhard_reg(addr);
+ if (reg >= 0) {
+ if (reg == 8 && !ncr->dma_active) {
+ v = 0;
+ } else {
+ v = ncr5380_bget(ncr, reg);
+ }
+ }
+ }
+
+ } else if (ncr->type == NCR5380_EMPLANT) {
+
+ if ((addr & 0xf000) >= 0xc000) {
+ v = ncr->rom[addr & 0x3fff];
+ } else {
+ reg = emplant_reg(addr);
+ if (reg == 8 && !ncr->dma_active)
+ reg = -1;
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ }
+ }
+
+ } else if (ncr->type == NONCR_HARDFRAME) {
+
+ if (addr == 0xc0) {
+ v = aic_bget_reg(ncr);
+ } else if (addr == 0xc2) {
+ v = aic_bget_data(ncr);
+ } else if (addr == 0x40) {
+ v = ncr->irq ? 0x80 : 0x00;
+ } else if (addr == 0x42) {
+ v = ncr->intena ? 0x10 : 0x00;
+ } else if (addr >= 0x80 && addr <= 0x9f) {
+ v = read_684xx_dma(ncr, addr & 31);
+ } else {
+ v = ncr->rom[addr];
+ }
+
+ } else if (ncr->type == NONCR_INMATE) {
+
+ if (!(addr & 0x8000)) {
+ if (addr == 0x80) {
+ v = aic_bget_reg(ncr);
+ } else if (addr == 0x82) {
+ v = aic_bget_data(ncr);
+ } else if (addr == 0x84) {
+ v = ncr->rc->device_settings & 0x7f;
+ if (!ncr->rc->autoboot_disabled)
+ v |= 1 << 4;
+ if (ncr->dma_direction)
+ v |= 1 << 7;
+ } else if (addr == 0x88 || addr == 0x89) {
+ v = aic_bget_dma(ncr, NULL);
+ }
+ } else {
+ v = ncr->rom[addr];
+ }
+
+ } else if (ncr->type == NCR5380_SUPRA) {
+
+ if (ncr->subtype == 4) {
+ if ((addr & 0xc000) == 0xc000) {
+ v = read_684xx_dma(ncr, addr);
+ } else if (addr & 0x8000) {
+ addresstype = (addr & 1) ? 0 : 1;
+ }
+ } else if (ncr->subtype == 3) {
+ if ((addr & 0x8000) && !(addr & 1))
+ addresstype = 0;
+ } else {
+ if (ncr->subtype != 1 && (addr & 1)) {
+ v = 0xff;
+ } else if (addr & 0x8000) {
+ addresstype = 1;
+ } else {
+ addresstype = 0;
+ }
+ }
+
+ if (addresstype == 1) {
+ v = ncr->rom[addr & 0x7fff];
+ } else if (addresstype == 0) {
+ reg = supra_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = ncr5380_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == NONCR_GOLEM) {
+
+ int bank = addr & 0x8f81;
+ struct raw_scsi *rs = &ncr->rscsi;
+ switch(bank)
+ {
+ case 0x8000:
+ case 0x8001:
+ case 0x8002:
+ case 0x8003:
+ v = raw_scsi_get_data(rs, true);
+ // message is not retrieved by driver, perhaps hardware does it?
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN)
+ raw_scsi_get_data(rs, true);
+ break;
+ case 0x8200:
+ {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ if (!(t & SCSI_IO_BUSY))
+ v |= 1 << (8 - 8);
+ if (rs->bus_phase >= 0) {
+ if (!(rs->bus_phase & SCSI_IO_DIRECTION))
+ v |= 1 << (13 - 8);
+ if (!(rs->bus_phase & SCSI_IO_COMMAND))
+ v |= 1 << (10 - 8);
+ if (rs->bus_phase != SCSI_SIGNAL_PHASE_STATUS)
+ v |= 1 << (15 - 8);
+ }
+ }
+ break;
+ case 0x8201:
+ {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 6;
+ }
+ break;
+ default:
+ if ((addr & 0xc000) == 0x0000)
+ v = ncr->rom[addr];
+ break;
+ }
+
+ } else if (ncr->type == NCR5380_STARDRIVE) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr < sizeof ncr->acmemory) {
+ v = ncr->acmemory[addr];
+ } else {
+ reg = stardrive_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else if (addr == 0x104) {
+ v = 0;
+ // bit 3: dreq
+ if (rs->bus_phase >= 0 && (rs->io & SCSI_IO_REQ) && (ncr->regs[2] & 2))
+ v |= 1 << 3;
+ }
+ }
+
+ } else if (ncr->type == NCR5380_CLTD) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (!ncr->configured && addr < sizeof ncr->acmemory) {
+ v = ncr->acmemory[addr];
+ } else {
+ reg = cltd_reg(ncr, addr);
+ if (reg >= 0)
+ v = ncr5380_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == NCR5380_PTNEXUS) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (!ncr->configured && addr < sizeof ncr->acmemory) {
+ v = ncr->acmemory[addr];
+ } else if (addr & 0x8000) {
+ v = ncr->rom[addr & 16383];
+ } else {
+ reg = ptnexus_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else if (addr == 0x11) {
+ // fake dma status
+ v = 0;
+ }
+ }
+
+ } else if (ncr->type == NONCR_KOMMOS) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr & 0x8000) {
+ v = ncr->rom[addr & 0x7fff];
+ } else if ((origaddr & 0xf00000) != 0xf00000) {
+ if (!(addr & 8)) {
+ v = raw_scsi_get_data(rs, true);
+ } else {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ if (t & SCSI_IO_BUSY)
+ v |= 1 << 1;
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 0;
+ if (t & SCSI_IO_DIRECTION)
+ v |= 1 << 4;
+ if (t & SCSI_IO_COMMAND)
+ v |= 1 << 3;
+ if (t & SCSI_IO_MESSAGE)
+ v |= 1 << 2;
+ }
+ }
+
+ } else if (ncr->type == NONCR_VECTOR) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr < sizeof ncr->acmemory) {
+ v = ncr->acmemory[addr];
+ } else if (!(addr & 0x8000)) {
+ v = ncr->rom[addr];
+ } else {
+ if ((addr & 0x201) == 0x200) {
+ v = (1 << 0);
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (t & SCSI_IO_BUSY)
+ v &= ~(1 << 0);
+ if (t & SCSI_IO_DIRECTION)
+ v |= (1 << 6);
+ if (t & SCSI_IO_COMMAND)
+ v |= (1 << 7);
+ } else if ((addr & 0x201) == 0x201) {
+ v = 0;
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (t & SCSI_IO_REQ)
+ v |= 1 << 1;
+
+ } else if ((addr & 0x300) == 0x000) {
+ if (size > 1) {
+ v = raw_scsi_get_data(rs, true);
+ vector_scsi_status(rs);
+ } else {
+ v = rs->status >= 2 ? 2 : 0;
+ }
+ } else if ((addr & 0x300) == 0x300) {
+ raw_scsi_reset(rs);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_PROTAR) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr < sizeof ncr->acmemory) {
+ if (!ncr->configured) {
+ v = ncr->acmemory[addr];
+ } else {
+ reg = protar_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ }
+ }
+ } else {
+ v = ncr->rom[addr & 65535];
+ }
+
+ } else if (ncr->type == NCR5380_ADD500) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr & 0x8000) {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if ((addr & 0x8048) == 0x8000) {
+ if (!(addr & 1)) {
+ if (t & SCSI_IO_REQ) {
+ ncr->databuffer[0] = ncr->databuffer[1];
+ ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8;
+ ncr->databuffer[1] |= raw_scsi_get_data(rs, true);
+ if (ncr->databuffer_empty) {
+ ncr->databuffer[0] = ncr->databuffer[1];
+ ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8;
+ ncr->databuffer[1] |= raw_scsi_get_data(rs, true);
+ }
+ ncr->databuffer_empty = false;
+ } else {
+ ncr->databuffer_empty = true;
+ }
+ }
+ v = ncr->databuffer[0] >> 8;
+ ncr->databuffer[0] <<= 8;
+ } else {
+ reg = add500_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else if ((addr & 0x8049) == 0x8009) {
+ v = 0;
+ if (!(t & SCSI_IO_REQ) && ncr->databuffer_empty) {
+ v |= 1 << 0;
+ }
+ }
+ }
+ } else {
+ v = ncr->rom[addr];
+ }
+
+ } else if (ncr->type == NCR5380_ADSCSI) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (ncr->configured)
+ reg = adscsi_reg(ncr, addr, false);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else {
+ v = ncr->rom[addr & 65535];
+ }
+ if (addr == 0x40) {
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = 0;
+ // bits 0 to 2: ID (inverted)
+ v |= (ncr->rc->device_id ^ 7) & 7;
+ // shorter delay before drive detection (8s vs 18s)
+ v |= 1 << 5;
+ if (t & SCSI_IO_REQ) {
+ v |= 1 << 6;
+ v |= 1 << 7;
+ }
+ }
+
+ } else if (ncr->type == NCR5380_KRONOS) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr < sizeof ncr->acmemory)
+ v = ncr->acmemory[addr];
+ if (ncr->configured) {
+ reg = kronos_reg(addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else if (addr == 0x40) {
+ v = 0;
+ if (eeprom93xx_read(ncr->eeprom))
+ v |= 1 << 6;
+ }
+ }
+ if (addr & 0x8000) {
+ v = ncr->rom[addr & 8191];
+ }
+
+ } else if (ncr->type == NCR5380_ROCHARD) {
+
+ int reg = (addr & 15) / 2;
+ if ((addr & 0x300) == 0x300)
+ v = ncr53400_bget(ncr, reg | 0x100);
+ else if (addr & 0x200)
+ v = ncr53400_bget(ncr, reg | 0x80);
+ else
+ v = ncr53400_bget(ncr, reg);
+
+ } else if (ncr->type == NCR5380_DATAFLYER) {
+
+ reg = addr & 0xff;
+ v = ncr5380_bget(ncr, reg);
+
+ } else if (ncr->type == NCR5380_DATAFLYERPLUS) {
+
+ if (addr < 0x80 && ncr->configured) {
+ reg = dataflyerplus_reg(addr);
+ if (reg >= 0)
+ v = ncr5380_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == NONCR_TECMAR) {
+
+ v = ncr->rom[addr];
+ if (addr >= 0x2000 && addr < 0x3000) {
+ if (addr == 0x2040)
+ v = tecmar_clock_bget(0);
+ else if (addr == 0x2042)
+ v = tecmar_clock_bget(1);
+ } else if (addr >= 0x4000 && addr < 0x5000) {
+ if (addr == 0x4040)
+ v = sasi_tecmar_bget(ncr, 1);
+ else if (addr == 0x4042)
+ v = sasi_tecmar_bget(ncr, 0);
+ }
+
+ } else if (ncr->type == NCR5380_XEBEC) {
+
+ reg = xebec_reg(ncr, addr);
+ if (reg >= 0 && reg < 8) {
+ v = ncr5380_bget(ncr, reg);
+ } else if (reg >= 0x80000) {
+ int offset = reg & (ncr->databuffer_size - 1);
+ v = ncr->databufferptr[offset];
+ }
+
+ } else if (ncr->type == NONCR_MICROFORGE) {
+
+ reg = microforge_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = sasi_microforge_bget(ncr, reg);
+
+ } else if (ncr->type == OMTI_HD3000) {
+
+ if (addr < 0x4000) {
+ v = ncr->rom[addr];
+ } else {
+ reg = hd3000_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = omti_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == OMTI_PROFEX) {
+
+ if (addr < 0x4000) {
+ v = ncr->rom[addr];
+ } else {
+ reg = profex_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = omti_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == OMTI_HDA506) {
+
+ reg = hda506_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = omti_bget(ncr, reg);
+
+ } else if (ncr->type == OMTI_ALF1 || ncr->type == OMTI_ADAPTER) {
+
+ reg = alf1_reg(ncr, addr, false);
+ if (reg >= 0)
+ v = omti_bget(ncr, reg);
+
+ } else if (ncr->type == OMTI_PROMIGOS) {
+
+ reg = promigos_reg(ncr, addr, size, false);
+ if (reg >= 0)
+ v = omti_bget(ncr, reg);
+
+ } else if (ncr->type == OMTI_WEDGE) {
+
+ reg = wedge_reg(ncr, addr, size, false);
+ if (reg >= 0) {
+ v = omti_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == OMTI_SYSTEM2000) {
+
+ reg = system2000_reg(ncr, addr, size, false);
+ if (reg >= 0) {
+ v = omti_bget(ncr, reg);
+ } else if (addr < 0x4000) {
+ v = ncr->rom[addr];
+ } else if (ncr->rscsi.bus_phase >= 0) {
+ if ((addr & 0xc000) == 0x8000) {
+ v = ncr->databuffer[addr & 1];
+ ncr->databuffer[addr & 1] = omti_bget(ncr, 0);
+ } else if ((addr & 0xc000) == 0xc000) {
+ v = ncr->databuffer[addr & 1];
+ }
+ }
+
+ } else if (ncr->type == NCR5380_PHOENIXBOARD) {
+
+ reg = phoenixboard_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else if (addr < 0x8000) {
+ v = ncr->rom[addr];
+ }
+
+ } else if (ncr->type == NCR5380_SCRAM) {
+
+ if (addr < 0x4000 || addr >= 0xc000) {
+ v = 0xff;
+ if (!(addr & 1))
+ v = ncr->rom[(addr >> 1) & 8191];
+ } else if (addr >= 0x8000 && addr < 0xa000) {
+ if (!(addr & 1))
+ v = ncr5380_bget(ncr, 8);
+ } else if (addr >= 0x6000 && addr < 0x8000) {
+ if (!(addr & 1)) {
+ reg = (addr >> 1) & 7;
+ v = ncr5380_bget(ncr, reg);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_OSSI) {
+
+ if (!(addr & 0x8000)) {
+ v = ncr->rom[addr & 16383];
+ } else {
+ reg = ossi_reg(ncr, addr);
+ if (reg >= 0)
+ v = ncr5380_bget(ncr, reg);
+ }
+
+ } else if (ncr->type == NCR5380_TRUMPCARDPRO || ncr->type == NCR5380_IVSVECTOR || ncr->type == NCR5380_TRUMPCARD) {
+
+ reg = trumpcardpro_reg(ncr, addr, ncr->type == NCR5380_IVSVECTOR);
+ if (reg >= 0) {
+ if (reg == 8 && !ncr->dma_active) {
+ v = 0;
+ } else {
+ v = ncr5380_bget(ncr, reg);
+ }
+ } else if ((addr & 0x8000) && ncr->type != NCR5380_IVSVECTOR) {
+ if (!ncr->rc->autoboot_disabled)
+ v = ncr->rom[addr & 0x7fff];
+ } else if (addr == 0x100 && ncr->type == NCR5380_IVSVECTOR) {
+ // bits 0,1 = 0 = 32M
+ // bits 0,1 = 1 = 16M
+ // bits 0,1 = 2 = 8M
+ // bits 0,1 = 3 = 4M
+ // bit 3 = JP17 DisFastROM (1 = disabled, 0 = on)
+ // bit 5 = disable RAM in 68000 mode
+ // bit 4 = JP20 autoboot (1 = off, 0 = on)
+ // bit 6 = 68030 burst (1 = on, 0 = off)
+ v = currprefs.cpuboard_settings;
+ v |= 4;
+ v ^= 0xff & ~0x40;
+ } else if (addr > 0x100 && ncr->type == NCR5380_IVSVECTOR) {
+ v = ncr->rom[addr];
+ } else if ((addr & 0xe0) == 0xc0 && ncr->type != NCR5380_TRUMPCARD) {
+ struct raw_scsi *rs = &ncr->rscsi;
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ v = ncr->irq && ncr->intena ? 4 : 0;
+ // actually this is buffer empty/full
+ v |= (t & SCSI_IO_DIRECTION) ? 2 : 0;
+ v |= ((ncr->rc->device_id ^ 7) & 7) << 3;
+ } else if ((addr & 0xe0) == 0xa0 && ncr->type != NCR5380_TRUMPCARD) {
+ // long data port
+ if (ncr->dma_active)
+ v = ncr5380_bget(ncr, 8);
+ }
+
+ } else if (ncr->type == NCR5380_EVESHAMREF) {
+
+ reg = eveshamref_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else {
+ v = ncr->rom[addr & 0x7fff];
+ }
+
+ } else if (ncr->type == NCR5380_FASTTRAK) {
+
+ reg = fasttrak_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else {
+ v = ncr->rom[addr & 0x7fff];
+ }
+
+ } else if (ncr->type == NCR5380_12GAUGE) {
+
+ reg = twelvegauge_reg(ncr, addr);
+ if (reg >= 0) {
+ v = ncr5380_bget(ncr, reg);
+ } else {
+ v = ncr->rom[addr & 0x7fff];
+ }
+
+ } else if (ncr->type == NCR5380_OVERDRIVE) {
+
+ reg = overdrive_reg(ncr, addr);
+ if (reg >= 0) {
+ if (reg >= 0x100)
+ v = read_684xx_dma(ncr, reg);
+ else
+ v = ncr5380_bget(ncr, reg);
+ } else {
+ v = ncr->rom[addr & 0x3fff];
+ }
+
+ }
+
+#if NCR5380_DEBUG > 1
+ if (0 || origaddr < 0x8000)
+ write_log(_T("GET %08x %02x %d %08x %d\n"), origaddr, v, reg, M68K_GETPC, regs.intmask);
+#endif
+
+ return v;
+}
+
+static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int size)
+{
+ int reg = -1;
+ int addresstype = -1;
+ uaecptr origaddr = addr;
+
+ addr &= ncr->board_mask;
+
+ if (ncr->type == NCR5380_MALIBU) {
+
+ reg = malibu_reg(addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == NCR5380_ADDHARD) {
+
+ reg = addhard_reg(addr);
+ if (reg >= 0) {
+ if (reg == 8 && !ncr->dma_active) {
+ ;
+ } else {
+ ncr5380_bput(ncr, reg, val);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_EMPLANT) {
+
+ reg = emplant_reg(addr);
+ if (reg == 8 && !ncr->dma_active)
+ reg = -1;
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ } else if ((addr & 0xff00) == 0x3800) {
+ if ((val & 0x88) == 0x88) {
+ ncr->intena = true;
+ } else if ((val & 0x88) == 0x08) {
+ ncr->intena = false;
+ }
+ }
+
+ } else if (ncr->type == NONCR_HARDFRAME) {
+
+ if (addr == 0xc0) {
+ aic_bput_reg(ncr, val);
+ } else if (addr == 0xc2) {
+ aic_bput_data(ncr, val);
+ } else if (addr == 0x42) {
+ ncr->intena = (val & 0x10) != 0;
+ } else if (addr >= 0x80 && addr <= 0x9f) {
+ write_684xx_dma(ncr, addr & 31, val);
+ }
+
+ } else if (ncr->type == NONCR_INMATE) {
+
+ if (addr == 0x80) {
+ aic_bput_reg(ncr, val);
+ } else if (addr == 0x82) {
+ aic_bput_data(ncr, val);
+ } else if (addr == 0x88 || addr == 0x89) {
+ aic_bput_dma(ncr, val, NULL);
+ }
+
+ } else if (ncr->type == NCR5380_SUPRA) {
+
+ if (ncr->subtype == 4) {
+ if ((addr & 0xc000) == 0xc000) {
+ write_684xx_dma(ncr, addr, val);
+ } else if (addr & 0x8000) {
+ addresstype = (addr & 1) ? 0 : 1;
+ }
+ } else if (ncr->subtype == 3) {
+ if ((addr & 0x8000) && !(addr & 1))
+ addresstype = 0;
+ } else {
+ if (ncr->subtype != 1 && (addr & 1))
+ return;
+ if (!(addr & 0x8000))
+ addresstype = 0;
+ }
+ if (addresstype == 0) {
+ reg = supra_reg(ncr, addr, true);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == NONCR_GOLEM) {
+
+ int bank = addr & 0x8f81;
+ struct raw_scsi *rs = &ncr->rscsi;
+ switch(bank)
+ {
+ case 0x8080:
+ case 0x8081:
+ case 0x8082:
+ case 0x8083:
+ raw_scsi_put_data(rs, val, true);
+ break;
+ case 0x8380:
+ {
+ raw_scsi_put_data(rs, val, true);
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (t & SCSI_IO_BUSY)
+ raw_scsi_set_signal_phase(rs, true, false, false);
+ }
+ break;
+ }
+
+ } else if (ncr->type == NCR5380_STARDRIVE) {
+
+ reg = stardrive_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_CLTD) {
+
+ if (ncr->configured) {
+ reg = cltd_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == NCR5380_PTNEXUS) {
+
+ if (ncr->configured) {
+ reg = ptnexus_reg(ncr, addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ } else if (addr == 0x11) {
+ ncr->chip_state = val;
+ }
+ }
+
+ } else if (ncr->type == NONCR_KOMMOS) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (!(addr & 0x8000) && (origaddr & 0xf00000) != 0xf00000) {
+ if (!(addr & 8)) {
+ raw_scsi_put_data(rs, val, true);
+ } else {
+ // select?
+ if (val & 4) {
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (t & SCSI_IO_BUSY)
+ raw_scsi_set_signal_phase(rs, true, false, false);
+ }
+ }
+ }
+
+ } else if (ncr->type == NONCR_VECTOR) {
+
+ struct raw_scsi *rs = &ncr->rscsi;
+ if (addr & 0x8000) {
+ if ((addr & 0x300) == 0x300) {
+ raw_scsi_put_data(rs, val, false);
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (t & SCSI_IO_BUSY)
+ raw_scsi_set_signal_phase(rs, true, false, false);
+ } else if ((addr & 0x300) == 0x000) {
+ raw_scsi_put_data(rs, val, true);
+ vector_scsi_status(rs);
+ }
+
+ }
+
+ } else if (ncr->type == NCR5380_PROTAR) {
+
+ reg = protar_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_ADD500) {
+
+ if ((addr & 0x8048) == 0x8008) {
+ struct raw_scsi *rs = &ncr->rscsi;
+ ncr->databuffer_empty = true;
+ } else {
+ reg = add500_reg(ncr, addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_ADSCSI) {
+
+ if (ncr->configured)
+ reg = adscsi_reg(ncr, addr, true);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == NCR5380_KRONOS) {
+
+ reg = kronos_reg(addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ } else if (addr == 0x60) {
+ eeprom93xx_write(ncr->eeprom, (val & 0x40) != 0, (val & 0x10) != 0, (val & 0x20) != 0);
+ }
+
+ } else if (ncr->type == NCR5380_ROCHARD) {
+
+ int reg = (addr & 15) / 2;
+ if ((addr & 0x300) == 0x300)
+ ncr53400_bput(ncr, reg | 0x100, val);
+ else if (addr & 0x200)
+ ncr53400_bput(ncr, reg | 0x80, val);
+ else
+ ncr53400_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_DATAFLYER) {
+
+ reg = addr & 0xff;
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_DATAFLYERPLUS) {
+
+ if (ncr->configured && addr < 0x80) {
+ reg = dataflyerplus_reg(addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ }
+ }
+
+ } else if (ncr->type == NONCR_TECMAR) {
+
+ if (addr == 0x22) {
+ // box
+ ncr->baseaddress = AUTOCONFIG_Z2 + ((val & 0x7f) * 4096);
+ map_banks_z2(ncr->bank, ncr->baseaddress >> 16, 1);
+ expamem_next(ncr->bank, NULL);
+ } else if (addr == 0x1020) {
+ // memory board control/status
+ ncr->rom[addr] = val & (0x80 | 0x40 | 0x02);
+ } else if (addr == 0x1024) {
+ // memory board memory address reg
+ write_log(_T("TECMAR RAM %08x-%08x\n"), val << 16, (val << 16) + currprefs.fastmem[0].size);
+ if (currprefs.fastmem[0].size)
+ map_banks_z2(&fastmem_bank[0], val, currprefs.fastmem[0].size >> 16);
+ }
+ else if (addr >= 0x2000 && addr < 0x3000) {
+ // clock
+ if (addr == 0x2040)
+ tecmar_clock_bput(0, val);
+ else if (addr == 0x2042)
+ tecmar_clock_bput(1, val);
+ } else if (addr >= 0x4000 && addr < 0x5000) {
+ // sasi
+ if (addr == 0x4040)
+ sasi_tecmar_bput(ncr, 1, val);
+ else if (addr == 0x4042)
+ sasi_tecmar_bput(ncr, 0, val);
+ }
+
+ } else if (ncr->type == NCR5380_XEBEC) {
+
+ reg = xebec_reg(ncr, addr);
+ if (reg >= 0 && reg < 8) {
+ ncr5380_bput(ncr, reg, val);
+ } else if (reg >= 0x80000) {
+ int offset = reg & (ncr->databuffer_size - 1);
+ ncr->databufferptr[offset] = val;
+ }
+
+ } else if (ncr->type == NONCR_MICROFORGE) {
+
+ reg = microforge_reg(ncr, addr, true);
+ if (reg >= 0)
+ sasi_microforge_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_HDA506) {
+
+ reg = hda506_reg(ncr, addr, true);
+ if (reg >= 0)
+ omti_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_HD3000) {
+
+ reg = hd3000_reg(ncr, addr, true);
+ if (reg >= 0)
+ omti_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_PROFEX) {
+
+ reg = profex_reg(ncr, addr, true);
+ if (reg >= 0)
+ omti_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_ALF1 || ncr->type == OMTI_ADAPTER) {
+
+ reg = alf1_reg(ncr, addr, true);
+ if (reg >= 0)
+ omti_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_PROMIGOS) {
+
+ reg = promigos_reg(ncr, addr, size, true);
+ if (reg >= 0)
+ omti_bput(ncr, reg, val);
+
+ } else if (ncr->type == OMTI_WEDGE) {
+
+ reg = wedge_reg(ncr, addr, size, true);
+ if (reg >= 0) {
+ omti_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == OMTI_SYSTEM2000) {
+
+ reg = system2000_reg(ncr, addr, size, true);
+ if (reg >= 0) {
+ omti_bput(ncr, reg, val);
+ } else if (ncr->rscsi.bus_phase >= 0) {
+ if ((addr & 0x8000) == 0x8000) {
+ omti_bput(ncr, 0, val);
+ }
+ }
+
+ } else if (ncr->type == NCR5380_PHOENIXBOARD) {
+
+ reg = phoenixboard_reg(ncr, addr);
+ if (reg >= 0) {
+ ncr5380_bput(ncr, reg, val);
+ }
+
+ } else if (ncr->type == NCR5380_SCRAM) {
+
+ if (addr >= 0x6000 && addr < 0x8000) {
+ if (!(addr & 1)) {
+ reg = (addr >> 1) & 7;
+ ncr5380_bput(ncr, reg, val);
+ }
+ } else if (addr >= 0x8000 && addr < 0xc000) {
+ if (!(addr & 1))
+ ncr5380_bput(ncr, 8, val);
+ }
+
+ } else if (ncr->type == NCR5380_OSSI) {
+
+ reg = ossi_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ //} else if (ncr->type == NCR5380_TRUMPCARDPRO || ncr->type == NCR5380_IVSVECTOR || ncr->type == NCR5380_TRUMPCARD) {
+
+ // reg = trumpcardpro_reg(ncr, addr, ncr->type == NCR5380_IVSVECTOR);
+ // if (reg >= 0) {
+ // if (reg == 8 && !ncr->dma_active) {
+ // ;
+ // } else {
+ // ncr5380_bput(ncr, reg, val);
+ // }
+ // } else if (addr >= 0x100 && ncr->type == NCR5380_IVSVECTOR) {
+ // if (addr == 0x200 && !(val & 0x80)) {
+ // if (currprefs.cpu_model >= 68020) {
+ // write_log(_T("IVS Vector 68000 mode!\n"));
+ // cpu_fallback(0);
+ // }
+ // }
+ // if (addr == 0x200 && (val & 0x80)) {
+ // if (currprefs.cpu_model < 68020) {
+ // write_log(_T("IVS Vector 68030 mode!\n"));
+ // cpu_fallback(1);
+ // }
+ // }
+ // } else if ((addr & 0xe0) == 0xa0 && ncr->type != NCR5380_TRUMPCARD) {
+ // // word data port
+ // if (ncr->dma_active)
+ // ncr5380_bput(ncr, 8, val);
+ // }
+
+ } else if (ncr->type == NCR5380_EVESHAMREF) {
+
+ reg = eveshamref_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_FASTTRAK) {
+
+ reg = fasttrak_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_12GAUGE) {
+
+ reg = twelvegauge_reg(ncr, addr);
+ if (reg >= 0)
+ ncr5380_bput(ncr, reg, val);
+
+ } else if (ncr->type == NCR5380_OVERDRIVE) {
+
+ reg = overdrive_reg(ncr, addr);
+ if (reg >= 0) {
+ if (reg >= 0x100)
+ write_684xx_dma(ncr, reg, val);
+ else
+ ncr5380_bput(ncr, reg, val);
+ }
+ }
+
+#if NCR5380_DEBUG > 1
+ if (origaddr < 0x8000)
+ write_log(_T("PUT %08x %02x %d %08x %d\n"), origaddr, val, reg, M68K_GETPC, regs.intmask);
+#endif
+}
+
+// mainhattan paradox scsi
+uae_u8 parallel_port_scsi_read(int reg, uae_u8 data, uae_u8 dir)
+{
+ struct soft_scsi *scsi = parallel_port_scsi_data;
+ if (!scsi)
+ return data;
+ struct raw_scsi *rs = &scsi->rscsi;
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if (reg == 0) {
+ data = raw_scsi_get_data_2(rs, true, false);
+ data ^= 0xff;
+ } else if (reg == 1) {
+ data &= ~3;
+ if (rs->bus_phase >= 0 && !(rs->bus_phase & SCSI_IO_COMMAND))
+ data |= 2; // POUT
+ data |= 1;
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_SELECT_2 || rs->bus_phase >= 0)
+ data &= ~1; // BUSY
+ }
+ t = raw_scsi_get_signal_phase(rs);
+ if ((t & SCSI_IO_REQ) && (scsi->chip_state & 4))
+ cia_parallelack();
+ return data;
+}
+void parallel_port_scsi_write(int reg, uae_u8 v, uae_u8 dir)
+{
+ struct soft_scsi *scsi = parallel_port_scsi_data;
+ if (!scsi)
+ return;
+ struct raw_scsi *rs = &scsi->rscsi;
+ if (reg == 0) {
+ v ^= 0xff;
+ raw_scsi_put_data(rs, v, true);
+ } else if (reg == 1) {
+ // SEL
+ if (!(v & 4) && (scsi->chip_state & 4)) {
+ raw_scsi_set_signal_phase(rs, false, true, false);
+ } else if ((v & 4) && !(scsi->chip_state & 4)) {
+ if (rs->bus_phase == SCSI_SIGNAL_PHASE_SELECT_2) {
+ raw_scsi_set_signal_phase(rs, false, false, false);
+ }
+ }
+ scsi->chip_state = v;
+ }
+ uae_u8 t = raw_scsi_get_signal_phase(rs);
+ if ((t & SCSI_IO_REQ) && (scsi->chip_state & 4))
+ cia_parallelack();
+}
+
+static bool isautoconfigaddr(uaecptr addr)
+{
+ return addr < 65536 || (addr >= 0xe80000 && addr < 0xe90000) || (addr >= 0xff000000 && addr < 0xff0000200);
+}
+
+static uae_u32 REGPARAM2 ncr80_lget(struct soft_scsi *ncr, uaecptr addr)
+{
+ uae_u32 v;
+ v = ncr80_bget2(ncr, addr + 0, 4) << 24;
+ v |= ncr80_bget2(ncr, addr + 1, 4) << 16;
+ v |= ncr80_bget2(ncr, addr + 2, 4) << 8;
+ v |= ncr80_bget2(ncr, addr + 3, 4) << 0;
+ return v;
+}
+
+static uae_u32 REGPARAM2 ncr80_wget(struct soft_scsi *ncr, uaecptr addr)
+{
+ uae_u32 v;
+ v = ncr80_bget2(ncr, addr, 2) << 8;
+ v |= ncr80_bget2(ncr, addr + 1, 2);
+ return v;
+}
+
+static uae_u32 REGPARAM2 ncr80_bget(struct soft_scsi *ncr, uaecptr addr)
+{
+ bool iaa = isautoconfigaddr(addr);
+ uae_u32 v;
+ addr &= ncr->board_mask;
+ if (!ncr->configured && iaa) {
+ addr &= 65535;
+ if (addr >= sizeof ncr->acmemory)
+ return 0;
+ return ncr->acmemory[addr];
+ }
+ v = ncr80_bget2(ncr, addr, 1);
+ return v;
+}
+
+static void REGPARAM2 ncr80_lput(struct soft_scsi *ncr, uaecptr addr, uae_u32 l)
+{
+ ncr80_bput2(ncr, addr + 0, l >> 24, 4);
+ ncr80_bput2(ncr, addr + 1, l >> 16, 4);
+ ncr80_bput2(ncr, addr + 2, l >> 8, 4);
+ ncr80_bput2(ncr, addr + 3, l >> 0, 4);
+}
+
+static void REGPARAM2 ncr80_wput(struct soft_scsi *ncr, uaecptr addr, uae_u32 w)
+{
+ bool iaa = isautoconfigaddr(addr);
+ w &= 0xffff;
+ if (!ncr->configured && iaa) {
+ return;
+ }
+ ncr80_bput2(ncr, addr, w >> 8, 2);
+ ncr80_bput2(ncr, addr + 1, w & 0xff, 2);
+}
+
+static void REGPARAM2 ncr80_bput(struct soft_scsi *ncr, uaecptr addr, uae_u32 b)
+{
+ bool iaa = isautoconfigaddr(addr);
+ b &= 0xff;
+ addr &= ncr->board_mask;
+ if (!ncr->configured && iaa) {
+ addr &= 65535;
+ switch (addr)
+ {
+ case 0x48:
+ map_banks_z2(ncr->bank, expamem_board_pointer >> 16, ncr->board_size >> 16);
+ ncr->baseaddress = expamem_board_pointer;
+ ncr->configured = 1;
+ expamem_next (ncr->bank, NULL);
+ break;
+ case 0x4c:
+ ncr->configured = 1;
+ expamem_shutup(ncr->bank);
+ break;
+ }
+ return;
+ }
+ ncr80_bput2(ncr, addr, b, 1);
+}
+
+static void REGPARAM2 soft_generic_bput (uaecptr addr, uae_u32 b)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ ncr80_bput(ncr, addr, b);
+}
+
+static void REGPARAM2 soft_generic_wput (uaecptr addr, uae_u32 b)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ ncr80_wput(ncr, addr, b);
+}
+static void REGPARAM2 soft_generic_lput (uaecptr addr, uae_u32 b)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ ncr80_lput(ncr, addr, b);
+}
+static uae_u32 REGPARAM2 soft_generic_bget (uaecptr addr)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ return ncr80_bget(ncr, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 soft_generic_wget (uaecptr addr)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ return ncr80_wget(ncr, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 soft_generic_lget (uaecptr addr)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (ncr)
+ return ncr80_lget(ncr, addr);
+ return 0;
+}
+
+static int REGPARAM2 soft_check(uaecptr addr, uae_u32 size)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (!ncr)
+ return 0;
+ if (!ncr->rom)
+ return 0;
+ return 1;
+}
+static uae_u8 *REGPARAM2 soft_xlate(uaecptr addr)
+{
+ struct soft_scsi *ncr = getscsiboard(addr);
+ if (!ncr)
+ return 0;
+ return ncr->rom + (addr & (ncr->rom_size - 1));
+}
+
+addrbank soft_bank_generic = {
+ soft_generic_lget, soft_generic_wget, soft_generic_bget,
+ soft_generic_lput, soft_generic_wput, soft_generic_bput,
+ soft_xlate, soft_check, NULL, NULL, _T("LOWLEVEL/5380 SCSI"),
+ soft_generic_wget,
+ ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
+};
+
+void soft_scsi_put(uaecptr addr, int size, uae_u32 v)
+{
+ if (size == 4)
+ soft_generic_lput(addr, v);
+ else if (size == 2)
+ soft_generic_wput(addr, v);
+ else
+ soft_generic_bput(addr, v);
+}
+uae_u32 soft_scsi_get(uaecptr addr, int size)
+{
+ uae_u32 v;
+ if (size == 4)
+ v = soft_generic_lget(addr);
+ else if (size == 2)
+ v = soft_generic_wget(addr);
+ else
+ v = soft_generic_bget(addr);
+ return v;
+}
+
+static void soft_scsi_free(void)
+{
+ parallel_port_scsi = false;
+ parallel_port_scsi_data = NULL;
+ x86_hd_data = NULL;
+ for (int i = 0; soft_scsi_devices[i]; i++) {
+ soft_scsi_free_unit(soft_scsi_devices[i]);
+ soft_scsi_devices[i] = NULL;
+ }
+}
+
+static void soft_scsi_reset(int hardreset)
+{
+ for (int i = 0; soft_scsi_devices[i]; i++) {
+ raw_scsi_reset(&soft_scsi_devices[i]->rscsi);
+ }
+}
+
+static struct soft_scsi *getscsi(struct romconfig *rc)
+{
+ device_add_rethink(ncr80_rethink);
+ device_add_reset(soft_scsi_reset);
+ device_add_exit(soft_scsi_free);
+ if (rc->unitdata)
+ return (struct soft_scsi *)rc->unitdata;
+ return NULL;
+}
+
+static void scsi_add_reset(void)
+{
+ device_add_reset(soft_scsi_reset);
+}
+
+/*
+ $8380 select unit (unit mask)
+
+ $8200
+ 6: REQ (1=active)
+ 8: BSY (0=active)
+ 10: C/D (1=data)
+ 13: I/O (1=to target)
+ 15: If not status?
+
+ $8080 write data
+ $8000 read data
+
+*/
+
+bool supra_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_SUPRA);
+ aci->autoconfigp = ert->subtypes[aci->rc->subtype].autoconfig;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+
+ struct zfile *z = NULL;
+ scsi->subtype = aci->rc->subtype;
+ if (!aci->rc->autoboot_disabled && scsi->subtype != 3) {
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->subtypes[aci->rc->subtype].autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ load_rom_rc(aci->rc, ROMTYPE_SUPRA, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void supra_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_SUPRA, 65536, 2 * 16384, ROMTYPE_SUPRA);
+}
+
+bool golem_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_GOLEM, 8192, aci->rc->autoboot_disabled ? 8192 : 0, aci->autoconfig_raw, 128, 0);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_GOLEM, 8192, aci->rc->autoboot_disabled ? 8192 : 0, scsi->rom, 8192, 0);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void golem_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_GOLEM, 65536, 8192, ROMTYPE_GOLEM);
+}
+
+bool stardrive_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_STARDRIVE);
+ aci->autoconfigp = ert->autoconfig;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void stardrive_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_STARDRIVE, 65536, 0, ROMTYPE_STARDRIVE);
+}
+
+bool kommos_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ scsi->configured = 1;
+
+ load_rom_rc(aci->rc, ROMTYPE_KOMMOS, 32768, 0, scsi->rom, 32768, 0);
+
+ map_banks(scsi->bank, 0xf10000 >> 16, 1, 0);
+ map_banks(scsi->bank, 0xeb0000 >> 16, 1, 0);
+ scsi->baseaddress = 0xeb0000;
+ scsi->baseaddress2 = 0xf10000;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void kommos_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_KOMMOS, 65536, 32768, ROMTYPE_KOMMOS);
+}
+
+bool vector_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_VECTOR, 32768, 0, aci->autoconfig_raw, 128, 0);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ int roms[2];
+
+ if (!scsi)
+ return false;
+
+ roms[0] = 128;
+ roms[1] = -1;
+
+ scsi->intena = true;
+
+ if (!aci->rc->autoboot_disabled) {
+ load_rom_rc(aci->rc, ROMTYPE_VECTOR, 32768, 0, scsi->rom, 32768, 0);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void vector_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_VECTOR, 65536, 32768, ROMTYPE_VECTOR);
+}
+
+
+bool protar_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_PROTAR, 32768, 0x200, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_PROTAR, 32768, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE);
+ memcpy(scsi->acmemory, scsi->rom + 0x200 * 2, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void protar_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_PROTAR, 65536, 65536, ROMTYPE_PROTAR);
+}
+
+bool add500_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_ADD500, 16384, 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_ADD500, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void add500_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_ADD500, 65536, 32768, ROMTYPE_ADD500);
+}
+
+static uae_u8 kronos_eeprom[32] =
+{
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 7 << 5, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+bool kronos_init(struct autoconfig_info *aci)
+{
+ //const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_KRONOS);
+ //scsi_add_reset();
+ //aci->autoconfigp = ert->autoconfig;
+ //if (!aci->doinit)
+ // return true;
+
+ //struct soft_scsi *scsi = getscsi(aci->rc);
+ //if (!scsi)
+ // return false;
+
+ //scsi->databuffer_size = 1024;
+ //scsi->databufferptr = xcalloc(uae_u8, scsi->databuffer_size);
+
+ //uae_u16 sum = 0, xor = 0;
+ //for (int i = 0; i < 16 - 2; i++) {
+ // uae_u16 v = (kronos_eeprom[i * 2 + 0] << 8) | (kronos_eeprom[i * 2 + 1]);
+ // sum += v;
+ // xor ^= v;
+ //}
+ //sum = 0 - sum;
+ //kronos_eeprom[14 * 2 + 0] = sum >> 8;
+ //kronos_eeprom[14 * 2 + 1] = (uae_u8)sum;
+ //xor ^= sum;
+ //kronos_eeprom[15 * 2 + 0] = xor >> 8;
+ //kronos_eeprom[15 * 2 + 1] = (uae_u8)xor;
+
+ //scsi->eeprom = eeprom93xx_new(kronos_eeprom, 16, NULL);
+
+ //load_rom_rc(aci->rc, ROMTYPE_KRONOS, 4096, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ //aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void kronos_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_KRONOS, 65536, 32768, ROMTYPE_KRONOS);
+}
+
+bool adscsi_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_ADSCSI, 32768, 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_ADSCSI, 32768, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void adscsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_ADSCSI, 65536, 65536, ROMTYPE_ADSCSI);
+}
+
+bool trumpcardpro_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_IVSTPRO);
+ scsi_add_reset();
+ aci->autoconfigp = ert->autoconfig;
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_IVSTPRO, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void trumpcardpro_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_TRUMPCARDPRO, 65536, 32768, NCR5380_TRUMPCARDPRO);
+}
+
+bool trumpcard_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_IVSTC);
+ scsi_add_reset();
+ aci->autoconfigp = ert->autoconfig;
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+ scsi->dma_autodack = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_IVSTC, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void trumpcard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_TRUMPCARD, 65536, 32768, ROMTYPE_IVSTC);
+}
+
+bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress)
+{
+ struct soft_scsi *scsi = getscsi(rc);
+ scsi->configured = true;
+ scsi->c400 = true;
+ scsi->dma_controller = true;
+ scsi->baseaddress = baseaddress;
+ return scsi != NULL;
+}
+
+void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_ROCHARD, 65536, -1, ROMTYPE_ROCHARD);
+}
+
+uae_u8 idescsi_scsi_get(uaecptr addr)
+{
+ return soft_generic_bget(addr);
+}
+
+void idescsi_scsi_put(uaecptr addr, uae_u8 v)
+{
+ soft_generic_bput(addr, v);
+}
+
+bool cltda1000scsi_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_CLTDSCSI);
+ scsi_add_reset();
+ aci->autoconfigp = ert->autoconfig;
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+ scsi->delayed_irq = true;
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void cltda1000scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_CLTD, 65536, 0, ROMTYPE_CLTDSCSI);
+}
+
+bool ptnexus_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_PTNEXUS);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+ scsi->delayed_irq = true;
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ load_rom_rc(aci->rc, ROMTYPE_PTNEXUS, 8192, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_PTNEXUS, 65536, 65536, ROMTYPE_PTNEXUS);
+}
+
+bool dataflyer_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ scsi->baseaddress = (currprefs.cs_ide == IDE_A4000) ? 0xdd2000 : 0xda0000;
+ scsi->configured = true;
+
+ gayle_dataflyer_enable(true);
+
+ return true;
+}
+
+void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYER, 4096, 0, ROMTYPE_DATAFLYERP);
+}
+
+static void expansion_add_protoautoconfig_data(uae_u8 *p, uae_u16 manufacturer_id, uae_u8 product_id)
+{
+ memset(p, 0, 4096);
+ p[0x02] = product_id;
+ p[0x08] = manufacturer_id >> 8;
+ p[0x0a] = (uae_u8)manufacturer_id;
+}
+
+static void expansion_add_protoautoconfig_box(uae_u8 *p, int box_size, uae_u16 manufacturer_id, uae_u8 product_id)
+{
+ expansion_add_protoautoconfig_data(p, manufacturer_id, product_id);
+ // "box without init/diagnostics code"
+ p[0] = 0x40 | (box_size << 3);
+}
+static void expansion_add_protoautoconfig_board(uae_u8 *p, int board, uae_u16 manufacturer_id, uae_u8 product_id, int memorysize)
+{
+ p += (board + 1) * 4096;
+ expansion_add_protoautoconfig_data(p, manufacturer_id, product_id);
+ // "board without init/diagnostic code"
+ p[0] = 0x08;
+ if (memorysize) {
+ int v = 0;
+ switch (memorysize)
+ {
+ case 64 * 1024:
+ v = 1;
+ break;
+ case 128 * 1024:
+ v = 2;
+ break;
+ case 256 * 1024:
+ v = 3;
+ break;
+ case 512 * 1024:
+ v = 4;
+ break;
+ case 1024 * 1024:
+ v = 5;
+ break;
+ case 2048 * 1024:
+ v = 6;
+ break;
+ case 4096 * 1024:
+ default:
+ v = 7;
+ break;
+ }
+ p[0] |= v;
+ }
+}
+
+bool tecmar_init(struct autoconfig_info *aci)
+{
+ static const uae_u8 ac[16] = { 0x40, 0x00, 0, 0, 1001 >> 8, (uae_u8)1001 };
+
+ scsi_add_reset();
+ aci->hardwired = true;
+ if (!aci->doinit) {
+ aci->zorro = 1;
+ aci->autoconfigp = ac;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ int index = 0;
+ if (!scsi)
+ return false;
+
+ scsi->rom = xcalloc(uae_u8, 65536);
+ expansion_add_protoautoconfig_box(scsi->rom, 3, 1001, 0);
+ // memory
+ expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 1, currprefs.fastmem[0].size);
+ // clock
+ expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 2, 0);
+ // serial
+ expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 3, 0);
+ // parallel
+ expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 4, 0);
+ // sasi
+ expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 4, 0);
+ memset(tecmar_clock_regs, 0, sizeof tecmar_clock_regs);
+ tecmar_clock_regs[11] = 0x04 | 0x02 | 0x01;
+ scsi->configured = true;
+ scsi->baseaddress = AUTOCONFIG_Z2;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void tecmar_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_TECMAR, 65536, 65536, ROMTYPE_TECMAR);
+}
+
+bool microforge_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xef0000;
+ aci->size = 0x10000;
+ aci->zorro = 0;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->configured = 1;
+
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->baseaddress = aci->start;
+ return true;
+}
+
+void microforge_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_MICROFORGE, 65536, 0, ROMTYPE_MICROFORGE);
+}
+
+bool xebec_init(struct autoconfig_info *aci)
+{
+ aci->start = 0x600000;
+ aci->size = 0x800000 - aci->start;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->configured = 1;
+
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = 0x1fffff;
+ scsi->baseaddress = aci->start;
+ scsi->level6 = true;
+ scsi->intena = true;
+ scsi->dma_controller = true;
+ scsi->databuffer_size = 32768;
+ scsi->databufferptr = xcalloc(uae_u8, scsi->databuffer_size);
+ return true;
+}
+
+void xebec_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_XEBEC, 65536, 0, ROMTYPE_XEBEC);
+}
+
+bool paradox_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->configured = 1;
+ parallel_port_scsi = true;
+ parallel_port_scsi_data = scsi;
+
+ return true;
+}
+
+void paradox_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_PARADOX, 0, 0, ROMTYPE_PARADOX);
+}
+
+bool hda506_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_HDA506);
+
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ scsi->level6 = true;
+ scsi->intena = true;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void hda506_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_HDA506, 0, 0, ROMTYPE_HDA506);
+}
+
+bool alf1_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xef0000;
+ aci->size = 0x10000;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = aci->size - 1;
+ scsi->baseaddress = aci->start;
+ scsi->configured = 1;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void alf1_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_ALF1, 65536, 0, ROMTYPE_ALF1);
+}
+
+bool promigos_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xf40000;
+ aci->size = 0x10000;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = aci->size - 1;
+ scsi->baseaddress = aci->start;
+ scsi->configured = 1;
+ scsi->intena = true;
+
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void promigos_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_PROMIGOS, 65536, 0, ROMTYPE_PROMIGOS);
+}
+
+bool system2000_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xf00000;
+ aci->size = 0x10000;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+ return true;
+}
+
+bool system2000_preinit(struct autoconfig_info *aci)
+{
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = aci->size - 1;
+ scsi->baseaddress = aci->start;
+ scsi->configured = 1;
+ if (!aci->rc->autoboot_disabled) {
+ load_rom_rc(aci->rc, ROMTYPE_SYSTEM2000, 16384, 0, scsi->rom, 16384, 0);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void system2000_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_SYSTEM2000, 65536, 16384, ROMTYPE_SYSTEM2000);
+}
+
+bool wedge_init(struct autoconfig_info *aci)
+{
+ aci->start = 0xea0000;
+ aci->size = 0x10000;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+ return true;
+}
+
+bool wedge_preinit(struct autoconfig_info *aci)
+{
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = aci->size - 1;
+ scsi->baseaddress = aci->start;
+ scsi->configured = 1;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void wedge_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_WEDGE, 65536, 0, ROMTYPE_WEDGE);
+}
+
+bool omtiadapter_init(struct autoconfig_info *aci)
+{
+ aci->start = 0x8f0000;
+ aci->size = 0x10000;
+ scsi_add_reset();
+ if (!aci->doinit)
+ return true;
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+ map_banks(scsi->bank, aci->start >> 16, aci->size >> 16, 0);
+ scsi->board_mask = aci->size - 1;
+ scsi->baseaddress = aci->start;
+ scsi->configured = 1;
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void omtiadapter_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_ADAPTER, 65536, 0, ROMTYPE_OMTIADAPTER);
+}
+
+bool phoenixboard_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_PHOENIXB, 8192, aci->rc->autoboot_disabled ? 0 : 8192, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_PHOENIXB, 8192, aci->rc->autoboot_disabled ? 0 : 8192, scsi->rom, 16384, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ load_rom_rc(aci->rc, ROMTYPE_PHOENIXB, 16384, 16384, scsi->rom + 16384, 16384, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void phoenixboard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_PHOENIXBOARD, 65536, 32768, ROMTYPE_PHOENIXB);
+}
+
+void twelvegauge_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_12GAUGE, 65536, 65536, ROMTYPE_CB_12GAUGE);
+}
+
+bool twelvegauge_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_CB_12GAUGE);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_CB_12GAUGE, 32768, 0, aci->autoconfig_raw, 128, 0);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+ scsi->busy_delayed_hack = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_CB_12GAUGE, 32768, 0, scsi->rom, 32768, 0);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+
+ aci->addrbankp = scsi->bank;
+
+ return true;
+}
+
+void ivsvector_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_IVSVECTOR, 65536, 65536, ROMTYPE_CB_VECTOR);
+}
+
+bool ivsvector_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_CB_VECTOR);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_CB_VECTOR, 65536, 0x300, aci->autoconfig_raw, 128, 0);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_CB_VECTOR, 65536, 0, scsi->rom, 65536, 0);
+
+ memcpy(scsi->acmemory, scsi->rom + 0x300, sizeof scsi->acmemory);
+
+ aci->addrbankp = scsi->bank;
+ aci->hardwired = true;
+
+ if (!currprefs.address_space_24) {
+ map_banks(aci->addrbankp, 0x01000000 >> 16, (65536 * 16) >> 16, 65536);
+ scsi->baseaddress2 = 0x01000000;
+ scsi->board_mask2 = (65536 * 16) - 1;
+ }
+
+ return true;
+}
+
+bool scram5380_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_SCRAM5380);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ scsi->intena = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_SCRAM5380, 8192, 0, scsi->rom, 8192, 0);
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void scram5380_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_SCRAM, 65536, 8192, ROMTYPE_SCRAM5380);
+}
+
+bool ossi_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_OSSI);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ if (!load_rom_rc(aci->rc, ROMTYPE_OSSI, 32768, aci->rc->autoboot_disabled ? 16384 : 0, aci->autoconfig_raw, 128, 0))
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ if (load_rom_rc(aci->rc, ROMTYPE_OSSI, 32768, aci->rc->autoboot_disabled ? 16384 : 0, scsi->rom, 16384, 0)) {
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ } else {
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void ossi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_OSSI, 65536, 16384, ROMTYPE_OSSI);
+}
+
+bool dataflyerplus_scsi_init(struct romconfig *rc, uaecptr baseaddress)
+{
+ struct soft_scsi *scsi = getscsi(rc);
+ scsi->configured = true;
+ scsi->baseaddress = baseaddress;
+ scsi->intena = true;
+ return scsi != NULL;
+}
+
+void dataflyerplus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYERPLUS, 65536, -1, ROMTYPE_DATAFLYER);
+}
+
+bool hardframe_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_HARDFRAME, 32768, aci->rc->autoboot_disabled ? 64 : 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_HARDFRAME, 32768, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ if (aci->rc->autoboot_disabled)
+ memcpy(scsi->rom, scsi->rom + 128, 128);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void hardframe_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_HARDFRAME, 65536, 65536, ROMTYPE_HARDFRAME);
+}
+
+bool inmate_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_INMATE, 32768, 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_INMATE, 32768, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void inmate_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NONCR_INMATE, 65536, 65536, ROMTYPE_INMATE);
+}
+
+bool malibu_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_MALIBU);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_MALIBU, 8192, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ if (aci->rc->autoboot_disabled && i == 0)
+ b = 0xc1;
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void malibu_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_MALIBU, 65536, 16384, ROMTYPE_MALIBU);
+}
+
+bool addhard_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_ADDHARD);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_ADDHARD, 16384, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ scsi->intena = true;
+ return true;
+}
+
+void addhard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_ADDHARD, 65536, 32768, ROMTYPE_ADDHARD);
+}
+
+bool emplant_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_EMPLANT);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_EMPLANT, 8192, 0, scsi->rom, 16384, LOADROM_EVENONLY_ODDONE);
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void emplant_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_EMPLANT, 65536, 16384, ROMTYPE_EMPLANT);
+}
+
+bool hd3000_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_GOLEMHD3000);
+
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_GOLEMHD3000, 8192, !aci->rc->autoboot_disabled ? 0 : 8192, aci->autoconfig_raw, 128, 0);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_GOLEMHD3000, 8192, !aci->rc->autoboot_disabled ? 0 : 8192, scsi->rom, 65536, 0);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void hd3000_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, OMTI_HD3000, 65536, 16384, ROMTYPE_GOLEMHD3000);
+}
+
+bool eveshamref_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_EVESHAMREF, 65536, aci->rc->autoboot_disabled ? 0x1000 : 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_EVESHAMREF, 65536, aci->rc->autoboot_disabled ? 0x1000 : 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void eveshamref_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_EVESHAMREF, 65536, 65536, ROMTYPE_EVESHAMREF);
+}
+
+bool profex_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_PROFEX);
+
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_PROFEX, 8192, 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ if (aci->rc->autoboot_disabled)
+ aci->autoconfig_raw[0] &= ~0x10;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_PROFEX, 8192, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+ if (aci->rc->autoboot_disabled)
+ scsi->rom[0] &= ~0x10;
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void profex_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ struct soft_scsi *ss = generic_soft_scsi_add(ch, ci, rc, OMTI_PROFEX, 65536, 16384, ROMTYPE_PROFEX);
+ if (ss && ch >= 0) {
+ // Boot ROM requires OMTI-55 "55" identifier.
+ ss->rscsi.device[ch]->hfd->sector_buffer[0] = '5';
+ ss->rscsi.device[ch]->hfd->sector_buffer[1] = '5';
+ }
+}
+
+bool fasttrak_init(struct autoconfig_info *aci)
+{
+ scsi_add_reset();
+ if (!aci->doinit) {
+ load_rom_rc(aci->rc, ROMTYPE_FASTTRAK, 65536, aci->rc->autoboot_disabled ? 0x4000 : 0x6000, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_FASTTRAK, 65536, aci->rc->autoboot_disabled ? 0x4000 : 0x6000, scsi->rom, 0x4000, LOADROM_EVENONLY_ODDONE);
+ memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void fasttrak_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_FASTTRAK, 65536, 65536, ROMTYPE_FASTTRAK);
+}
+
+bool overdrive_init(struct autoconfig_info *aci)
+{
+ const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_OVERDRIVE);
+ scsi_add_reset();
+ if (!aci->doinit) {
+ aci->autoconfigp = ert->autoconfig;
+ return true;
+ }
+
+ struct soft_scsi *scsi = getscsi(aci->rc);
+ if (!scsi)
+ return false;
+
+ load_rom_rc(aci->rc, ROMTYPE_OVERDRIVE, 8192, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE);
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = ert->autoconfig[i];
+ if (aci->rc->autoboot_disabled) {
+ if (i == 0)
+ b = 0xc1;
+ if (i == 10)
+ b = 0;
+ }
+ ew(scsi, i * 4, b);
+ }
+ aci->addrbankp = scsi->bank;
+ return true;
+}
+
+void overdrive_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ generic_soft_scsi_add(ch, ci, rc, NCR5380_OVERDRIVE, 65536, 32768, ROMTYPE_OVERDRIVE);
+}
+
+// x86 bridge scsi rancho rt1000
+void x86_rt1000_bput(int portnum, uae_u8 v)
+{
+ struct soft_scsi *scsi = x86_hd_data;
+ if (!scsi)
+ return;
+ if (portnum < 0) {
+ struct raw_scsi *rs = &scsi->rscsi;
+ raw_scsi_busfree(rs);
+ scsi->chip_state = 0;
+ return;
+ }
+ ncr53400_bput(scsi, portnum, v);
+}
+uae_u8 x86_rt1000_bget(int portnum)
+{
+ uae_u8 v = 0xff;
+ struct soft_scsi *scsi = x86_hd_data;
+ if (!scsi)
+ return v;
+ v = ncr53400_bget(scsi, portnum);
+ return v;
+}
+
+//extern void x86_rt1000_bios(struct zfile*, struct romconfig *rc);
+//bool x86_rt1000_init(struct autoconfig_info *aci)
+//{
+// static const int parent[] = { ROMTYPE_A1060, ROMTYPE_A2088, ROMTYPE_A2088T, ROMTYPE_A2286, ROMTYPE_A2386, 0 };
+// aci->parent_romtype = parent;
+// scsi_add_reset();
+// if (!aci->doinit)
+// return true;
+//
+// struct soft_scsi *scsi = getscsi(aci->rc);
+//
+// if (!scsi)
+// return false;
+// struct zfile *f = read_device_from_romconfig(aci->rc, 0);
+// if (f) {
+// x86_rt1000_bios(f, aci->rc);
+// zfile_fclose(f);
+// }
+// scsi->configured = 1;
+// scsi->dma_controller = true;
+// scsi->c400 = true;
+// x86_hd_data = scsi;
+// return true;
+//}
+
+//void x86_rt1000_add_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+//{
+// generic_soft_scsi_add(ch, ci, rc, NCR5380_X86_RT1000, 0, 0, ROMTYPE_X86_RT1000);
+//}
diff --git a/src/scsiemul.cpp b/src/scsiemul.cpp
new file mode 100644
index 00000000..aad0b5a8
--- /dev/null
+++ b/src/scsiemul.cpp
@@ -0,0 +1,1622 @@
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* scsi.device emulation
+*
+* Copyright 1995 Bernd Schmidt
+* Copyright 1999 Patrick Ohly
+* Copyright 2001 Brian King
+* Copyright 2002 Toni Wilen
+*
+*/
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "threaddep/thread.h"
+#include "options.h"
+#include "memory.h"
+#include "autoconf.h"
+#include "traps.h"
+#include "execlib.h"
+#include "native2amiga.h"
+#include "blkdev.h"
+#include "scsidev.h"
+#include "uae.h"
+#include "execio.h"
+#include "savestate.h"
+
+#define CDDEV_COMMANDS
+
+#define UAEDEV_SCSI _T("uaescsi.device")
+#define UAEDEV_SCSI_ID 1
+#define UAEDEV_DISK _T("uaedisk.device")
+#define UAEDEV_DISK_ID 2
+
+#define MAX_ASYNC_REQUESTS 20
+#define MAX_OPEN_DEVICES 20
+
+#define ASYNC_REQUEST_NONE 0
+#define ASYNC_REQUEST_TEMP 1
+#define ASYNC_REQUEST_CHANGEINT 10
+#define ASYNC_REQUEST_FRAMEINT 11
+
+struct devstruct {
+ int unitnum, aunit;
+ int opencnt;
+ int changenum;
+ int drivetype;
+ int iscd;
+ volatile uaecptr d_request[MAX_ASYNC_REQUESTS];
+ volatile uae_u8 *d_request_iobuf[MAX_ASYNC_REQUESTS];
+ volatile int d_request_type[MAX_ASYNC_REQUESTS];
+ volatile uae_u32 d_request_data[MAX_ASYNC_REQUESTS];
+ struct device_info di;
+ uaecptr changeint;
+ int changeint_mediastate;
+
+ int configblocksize;
+ int volumelevel;
+ int fadeframes;
+ int fadetarget;
+ int fadecounter;
+
+ smp_comm_pipe requests;
+ int thread_running;
+ uae_sem_t sync_sem;
+ TCHAR *tape_directory;
+ bool readonly;
+};
+
+struct priv_devstruct {
+ int inuse;
+ int unit;
+ int mode;
+ int type;
+ int flags; /* OpenDevice() */
+};
+
+static struct devstruct devst[MAX_TOTAL_SCSI_DEVICES];
+static struct priv_devstruct pdevst[MAX_OPEN_DEVICES];
+static uae_u32 nscmd_cmd;
+static uae_sem_t change_sem;
+
+static struct device_info *devinfo (struct devstruct *devst, struct device_info *di)
+{
+ struct device_info *dio = sys_command_info (devst->unitnum, di, 0);
+ if (dio) {
+ if (!devst->configblocksize)
+ devst->configblocksize = dio->bytespersector;
+ }
+ return di;
+}
+
+static void io_log(const TCHAR *msg, uae_u8 *iobuf, uaecptr request)
+{
+ //if (log_scsi)
+ // write_log (_T("%s: %08X %d %08X %d %d io_actual=%d io_error=%d\n"),
+ // msg, request, get_word_host(iobuf + 28), get_long_host(iobuf + 40),
+ // get_long_host(iobuf + 36), get_long_host(iobuf + 44),
+ // get_long_host(iobuf + 32), get_byte_host(iobuf + 31));
+}
+
+static struct devstruct *getdevstruct (int unit)
+{
+ int i;
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unit >= 0 && devst[i].aunit == unit)
+ return &devst[i];
+ }
+ return 0;
+}
+
+static struct priv_devstruct *getpdevstruct(TrapContext *ctx, uaecptr request)
+{
+ int i = trap_get_long(ctx, request + 24);
+ if (i < 0 || i >= MAX_OPEN_DEVICES || pdevst[i].inuse == 0) {
+ write_log (_T("uaescsi.device: corrupt iorequest %08X %d\n"), request, i);
+ return 0;
+ }
+ return &pdevst[i];
+}
+
+static const TCHAR *getdevname (int type)
+{
+ switch (type) {
+ case UAEDEV_SCSI_ID:
+ return UAEDEV_SCSI;
+ case UAEDEV_DISK_ID:
+ return UAEDEV_DISK;
+ default:
+ return _T("NULL");
+ }
+}
+
+static int dev_thread(void *devs);
+static int start_thread(struct devstruct *dev)
+{
+ if (dev->thread_running)
+ return 1;
+ init_comm_pipe (&dev->requests, 300, 3);
+ uae_sem_init (&dev->sync_sem, 0, 0);
+ uae_start_thread (_T("uaescsi"), dev_thread, dev, NULL);
+ uae_sem_wait (&dev->sync_sem);
+ return dev->thread_running;
+}
+
+static void dev_close_3(struct devstruct *dev, struct priv_devstruct *pdev)
+{
+ if (!dev->opencnt) return;
+ dev->opencnt--;
+ if (!dev->opencnt) {
+ sys_command_close (dev->unitnum);
+ pdev->inuse = 0;
+ write_comm_pipe_pvoid(&dev->requests, NULL, 0);
+ write_comm_pipe_pvoid(&dev->requests, NULL, 0);
+ write_comm_pipe_u32(&dev->requests, 0, 1);
+ }
+}
+
+static uae_u32 REGPARAM2 dev_close_2(TrapContext *ctx)
+{
+ uae_u32 request = trap_get_areg(ctx, 1);
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+ struct devstruct *dev;
+
+ if (!pdev)
+ return 0;
+ dev = getdevstruct(pdev->unit);
+ //if (log_scsi)
+ // write_log (_T("%s:%d close, req=%08X\n"), getdevname (pdev->type), pdev->unit, request);
+ if (!dev)
+ return 0;
+ dev_close_3 (dev, pdev);
+ trap_put_long(ctx, request + 24, 0);
+ trap_put_word(ctx, trap_get_areg(ctx, 6) + 32, trap_get_word(ctx, trap_get_areg(ctx, 6) + 32) - 1);
+ return 0;
+}
+
+static uae_u32 REGPARAM2 dev_close(TrapContext *context)
+{
+ return dev_close_2(context);
+}
+static uae_u32 REGPARAM2 diskdev_close(TrapContext *context)
+{
+ return dev_close_2(context);
+}
+
+static int openfail(TrapContext *ctx, uaecptr ioreq, int error)
+{
+ trap_put_long(ctx, ioreq + 20, -1);
+ trap_put_byte(ctx, ioreq + 31, error);
+ return (uae_u32)-1;
+}
+
+static uae_u32 REGPARAM2 dev_open_2(TrapContext *ctx, int type)
+{
+ uaecptr ioreq = trap_get_areg(ctx, 1);
+ uae_u32 unit = trap_get_dreg(ctx, 0);
+ uae_u32 flags = trap_get_dreg(ctx, 1);
+ struct devstruct *dev = getdevstruct(unit);
+ struct priv_devstruct *pdev = 0;
+ int i, v;
+
+ //if (log_scsi)
+ // write_log (_T("opening %s:%d ioreq=%08X\n"), getdevname (type), unit, ioreq);
+ uae_u16 len = trap_get_word(ctx, ioreq + 0x12);
+ if (len < IOSTDREQ_SIZE && len > 0)
+ return openfail(ctx, ioreq, IOERR_BADLENGTH);
+ if (!dev)
+ return openfail(ctx, ioreq, 32); /* badunitnum */
+ if (!dev->opencnt) {
+ for (i = 0; i < MAX_OPEN_DEVICES; i++) {
+ pdev = &pdevst[i];
+ if (pdev->inuse == 0)
+ break;
+ }
+ //if (dev->drivetype == INQ_SEQD) {
+ // v = sys_command_open_tape(dev->unitnum, dev->tape_directory, dev->readonly);
+ //} else {
+ v = sys_command_open(dev->unitnum);
+ //}
+ if (!v)
+ return openfail(ctx, ioreq, IOERR_OPENFAIL);
+ pdev->type = type;
+ pdev->unit = unit;
+ pdev->flags = flags;
+ pdev->inuse = 1;
+ trap_put_long(ctx, ioreq + 24, pdev - pdevst);
+ start_thread (dev);
+ } else {
+ for (i = 0; i < MAX_OPEN_DEVICES; i++) {
+ pdev = &pdevst[i];
+ if (pdev->inuse && pdev->unit == unit) break;
+ }
+ if (i == MAX_OPEN_DEVICES)
+ return openfail(ctx, ioreq, IOERR_OPENFAIL);
+ trap_put_long(ctx, ioreq + 24, pdev - pdevst);
+ }
+ dev->opencnt++;
+
+ trap_put_word(ctx, trap_get_areg(ctx, 6) + 32, trap_get_word(ctx, trap_get_areg(ctx, 6) + 32) + 1);
+ trap_put_byte(ctx, ioreq + 31, 0);
+ trap_put_byte(ctx, ioreq + 8, 7);
+ return 0;
+}
+
+static uae_u32 REGPARAM2 dev_open(TrapContext *ctx)
+{
+ return dev_open_2(ctx, UAEDEV_SCSI_ID);
+}
+static uae_u32 REGPARAM2 diskdev_open (TrapContext *ctx)
+{
+ return dev_open_2(ctx, UAEDEV_DISK_ID);
+}
+
+static uae_u32 REGPARAM2 dev_expunge(TrapContext *ctx)
+{
+ return 0;
+}
+static uae_u32 REGPARAM2 diskdev_expunge(TrapContext *ctx)
+{
+ return 0;
+}
+
+static int is_async_request(struct devstruct *dev, uaecptr request)
+{
+ int i = 0;
+ while (i < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request[i] == request)
+ return 1;
+ i++;
+ }
+ return 0;
+}
+
+#if 0
+static int scsiemul_switchscsi (const TCHAR *name)
+{
+ struct devstruct *dev = NULL;
+ struct device_info *discsi, discsi2;
+ int i, opened[MAX_TOTAL_SCSI_DEVICES];
+ bool wasopen = false;
+
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
+ opened[i] = sys_command_isopen (i);
+
+ dev = &devst[0];
+ if (dev->opencnt)
+ wasopen = true;
+ sys_command_close (dev->unitnum);
+
+ dev = NULL;
+ if (device_func_init (DEVICE_TYPE_ANY)) {
+ if (devst[0].di.media_inserted < 0)
+ devst[0].di.media_inserted = 0;
+ i = 0;
+ while (i < MAX_TOTAL_SCSI_DEVICES && dev == NULL) {
+ discsi = 0;
+ if (sys_command_open ( i)) {
+ discsi = sys_command_info (i, &discsi2, 0);
+ if (discsi && discsi->type == INQ_ROMD) {
+ if (!_tcsicmp (currprefs.cdimagefile[0], discsi->label)) {
+ dev = &devst[0];
+ dev->unitnum = i;
+ dev->drivetype = discsi->type;
+ memcpy (&dev->di, discsi, sizeof (struct device_info));
+ dev->iscd = 1;
+ write_log (_T("%s mounted as uaescsi.device:0\n"), discsi->label);
+ if (dev->di.media_inserted) {
+ dev->di.media_inserted = 0;
+ scsi_do_disk_change (dev->di.id, 1, NULL);
+ }
+ }
+ }
+ if (opened[i] == 0 && !wasopen)
+ sys_command_close ( i);
+ }
+ i++;
+ }
+ if (dev)
+ return dev->unitnum;
+ }
+ return -1;
+}
+#endif
+
+// pollmode is 1 if no change interrupts found -> increase time of media change
+int scsi_do_disk_change(int unitnum, int insert, int *pollmode)
+{
+ int i, j, ret;
+
+ ret = -1;
+ if (!change_sem)
+ return ret;
+ uae_sem_wait (&change_sem);
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ struct devstruct *dev = &devst[i];
+ if (dev->di.unitnum == unitnum + 1) {
+ ret = i;
+ if ((dev->changeint_mediastate > 0 && insert == 0) || (dev->changeint_mediastate <= 0 && insert)) {
+ dev->changeint_mediastate = insert;
+ if (pollmode)
+ *pollmode = 1;
+ if (dev->aunit >= 0) {
+ struct priv_devstruct *pdev = &pdevst[dev->aunit];
+ devinfo (dev, &dev->di);
+ }
+ dev->changenum++;
+ j = 0;
+ while (j < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request_type[j] == ASYNC_REQUEST_CHANGEINT) {
+ uae_Cause (dev->d_request_data[j]);
+ if (pollmode)
+ *pollmode = 0;
+ }
+ j++;
+ }
+ if (dev->changeint) {
+ uae_Cause (dev->changeint);
+ if (pollmode)
+ *pollmode = 0;
+ }
+ }
+ }
+ }
+ uae_sem_post (&change_sem);
+ return ret;
+}
+
+static int add_async_request(struct devstruct *dev, uae_u8 *iobuf, uaecptr request, int type, uae_u32 data)
+{
+ int i;
+
+ //if (log_scsi)
+ // write_log (_T("async request %08x (%d) %p added\n"), request, type, iobuf);
+ i = 0;
+ while (i < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request[i] == request) {
+ dev->d_request_type[i] = type;
+ dev->d_request_data[i] = data;
+ return 0;
+ }
+ i++;
+ }
+ i = 0;
+ while (i < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request[i] == 0) {
+ dev->d_request_iobuf[i] = iobuf;
+ dev->d_request[i] = request;
+ dev->d_request_type[i] = type;
+ dev->d_request_data[i] = data;
+ return 0;
+ }
+ i++;
+ }
+ return -1;
+}
+
+static int release_async_request(struct devstruct *dev, uaecptr request)
+{
+ int i = 0;
+
+ //if (log_scsi)
+ // write_log (_T("async request %08x removed\n"), request);
+ while (i < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request[i] == request) {
+ int type = dev->d_request_type[i];
+ dev->d_request[i] = 0;
+ xfree((uae_u8*)dev->d_request_iobuf[i]);
+ dev->d_request_iobuf[i] = 0;
+ dev->d_request_data[i] = 0;
+ dev->d_request_type[i] = 0;
+ return type;
+ }
+ i++;
+ }
+ return -1;
+}
+
+static void abort_async(struct devstruct *dev, uaecptr request, int errcode, int type)
+{
+ int i;
+ i = 0;
+ while (i < MAX_ASYNC_REQUESTS) {
+ if (dev->d_request[i] == request && dev->d_request_type[i] == ASYNC_REQUEST_TEMP) {
+ /* ASYNC_REQUEST_TEMP = request is processing */
+ sleep_millis (10);
+ i = 0;
+ continue;
+ }
+ i++;
+ }
+ i = release_async_request (dev, request);
+ //if (i >= 0 && log_scsi)
+ // write_log (_T("asyncronous request=%08X aborted, error=%d\n"), request, errcode);
+}
+
+static int command_read(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+{
+ int blocksize = dev->di.bytespersector;
+
+ length /= blocksize;
+ offset /= blocksize;
+ while (length > 0) {
+ uae_u8 buffer[4096];
+ if (!sys_command_read (dev->unitnum, buffer, offset, 1))
+ return 20;
+ trap_memcpyha_safe(ctx, data, buffer, blocksize);
+ data += blocksize;
+ offset++;
+ length--;
+ }
+ return 0;
+}
+
+static int command_write(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+{
+ uae_u32 blocksize = dev->di.bytespersector;
+ length /= blocksize;
+ offset /= blocksize;
+ while (length > 0) {
+ uae_u8 buffer[4096];
+ int err;
+ trap_memcpyah_safe(ctx, buffer, data, blocksize);
+ err = sys_command_write (dev->unitnum, buffer, offset, 1);
+ if (!err)
+ return 20;
+ if (err < 0)
+ return 28; // write protected
+ data += blocksize;
+ offset++;
+ length--;
+ }
+ return 0;
+}
+
+static int command_cd_read(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+{
+ uae_u32 len, sector, startoffset;
+ int blocksize;
+
+ blocksize = dev->configblocksize;
+ *io_actual = 0;
+ startoffset = offset % blocksize;
+ offset -= startoffset;
+ sector = offset / blocksize;
+ while (length > 0) {
+ uae_u8 temp[4096];
+ if (blocksize != 2048) {
+ if (!sys_command_cd_rawread (dev->unitnum, temp, sector, 1, blocksize))
+ return 20;
+ } else {
+ if (!sys_command_cd_read (dev->unitnum, temp, sector, 1))
+ return 20;
+ }
+ if (startoffset > 0) {
+ len = blocksize - startoffset;
+ if (len > length)
+ len = length;
+ trap_memcpyha_safe(ctx, data, temp + startoffset, len);
+ length -= len;
+ data += len;
+ startoffset = 0;
+ *io_actual += len;
+ } else if (length >= blocksize) {
+ len = blocksize;
+ trap_memcpyha_safe(ctx, data, temp, len);
+ length -= len;
+ data += len;
+ *io_actual += len;
+ } else {
+ trap_memcpyha_safe(ctx, data, temp, length);
+ *io_actual += length;
+ length = 0;
+ }
+ sector++;
+ }
+ return 0;
+}
+
+static int dev_do_io_other(TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
+{
+ uae_u32 command;
+ uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
+ uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
+ uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
+ uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
+ uae_u32 io_error = 0;
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+
+ if (!pdev)
+ return 0;
+ command = get_word_host(iobuf + 28);
+
+ //if (log_scsi)
+ // write_log (_T("SCSI OTHER %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
+ // command, io_data, io_length, io_offset, io_actual);
+ switch (command)
+ {
+ case CMD_UPDATE:
+ case CMD_CLEAR:
+ case CMD_FLUSH:
+ case CMD_MOTOR:
+ case CMD_SEEK:
+ io_actual = 0;
+ break;
+ case CMD_GETDRIVETYPE:
+ io_actual = dev->drivetype;
+ break;
+ case HD_SCSICMD:
+ {
+ uae_u32 sdd = get_long_host(iobuf + 40);
+ io_error = sys_command_scsi_direct(ctx, dev->unitnum, dev->drivetype, sdd);
+ //if (log_scsi)
+ // write_log (_T("scsidev other: did io: sdd %08x request %08x error %d\n"), sdd, request, get_byte (request + 31));
+ }
+ break;
+ default:
+ io_error = IOERR_NOCMD;
+ break;
+ }
+
+ put_long_host(iobuf + 32, io_actual);
+ put_byte_host(iobuf + 31, io_error);
+ io_log (_T("dev_io_other"), iobuf, request);
+ return 0;
+}
+
+
+static int dev_do_io_tape (TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
+{
+ uae_u32 command;
+ uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
+ uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
+ uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
+ uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
+ uae_u32 io_error = 0;
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+
+ if (!pdev)
+ return 0;
+ command = get_word_host(iobuf + 28);
+
+ //if (log_scsi)
+ // write_log (_T("TAPE %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
+ // command, io_data, io_length, io_offset, io_actual);
+ switch (command)
+ {
+ case CMD_UPDATE:
+ case CMD_CLEAR:
+ case CMD_FLUSH:
+ case CMD_MOTOR:
+ case CMD_SEEK:
+ io_actual = 0;
+ break;
+ case CMD_GETDRIVETYPE:
+ io_actual = dev->drivetype;
+ break;
+ case HD_SCSICMD:
+ {
+ uae_u32 sdd = get_long_host(iobuf + 40);
+ io_error = sys_command_scsi_direct(ctx, dev->unitnum, INQ_SEQD, sdd);
+ //if (log_scsi)
+ // write_log (_T("scsidev tape: did io: sdd %08x request %08x error %d\n"), sdd, request, get_byte (request + 31));
+ }
+ break;
+ default:
+ io_error = IOERR_NOCMD;
+ break;
+ }
+
+ put_long_host(iobuf + 32, io_actual);
+ put_byte_host(iobuf + 31, io_error);
+ io_log (_T("dev_io_tape"), iobuf, request);
+ return 0;
+}
+
+static int dev_do_io_cd (TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
+{
+ uae_u32 command;
+ uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
+ uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
+ uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
+ uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
+ uae_u32 io_error = 0;
+ uae_u64 io_offset64;
+ int async = 0;
+ int bmask = dev->di.bytespersector - 1;
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+
+ if (!pdev)
+ return 0;
+ command = get_word_host(iobuf + 28);
+
+ //if (log_scsi)
+ // write_log (_T("CD %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
+ // command, io_data, io_length, io_offset, io_actual);
+
+ switch (command)
+ {
+ case CMD_READ:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ if (dev->drivetype == INQ_ROMD) {
+ io_error = command_cd_read(ctx, dev, io_data, io_offset, io_length, &io_actual);
+ } else {
+ if ((io_offset & bmask) || bmask == 0 || io_data == 0)
+ goto bad_command;
+ if ((io_length & bmask) || io_length == 0)
+ goto bad_len;
+ io_error = command_read(ctx, dev, io_data, io_offset, io_length, &io_actual);
+ }
+ break;
+ case TD_READ64:
+ case NSCMD_TD_READ64:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
+ if ((io_offset64 & bmask) || bmask == 0 || io_data == 0)
+ goto bad_command;
+ if ((io_length & bmask) || io_length == 0)
+ goto bad_len;
+ if (dev->drivetype == INQ_ROMD)
+ io_error = command_cd_read(ctx, dev, io_data, io_offset64, io_length, &io_actual);
+ else
+ io_error = command_read(ctx, dev, io_data, io_offset64, io_length, &io_actual);
+ break;
+
+ case CMD_WRITE:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
+ io_error = 28; /* writeprotect */
+ } else if ((io_offset & bmask) || bmask == 0 || io_data == 0) {
+ goto bad_command;
+ } else if ((io_length & bmask) || io_length == 0) {
+ goto bad_len;
+ } else {
+ io_error = command_write(ctx, dev, io_data, io_offset, io_length, &io_actual);
+ }
+ break;
+ case TD_WRITE64:
+ case NSCMD_TD_WRITE64:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
+ if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
+ io_error = 28; /* writeprotect */
+ } else if ((io_offset64 & bmask) || bmask == 0 || io_data == 0) {
+ goto bad_command;
+ } else if ((io_length & bmask) || io_length == 0) {
+ goto bad_len;
+ } else {
+ io_error = command_write(ctx, dev, io_data, io_offset64, io_length, &io_actual);
+ }
+ break;
+
+ case CMD_FORMAT:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
+ io_error = 28; /* writeprotect */
+ } else if ((io_offset & bmask) || bmask == 0 || io_data == 0) {
+ goto bad_command;
+ } else if ((io_length & bmask) || io_length == 0) {
+ goto bad_len;
+ } else {
+ io_error = command_write(ctx, dev, io_data, io_offset, io_length, &io_actual);
+ }
+ break;
+ case TD_FORMAT64:
+ case NSCMD_TD_FORMAT64:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
+ if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
+ io_error = 28; /* writeprotect */
+ } else if ((io_offset64 & bmask) || bmask == 0 || io_data == 0) {
+ goto bad_command;
+ } else if ((io_length & bmask) || io_length == 0) {
+ goto bad_len;
+ } else {
+ io_error = command_write(ctx, dev, io_data, io_offset64, io_length, &io_actual);
+ }
+ break;
+
+ case CMD_UPDATE:
+ case CMD_CLEAR:
+ case CMD_FLUSH:
+ case CMD_MOTOR:
+ case CMD_SEEK:
+ io_actual = 0;
+ break;
+ case CMD_REMOVE:
+ io_actual = dev->changeint;
+ dev->changeint = io_data;
+ dev->changeint_mediastate = dev->di.media_inserted;
+ break;
+ case CMD_CHANGENUM:
+ io_actual = dev->changenum;
+ break;
+ case CMD_CHANGESTATE:
+ if (dev->di.media_inserted >= 0) {
+ io_actual = devinfo (dev, &dev->di)->media_inserted > 0 ? 0 : 1;
+ } else {
+ io_actual = 1;
+ }
+ break;
+ case CMD_PROTSTATUS:
+ io_actual = devinfo (dev, &dev->di)->write_protected ? -1 : 0;
+ break;
+ case CMD_GETDRIVETYPE:
+ io_actual = dev->drivetype;
+ break;
+ case CMD_GETNUMTRACKS:
+ if (dev->di.media_inserted <= 0)
+ goto no_media;
+ io_actual = dev->di.cylinders;
+ break;
+ case CMD_GETGEOMETRY:
+ {
+ struct device_info *di;
+ uae_u8 geom[30];
+ di = devinfo (dev, &dev->di);
+ if (di->media_inserted <= 0)
+ goto no_media;
+ put_long_host(geom + 0, di->bytespersector);
+ put_long_host(geom + 4, di->sectorspertrack * di->trackspercylinder * di->cylinders);
+ put_long_host(geom + 8, di->cylinders);
+ put_long_host(geom + 12, di->sectorspertrack * di->trackspercylinder);
+ put_long_host(geom + 16, di->trackspercylinder);
+ put_long_host(geom + 20, di->sectorspertrack);
+ put_long_host(geom + 24, 0); /* bufmemtype */
+ put_byte_host(geom + 28, di->type);
+ put_byte_host(geom + 29, di->removable ? 1 : 0); /* flags */
+ trap_put_bytes(ctx, geom, io_data, sizeof geom);
+ io_actual = 30;
+ }
+ break;
+ case CMD_ADDCHANGEINT:
+ dev->changeint_mediastate = dev->di.media_inserted;
+ io_error = add_async_request (dev, iobuf, request, ASYNC_REQUEST_CHANGEINT, io_data);
+ if (!io_error)
+ async = 1;
+ break;
+ case CMD_REMCHANGEINT:
+ release_async_request (dev, request);
+ break;
+
+ case CD_TOCLSN:
+ case CD_TOCMSF:
+ {
+ int msf = command == CD_TOCMSF;
+ struct cd_toc_head toc;
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ if (io_offset == 0 && io_length > 0) {
+ int pos = toc.lastaddress;
+ trap_put_byte(ctx, io_data, toc.first_track);
+ trap_put_byte(ctx, io_data + 1, toc.last_track);
+ if (msf)
+ pos = lsn2msf (pos);
+ trap_put_long(ctx, io_data + 2, pos);
+ io_offset++;
+ io_length--;
+ io_data += 6;
+ io_actual++;
+ }
+ for (int i = toc.first_track_offset; i < toc.last_track_offset && io_length > 0; i++) {
+ if (io_offset == toc.toc[i].point) {
+ int pos = toc.toc[i].paddress;
+ trap_put_byte(ctx, io_data, (toc.toc[i].control << 4) | toc.toc[i].adr);
+ trap_put_byte(ctx, io_data + 1, toc.toc[i].point);
+ if (msf)
+ pos = lsn2msf (pos);
+ trap_put_long(ctx, io_data + 2, pos);
+ io_offset++;
+ io_length--;
+ io_data += 6;
+ io_actual++;
+ }
+ }
+ } else {
+ io_error = IOERR_NotSpecified;
+ }
+ }
+ break;
+ case CD_ADDFRAMEINT:
+ io_error = add_async_request (dev, iobuf, request, ASYNC_REQUEST_FRAMEINT, io_data);
+ if (!io_error)
+ async = 1;
+ break;
+ case CD_REMFRAMEINT:
+ release_async_request (dev, request);
+ break;
+ case CD_ATTENUATE:
+ {
+ if (io_offset != -1) {
+ dev->fadeframes = io_length & 0x7fff;
+ dev->fadetarget = io_offset & 0x7fff;
+ }
+ io_actual = dev->volumelevel;
+ }
+ break;
+ case CD_INFO:
+ {
+ uae_u16 status = 0;
+ struct cd_toc_head toc;
+ uae_u8 cdinfo[34] = { 0 };
+ uae_u8 subq[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (dev->di.unitnum, subq, -1, false);
+ status |= 1 << 0; // door closed
+ if (dev->di.media_inserted) {
+ status |= 1 << 1;
+ status |= 1 << 2; // motor on
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ status |= 1 << 3; // toc
+ if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED)
+ status |= 1 << 5; // audio play
+ if (subq[1] == AUDIO_STATUS_PAUSED)
+ status |= 1 << 6; // paused
+ if (isdatatrack (&toc, 0))
+ status |= 1 << 4; // data track
+ }
+ }
+ put_word_host(cdinfo + 0, 75); // PlaySpeed
+ put_word_host(cdinfo + 2, 1200); // ReadSpeed (randomly chose 16x)
+ put_word_host(cdinfo + 4, 1200); // ReadXLSpeed
+ put_word_host(cdinfo + 6, dev->configblocksize); // SectorSize
+ put_word_host(cdinfo + 8, -1); // XLECC
+ put_word_host(cdinfo + 10, 0); // EjectReset
+ put_word_host(cdinfo + 12, 0); // Reserved * 4
+ put_word_host(cdinfo + 14, 0);
+ put_word_host(cdinfo + 16, 0);
+ put_word_host(cdinfo + 18, 0);
+ put_word_host(cdinfo + 20, 1200); // MaxSpeed
+ put_word_host(cdinfo + 22, 0xffff); // AudioPrecision (volume)
+ put_word_host(cdinfo + 24, status); // Status
+ put_word_host(cdinfo + 26, 0); // Reserved2 * 4
+ put_word_host(cdinfo + 28, 0);
+ put_word_host(cdinfo + 30, 0);
+ put_word_host(cdinfo + 32, 0);
+ io_actual = 34;
+ trap_put_bytes(ctx, cdinfo, io_data, io_actual);
+ }
+ break;
+ case CD_CONFIG:
+ {
+ while (trap_get_long(ctx, io_data) != TAG_DONE) {
+ uae_u32 tag = trap_get_long(ctx, io_data);
+ uae_u32 data = trap_get_long(ctx, io_data + 4);
+ if (tag == 4) {
+ // TAGCD_SECTORSIZE
+ if (data == 2048 || data == 2336 || data == 2352)
+ dev->configblocksize = data;
+ else
+ io_error = IOERR_BADADDRESS;
+
+ }
+ io_data += 8;
+ }
+ break;
+ }
+ case CD_PAUSE:
+ {
+ int old = sys_command_cd_pause (dev->di.unitnum, io_length);
+ if (old >= 0)
+ io_actual = old;
+ else
+ io_error = IOERR_BADADDRESS;
+ break;
+ }
+ case CD_PLAYLSN:
+ {
+ int start = io_offset;
+ int end = io_length + start;
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_PLAYMSF:
+ {
+ int start = msf2lsn (io_offset);
+ int end = msf2lsn (io_length) + start;
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_PLAYTRACK:
+ {
+ struct cd_toc_head toc;
+ int ok = 0;
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ for (int i = toc.first_track_offset; i < toc.last_track_offset; i++) {
+ if (i == io_offset && i + io_length <= toc.last_track_offset) {
+ ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0);
+ break;
+ }
+ }
+ }
+ if (!ok)
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_QCODEMSF:
+ case CD_QCODELSN:
+ {
+ uae_u8 subq[SUBQ_SIZE];
+ if (sys_command_cd_qcode (dev->di.unitnum, subq, -1, false)) {
+ if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED) {
+ uae_u8 subqdata[12];
+ put_byte_host(subqdata + 0, subq[4 + 0]);
+ put_byte_host(subqdata + 1, frombcd (subq[4 + 1]));
+ put_byte_host(subqdata + 2, frombcd (subq[4 + 2]));
+ put_byte_host(subqdata + 3, subq[4 + 6]);
+ int trackpos = fromlongbcd (subq + 4 + 3);
+ int diskpos = fromlongbcd (subq + 4 + 7);
+ if (command == CD_QCODELSN) {
+ trackpos = msf2lsn (trackpos);
+ diskpos = msf2lsn (diskpos);
+ }
+ put_long_host(subqdata + 4, trackpos);
+ put_long_host(subqdata + 8, diskpos);
+ io_actual = 12;
+ trap_put_bytes(ctx, subqdata, io_data, io_actual);
+ } else {
+ io_error = IOERR_InvalidState;
+ }
+ } else {
+ io_error = IOERR_BADADDRESS;
+ }
+ }
+ break;
+
+ case HD_SCSICMD:
+ {
+ uae_u32 sdd = get_long_host(iobuf + 40);
+ io_error = sys_command_scsi_direct(ctx, dev->unitnum, INQ_ROMD, sdd);
+ io_actual = 0;
+ //if (log_scsi)
+ // write_log (_T("scsidev cd: did io: sdd %08x request %08x error %d\n"), sdd, request, io_error);
+ }
+ break;
+ case NSCMD_DEVICEQUERY:
+ trap_put_long(ctx, io_data + 0, 0);
+ trap_put_long(ctx, io_data + 4, 16); /* size */
+ trap_put_word(ctx, io_data + 8, NSDEVTYPE_TRACKDISK);
+ trap_put_word(ctx, io_data + 10, 0);
+ trap_put_long(ctx, io_data + 12, nscmd_cmd);
+ io_actual = 16;
+ break;
+ default:
+ io_error = IOERR_NOCMD;
+ break;
+bad_len:
+ io_error = IOERR_BADLENGTH;
+ break;
+bad_command:
+ io_error = IOERR_BADADDRESS;
+ break;
+no_media:
+ io_error = TDERR_DiskChanged;
+ break;
+ }
+ put_long_host(iobuf + 32, io_actual);
+ put_byte_host(iobuf + 31, io_error);
+ io_log (_T("dev_io_cd"), iobuf, request);
+ return async;
+}
+
+static int dev_do_io(TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
+{
+ if (dev->drivetype == INQ_SEQD) {
+ return dev_do_io_tape(ctx, dev, iobuf, request);
+ } else if (dev->drivetype == INQ_ROMD) {
+ return dev_do_io_cd(ctx, dev, iobuf, request);
+ } else {
+ return dev_do_io_other(ctx, dev, iobuf, request);
+ }
+}
+
+static int dev_can_quick(uae_u32 command)
+{
+ switch (command)
+ {
+ case CMD_RESET:
+ case CMD_STOP:
+ case CMD_START:
+ case CMD_CHANGESTATE:
+ case CMD_PROTSTATUS:
+ case CMD_GETDRIVETYPE:
+ return 1;
+ case CMD_GETNUMTRACKS:
+ case CMD_ADDCHANGEINT:
+ case CMD_REMCHANGEINT:
+ case CD_ADDFRAMEINT:
+ case CD_REMFRAMEINT:
+ return -1;
+ }
+ return 0;
+}
+
+static int dev_canquick(struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
+{
+ uae_u32 command = get_word_host(iobuf + 28);
+ return dev_can_quick (command);
+}
+
+static uae_u32 REGPARAM2 dev_beginio(TrapContext *ctx)
+{
+ uae_u32 request = trap_get_areg(ctx, 1);
+
+ uae_u8 *iobuf = xmalloc(uae_u8, 48);
+
+ trap_get_bytes(ctx, iobuf, request, 48);
+
+ uae_u8 flags = get_byte_host(iobuf + 30);
+ int command = get_word_host(iobuf + 28);
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+ struct devstruct *dev;
+ int canquick;
+
+ put_byte_host(iobuf + 8, NT_MESSAGE);
+ if (!pdev) {
+ uae_u8 err = 32;
+ put_byte_host(iobuf + 31, err);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ xfree(iobuf);
+ return err;
+ }
+ dev = getdevstruct (pdev->unit);
+ if (!dev) {
+ uae_u8 err = 32;
+ put_byte_host(iobuf + 31, err);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ xfree(iobuf);
+ return err;
+ }
+
+ put_byte_host(iobuf + 31, 0);
+ canquick = dev_canquick (dev, iobuf, request);
+ if (((flags & 1) && canquick) || (canquick < 0)) {
+ bool async = dev_do_io(ctx, dev, iobuf, request) != 0;
+ uae_u8 v = get_byte_host(iobuf + 31);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ if (!async)
+ xfree(iobuf);
+ if (!(flags & 1) && !async)
+ uae_ReplyMsg (request);
+ return v;
+ } else {
+ add_async_request (dev, iobuf, request, ASYNC_REQUEST_TEMP, 0);
+ put_byte_host(iobuf + 30, get_byte_host(iobuf + 30) & ~1);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ trap_set_background(ctx);
+ write_comm_pipe_pvoid(&dev->requests, ctx, 0);
+ write_comm_pipe_pvoid(&dev->requests, iobuf, 0);
+ write_comm_pipe_u32(&dev->requests, request, 1);
+ return 0;
+ }
+}
+
+static int dev_thread (void *devs)
+{
+ struct devstruct *dev = (struct devstruct*)devs;
+
+ uae_set_thread_priority (NULL, 1);
+ dev->thread_running = 1;
+ uae_sem_post (&dev->sync_sem);
+ for (;;) {
+ TrapContext *ctx = (TrapContext*)read_comm_pipe_pvoid_blocking(&dev->requests);
+ uae_u8 *iobuf = (uae_u8*)read_comm_pipe_pvoid_blocking(&dev->requests);
+ uaecptr request = (uaecptr)read_comm_pipe_u32_blocking (&dev->requests);
+ uae_sem_wait (&change_sem);
+ if (!request) {
+ dev->thread_running = 0;
+ uae_sem_post (&dev->sync_sem);
+ uae_sem_post (&change_sem);
+ return 0;
+ } else if (dev_do_io(ctx, dev, iobuf, request) == 0) {
+ put_byte_host(iobuf + 30, get_byte_host(iobuf + 30) & ~1);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ release_async_request (dev, request);
+ uae_ReplyMsg (request);
+ } else {
+ //if (log_scsi)
+ // write_log (_T("%s:%d async request %08X\n"), getdevname(0), dev->unitnum, request);
+ trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
+ }
+ trap_background_set_complete(ctx);
+ uae_sem_post (&change_sem);
+ }
+}
+
+static uae_u32 REGPARAM2 dev_init_2(TrapContext *ctx, int type)
+{
+ uae_u32 base = trap_get_dreg(ctx, 0);
+ //if (log_scsi)
+ // write_log (_T("%s init\n"), getdevname (type));
+ return base;
+}
+
+static uae_u32 REGPARAM2 dev_init(TrapContext *ctx)
+{
+ return dev_init_2(ctx, UAEDEV_SCSI_ID);
+}
+static uae_u32 REGPARAM2 diskdev_init(TrapContext *ctx)
+{
+ return dev_init_2(ctx, UAEDEV_DISK_ID);
+}
+
+static uae_u32 REGPARAM2 dev_abortio (TrapContext *ctx)
+{
+ uae_u32 request = trap_get_areg(ctx, 1);
+ struct priv_devstruct *pdev = getpdevstruct(ctx, request);
+ struct devstruct *dev;
+
+ if (!pdev) {
+ uae_u8 err = 32;
+ trap_put_byte(ctx, request + 31, err);
+ return err;
+ }
+ dev = getdevstruct (pdev->unit);
+ if (!dev) {
+ uae_u8 err = 32;
+ trap_put_byte(ctx, request + 31, err);
+ return err;
+ }
+ trap_put_byte(ctx, request + 31, IOERR_ABORTED);
+ //if (log_scsi)
+ // write_log (_T("abortio %s unit=%d, request=%08X\n"), getdevname (pdev->type), pdev->unit, request);
+ abort_async(dev, request, IOERR_ABORTED, 0);
+ return 0;
+}
+
+#define BTL2UNIT(bus, target, lun) (2 * (bus) + (target) / 8) * 100 + (lun) * 10 + (target % 8)
+
+uae_u32 scsi_get_cd_drive_mask (void)
+{
+ uae_u32 mask = 0;
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ struct devstruct *dev = &devst[i];
+ if (dev->iscd)
+ mask |= 1 << i;
+ }
+ return mask;
+}
+uae_u32 scsi_get_cd_drive_media_mask (void)
+{
+ uae_u32 mask = 0;
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ struct devstruct *dev = &devst[i];
+ if (dev->iscd && dev->changeint_mediastate)
+ mask |= 1 << i;
+ }
+ return mask;
+}
+int scsi_add_tape (struct uaedev_config_info *uci)
+{
+ for (int i = 4; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ struct devstruct *dev = &devst[i];
+ if (dev->unitnum >= 0 || dev->drivetype > 0)
+ continue;
+ //if (sys_command_open_tape (i, uci->rootdir, uci->readonly)) {
+ // dev->drivetype = INQ_SEQD;
+ // dev->aunit = i;
+ // dev->unitnum = i;
+ // dev->tape_directory = my_strdup (uci->rootdir);
+ // write_log (_T("%s:%d = '%s''\n"), UAEDEV_SCSI, dev->aunit, uci->rootdir);
+ // return i;
+ //}
+ }
+ return -1;
+}
+static void dev_reset (void)
+{
+ int i, j;
+ struct devstruct *dev;
+ int unitnum = 0;
+
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ dev = &devst[i];
+ if (dev->opencnt > 0) {
+ for (j = 0; j < MAX_ASYNC_REQUESTS; j++) {
+ uaecptr request;
+ if ((request = dev->d_request[i]))
+ abort_async (dev, request, 0, 0);
+ }
+ dev->opencnt = 1;
+ if (dev->unitnum >= 0)
+ sys_command_close (dev->unitnum);
+ }
+ memset (dev, 0, sizeof (struct devstruct));
+ xfree (dev->tape_directory);
+ dev->unitnum = dev->aunit = -1;
+ }
+ for (i = 0; i < MAX_OPEN_DEVICES; i++)
+ memset (&pdevst[i], 0, sizeof (struct priv_devstruct));
+
+ device_func_init (0);
+ i = 0;
+ while (i < MAX_TOTAL_SCSI_DEVICES) {
+ dev = &devst[i];
+ struct device_info *discsi, discsi2;
+ if (sys_command_open (i)) {
+ discsi = sys_command_info (i, &discsi2, 0);
+ if (discsi) {
+ dev->unitnum = i;
+ dev->drivetype = discsi->type;
+ memcpy (&dev->di, discsi, sizeof (struct device_info));
+ dev->changeint_mediastate = discsi->media_inserted;
+ dev->configblocksize = discsi->bytespersector;
+ if (discsi->type == INQ_ROMD)
+ dev->iscd = 1;
+ } else {
+ sys_command_close (i);
+ }
+ }
+ i++;
+ }
+ unitnum = 0;
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ dev = &devst[i];
+ if (dev->unitnum >= 0)
+ sys_command_close (dev->unitnum);
+ if (dev->unitnum >= 0 && dev->iscd) {
+ dev->aunit = unitnum;
+ dev->volumelevel = 0x7fff;
+ unitnum++;
+ }
+ }
+ if (unitnum == 0)
+ unitnum = 1;
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ dev = &devst[i];
+ if (dev->unitnum >= 0) {
+ if (!dev->iscd) {
+ dev->aunit = unitnum;
+ unitnum++;
+ }
+ write_log (_T("%s:%d = %s:'%s',%d\n"), UAEDEV_SCSI, dev->aunit, dev->di.backend, dev->di.label, dev->di.type);
+ }
+ dev->di.label[0] = 0;
+ }
+}
+
+static uaecptr ROM_scsidev_resname = 0,
+ ROM_scsidev_resid = 0,
+ ROM_scsidev_init = 0;
+
+static uaecptr ROM_diskdev_resname = 0,
+ ROM_diskdev_resid = 0,
+ ROM_diskdev_init = 0;
+
+
+static uaecptr diskdev_startup (TrapContext *ctx, uaecptr resaddr)
+{
+ /* Build a struct Resident. This will set up and initialize
+ * the cd.device */
+ //if (log_scsi)
+ // write_log (_T("diskdev_startup(0x%x)\n"), resaddr);
+ trap_put_word(ctx, resaddr + 0x0, 0x4AFC);
+ trap_put_long(ctx, resaddr + 0x2, resaddr);
+ trap_put_long(ctx, resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
+ trap_put_word(ctx, resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
+ trap_put_word(ctx, resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
+ trap_put_long(ctx, resaddr + 0xE, ROM_diskdev_resname);
+ trap_put_long(ctx, resaddr + 0x12, ROM_diskdev_resid);
+ trap_put_long(ctx, resaddr + 0x16, ROM_diskdev_init);
+ resaddr += 0x1A;
+ return resaddr;
+}
+
+uaecptr scsidev_startup(TrapContext *ctx, uaecptr resaddr)
+{
+ if (currprefs.scsi != 1)
+ return resaddr;
+ //if (log_scsi)
+ // write_log (_T("scsidev_startup(0x%x)\n"), resaddr);
+ /* Build a struct Resident. This will set up and initialize
+ * the uaescsi.device */
+ trap_put_word(ctx, resaddr + 0x0, 0x4AFC);
+ trap_put_long(ctx, resaddr + 0x2, resaddr);
+ trap_put_long(ctx, resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
+ trap_put_word(ctx, resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
+ trap_put_word(ctx, resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
+ trap_put_long(ctx, resaddr + 0xE, ROM_scsidev_resname);
+ trap_put_long(ctx, resaddr + 0x12, ROM_scsidev_resid);
+ trap_put_long(ctx, resaddr + 0x16, ROM_scsidev_init); /* calls scsidev_init */
+ resaddr += 0x1A;
+ return resaddr;
+ //return diskdev_startup(ctx, resaddr);
+}
+
+static void diskdev_install (void)
+{
+ uae_u32 functable, datatable;
+ uae_u32 initcode, openfunc, closefunc, expungefunc;
+ uae_u32 beginiofunc, abortiofunc;
+
+ if (currprefs.scsi != 1)
+ return;
+ //if (log_scsi)
+ // write_log (_T("diskdev_install(): 0x%x\n"), here ());
+
+ ROM_diskdev_resname = ds (UAEDEV_DISK);
+ ROM_diskdev_resid = ds (_T("UAE disk.device 0.1"));
+
+ /* initcode */
+ initcode = here ();
+ calltrap (deftrap (diskdev_init)); dw (RTS);
+
+ /* Open */
+ openfunc = here ();
+ calltrap (deftrap (diskdev_open)); dw (RTS);
+
+ /* Close */
+ closefunc = here ();
+ calltrap (deftrap (diskdev_close)); dw (RTS);
+
+ /* Expunge */
+ expungefunc = here ();
+ calltrap (deftrap (diskdev_expunge)); dw (RTS);
+
+ /* BeginIO */
+ beginiofunc = here ();
+ calltrap (deftrap (dev_beginio));
+ dw (RTS);
+
+ /* AbortIO */
+ abortiofunc = here ();
+ calltrap (deftrap (dev_abortio)); dw (RTS);
+
+ /* FuncTable */
+ functable = here ();
+ dl (openfunc); /* Open */
+ dl (closefunc); /* Close */
+ dl (expungefunc); /* Expunge */
+ dl (EXPANSION_nullfunc); /* Null */
+ dl (beginiofunc); /* BeginIO */
+ dl (abortiofunc); /* AbortIO */
+ dl (0xFFFFFFFFul); /* end of table */
+
+ /* DataTable */
+ datatable = here ();
+ dw (0xE000); /* INITBYTE */
+ dw (0x0008); /* LN_TYPE */
+ dw (0x0300); /* NT_DEVICE */
+ dw (0xC000); /* INITLONG */
+ dw (0x000A); /* LN_NAME */
+ dl (ROM_diskdev_resname);
+ dw (0xE000); /* INITBYTE */
+ dw (0x000E); /* LIB_FLAGS */
+ dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
+ dw (0xD000); /* INITWORD */
+ dw (0x0014); /* LIB_VERSION */
+ dw (0x0004); /* 0.4 */
+ dw (0xD000); /* INITWORD */
+ dw (0x0016); /* LIB_REVISION */
+ dw (0x0000); /* end of table already ??? */
+ dw (0xC000); /* INITLONG */
+ dw (0x0018); /* LIB_IDSTRING */
+ dl (ROM_diskdev_resid);
+ dw (0x0000); /* end of table */
+
+ ROM_diskdev_init = here ();
+ dl (0x00000100); /* size of device base */
+ dl (functable);
+ dl (datatable);
+ dl (initcode);
+}
+
+
+void scsidev_install (void)
+{
+ uae_u32 functable, datatable;
+ uae_u32 initcode, openfunc, closefunc, expungefunc;
+ uae_u32 beginiofunc, abortiofunc;
+
+ if (currprefs.scsi != 1)
+ return;
+ //if (log_scsi)
+ // write_log (_T("scsidev_install(): 0x%x\n"), here ());
+
+ ROM_scsidev_resname = ds (UAEDEV_SCSI);
+ ROM_scsidev_resid = ds (_T("UAE scsi.device 0.2"));
+
+ /* initcode */
+ initcode = here ();
+ calltrap (deftrap (dev_init)); dw (RTS);
+
+ /* Open */
+ openfunc = here ();
+ calltrap (deftrap (dev_open)); dw (RTS);
+
+ /* Close */
+ closefunc = here ();
+ calltrap (deftrap (dev_close)); dw (RTS);
+
+ /* Expunge */
+ expungefunc = here ();
+ calltrap (deftrap (dev_expunge)); dw (RTS);
+
+ /* BeginIO */
+ beginiofunc = here ();
+ calltrap (deftrap (dev_beginio));
+ dw (RTS);
+
+ /* AbortIO */
+ abortiofunc = here ();
+ calltrap (deftrap (dev_abortio)); dw (RTS);
+
+ /* FuncTable */
+ functable = here ();
+ dl (openfunc); /* Open */
+ dl (closefunc); /* Close */
+ dl (expungefunc); /* Expunge */
+ dl (EXPANSION_nullfunc); /* Null */
+ dl (beginiofunc); /* BeginIO */
+ dl (abortiofunc); /* AbortIO */
+ dl (0xFFFFFFFFul); /* end of table */
+
+ /* DataTable */
+ datatable = here ();
+ dw (0xE000); /* INITBYTE */
+ dw (0x0008); /* LN_TYPE */
+ dw (0x0300); /* NT_DEVICE */
+ dw (0xC000); /* INITLONG */
+ dw (0x000A); /* LN_NAME */
+ dl (ROM_scsidev_resname);
+ dw (0xE000); /* INITBYTE */
+ dw (0x000E); /* LIB_FLAGS */
+ dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
+ dw (0xD000); /* INITWORD */
+ dw (0x0014); /* LIB_VERSION */
+ dw (0x0004); /* 0.4 */
+ dw (0xD000); /* INITWORD */
+ dw (0x0016); /* LIB_REVISION */
+ dw (0x0000);
+ dw (0xC000); /* INITLONG */
+ dw (0x0018); /* LIB_IDSTRING */
+ dl (ROM_scsidev_resid);
+ dw (0x0000); /* end of table */
+
+ ROM_scsidev_init = here ();
+ dl (0x00000100); /* size of device base */
+ dl (functable);
+ dl (datatable);
+ dl (initcode);
+
+ nscmd_cmd = here ();
+ dw (NSCMD_DEVICEQUERY);
+ dw (CMD_RESET);
+ dw (CMD_READ);
+ dw (CMD_WRITE);
+ dw (CMD_UPDATE);
+ dw (CMD_CLEAR);
+ dw (CMD_START);
+ dw (CMD_STOP);
+ dw (CMD_FLUSH);
+ dw (CMD_MOTOR);
+ dw (CMD_SEEK);
+ dw (CMD_FORMAT);
+ dw (CMD_REMOVE);
+ dw (CMD_CHANGENUM);
+ dw (CMD_CHANGESTATE);
+ dw (CMD_PROTSTATUS);
+ dw (CMD_GETDRIVETYPE);
+ dw (CMD_GETGEOMETRY);
+ dw (CMD_ADDCHANGEINT);
+ dw (CMD_REMCHANGEINT);
+ dw (HD_SCSICMD);
+ dw (NSCMD_TD_READ64);
+ dw (NSCMD_TD_WRITE64);
+ dw (NSCMD_TD_SEEK64);
+ dw (NSCMD_TD_FORMAT64);
+ dw (0);
+
+ diskdev_install ();
+}
+
+void scsidev_start_threads (void)
+{
+ if (currprefs.scsi != 1) /* quite useless.. */
+ return;
+ //if (log_scsi)
+ // write_log (_T("scsidev_start_threads()\n"));
+ uae_sem_init (&change_sem, 0, 1);
+}
+
+void scsidev_reset (void)
+{
+ if (currprefs.scsi != 1)
+ return;
+ dev_reset ();
+}
+
+uae_u8 *save_scsidev (int num, int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dstbak, *dst;
+ struct priv_devstruct *pdev;
+ struct devstruct *dev;
+
+ pdev = &pdevst[num];
+ if (!pdev->inuse)
+ return NULL;
+ if (dstptr)
+ dstbak = dst = dstptr;
+ else
+ dstbak = dst = xmalloc (uae_u8, 1000);
+ save_u32 (num);
+ save_u32 (0);
+ save_u32 (pdev->unit);
+ save_u32 (pdev->type);
+ save_u32 (pdev->mode);
+ save_u32 (pdev->flags);
+ dev = getdevstruct (pdev->unit);
+ if (dev) {
+ save_u32 (0);
+ save_u32 (dev->aunit);
+ save_u32 (dev->opencnt);
+ save_u32 (dev->changenum);
+ save_u32 (dev->changeint);
+ save_u32 (dev->changeint_mediastate);
+ save_u32 (dev->configblocksize);
+ save_u32 (dev->fadecounter);
+ save_u32 (dev->fadeframes);
+ save_u32 (dev->fadetarget);
+ for (int i = 0; i < MAX_ASYNC_REQUESTS; i++) {
+ if (dev->d_request[i]) {
+ save_u32 (dev->d_request[i]);
+ save_u32 (dev->d_request_type[i]);
+ save_u32 (dev->d_request_data[i]);
+ }
+ }
+ save_u32 (0xffffffff);
+ } else {
+ save_u32 (0xffffffff);
+ }
+ *len = dst - dstbak;
+ return dstbak;
+}
+
+uae_u8 *restore_scsidev (uae_u8 *src)
+{
+ struct priv_devstruct *pdev;
+ struct devstruct *dev;
+ int i;
+
+ int num = restore_u32 ();
+ if (num == 0)
+ dev_reset ();
+ pdev = &pdevst[num];
+ restore_u32 ();
+ restore_u32 ();
+ pdev->type = restore_u32 ();
+ pdev->mode = restore_u32 ();
+ pdev->flags = restore_u32 ();
+ if (restore_u32 () != 0xffffffff) {
+ dev = getdevstruct (pdev->unit);
+ if (dev) {
+ dev->aunit = restore_u32 ();
+ dev->opencnt = restore_u32 ();
+ dev->changenum = restore_u32 ();
+ dev->changeint = restore_u32 ();
+ dev->changeint_mediastate = restore_u32 ();
+ dev->configblocksize = restore_u32 ();
+ dev->fadecounter = restore_u32 ();
+ dev->fadeframes = restore_u32 ();
+ dev->fadetarget = restore_u32 ();
+ i = 0;
+ for (;;) {
+ uae_u32 v = restore_u32 ();
+ if (v == 0xffffffff)
+ break;
+ dev->d_request[i] = v;
+ dev->d_request_type[i] = restore_u32 ();
+ dev->d_request_data[i] = restore_u32 ();
+ }
+ }
+ }
+ return src;
+}
diff --git a/src/statusline.cpp b/src/statusline.cpp
index a84fda44..d0141efa 100644
--- a/src/statusline.cpp
+++ b/src/statusline.cpp
@@ -1,8 +1,9 @@
-#include
-#include
-
+#include "sysconfig.h"
#include "sysdeps.h"
+#include
+#include
+
#include "options.h"
#include "uae.h"
#include "xwin.h"
diff --git a/src/traps.cpp b/src/traps.cpp
index 72401e6d..44428bcd 100644
--- a/src/traps.cpp
+++ b/src/traps.cpp
@@ -843,9 +843,9 @@ void init_extended_traps (void)
exit_trap_trapaddr = here();
calltrap (deftrap2 (exit_trap_handler, TRAPFLAG_NO_RETVAL, _T("exit_trap")));
- if(trap_mutex != 0)
- uae_sem_destroy(&trap_mutex);
- trap_mutex = 0;
+ if(trap_mutex != 0)
+ uae_sem_destroy(&trap_mutex);
+ trap_mutex = 0;
uae_sem_init (&trap_mutex, 0, 1);
}
diff --git a/src/uaelib.cpp b/src/uaelib.cpp
index ad6956fe..3354fc89 100644
--- a/src/uaelib.cpp
+++ b/src/uaelib.cpp
@@ -1,19 +1,24 @@
/*
- * UAE - The U*nix Amiga Emulator
- *
- * UAE Library v0.1
- *
- * (c) 1996 Tauno Taipaleenmaki
- *
- * Change UAE parameters and other stuff from inside the emulation.
- */
+* UAE - The U*nix Amiga Emulator
+*
+* UAE Library v0.1
+*
+* (c) 1996 Tauno Taipaleenmaki
+*
+* Change UAE parameters and other stuff from inside the emulation.
+*/
+#include "sysconfig.h"
#include "sysdeps.h"
+#include
+#include
+
#include "options.h"
#include "uae.h"
#include "memory.h"
#include "autoconf.h"
+#include "traps.h"
#include "disk.h"
#include "gensound.h"
#include "picasso96.h"
@@ -301,18 +306,18 @@ static uae_u32 uaelib_demux_common(TrapContext *ctx, uae_u32 ARG0, uae_u32 ARG1,
/* The next call brings bad luck */
case 13: return emulib_ExitEmu();
case 14: return emulib_GetDisk(ctx, ARG1, ARG2);
- case 15: return 0;
+ case 15: return 0;
case 68: return 0;
case 69: return 0;
case 70: return 0; /* RESERVED. Something uses this.. */
- case 80:
- return 0xffffffff;
+ case 80:
+ return 0xffffffff;
case 81: return cfgfile_uaelib(ctx, ARG1, ARG2, ARG3, ARG4);
case 82: return cfgfile_uaelib_modify(ctx, ARG1, ARG2, ARG3, ARG4, ARG5);
- case 83: return 0;
+ case 83: return 0;
case 85: return native_dos_op(ctx, ARG1, ARG2, ARG3, ARG4);
case 86:
if (valid_address(ARG1, 1)) {