Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dosdev #3347

Merged
merged 3 commits into from
Mar 22, 2022
Merged

Dosdev #3347

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions include/dos_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,46 @@ class DOS_Device : public DOS_File {
Bitu devnum;
};

struct ExtDeviceData {
uint16_t attribute;
uint16_t segment;
uint16_t strategy;
uint16_t interrupt;
};

class DOS_ExtDevice : public DOS_Device {
public:
DOS_ExtDevice(const DOS_ExtDevice& orig) :DOS_Device(orig) {
ext = orig.ext;
}
DOS_ExtDevice(const char* name, uint16_t seg, uint16_t off) {
SetName(name);
ext.attribute = real_readw(seg, off + 4);
ext.segment = seg;
ext.strategy = real_readw(seg, off + 6);
ext.interrupt = real_readw(seg, off + 8);
}
DOS_ExtDevice& operator= (const DOS_ExtDevice& orig) {
DOS_Device::operator=(orig);
ext = orig.ext;
return *this;
}

virtual bool Read(uint8_t* data, uint16_t* size);
virtual bool Write(const uint8_t* data, uint16_t* size);
virtual bool Seek(uint32_t* pos, uint32_t type);
virtual bool Close();
virtual uint16_t GetInformation(void);
virtual bool ReadFromControlChannel(PhysPt bufptr, uint16_t size, uint16_t* retcode);
virtual bool WriteToControlChannel(PhysPt bufptr, uint16_t size, uint16_t* retcode);
virtual uint8_t GetStatus(bool input_flag);
bool CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off);
uint16_t CallDeviceFunction(uint8_t command, uint8_t length, uint16_t seg, uint16_t offset, uint16_t size);
private:
struct ExtDeviceData ext;

};

class localFile : public DOS_File {
public:
localFile();
Expand Down
45 changes: 42 additions & 3 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,8 @@ static Bitu DOS_21Handler(void) {
/* TODO: If handle is STDIN and not binary do CTRL+C checking */
{
uint16_t toread=reg_cx;
uint32_t handle = RealHandle(reg_bx);
bool fRead = false;

/* if the offset and size exceed the end of the 64KB segment,
* truncate the read according to observed MS-DOS 5.0 behavior
Expand All @@ -1879,8 +1881,27 @@ static Bitu DOS_21Handler(void) {
}

dos.echo=true;
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);

if(handle >= DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
} else
if(!Files[handle] || !Files[handle]->IsOpen())
DOS_SetError(DOSERR_INVALID_HANDLE);
else if(Files[handle]->GetInformation() & EXT_DEVICE_BIT)
{
fRead = !(((DOS_ExtDevice*)Files[handle])->CallDeviceFunction(4, 26, SegValue(ds), reg_dx, toread) & 0x8000);
#if defined(USE_TTF)
if(fRead && ttf.inUse && reg_bx == WPvga512CHMhandle)
MEM_BlockRead(SegPhys(ds) + reg_dx, dos_copybuf, toread);
#endif
}
else
{
if(fRead = DOS_ReadFile(reg_bx, dos_copybuf, &toread))
MEM_BlockWrite(SegPhys(ds) + reg_dx, dos_copybuf, toread);
}

if (fRead) {
reg_ax=toread;
#if defined(USE_TTF)
if (ttf.inUse && reg_bx == WPvga512CHMhandle){
Expand Down Expand Up @@ -1928,6 +1949,7 @@ static Bitu DOS_21Handler(void) {
unmask_irq0 |= disk_io_unmask_irq0;
{
uint16_t towrite=reg_cx;
bool fWritten;

/* if the offset and size exceed the end of the 64KB segment,
* truncate the write according to observed MS-DOS 5.0 READ behavior
Expand All @@ -1946,7 +1968,24 @@ static Bitu DOS_21Handler(void) {

MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite);
packerr=reg_bx==2&&towrite==22&&!strncmp((char *)dos_copybuf,"Packed file is corrupt",towrite);
if ((packerr && !(i4dos && !shellrun) && (!autofixwarn || (autofixwarn==2 && infix==0) || (autofixwarn==1 && infix==1))) || DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
fWritten = (packerr && !(i4dos && !shellrun) && (!autofixwarn || (autofixwarn == 2 && infix == 0) || (autofixwarn == 1 && infix == 1)));
if(!fWritten)
{
uint32_t handle = RealHandle(reg_bx);

if(handle >= DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
}
else
if(!Files[handle] || !Files[handle]->IsOpen())
DOS_SetError(DOSERR_INVALID_HANDLE);
else if(Files[handle]->GetInformation() & EXT_DEVICE_BIT)
{
fWritten = !(((DOS_ExtDevice*)Files[handle])->CallDeviceFunction(8, 26, SegValue(ds), reg_dx, towrite) & 0x8000);
}
else fWritten = DOS_WriteFile(reg_bx, dos_copybuf, &towrite);
}
if (fWritten) {
reg_ax=towrite;
CALLBACK_SCF(false);
} else {
Expand Down
48 changes: 9 additions & 39 deletions src/dos/dos_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,36 +49,6 @@ bool isDBCSCP(), shiftjis_lead_byte(int c);
bool Network_IsNetworkResource(const char * filename), TTF_using(void);
bool CodePageGuestToHostUTF16(uint16_t *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/);

struct ExtDeviceData {
uint16_t attribute;
uint16_t segment;
uint16_t strategy;
uint16_t interrupt;
};

class DOS_ExtDevice : public DOS_Device {
public:
DOS_ExtDevice(const char *name, uint16_t seg, uint16_t off) {
SetName(name);
ext.attribute = real_readw(seg, off + 4);
ext.segment = seg;
ext.strategy = real_readw(seg, off + 6);
ext.interrupt = real_readw(seg, off + 8);
}
virtual bool Read(uint8_t * data,uint16_t * size);
virtual bool Write(const uint8_t * data,uint16_t * size);
virtual bool Seek(uint32_t * pos,uint32_t type);
virtual bool Close();
virtual uint16_t GetInformation(void);
virtual bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
virtual bool WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
virtual uint8_t GetStatus(bool input_flag);
bool CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off);
private:
struct ExtDeviceData ext;

uint16_t CallDeviceFunction(uint8_t command, uint8_t length, PhysPt bufptr, uint16_t size);
};

bool DOS_ExtDevice::CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off) {
if(seg == ext.segment && s_off == ext.strategy && i_off == ext.interrupt) {
Expand All @@ -87,7 +57,7 @@ bool DOS_ExtDevice::CheckSameDevice(uint16_t seg, uint16_t s_off, uint16_t i_off
return false;
}

uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, PhysPt bufptr, uint16_t size) {
uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, uint16_t seg, uint16_t offset, uint16_t size) {
uint16_t oldbx = reg_bx;
uint16_t oldes = SegValue(es);

Expand All @@ -98,8 +68,8 @@ uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, Phys
real_writed(dos.dcp, 5, 0);
real_writed(dos.dcp, 9, 0);
real_writeb(dos.dcp, 13, 0);
real_writew(dos.dcp, 14, (uint16_t)(bufptr & 0x000f));
real_writew(dos.dcp, 16, (uint16_t)(bufptr >> 4));
real_writew(dos.dcp, 14, offset);
real_writew(dos.dcp, 16, seg);
real_writew(dos.dcp, 18, size);

reg_bx = 0;
Expand All @@ -115,7 +85,7 @@ uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, Phys
bool DOS_ExtDevice::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
if(ext.attribute & 0x4000) {
// IOCTL INPUT
if((CallDeviceFunction(3, 26, bufptr, size) & 0x8000) == 0) {
if((CallDeviceFunction(3, 26, (uint16_t)(bufptr >> 4), (uint16_t)(bufptr & 0x000f), size) & 0x8000) == 0) {
*retcode = real_readw(dos.dcp, 18);
return true;
}
Expand All @@ -126,7 +96,7 @@ bool DOS_ExtDevice::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t
bool DOS_ExtDevice::WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
if(ext.attribute & 0x4000) {
// IOCTL OUTPUT
if((CallDeviceFunction(12, 26, bufptr, size) & 0x8000) == 0) {
if((CallDeviceFunction(12, 26, (uint16_t)(bufptr >> 4), (uint16_t)(bufptr & 0x000f), size) & 0x8000) == 0) {
*retcode = real_readw(dos.dcp, 18);
return true;
}
Expand All @@ -138,7 +108,7 @@ bool DOS_ExtDevice::Read(uint8_t * data,uint16_t * size) {
PhysPt bufptr = (dos.dcp << 4) | 32;
for(uint16_t no = 0 ; no < *size ; no++) {
// INPUT
if((CallDeviceFunction(4, 26, bufptr, 1) & 0x8000)) {
if((CallDeviceFunction(4, 26, dos.dcp + 2, 0, 1) & 0x8000)) {
return false;
} else {
if(real_readw(dos.dcp, 18) != 1) {
Expand All @@ -155,7 +125,7 @@ bool DOS_ExtDevice::Write(const uint8_t * data,uint16_t * size) {
for(uint16_t no = 0 ; no < *size ; no++) {
mem_writeb(bufptr, *data);
// OUTPUT
if((CallDeviceFunction(8, 26, bufptr, 1) & 0x8000)) {
if((CallDeviceFunction(8, 26, dos.dcp + 2, 0, 1) & 0x8000)) {
return false;
} else {
if(real_readw(dos.dcp, 18) != 1) {
Expand Down Expand Up @@ -186,10 +156,10 @@ uint8_t DOS_ExtDevice::GetStatus(bool input_flag) {
uint16_t status;
if(input_flag) {
// NON-DESTRUCTIVE INPUT NO WAIT
status = CallDeviceFunction(5, 14, 0, 0);
status = CallDeviceFunction(5, 14, 0, 0, 0);
} else {
// OUTPUT STATUS
status = CallDeviceFunction(10, 13, 0, 0);
status = CallDeviceFunction(10, 13, 0, 0, 0);
}
// check NO ERROR & BUSY
if((status & 0x8200) == 0) {
Expand Down
5 changes: 4 additions & 1 deletion src/dos/dos_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,10 @@ bool DOS_OpenFile(char const * name,uint8_t flags,uint16_t * entry,bool fcb) {
}
bool exists=false;
if (device) {
Files[handle]=new DOS_Device(*Devices[devnum]);
if (Devices[devnum]->GetInformation() & EXT_DEVICE_BIT)
Files[handle] = new DOS_ExtDevice(*(DOS_ExtDevice*)Devices[devnum]);
else
Files[handle]=new DOS_Device(*Devices[devnum]);
} else {
exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags) || Drives[drive]->FileOpen(&Files[handle],upcase(fullname),flags);
if (exists) Files[handle]->SetDrive(drive);
Expand Down