aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Serpell <daniel.serpell@gmail.com>2019-12-20 21:38:56 -0300
committerDaniel Serpell <daniel.serpell@gmail.com>2019-12-20 21:40:11 -0300
commita45af65ffcf4172726796b566b2e2a9c894ef390 (patch)
treed9d062e773c5413e058b7e891d41fea879521fd1
parente3431dea05d3d9dc425953e9a73c38c13bd47852 (diff)
downloademu2-a45af65ffcf4172726796b566b2e2a9c894ef390.tar.gz
Implement find-first and find-next FCB.
-rw-r--r--src/dos.c104
-rw-r--r--src/dosnames.c27
-rw-r--r--src/dosnames.h1
3 files changed, 121 insertions, 11 deletions
diff --git a/src/dos.c b/src/dos.c
index 1af4dc0..5e12dc2 100644
--- a/src/dos.c
+++ b/src/dos.c
@@ -269,9 +269,20 @@ static void dos_open_file(int create)
free(fname);
}
+static int get_ex_fcb(void)
+{
+ return cpuGetAddrDS(cpuGetDX());
+}
+
+static int get_fcb(void)
+{
+ int fcb = cpuGetAddrDS(cpuGetDX());
+ return memory[fcb] == 255 ? fcb + 7 : fcb;
+}
+
static int get_fcb_handle(void)
{
- return get16(0x18 + cpuGetAddrDS(cpuGetDX()));
+ return get16(0x18 + get_fcb());
}
static void dos_show_fcb()
@@ -298,7 +309,7 @@ static void dos_open_file_fcb(int create)
cpuSetFlag(cpuFlag_CF);
return;
}
- int fcb_addr = cpuGetAddrDS(cpuGetDX());
+ int fcb_addr = get_fcb();
char *fname = dos_unix_path_fcb(fcb_addr, create);
if(!fname)
{
@@ -352,7 +363,7 @@ static int dos_read_record_fcb(int addr, int update)
if(!f)
return 1; // no data read
- int fcb = cpuGetAddrDS(cpuGetDX());
+ int fcb = get_fcb();
unsigned rsize = get16(0x0E + fcb);
unsigned pos = rsize * get32(0x21 + fcb);
uint8_t *buf = getptr(addr, rsize);
@@ -391,7 +402,7 @@ int dos_write_record_fcb(int addr, int update)
if(!f)
return 1; // no data write
- int fcb = cpuGetAddrDS(cpuGetDX());
+ int fcb = get_fcb();
unsigned rsize = get16(0x0E + fcb);
unsigned pos = rsize * get32(0x21 + fcb);
uint8_t *buf = getptr(addr, rsize);
@@ -654,6 +665,83 @@ static void int21_4f(void)
}
}
+static void dos_find_next_fcb(void)
+{
+ struct find_first_dta *p = get_find_first_dta();
+ struct dos_file_list *d = p->find_first_ptr;
+
+ if(!d || !p->find_first_ptr->unixname)
+ {
+ debug(debug_dos, "\t(end)\n");
+ clear_find_first_dta(p);
+ cpuSetAX(0xFF);
+ }
+ else
+ {
+ debug(debug_dos, "\t'%s' ('%s')\n", d->dosname, d->unixname);
+ // Fills output FCB at DTA - use extended or normal depending on input
+ int ofcb = memory[get_ex_fcb()] == 0xFF ? dosDTA + 7 : dosDTA;
+ int pos = 1;
+ for(char *c = d->dosname; *c; c++)
+ {
+ if( *c != '.' )
+ memory[ofcb+pos++] = *c;
+ else
+ while(pos < 9)
+ memory[ofcb+pos++] = ' ';
+ }
+ while(pos < 12)
+ memory[ofcb+pos++] = ' ';
+ if( strcmp("//", d->unixname) )
+ {
+ // Get file info
+ uint32_t td = 0x10001;
+ uint8_t attr = 0x0;
+ uint32_t sz = 0;
+ struct stat st;
+ // Ignore errors.
+ if(0 == stat(d->unixname, &st))
+ {
+ td = get_time_date(st.st_mtime);
+ attr = get_attributes(st.st_mode);
+ if(st.st_size & ~0x7FFFFFFF)
+ sz = 0x7FFFFFFF;
+ else
+ sz = st.st_size;
+ }
+ // Fills file size
+ memory[ofcb+0x0C] = attr;
+ put32(ofcb+0x17, td);
+ put32(ofcb+0x1D, sz);
+ // Fill drive letter
+ memory[ofcb] = memory[get_fcb()];
+ }
+ p->find_first_ptr++;
+ cpuSetAX(0x00);
+ }
+}
+
+static void dos_find_first_fcb(void)
+{
+ struct find_first_dta *p = get_find_first_dta();
+ // Gets all directory entries
+ if(p->find_first_list)
+ dos_free_file_list(p->find_first_list);
+
+ int efcb = get_ex_fcb();
+ if( memory[efcb] == 0xFF && memory[efcb+6] == 0x08 )
+ {
+ p->find_first_list = calloc(2, sizeof(struct dos_file_list));
+ p->find_first_list[0].unixname = strdup("//");
+ memcpy(p->find_first_list[0].dosname, "DISK LABEL", 11);
+ p->find_first_list[1].unixname = 0;
+ }
+ else
+ p->find_first_list = dos_find_first_file_fcb(get_fcb());
+ p->find_first_ptr = p->find_first_list;
+ return dos_find_next_fcb();
+}
+
// DOS int 21, ah=57
static void int21_57(void)
{
@@ -952,6 +1040,12 @@ void int21()
dos_show_fcb();
cpuSetAX(dos_close_file(get_fcb_handle()) ? 0xFF : 0);
break;
+ case 0x11: // FIND FIRST FILE USING FCB
+ dos_find_first_fcb();
+ break;
+ case 0x12: // FIND NEXT FILE USING FCB
+ dos_find_next_fcb();
+ break;
case 0x14: // SEQUENTIAL READ USING FCB
dos_show_fcb();
cpuSetAX(dos_read_record_fcb(dosDTA, 1));
@@ -991,7 +1085,7 @@ void int21()
case 0x27: // BLOCK READ FROM FCB
case 0x28: // BLOCK WRITE TO FCB
{
- int fcb = cpuGetAddrDS(cpuGetDX());
+ int fcb = get_fcb();
unsigned count = cpuGetCX();
unsigned rsize = get16(0x0E + fcb);
unsigned e = 0;
diff --git a/src/dosnames.c b/src/dosnames.c
index ffa4634..d0aac31 100644
--- a/src/dosnames.c
+++ b/src/dosnames.c
@@ -559,14 +559,20 @@ char *dos_unix_path_fcb(int addr, int force)
opos = strlen(path);
for(int pos=0; pos<8 && opos<63; pos++, opos++)
- if( 0 == (path[opos] = dos_valid_char(fcb_name[pos])) )
+ if( fcb_name[pos] == '?' )
+ path[opos] = '?';
+ else if( 0 == (path[opos] = dos_valid_char(fcb_name[pos])) )
break;
- if(opos<63 && dos_valid_char(fcb_name[8]))
+ if(opos<63 && (dos_valid_char(fcb_name[8]) || fcb_name[8] == '?') )
path[opos++] = '.';
for(int pos=8; pos<11 && opos<63; pos++, opos++)
- if( 0 == (path[opos] = dos_valid_char(fcb_name[pos])) )
+ if( fcb_name[pos] == '?' )
+ path[opos] = '?';
+ else if( 0 == (path[opos] = dos_valid_char(fcb_name[pos])) )
break;
path[opos] = 0;
+
+ debug(debug_dos, "\ttemp name '%s'\n", path);
// Get UNIX base path:
const char *base = get_base_path(drive);
// Adds CWD if path is not absolute
@@ -576,10 +582,9 @@ char *dos_unix_path_fcb(int addr, int force)
////////////////////////////////////////////////////////////////////
// Implements FindFirstFile
-struct dos_file_list *dos_find_first_file(int addr)
+// NOTE: this frees fspec before return
+static struct dos_file_list *find_first_file(char *fspec)
{
- // Convert the filespec to a unix path
- char *fspec = dos_unix_path(addr, 1);
// Now, separate the path to the spec
char *glob, *unixpath, *p = rindex(fspec, '/');
if(!p)
@@ -601,3 +606,13 @@ struct dos_file_list *dos_find_first_file(int addr)
return dirEntries;
}
+
+struct dos_file_list *dos_find_first_file(int addr)
+{
+ return find_first_file(dos_unix_path(addr, 1));
+}
+
+struct dos_file_list *dos_find_first_file_fcb(int addr)
+{
+ return find_first_file(dos_unix_path_fcb(addr, 1));
+}
diff --git a/src/dosnames.h b/src/dosnames.h
index 38362e6..e7181ed 100644
--- a/src/dosnames.h
+++ b/src/dosnames.h
@@ -40,6 +40,7 @@ struct dos_file_list
// Returns a list with filenames compatibles with the DOS filespec, as pairs
// The list will be deleted at the next call
struct dos_file_list *dos_find_first_file(int addr);
+struct dos_file_list *dos_find_first_file_fcb(int addr);
// Frees a fileList.
void dos_free_file_list(struct dos_file_list *dl);
Un proyecto texto-plano.xyz