From 725f2c71292c1edd8055c4ce7e44fcb80b61bd3d Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Wed, 17 Jun 2020 23:41:23 +0200 Subject: [PATCH] Implemented CD support from WinUAE - Added support for CD mounting under AmigaOS - fixes #37 - Added CDTV implementation (WIP #658) --- Makefile | 4 + VisualGDB/Amiberry/Amiberry.vcxproj | 9 + VisualGDB/Amiberry/Amiberry.vcxproj.filters | 27 + src/ar.cpp | 4 +- src/autoconf.cpp | 92 +- src/blitter.cpp | 28 +- src/blkdev.cpp | 1717 ++++++- src/blkdev_cdimage.cpp | 339 +- src/cdtv.cpp | 1948 +++++++ src/cdtvcr.cpp | 1574 ++++++ src/cfgfile.cpp | 60 +- src/cia.cpp | 1 + src/crc32.cpp | 2 +- src/custom.cpp | 28 +- src/devices.cpp | 4 +- src/disk.cpp | 2 + src/diskutil.cpp | 89 +- src/drawing.cpp | 10 +- src/events.cpp | 5 +- src/expansion.cpp | 1335 ++++- src/filesys.asm | 1120 +++- src/filesys.cpp | 390 +- src/fsdb.cpp | 400 +- src/fsdb_unix.cpp | 24 +- src/fsusage.cpp | 234 +- src/gayle.cpp | 16 +- src/include/akiko.h | 2 +- src/include/autoconf.h | 106 +- src/include/blkdev.h | 131 +- src/include/cdtv.h | 26 + src/include/cdtvcr.h | 6 + src/include/cia.h | 13 +- src/include/commpipe.h | 18 +- src/include/cpu_prefetch.h | 402 +- src/include/custom.h | 6 +- src/include/isofs.h | 387 ++ src/include/isofs_api.h | 38 + src/include/memory.h | 180 +- src/include/newcpu.h | 67 +- src/include/rommgr.h | 1 + src/include/scsi.h | 1 + src/include/scsidev.h | 35 + src/inputdevice.cpp | 1 + src/isofs.cpp | 2710 ++++++++++ src/memory.cpp | 680 ++- src/osdep/amiberry.cpp | 8 + src/osdep/sysconfig.h | 4 +- src/osdep/target.h | 4 +- src/rommgr.cpp | 1256 +++-- src/savestate.cpp | 594 +-- src/scsi.cpp | 5075 ++++++++++++++++++- src/scsiemul.cpp | 1622 ++++++ src/statusline.cpp | 7 +- src/traps.cpp | 6 +- src/uaelib.cpp | 29 +- 55 files changed, 20682 insertions(+), 2195 deletions(-) create mode 100644 src/cdtv.cpp create mode 100644 src/cdtvcr.cpp create mode 100644 src/include/cdtv.h create mode 100644 src/include/cdtvcr.h create mode 100644 src/include/isofs.h create mode 100644 src/include/isofs_api.h create mode 100644 src/include/scsidev.h create mode 100644 src/isofs.cpp create mode 100644 src/scsiemul.cpp diff --git a/Makefile b/Makefile index d2093029d..8f441b0d0 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 51eb0a716..dcbcd0a3b 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 0ceaae7e7..20a3736c8 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 d1dd9f2d9..dde6c8c4c 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 0a6562bfb..a7bcd0f49 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 (); + + rtarea_init_mem (); + memset (rtarea_bank.baseaddr, 0, RTAREA_SIZE); - _stprintf(uaever, _T("uae-%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV); + _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 f5f0f2233..ccac0e837 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 f069f3fcc..37b9844b2 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 @@ static int get_standard_cd_unit2 (struct uae_prefs *p, cd_standard_unit csu) 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 0d5643119..fe5b256bb 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 @@ static int parsemds(struct cdunit* cdu, struct zfile* zmds, const TCHAR* img, co 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 000000000..ec901a700 --- /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 000000000..27ef26e01 --- /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 9b91bd565..548075d36 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 }, + + { _T("ide%d"), 0 }, + { _T("ide%d_mainboard"), ROMTYPE_MB_IDE }, - {nullptr} + { _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 804625026..947dbce39 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 6a722f361..200da20bd 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 342c16859..428056fc1 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 3d5b33a1c..f99cc55d7 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 84f7e6313..8c8a75f86 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 391e8bb72..47ba93ad9 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 19414799f..3f7f7e833 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 a6863ffd6..b1fa28276 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 99c1c9b8d..df5e32463 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 */ +static const struct expansionboardsettings cdtvsram_settings[] = { + { + _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 + }, + { + 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 */ -#ifdef CD32 { _T("cd32fmv"), _T("CD32 FMV"), _T("Commodore"), - expamem_init_cd32fmv, NULL, ROMTYPE_CD32CART, BOARD_AUTOCONFIG_Z2, - EXPANSIONTYPE_INTERNAL + NULL, expamem_init_cd32fmv, NULL, NULL, ROMTYPE_CD32CART, 0, 0, BOARD_AUTOCONFIG_Z2, true, + NULL, 0, + false, EXPANSIONTYPE_INTERNAL }, -#endif + { + _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"), - gayle_ide_init, gayle_add_ide_unit, ROMTYPE_MB_IDE | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE, - EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_IDE + 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"), - gayle_init_pcmcia, NULL, ROMTYPE_MB_PCMCIA | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE, - EXPANSIONTYPE_INTERNAL + NULL, gayle_init_pcmcia, NULL, NULL, ROMTYPE_MB_PCMCIA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true, + NULL, 0, + false, EXPANSIONTYPE_INTERNAL }, - { - NULL - } + /* 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 d5978fd36..d071661f6 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 d5ee79c22..a4b3a7cf6 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 6a6fea3c5..05ab705b7 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; - - /* 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; - } + 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; + } - 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; - } - - 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); + 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); } diff --git a/src/fsdb_unix.cpp b/src/fsdb_unix.cpp index a71651d21..796a792cf 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 472ae5480..e18a984e8 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 (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 (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); } #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) - - struct filsys fsd; - int fd; - - 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; + adjust_blocks ((B), (fsd.s_type == Fs2b ? 1024 : 512), 512) + + struct filsys fsd; + int fd; + + 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; #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 c0061f377..ecc121322 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 891fcd904..502d6e367 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 2a310c4db..720f01d37 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 39bdedb6f..d27456ddc 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 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 blkdev_vsync(void); +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 close_standard_cd_unit (int); +extern void blkdev_cd_change (int unitnum, const TCHAR *name); -extern int get_standard_cd_unit(enum cd_standard_unit csu); -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 000000000..a9212c5f1 --- /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 000000000..8220a5992 --- /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 1ba6989bd..7c623ae4f 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 227a730dc..8b267ce55 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 f4fe28cbf..6f2fc0244 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 67c02812e..d8dca017e 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 000000000..0dc1c48a9 --- /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 000000000..843afcdf3 --- /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 faf616323..2731a69f5 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 393481c84..b7432194f 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 a206df9a2..f946cbbf7 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 50f966fae..80952214a 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 000000000..073334f8f --- /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 46b2b952b..fdf4e640b 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 000000000..ffab58e7c --- /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 52f1152e3..d40748026 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(); - - mem_start = restore_u32(); - mem_size = restore_u32(); - mem_type = restore_u32(); - version = restore_u32(); - crc32 = restore_u32(); - romn = restore_string(); + 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 (); 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 7c460be33..b0a79139a 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 9af7cc036..eddd973ad 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 ace4e0a22..db7517884 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 6938dd9dc..ee4365bbf 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]; - - _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; - } + 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; + } _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; - - 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) - { + 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); + } + } + + 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; - - 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; + 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; } static int decode_rekick_rom_do (uae_u8 *mem, int size, int real_size) { - 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; + 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; } 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; - - 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) { + 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) { /* 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; - - /* find parent node */ - for (;;) { - if (rd2 == &roms[0]) - break; - if (rd2[-1].id != id) - break; - rd2--; - } + 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--; + } - 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++; + 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++; } 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; - - } - xfree (buf); - return NULL; -} - -struct zfile *rom_fopen (const TCHAR *name, const TCHAR *mode, int mask) + } + 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; +} + +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); - - 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; + 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; } 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 29bc7d854..db005c107 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 = 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 = 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); 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("BRAM"))) { + restore_bram(totallen, filepos); continue; - } else if (!_tcscmp (name, _T("A3K2"))) { - restore_a3000hram (totallen, filepos); + } + 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 +#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)) + 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("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")); for (i = 0; i < 4; i++) { - dst = save_disk2 (i, &len, 0); + dst = save_disk2(i, &len, 0); if (dst) { name[3] = i + '0'; - save_chunk (f, dst, len, name, comp); - xfree (dst); + 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 6333a5a7c..8e8413b36 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 @@ bool scsi_emulate_analyze (struct scsi_data *sd) 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 000000000..aad0b5a8b --- /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 a84fda441..d0141efa8 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 72401e6db..44428bcd3 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 ad6956feb..3354fc89b 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)) {