--- np2/generic/hostdrv.c 2004/01/09 05:07:03 1.2 +++ np2/generic/hostdrv.c 2005/05/20 13:59:46 1.18 @@ -1,3 +1,6 @@ +#include "compiler.h" + +#if defined(SUPPORT_HOSTDRV) /* ゲストOS(DOS)からホストOS(Win)にアクセスするの〜 @@ -6,28 +9,25 @@ 更に、手抜き版だし(マテ */ -#include "compiler.h" #include "dosio.h" #include "cpucore.h" #include "pccore.h" +#include "iocore.h" #include "hostdrv.h" #include "hostdrvs.h" #include "hostdrv.tbl" -#if 1 -#define IS_PERMITWRITE 0 -#else -#define IS_PERMITWRITE np2oscfg.hostdrv_permitwrite -#endif - -#define ROOTPATH "\\\\HOSTDRV\\" -#define ROOTPATH_SIZE (sizeof(ROOTPATH) - 1) +#define IS_PERMITWRITE (np2cfg.hdrvacc & HDFMODE_WRITE) +#define IS_PERMITDELETE (np2cfg.hdrvacc & HDFMODE_DELETE) -static const HDRVDIR hdd_volume = {"_HOSTDRIVE_", 0, 0x08}; -static const HDRVDIR hdd_owner = {". ", 0, 0x10}; -static const HDRVDIR hdd_parent = {".. ", 0, 0x10}; +#define ROOTPATH_NAME "\\\\HOSTDRV\\" +#define ROOTPATH_SIZE (sizeof(ROOTPATH_NAME) - 1) +static const char ROOTPATH[ROOTPATH_SIZE + 1] = ROOTPATH_NAME; +static const HDRVDIR hdd_volume = {"_HOSTDRIVE_", 0, 0, 0, 0x08, {0}, {0}}; +static const HDRVDIR hdd_owner = {". ", 0, 0, 0, 0x10, {0}, {0}}; +static const HDRVDIR hdd_parent = {".. ", 0, 0, 0, 0x10, {0}, {0}}; // see int2159-BX0000 enum { @@ -66,29 +66,29 @@ static void fetch_if4dos(void) { REG16 seg; IF4DOS if4dos; - off = i286_memoryread_w(IF4DOSPTR_ADDR); - seg = i286_memoryread_w(IF4DOSPTR_ADDR + 2); - i286_memstr_read(seg, off, &if4dos, sizeof(if4dos)); - hostdrv.drive_no = if4dos.drive_no; - hostdrv.dosver_major = if4dos.dosver_major; - hostdrv.dosver_minor = if4dos.dosver_minor; - hostdrv.sda_off = LOADINTELWORD(if4dos.sda_off); - hostdrv.sda_seg = LOADINTELWORD(if4dos.sda_seg); - - TRACEOUT(("hostdrv.drive_no = %d", if4dos.drive_no)); - TRACEOUT(("hostdrv.dosver = %d.%.2d", if4dos.dosver_major, if4dos.dosver_minor)); - TRACEOUT(("hostdrv.sda = %.4x:%.4x", hostdrv.sda_seg, hostdrv.sda_off)); + off = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 0); + seg = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 2); + MEMR_READS(seg, off, &if4dos, sizeof(if4dos)); + hostdrv.stat.drive_no = if4dos.drive_no; + hostdrv.stat.dosver_major = if4dos.dosver_major; + hostdrv.stat.dosver_minor = if4dos.dosver_minor; + hostdrv.stat.sda_off = LOADINTELWORD(if4dos.sda_off); + hostdrv.stat.sda_seg = LOADINTELWORD(if4dos.sda_seg); + + TRACEOUT(("hostdrv:drive_no = %d", if4dos.drive_no)); + TRACEOUT(("hostdrv:dosver = %d.%.2d", if4dos.dosver_major, if4dos.dosver_minor)); + TRACEOUT(("hostdrv.sda = %.4x:%.4x", hostdrv.stat.sda_seg, hostdrv.stat.sda_off)); } static void fetch_intr_regs(INTRST is) { - i286_memstr_read(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); + MEMR_READS(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); } static void store_intr_regs(INTRST is) { - i286_memstr_write(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); + MEMR_WRITES(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); } @@ -97,19 +97,19 @@ static void fetch_sda_currcds(SDACDS sc) REG16 off; REG16 seg; - if (hostdrv.dosver_major == 3) { - i286_memstr_read(hostdrv.sda_seg, hostdrv.sda_off, + if (hostdrv.stat.dosver_major == 3) { + MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, &sc->ver3.sda, sizeof(sc->ver3.sda)); off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); - i286_memstr_read(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); + MEMR_READS(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); } else { - i286_memstr_read(hostdrv.sda_seg, hostdrv.sda_off, + MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, &sc->ver4.sda, sizeof(sc->ver4.sda)); off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); - i286_memstr_read(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); + MEMR_READS(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); } } @@ -118,19 +118,19 @@ static void store_sda_currcds(SDACDS sc) REG16 off; REG16 seg; - if (hostdrv.dosver_major == 3) { - i286_memstr_write(hostdrv.sda_seg, hostdrv.sda_off, + if (hostdrv.stat.dosver_major == 3) { + MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, &sc->ver3.sda, sizeof(sc->ver3.sda)); off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); - i286_memstr_write(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); + MEMR_WRITES(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); } else { - i286_memstr_write(hostdrv.sda_seg, hostdrv.sda_off, + MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, &sc->ver4.sda, sizeof(sc->ver4.sda)); off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); - i286_memstr_write(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); + MEMR_WRITES(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); } } @@ -142,7 +142,7 @@ static void fetch_sft(INTRST is, SFTREC off = LOADINTELWORD(is->r.w.di); seg = LOADINTELWORD(is->r.w.es); - i286_memstr_read(seg, off, sft, sizeof(_SFTREC)); + MEMR_READS(seg, off, sft, sizeof(_SFTREC)); } static void store_sft(INTRST is, SFTREC sft) { @@ -152,7 +152,7 @@ static void store_sft(INTRST is, SFTREC off = LOADINTELWORD(is->r.w.di); seg = LOADINTELWORD(is->r.w.es); - i286_memstr_write(seg, off, sft, sizeof(_SFTREC)); + MEMR_WRITES(seg, off, sft, sizeof(_SFTREC)); } @@ -162,7 +162,7 @@ static void store_srch(INTRST is) { // SDA内のSRCHRECにセット srchrec = is->srchrec_ptr; - srchrec->drive_no = 0xc0 | hostdrv.drive_no; + srchrec->drive_no = 0xc0 | hostdrv.stat.drive_no; CopyMemory(srchrec->srch_mask, is->fcbname_ptr, 11); srchrec->attr_mask = *is->srch_attr_ptr; STOREINTELWORD(srchrec->dir_entry_no, ((UINT16)-1)); @@ -173,6 +173,7 @@ static void store_dir(INTRST is, const H DIRREC dirrec; UINT8 attr; + UINT16 reg; // SDA内のDIRRECにセット dirrec = is->dirrec_ptr; @@ -182,14 +183,28 @@ static void store_dir(INTRST is, const H attr |= 0x01; } dirrec->file_attr = attr; - STOREINTELDWORD(dirrec->file_time, 0); // di->datetime - STOREINTELDWORD(dirrec->start_sector, ((UINT32)-1)); + reg = 0; + if (di->caps & FLICAPS_TIME) { + reg |= (di->time.hour & 0x1f) << 11; + reg |= (di->time.minute & 0x3f) << 5; + reg |= (di->time.second & 0x3e) >> 1; + } + STOREINTELWORD(dirrec->file_time, reg); + reg = 0; + if (di->caps & FLICAPS_DATE) { + reg |= ((di->date.year - 1980) & 0x7f) << 9; + reg |= (di->date.month & 0x0f) << 5; + reg |= di->date.day & 0x1f; + } + STOREINTELWORD(dirrec->file_date, reg); + STOREINTELWORD(dirrec->start_sector, ((UINT16)-1)); STOREINTELDWORD(dirrec->file_size, di->size); } static void fill_sft(INTRST is, SFTREC sft, UINT num, HDRVDIR *di) { UINT8 attr; + UINT16 reg; attr = di->attr; if (!IS_PERMITWRITE) { @@ -197,11 +212,26 @@ static void fill_sft(INTRST is, SFTREC s } sft->file_attr = attr; STOREINTELWORD(sft->start_sector, (UINT16)num); - STOREINTELDWORD(sft->file_time, 0); // di->datetime + + reg = 0; + if (di->caps & FLICAPS_TIME) { + reg |= (di->time.hour & 0x1f) << 11; + reg |= (di->time.minute & 0x3f) << 5; + reg |= (di->time.second & 0x3e) >> 1; + } + STOREINTELWORD(sft->file_time, reg); + reg = 0; + if (di->caps & FLICAPS_DATE) { + reg |= ((di->date.year - 1980) & 0x7f) << 9; + reg |= (di->date.month & 0x0f) << 5; + reg |= di->date.day & 0x1f; + } + STOREINTELWORD(sft->file_date, reg); STOREINTELDWORD(sft->file_size, di->size); STOREINTELWORD(sft->dir_sector, (UINT16)-1); sft->dir_entry_no = (UINT8)-1; CopyMemory(sft->file_name, is->fcbname_ptr, 11); + TRACEOUT(("open -> size %d", di->size)); } static void init_sft(SFTREC sft) { @@ -212,7 +242,7 @@ static void init_sft(SFTREC sft) { else { sft->open_mode[0] &= 0x0f; } - sft->dev_info_word[0] = (BYTE)(0x40 | hostdrv.drive_no); + sft->dev_info_word[0] = (UINT8)(0x40 | hostdrv.stat.drive_no); sft->dev_info_word[1] = 0x80; STOREINTELDWORD(sft->dev_drvr_ptr, 0); STOREINTELDWORD(sft->file_pos, 0); @@ -255,7 +285,7 @@ static void setup_ptrs(INTRST is, SDACDS char *rootpath; int off; - if (hostdrv.dosver_major == 3) { + if (hostdrv.stat.dosver_major == 3) { is->fcbname_ptr = sc->ver3.sda.fcb_name; is->filename_ptr = sc->ver3.sda.file_name + ROOTPATH_SIZE - 1; is->fcbname_ptr_2 = sc->ver3.sda.fcb_name_2; @@ -292,12 +322,28 @@ static void setup_ptrs(INTRST is, SDACDS } -static BOOL read_data(UINT num, UINT32 pos, UINT size, - UINT16 seg, UINT16 off) { +static BOOL pathishostdrv(INTRST is, SDACDS sc) { + + fetch_sda_currcds(sc); + setup_ptrs(is, sc); + + if (memcmp(is->root_path, ROOTPATH, ROOTPATH_SIZE)) { + CPU_FLAG &= ~Z_FLAG; // chain + return(FAILURE); + } + if (is->is_chardev) { + fail(is, ERR_ACCESSDENIED); + return(FAILURE); + } + return(SUCCESS); +} + + +static BOOL read_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { HDRVFILE hdf; FILEH fh; - BYTE work[1024]; + UINT8 work[1024]; UINT r; hdf = (HDRVFILE)listarray_getitem(hostdrv.fhdl, num); @@ -313,13 +359,45 @@ static BOOL read_data(UINT num, UINT32 p if (file_read(fh, work, r) != r) { return(FAILURE); } - i286_memstr_write(seg, off, work, r); + MEMR_WRITES(seg, off, work, r); off += r; size -= r; } return(SUCCESS); } +static BOOL write_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { + + HDRVFILE hdf; + FILEH fh; + UINT8 work[1024]; + UINT r; + + hdf = (HDRVFILE)listarray_getitem(hostdrv.fhdl, num); + if (hdf == NULL) { + return(FAILURE); + } + fh = (FILEH)hdf->hdl; + if (file_seek(fh, (long)pos, FSEEK_SET) != (long)pos) { + return(FAILURE); + } + if (!size) { + file_write(fh, work, 0); + } + else { + do { + r = min(size, sizeof(work)); + MEMR_READS(seg, off, work, r); + if (file_write(fh, work, r) != r) { + return(FAILURE); + } + off += r; + size -= r; + } while(size); + } + return(SUCCESS); +} + static BOOL find_file1(INTRST is, const HDRVDIR *di) { @@ -348,7 +426,7 @@ const HDRVDIR *di; store_srch(is); ret = FAILURE; - pos = hostdrv.flistpos; + pos = hostdrv.stat.flistpos; do { if (pos == 0) { di = &hdd_owner; @@ -359,6 +437,8 @@ const HDRVDIR *di; else { hdl = listarray_getitem(hostdrv.flist, pos - 2); if (hdl == NULL) { + listarray_destroy(hostdrv.flist); + hostdrv.flist = NULL; break; } di = &hdl->di; @@ -366,7 +446,7 @@ const HDRVDIR *di; pos++; ret = find_file1(is, di); } while(ret != SUCCESS); - hostdrv.flistpos = pos; + hostdrv.stat.flistpos = pos; return(ret); } @@ -388,19 +468,12 @@ static void change_currdir(INTRST intrst char *ptr; HDRVPATH hdp; - fetch_sda_currcds(&sc); - setup_ptrs(intrst, &sc); - - if (strncmp(intrst->root_path, ROOTPATH, ROOTPATH_SIZE) != 0) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - if (intrst->is_chardev) { - fail(intrst, ERR_ACCESSDENIED); + if (pathishostdrv(intrst, &sc) != SUCCESS) { return; } ptr = intrst->filename_ptr; + TRACEOUT(("change_currdir %s", intrst->filename_ptr)); if (ptr[0] == '\0') { // るーと strcpy(intrst->filename_ptr, "\\"); strcpy(intrst->current_path, intrst->filename_ptr); @@ -408,7 +481,8 @@ static void change_currdir(INTRST intrst succeed(intrst); return; } - if ((is_wildcards(intrst->fcbname_ptr) != FALSE) || + if ((strlen(intrst->filename_ptr) >= (67 - ROOTPATH_SIZE)) || + (is_wildcards(intrst->fcbname_ptr) != FALSE) || (hostdrvs_getrealpath(&hdp, ptr) != SUCCESS) || (hdp.di.fcbname[0] == ' ') || (!(hdp.di.attr & 0x10))) { fail(intrst, ERR_PATHNOTFOUND); @@ -432,7 +506,7 @@ static void close_file(INTRST intrst) { fetch_sft(intrst, &sft); setup_ptrs(intrst, &sc); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.drive_no) { + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { CPU_FLAG &= ~Z_FLAG; // chain return; } @@ -464,7 +538,7 @@ static void commit_file(INTRST intrst) { fetch_sda_currcds(&sc); fetch_sft(intrst, &sft); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.drive_no) { + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { CPU_FLAG &= ~Z_FLAG; // chain return; } @@ -486,7 +560,7 @@ static void read_file(INTRST intrst) { fetch_sft(intrst, &sft); setup_ptrs(intrst, &sc); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.drive_no) { + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { CPU_FLAG &= ~Z_FLAG; // chain return; } @@ -512,11 +586,61 @@ static void read_file(INTRST intrst) { fail(intrst, ERR_READFAULT); return; } + file_pos += cx; STOREINTELDWORD(sft.file_pos, file_pos); store_sft(intrst, &sft); - store_sda_currcds(&sc); +// store_sda_currcds(&sc); // ver0.74 Yui / sdaは変更無し + succeed(intrst); +} + +/* 09 */ +static void write_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 cx; + UINT file_size; + UINT32 file_pos; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + setup_ptrs(intrst, &sc); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + + if ((!IS_PERMITWRITE) || + (!(sft.open_mode[0] & 3))) { // read only + fail(intrst, ERR_ACCESSDENIED); + return; + } + + cx = LOADINTELWORD(intrst->r.w.cx); + file_size = LOADINTELDWORD(sft.file_size); + file_pos = LOADINTELDWORD(sft.file_pos); + if (write_data(LOADINTELWORD(sft.start_sector), file_pos, cx, + LOADINTELWORD(sc.ver3.sda.current_dta.seg), + LOADINTELWORD(sc.ver3.sda.current_dta.off)) != SUCCESS) { + fail(intrst, ERR_WRITEFAULT); + return; + } + if (cx) { + file_pos += cx; + if (file_size < file_pos) { + file_size = file_pos; + } + } + else { + file_size = file_pos; + } + + STOREINTELDWORD(sft.file_size, file_size); + STOREINTELDWORD(sft.file_pos, file_pos); + store_sft(intrst, &sft); succeed(intrst); } @@ -529,7 +653,7 @@ static void lock_file(INTRST intrst) { fetch_sda_currcds(&sc); fetch_sft(intrst, &sft); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.drive_no) { + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { CPU_FLAG &= ~Z_FLAG; // chain return; } @@ -546,7 +670,7 @@ static void unlock_file(INTRST intrst) { fetch_sda_currcds(&sc); fetch_sft(intrst, &sft); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.drive_no) { + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { CPU_FLAG &= ~Z_FLAG; // chain return; } @@ -554,29 +678,49 @@ static void unlock_file(INTRST intrst) { TRACEOUT(("hostdrv: unlock_file")); } -/* 0F */ -static void get_fileattr(INTRST intrst) { +/* 0E */ +static void set_fileattr(INTRST intrst) { _SDACDS sc; HDRVPATH hdp; - UINT16 ax; - - fetch_sda_currcds(&sc); - setup_ptrs(intrst, &sc); + REG16 attr; - if (strncmp(intrst->root_path, ROOTPATH, ROOTPATH_SIZE) != 0) { - CPU_FLAG &= ~Z_FLAG; // chain + if (pathishostdrv(intrst, &sc) != SUCCESS) { return; } - if (intrst->is_chardev) { + if ((is_wildcards(intrst->fcbname_ptr)) || + (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != SUCCESS)) { + fail(intrst, ERR_FILENOTFOUND); + return; + } + if (!IS_PERMITWRITE) { fail(intrst, ERR_ACCESSDENIED); return; } + attr = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)) & 0x37; + + // 成功したことにする... + succeed(intrst); +} + +/* 0F */ +static void get_fileattr(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp; + UINT16 ax; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + + TRACEOUT(("get_fileattr: ->%s", intrst->fcbname_ptr)); if ((is_wildcards(intrst->fcbname_ptr)) || (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != SUCCESS)) { fail(intrst, ERR_FILENOTFOUND); return; } + TRACEOUT(("get_fileattr: %s - %x", hdp.path, hdp.di.attr)); ax = hdp.di.attr & 0x37; if (!IS_PERMITWRITE) { ax |= 0x01; @@ -585,27 +729,63 @@ static void get_fileattr(INTRST intrst) STOREINTELWORD(intrst->r.w.ax, ax); } +/* 11 */ +static void rename_file(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp1; + HDRVPATH hdp2; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + + // ワイルドカードくるんで要修正… + if ((hostdrvs_getrealpath(&hdp1, intrst->filename_ptr) != SUCCESS) || + (hostdrvs_getrealpath(&hdp2, intrst->filename_ptr_2) != SUCCESS)) { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + TRACEOUT(("rename_file %s to %s - failed", hdp1.path, hdp2.path)); + fail(intrst, ERR_ACCESSDENIED); +} + +/* 13 */ +static void delete_file(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + + // ワイルドカードくるんで要修正… + if ((hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != SUCCESS) || + (hdp.di.attr & 0x10)) { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + TRACEOUT(("delete_file %s - failed", hdp.path)); + fail(intrst, ERR_ACCESSDENIED); +} + /* 16 */ static void open_file(INTRST intrst) { _SDACDS sc; _SFTREC sft; HDRVPATH hdp; - HDRVFILE hdf; + UINT mode; FILEH fh; + HDRVFILE hdf; - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - setup_ptrs(intrst, &sc); - - if (strncmp(intrst->root_path, ROOTPATH, ROOTPATH_SIZE) != 0) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - if (intrst->is_chardev) { - fail(intrst, ERR_ACCESSDENIED); + if (pathishostdrv(intrst, &sc) != SUCCESS) { return; } +// fetch_sft(intrst, &sft); + ZeroMemory(&sft, sizeof(sft)); + if ((is_wildcards(intrst->fcbname_ptr)) || (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != SUCCESS) || (hdp.di.attr & 0x10)) { @@ -616,26 +796,94 @@ static void open_file(INTRST intrst) { hdp.path, sft.open_mode[0] & 7)); switch(sft.open_mode[0] & 7) { case 1: // write only + mode = HDFMODE_WRITE; + break; + case 2: // read/write - if (!IS_PERMITWRITE) { - fail(intrst, ERR_ACCESSDENIED); - return; - } + mode = HDFMODE_READ | HDFMODE_WRITE; break; + + default: + mode = HDFMODE_READ; + break; + } + + if (mode & HDFMODE_WRITE) { + if (!IS_PERMITWRITE) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + fh = file_open(hdp.path); + } + else { + fh = file_open_rb(hdp.path); + } + if (fh == FILEH_INVALID) { + TRACEOUT(("file open error!")); + fail(intrst, ERR_PATHNOTFOUND); + return; } + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); if (hdf == NULL) { + file_close(fh); fail(intrst, ERR_PATHNOTFOUND); return; } - fh = file_open_rb(hdp.path); - if (fh == FILEH_INVALID) { - TRACEOUT(("file open error!")); + + hdf->hdl = (long)fh; + hdf->mode = mode; + file_cpyname(hdf->path, hdp.path, sizeof(hdf->path)); + + fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.di); + init_sft(&sft); + + store_sft(intrst, &sft); + store_sda_currcds(&sc); + succeed(intrst); +} + +/* 17 */ +static void create_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + HDRVPATH hdp; + HDRVFILE hdf; + FILEH fh; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + fetch_sft(intrst, &sft); + + if ((is_wildcards(intrst->fcbname_ptr)) || + (hostdrvs_newrealpath(&hdp, intrst->filename_ptr) != SUCCESS) || + (hdp.di.attr & 0x10)) { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + TRACEOUT(("create_file: %s -> %s %d", intrst->filename_ptr, + hdp.path, sft.open_mode[0] & 7)); + + if (!IS_PERMITWRITE) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); + if (hdf == NULL) { fail(intrst, ERR_PATHNOTFOUND); return; } + fh = file_create(hdp.path); + if (fh == FILEH_INVALID) { + TRACEOUT(("file create error!")); + fail(intrst, ERR_ACCESSDENIED); + return; + } hdf->hdl = (long)fh; - hdf->mode = 0; + hdf->mode = HDFMODE_READ | HDFMODE_WRITE; file_cpyname(hdf->path, hdp.path, sizeof(hdf->path)); fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.di); @@ -656,19 +904,11 @@ static void find_first(INTRST intrst) { flist = hostdrv.flist; if (flist) { hostdrv.flist = NULL; - hostdrv.flistpos = 0; + hostdrv.stat.flistpos = 0; listarray_destroy(flist); } - fetch_sda_currcds(&sc); - setup_ptrs(intrst, &sc); - - if (strncmp(intrst->root_path, ROOTPATH, ROOTPATH_SIZE) != 0) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - if (intrst->is_chardev) { - fail(intrst, ERR_ACCESSDENIED); + if (pathishostdrv(intrst, &sc) != SUCCESS) { return; } @@ -684,7 +924,7 @@ static void find_first(INTRST intrst) { } TRACEOUT(("find_first %s -> %s", intrst->current_path, hdp.path)); hostdrv.flist = hostdrvs_getpathlist(hdp.path); - hostdrv.flistpos = 0; + hostdrv.stat.flistpos = 0; if (find_file(intrst) != SUCCESS) { fail(intrst, ERR_PATHNOTFOUND); return; @@ -699,18 +939,16 @@ static void find_next(INTRST intrst) { _SDACDS sc; SRCHREC srchrec; -// char *curpath; fetch_sda_currcds(&sc); setup_ptrs(intrst, &sc); srchrec = intrst->srchrec_ptr; if ((!(srchrec->drive_no & 0x40)) || - ((srchrec->drive_no & 0x1f) != hostdrv.drive_no)) { + ((srchrec->drive_no & 0x1f) != hostdrv.stat.drive_no)) { CPU_FLAG &= ~Z_FLAG; // chain return; } -// curpath = intrst->current_path; if (find_file(intrst) != SUCCESS) { fail(intrst, ERR_NOMOREFILES); return; @@ -719,6 +957,220 @@ static void find_next(INTRST intrst) { succeed(intrst); } +#if 1 +/* 1E */ +static void do_redir(INTRST intrst) { + + _SDACDS sc; + REG16 mode; + REG16 bx; + char tmp[4]; + + TRACEOUT(("do_redir")); + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + mode = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)); + TRACEOUT(("do_redir: %.4x", mode)); + switch(mode) { + case 0x5f02: + bx = LOADINTELWORD(intrst->r.w.bx); + if (bx) { + fail(intrst, 0x12); + return; + } + MEMR_WRITE16(CPU_DS, CPU_BX + 2, 4); + MEMR_WRITE16(CPU_DS, CPU_BX + 4, 1); + tmp[0] = (char)('A' + hostdrv.stat.drive_no); + tmp[1] = ':'; + tmp[2] = '\0'; + MEMR_WRITES(LOADINTELWORD(intrst->r.w.ds), + LOADINTELWORD(intrst->r.w.si), tmp, 3); + MEMR_WRITES(LOADINTELWORD(intrst->r.w.es), + LOADINTELWORD(intrst->r.w.di), + ROOTPATH, ROOTPATH_SIZE + 1); + break; + + default: + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + succeed(intrst); +} +#endif + +/* 21 */ +// dos4以降呼ばれることはあんまない・・・ +static void seek_fromend(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 reg; + UINT32 pos; + UINT file_size; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + reg = LOADINTELWORD(intrst->r.w.cx); + pos = reg << 16; + reg = LOADINTELWORD(intrst->r.w.dx); + pos += reg; + file_size = LOADINTELDWORD(sft.file_size); + if (pos > file_size) { + pos = file_size; + } + reg = (UINT16)(pos >> 16); + STOREINTELWORD(intrst->r.w.dx, reg); + reg = (UINT16)pos; + STOREINTELWORD(intrst->r.w.ax, reg); + pos = file_size - pos; + STOREINTELDWORD(sft.file_pos, pos); + + store_sft(intrst, &sft); + intrst->r.b.flag_l &= ~C_FLAG; +} + +/* 2D */ +static void unknownfunc_2d(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } +#if 1 + TRACEOUT(("unknownfunc_2d")); +#else + intr_regs.flags &= ~C_FLAG; + intr_regs.ax = 2; +#endif +} + +/* 2E */ +// for dos4+ +static void ext_openfile(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + HDRVPATH hdp; + UINT mode; + BOOL create; + REG16 act; + REG16 cx; + FILEH fh; + HDRVFILE hdf; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + fetch_sft(intrst, &sft); + + // ファイルを探しに〜 + if ((is_wildcards(intrst->fcbname_ptr)) || + (hostdrvs_newrealpath(&hdp, intrst->filename_ptr) != SUCCESS) || + (hdp.di.attr & 0x10)) { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + + sft.open_mode[0] = sc.ver4.sda.mode_2E[0] & 0x7f; + sft.open_mode[1] = sc.ver4.sda.mode_2E[1] & 0x00; + act = LOADINTELWORD(sc.ver4.sda.action_2E); + + switch(sft.open_mode[0] & 7) { + case 1: // write only + mode = HDFMODE_WRITE; + break; + + case 2: // read/write + mode = HDFMODE_READ | HDFMODE_WRITE; + break; + + default: + mode = HDFMODE_READ; + break; + } + + create = FALSE; + if (hdp.di.exist) { // ファイルが存在 + switch(act & 3) { + case 1: + cx = 1; + break; + + case 2: + create = TRUE; + cx = 3; + break; + + default: + fail(intrst, ERR_ACCESSDENIED); + return; + } + } + else { // 新規ファイル + if (act & 0x10) { + create = TRUE; + cx = 2; + } + else { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + } + + if (create) { + if (!IS_PERMITWRITE) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + fh = file_create(hdp.path); + } + else if (mode & HDFMODE_WRITE) { + if (!IS_PERMITWRITE) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + fh = file_open(hdp.path); + } + else { + fh = file_open_rb(hdp.path); + } + if (fh == FILEH_INVALID) { + TRACEOUT(("file open error!")); + fail(intrst, ERR_PATHNOTFOUND); + return; + } + + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); + if (hdf == NULL) { + file_close(fh); + fail(intrst, ERR_PATHNOTFOUND); + return; + } + + hdf->hdl = (long)fh; + hdf->mode = mode; + file_cpyname(hdf->path, hdp.path, sizeof(hdf->path)); + + STOREINTELWORD(intrst->r.w.cx, cx); + fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.di); + init_sft(&sft); + store_sft(intrst, &sft); + + store_sda_currcds(&sc); + succeed(intrst); +} + // ---- @@ -734,31 +1186,32 @@ static const HDINTRFN intr_func[] = { close_file, /* 06 */ commit_file, /* 07 */ read_file, /* 08 */ - NULL, // write_file, /* 09 */ + write_file, /* 09 */ lock_file, /* 0A */ unlock_file, /* 0B */ NULL, // get_diskspace, /* 0C */ NULL, - NULL, // set_fileattr, /* 0E */ + set_fileattr, /* 0E */ get_fileattr, /* 0F */ NULL, - NULL, // rename_file, /* 11 */ + rename_file, /* 11 */ NULL, - NULL, // delete_file, /* 13 */ + delete_file, /* 13 */ NULL, NULL, open_file, /* 16 */ - NULL, // create_file, /* 17 */ + create_file, /* 17 */ NULL, NULL, NULL, find_first, /* 1B */ find_next, /* 1C */ NULL, + do_redir, NULL, NULL, + seek_fromend, /* 21 */ NULL, - NULL, // seek_fromend, /* 21 */ NULL, NULL, NULL, @@ -769,9 +1222,8 @@ static const HDINTRFN intr_func[] = { NULL, NULL, NULL, - NULL, - NULL, // unknownfunc_2d, /* 2D */ - NULL, // ext_openfile /* 2E */ + unknownfunc_2d, /* 2D */ + ext_openfile /* 2E */ }; @@ -804,24 +1256,29 @@ void hostdrv_reset(void) { // ---- for np2sysp -BOOL hostdrv_mount(void) { +void hostdrv_mount(const void *arg1, long arg2) { - if ((np2cfg.hdrvroot[0] == '\0') || (hostdrv.is_mount)) { - return(FAILURE); + if ((np2cfg.hdrvroot[0] == '\0') || (hostdrv.stat.is_mount)) { + np2sysp_outstr("ng", 0); + return; } - hostdrv.is_mount = TRUE; + hostdrv.stat.is_mount = TRUE; fetch_if4dos(); - return(SUCCESS); + np2sysp_outstr("ok", 0); + (void)arg1; + (void)arg2; } -void hostdrv_unmount(void) { +void hostdrv_unmount(const void *arg1, long arg2) { - if (hostdrv.is_mount) { + if (hostdrv.stat.is_mount) { hostdrv_reset(); } + (void)arg1; + (void)arg2; } -void hostdrv_intr(void) { +void hostdrv_intr(const void *arg1, long arg2) { _INTRST intrst; @@ -829,15 +1286,15 @@ void hostdrv_intr(void) { intrst.is_chardev = (CPU_FLAG & C_FLAG) == 0; CPU_FLAG &= ~(C_FLAG | Z_FLAG); // not fcb / chain - if (!hostdrv.is_mount) { + if (!hostdrv.stat.is_mount) { return; } fetch_intr_regs(&intrst); -// TRACEOUT(("hostdrv: AL=%.2x", intrst.r.b.al)); + TRACEOUT(("hostdrv: AL=%.2x", intrst.r.b.al)); - if ((intrst.r.b.al >= sizeof(intr_func) / sizeof(HDINTRFN)) || + if ((intrst.r.b.al >= NELEMENTS(intr_func)) || (intr_func[intrst.r.b.al] == NULL)) { return; } @@ -846,5 +1303,114 @@ void hostdrv_intr(void) { (*intr_func[intrst.r.b.al])(&intrst); store_intr_regs(&intrst); + + (void)arg1; + (void)arg2; +} + + +// ---- for statsave + +typedef struct { + UINT stat; + UINT files; + UINT flists; +} SFHDRV; + +static BOOL fhdl_wr(void *vpItem, void *vpArg) { + + OEMCHAR *p; + UINT len; + + p = ((HDRVFILE)vpItem)->path; + len = OEMSTRLEN(p); + statflag_write((STFLAGH)vpArg, &len, sizeof(len)); + if (len) { + if (len < MAX_PATH) { + ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); + } + statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVFILE)); + } + return(FALSE); +} + +static BOOL flist_wr(void *vpItem, void *vpArg) { + + OEMCHAR *p; + int len; + + p = ((HDRVLST)vpItem)->realname; + len = OEMSTRLEN(p); + if (len < MAX_PATH) { + ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); + } + statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVLST)); + return(FALSE); } +int hostdrv_sfsave(STFLAGH sfh, const SFENTRY *tbl) { + + SFHDRV sfhdrv; + int ret; + + if (!hostdrv.stat.is_mount) { + return(STATFLAG_SUCCESS); + } + sfhdrv.stat = sizeof(hostdrv.stat); + sfhdrv.files = listarray_getitems(hostdrv.fhdl); + sfhdrv.flists = listarray_getitems(hostdrv.flist); + ret = statflag_write(sfh, &sfhdrv, sizeof(sfhdrv)); + ret |= statflag_write(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); + listarray_enum(hostdrv.fhdl, fhdl_wr, sfh); + listarray_enum(hostdrv.flist, flist_wr, sfh); + (void)tbl; + return(ret); +} + +int hostdrv_sfload(STFLAGH sfh, const SFENTRY *tbl) { + + SFHDRV sfhdrv; + int ret; + UINT i; + UINT len; + HDRVFILE hdf; + FILEH fh; + HDRVLST hdl; + + listarray_clr(hostdrv.fhdl); + listarray_clr(hostdrv.flist); + + ret = statflag_read(sfh, &sfhdrv, sizeof(sfhdrv)); + if (sfhdrv.stat != sizeof(hostdrv.stat)) { + return(STATFLAG_FAILURE); + } + ret |= statflag_read(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); + for (i=0; imode & HDFMODE_WRITE) { + fh = file_open(hdf->path); + } + else { + fh = file_open_rb(hdf->path); + } + hdf->hdl = (long)fh; + } + } + for (i=0; i