Skip to content

Commit

Permalink
Merge pull request #3347 from leecher1337/dosdev
Browse files Browse the repository at this point in the history
Dosdev
  • Loading branch information
joncampbell123 committed Mar 22, 2022
2 parents 6ef9829 + 378b7dd commit 5c8b5e7
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 43 deletions.
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

0 comments on commit 5c8b5e7

Please sign in to comment.