Skip to content

Commit

Permalink
INT 13h Extensions: Add function AX=4B00h and AX=4B01h, though only f…
Browse files Browse the repository at this point in the history
…or no emulation boot, and return the correct data structure that indicates the drive and which IDE device it is attached to. Apparently it is now possible to boot a Windows XP install CD-ROM in DOSBox-X
  • Loading branch information
joncampbell123 committed Mar 23, 2024
1 parent 55b8990 commit 4120aec
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/bios_disk.h
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ void LogPrintPartitionTable(const std::vector<_PC98RawPartition> &parts);
void LogPrintPartitionTable(const std::vector<partTable::partentry_t> &parts);

extern unsigned char INT13_ElTorito_NoEmuDriveNumber;
extern signed char INT13_ElTorito_IDEInterface;
extern char INT13_ElTorito_NoEmuCDROMDrive;

#endif
10 changes: 10 additions & 0 deletions src/dos/dos_programs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,8 @@ void pc98_43d_write(Bitu port,Bitu val,Bitu iolen) {
}
}

int IDE_MatchCDROMDrive(char drv);

#if defined(WIN32)
#include <fcntl.h>
#else
Expand Down Expand Up @@ -2322,9 +2324,17 @@ class BOOT : public Program {
}

/* signal INT 13h to emulate a CD-ROM drive El Torito "no emulation" style */
INT13_ElTorito_IDEInterface = -1;
INT13_ElTorito_NoEmuDriveNumber = 0x90;
INT13_ElTorito_NoEmuCDROMDrive = el_torito_cd_drive;

/* this is required if INT 13h extensions are to correctly report what IDE controller the drive is connected to and master/slave */
{
int x = IDE_MatchCDROMDrive(el_torito_cd_drive);
if (x >= 0) INT13_ElTorito_IDEInterface = (char)x;
LOG_MSG("CD-ROM drive IDE interface number %d",INT13_ElTorito_IDEInterface);
}

SegSet16(cs, load_seg);
SegSet16(ds, 0);
SegSet16(es, 0);
Expand Down
20 changes: 20 additions & 0 deletions src/hardware/ide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,26 @@ const char* master_slave[] = { "Master", "Slave" };

static IDEController* idecontroller[MAX_IDE_CONTROLLERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};

int IDE_MatchCDROMDrive(char drv) {
for (unsigned int c=0;c < MAX_IDE_CONTROLLERS;c++) {
IDEController *cnt = idecontroller[c];
if (cnt != NULL) {
for (unsigned int d=0;d < 2;d++) {
IDEDevice *dev = cnt->device[d];
if (dev != NULL) {
if (dev->type == IDE_TYPE_CDROM) {
IDEATAPICDROMDevice *atapi = reinterpret_cast<IDEATAPICDROMDevice*>(dev);
if (atapi->drive_index == (unsigned char)(drv - 'A'))
return (c * 2) + d;
}
}
}
}
}

return -1;
}

static void IDE_DelayedCommand(Bitu pk/*which IDE device*/);
static IDEController* GetIDEController(Bitu idx);

Expand Down
1 change: 1 addition & 0 deletions src/ints/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9174,6 +9174,7 @@ class BIOS:public Module_base{

INT13_ElTorito_NoEmuDriveNumber = 0;
INT13_ElTorito_NoEmuCDROMDrive = 0;
INT13_ElTorito_IDEInterface = -1;

ACPI_mem_enable(false);
ACPI_REGION_SIZE = 0;
Expand Down
40 changes: 40 additions & 0 deletions src/ints/bios_disk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,7 @@ void diskio_delay(Bits value/*bytes*/, int type = -1);

/* For El Torito "No emulation" INT 13 services */
unsigned char INT13_ElTorito_NoEmuDriveNumber = 0;
signed char INT13_ElTorito_IDEInterface = -1; /* (controller * 2) + (is_slave?1:0) */
char INT13_ElTorito_NoEmuCDROMDrive = 0;

bool GetMSCDEXDrive(unsigned char drive_letter, CDROM_Interface **_cdrom);
Expand Down Expand Up @@ -2381,6 +2382,45 @@ static Bitu INT13_DiskHandler(void) {
reg_ah = 0x00;
CALLBACK_SCF(false);
} break;
case 0x4B: /* Terminate disk emulation or get emulation status */
/* NTS: Windows XP CD-ROM boot requires this call to work or else setup cannot find it's own files. */
if (reg_dl == 0x7F || (INT13_ElTorito_NoEmuDriveNumber != 0 && INT13_ElTorito_NoEmuDriveNumber == reg_dl)) {
if (reg_al <= 1) {
PhysPt p = (SegValue(ds) << 4) + reg_si;
phys_writeb(p + 0x00,0x13);
phys_writeb(p + 0x01,(0/*no emulation*/) + ((INT13_ElTorito_IDEInterface >= 0) ? 0x40 : 0));
phys_writeb(p + 0x02,INT13_ElTorito_NoEmuDriveNumber);
if (INT13_ElTorito_IDEInterface >= 0) {
phys_writeb(p + 0x03,(unsigned char)(INT13_ElTorito_IDEInterface >> 1)); /* which IDE controller */
phys_writew(p + 0x08,INT13_ElTorito_IDEInterface & 1);/* bit 0: IDE master/slave */
}
else {
phys_writeb(p + 0x03,0);
phys_writew(p + 0x08,0);
}
phys_writed(p + 0x04,0);
phys_writew(p + 0x0A,0);
phys_writew(p + 0x0C,0);
phys_writew(p + 0x0E,0);
phys_writeb(p + 0x10,0);
phys_writeb(p + 0x11,0);
phys_writeb(p + 0x12,0);
reg_ah = 0x00;
CALLBACK_SCF(false);
break;
}
else {
reg_ah=0xff;
CALLBACK_SCF(true);
return CBRET_NONE;
}
}
else {
reg_ah=0xff;
CALLBACK_SCF(true);
return CBRET_NONE;
}
break;
default:
LOG(LOG_BIOS,LOG_ERROR)("INT13: Function %x called on drive %x (dos drive %d)", (int)reg_ah, (int)reg_dl, (int)drivenum);
reg_ah=0xff;
Expand Down

1 comment on commit 4120aec

@Torinde
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! 🚀

Please sign in to comment.