1
0
Fork 0

Added FAT image access and DOS booter functionality

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1757
This commit is contained in:
Dean Beeler 2004-04-03 19:24:59 +00:00
parent 57a7795ae0
commit d0e2bfa15f
7 changed files with 2024 additions and 48 deletions

View file

@ -16,6 +16,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _BIOS_H_
#define _BIOS_H_
#define BIOS_BASE_ADDRESS_COM1 0x400
#define BIOS_BASE_ADDRESS_COM2 0x402
#define BIOS_BASE_ADDRESS_COM3 0x404
@ -96,23 +99,57 @@
/* The Section handling Bios Disk Access */
#define BIOS_MAX_DISK 10
class BIOS_Disk {
public:
virtual Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
virtual Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
struct diskGeo {
Bit32u ksize; /* Size in kilobytes */
Bit16u secttrack; /* Sectors per track */
Bit16u headscyl; /* Heads per cylinder */
Bit16u cylcount; /* Cylinders per side */
Bit16u biosval; /* Type to return from BIOS */
};
class imageDisk : public BIOS_Disk {
extern diskGeo DiskGeometryList[];
#include <stdio.h>
#include "mem.h"
#include "dos_inc.h"
class imageDisk {
public:
Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
imageDisk(char * file);
private:
Bit16u sector_size;
Bit16u heads,cylinders,sectors;
Bit8u * image;
Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data);
void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
Bit8u GetBiosType(void);
Bit32u getSectSize(void);
imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } };
bool hardDrive;
bool active;
FILE *diskimg;
Bit8u diskname[512];
Bit8u floppytype;
Bit32u sector_size;
Bit32u heads,cylinders,sectors;
};
void updateDPT(void);
#define MAX_HDD_IMAGES 2
extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES];
extern imageDisk *diskSwap[20];
extern Bits swapPosition;
extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
extern DOS_DTA *imgDTA;
void swapInDisks(void);
void swapInNextDisk(void);
void BIOS_ZeroExtendedSize(void);
void char_out(Bit8u chr,Bit32u att,Bit8u page);
@ -123,4 +160,4 @@ void INT2F_StartUp(void);
void INT33_StartUp(void);
void INT13_StartUp(void);
#endif

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_inc.h,v 1.38 2004-02-28 16:35:42 qbix79 Exp $ */
/* $Id: dos_inc.h,v 1.39 2004-04-03 19:19:29 canadacow Exp $ */
#ifndef DOS_H_
#define DOS_H_
@ -67,6 +67,25 @@ struct DOS_Block {
} tables;
};
#ifdef _MSC_VER
#pragma pack (1)
#endif
union bootSector {
struct entries {
Bit8u jump[3];
Bit8u oem_name[8];
Bit16u bytesect;
Bit8u sectclust;
Bit16u reserve_sect;
Bit8u misc[496];
} bootdata;
Bit8u rawdata[512];
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
#pragma pack ()
#endif
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_programs.cpp,v 1.22 2004-01-10 14:03:34 qbix79 Exp $ */
/* $Id: dos_programs.cpp,v 1.23 2004-04-03 19:21:28 canadacow Exp $ */
#include <stdlib.h>
#include <string.h>
@ -28,9 +28,13 @@
#include "regs.h"
#include "callback.h"
#include "cdrom.h"
#include "dos_system.h"
#include "dos_inc.h"
#include "bios.h"
void MSCDEX_SetCDInterface(int intNr, int forceCD);
void IMGMOUNT_ProgramStart(Program * * make);
class MOUNT : public Program {
public:
@ -196,6 +200,150 @@ static void MEM_ProgramStart(Program * * make) {
*make=new MEM;
}
extern Bit32u floppytype;
class BOOT : public Program {
private:
FILE *getFSFile(Bit8u * filename, Bit32u *ksize, Bit32u *bsize) {
Bit8u drive;
FILE *tmpfile;
char fullname[DOS_PATHLENGTH];
localDrive* ldp=0;
if (!DOS_MakeName((char *)filename,fullname,&drive)) return NULL;
ldp=(localDrive*)Drives[drive];
tmpfile = ldp->GetSystemFilePtr(fullname, "r");
if(tmpfile == NULL) {
WriteOut("Bootdisk file does not exist. Failing.\n");
return NULL;
}
fclose(tmpfile);
tmpfile = ldp->GetSystemFilePtr(fullname, "rb+");
if(tmpfile == NULL) {
WriteOut("Cannot open bootdisk file. Failing.\n");
return NULL;
}
fseek(tmpfile,0L, SEEK_END);
*ksize = (ftell(tmpfile) / 1024);
*bsize = ftell(tmpfile);
return tmpfile;
}
void printError(void) {
WriteOut("This command boots DosBox from either a floppy or hard disk image.\n\n");
WriteOut("For this command, one can specify a succession of floppy disks swappable\n");
WriteOut("by pressing Ctrl-F4, and -l specifies the mounted drive to boot from. If\n");
WriteOut("no drive letter is specified, this defaults to booting from the A drive.\n");
WriteOut("The only bootable drive letters are A, C, and D. For booting from a hard\n");
WriteOut("drive (C or D), the image should have already been mounted using the\n");
WriteOut("IMGMOUNT command.\n\n");
WriteOut("The syntax of this command is:\n\n");
WriteOut("BOOT [diskimg1.img diskimg2.img] [-l driveletter]\n");
}
public:
void Run(void) {
FILE *usefile;
Bitu i;
Bit32u floppysize, rombytesize;
Bit8u drive;
if(!cmd->GetCount()) {
printError();
return;
}
i=0;
drive = 'A';
while(i<cmd->GetCount()) {
if(cmd->FindCommand(i+1, temp_line)) {
if(temp_line == "-l") {
/* Specifying drive... next argument then is the drive */
i++;
if(cmd->FindCommand(i+1, temp_line)) {
drive=toupper(temp_line[0]);
if ((drive != 'A') && (drive != 'C') && (drive != 'D')) {
printError();
return;
}
} else {
printError();
return;
}
i++;
continue;
}
WriteOut("Opening image file: %s\n", temp_line.c_str());
usefile = getFSFile((Bit8u *)temp_line.c_str(), &floppysize, &rombytesize);
if(usefile != NULL) {
if(diskSwap[i] != NULL) delete diskSwap[i];
diskSwap[i] = new imageDisk(usefile, (Bit8u *)temp_line.c_str(), floppysize, false);
} else {
WriteOut("Cannot open %s", temp_line.c_str());
return;
}
}
i++;
}
swapPosition = 0;
swapInDisks();
if(imageDiskList[drive-65]==NULL) {
WriteOut("Unable to boot off of drive %c", drive);
return;
}
WriteOut("Booting from drive %c...\n", drive);
bootSector bootarea;
imageDiskList[drive-65]->Read_Sector(0,0,1,(Bit8u *)&bootarea);
for(i=0;i<512;i++) real_writeb(0, 0x7c00 + i, bootarea.rawdata[i]);
SegSet16(cs, 0);
reg_ip = 0x7c00;
/* Most likely a PCJr ROM */
/* Write it to E000:0000 */
/* Code inoperable at the moment */
/*
Bit8u rombuff[65536];
fseek(tmpfile,512L, SEEK_SET);
rombytesize-=512;
fread(rombuff, 1, rombytesize, tmpfile);
fclose(tmpfile);
for(i=0;i<rombytesize;i++) real_writeb(0xe000,i,rombuff[i]);
SegSet16(cs,0xe000);
SegSet16(ds,0x0060);
SegSet16(es,0x0060);
SegSet16(ss,0x0060);
reg_ip = 0x0;
reg_sp = 0x0;
reg_cx = 0xffff;
DEBUG_EnableDebugger();
*/
}
};
static void BOOT_ProgramStart(Program * * make) {
*make=new BOOT;
}
// LOADFIX
@ -351,4 +499,6 @@ void DOS_SetupPrograms(void) {
PROGRAMS_MakeFile("LOADFIX.COM",LOADFIX_ProgramStart);
PROGRAMS_MakeFile("RESCAN.COM",RESCAN_ProgramStart);
PROGRAMS_MakeFile("INTRO.COM",INTRO_ProgramStart);
PROGRAMS_MakeFile("BOOT.COM",BOOT_ProgramStart);
PROGRAMS_MakeFile("IMGMOUNT.COM", IMGMOUNT_ProgramStart);
}

1271
src/dos/drive_fat.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drive_local.cpp,v 1.45 2004-03-04 19:49:21 qbix79 Exp $ */
/* $Id: drive_local.cpp,v 1.46 2004-04-03 19:23:06 canadacow Exp $ */
#include <stdio.h>
#include <stdlib.h>
@ -103,6 +103,17 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
return true;
};
FILE * localDrive::GetSystemFilePtr(char * name, char * type) {
char newname[CROSS_LEN];
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
dirCache.ExpandName(newname);
return fopen(newname,type);
}
bool localDrive::FileUnlink(char * name) {
char newname[CROSS_LEN];
strcpy(newname,basedir);

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drives.h,v 1.19 2004-01-10 14:03:34 qbix79 Exp $ */
/* $Id: drives.h,v 1.20 2004-04-03 19:22:33 canadacow Exp $ */
#ifndef _DRIVES_H__
#define _DRIVES_H__
@ -24,6 +24,7 @@
#include <sys/types.h>
#include "dos_system.h"
#include "shell.h" /* for DOS_Shell */
#include "bios.h" /* for fatDrive */
bool WildFileCmp(const char * file, const char * wild);
@ -31,6 +32,7 @@ class localDrive : public DOS_Drive {
public:
localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid);
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
virtual FILE *GetSystemFilePtr(char * name, char * type);
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes);
virtual bool FileUnlink(char * name);
virtual bool RemoveDir(char * dir);
@ -61,6 +63,127 @@ private:
} allocation;
};
#ifdef _MSC_VER
#pragma pack (1)
#endif
struct bootstrap {
Bit8u nearjmp[3];
Bit8u oemname[8];
Bit16u bytespersector;
Bit8u sectorspercluster;
Bit16u reservedsectors;
Bit8u fatcopies;
Bit16u rootdirentries;
Bit16u totalsectorcount;
Bit8u mediadescriptor;
Bit16u sectorsperfat;
Bit16u sectorspertrack;
Bit16u headcount;
/* 32-bit FAT extensions */
Bit32u hiddensectorcount;
Bit32u totalsecdword;
Bit8u bootcode[474];
Bit8u magic1; /* 0x55 */
Bit8u magic2; /* 0xaa */
} GCC_ATTRIBUTE(packed);
struct direntry {
Bit8u entryname[11];
Bit8u attrib;
Bit8u NTRes;
Bit8u milliSecondStamp;
Bit16u crtTime;
Bit16u crtDate;
Bit16u accessDate;
Bit16u hiFirstClust;
Bit16u modTime;
Bit16u modDate;
Bit16u loFirstClust;
Bit32u entrysize;
} GCC_ATTRIBUTE(packed);
struct partTable {
Bit8u booter[446];
struct {
Bit8u bootflag;
Bit8u beginchs[3];
Bit8u parttype;
Bit8u endchs[3];
Bit32u absSectStart;
Bit32u partSize;
} pentry[4];
Bit8u magic1; /* 0x55 */
Bit8u magic2; /* 0xaa */
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
#pragma pack ()
#endif
class fatDrive : public DOS_Drive {
public:
fatDrive(const char * sysFilename, Bit32u bytesector, Bit32u cylsector, Bit32u headscyl, Bit32u cylinders, Bit32u startSector);
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes);
virtual bool FileUnlink(char * name);
virtual bool RemoveDir(char * dir);
virtual bool MakeDir(char * dir);
virtual bool TestDir(char * dir);
virtual bool FindFirst(char * _dir,DOS_DTA & dta);
virtual bool FindNext(DOS_DTA & dta);
virtual bool GetFileAttr(char * name,Bit16u * attr);
virtual bool Rename(char * oldname,char * newname);
virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
virtual bool FileExists(const char* name);
virtual bool FileStat(const char* name, FileStat_Block * const stat_block);
virtual Bit8u GetMediaByte(void);
virtual bool isRemote(void);
public:
Bit32u getAbsoluteSectFromBytePos(Bit32u startClustNum, Bit32u bytePos);
Bit32u getSectorSize(void);
Bit32u getAbsoluteSectFromChain(Bit32u startClustNum, Bit32u logicalSector);
bool allocateCluster(Bit32u useCluster, Bit32u prevCluster);
Bit32u appendCluster(Bit32u startCluster);
void deleteClustChain(Bit32u startCluster);
Bit32u getFirstFreeClust(void);
bool directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum);
bool directoryChange(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum);
imageDisk *loadedDisk;
private:
Bit32u getClusterValue(Bit32u clustNum);
void setClusterValue(Bit32u clustNum, Bit32u clustValue);
Bit32u getClustFirstSect(Bit32u clustNum);
bool FindNextInternal(Bit32u dirClustNumber, DOS_DTA & dta, direntry *foundEntry);
bool getDirClustNum(char * dir, Bit32u * clustNum, bool parDir);
bool getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry);
bool addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry);
void zeroOutCluster(Bit32u clustNumber);
bool getEntryName(char *fullname, char *entname);
friend void DOS_Shell::CMD_SUBST(char* args);
struct {
char srch_dir[CROSS_LEN];
} srchInfo[MAX_OPENDIRS];
struct {
Bit16u bytes_sector;
Bit8u sectors_cluster;
Bit16u total_clusters;
Bit16u free_clusters;
Bit8u mediaid;
} allocation;
bootstrap bootbuffer;
Bit8u fattype;
Bit32u CountOfClusters;
Bit32u partSectOff;
Bit32u firstDataSector;
Bit32u firstRootDirSect;
Bit32u cwdDirCluster;
Bit32u dirPosition; /* Position in directory search */
};
class cdromDrive : public localDrive
{
public:

View file

@ -21,60 +21,425 @@
#include "bios.h"
#include "regs.h"
#include "mem.h"
#include "keyboard.h"
#include "dos_inc.h" /* for Drives[] */
static Bitu call_int13;
static BIOS_Disk * Floppys[2];
static BIOS_Disk * Harddisks[BIOS_MAX_DISK];
#define MAX_SWAPPABLE_DISKS 20
diskGeo DiskGeometryList[] = {
{160, 8, 1, 40, 0},
{180, 9, 1, 40, 0},
{320, 8, 2, 40, 1},
{360, 9, 2, 40, 1},
{720, 9, 2, 80, 3},
{1200, 15, 2, 80, 2},
{1440, 18, 2, 80, 4},
{2880, 36, 2, 80, 6},
{0, 0, 0 , 0},
};
Bitu call_int13;
Bitu diskparm0, diskparm1;
static Bit8u last_status;
static Bit8u last_drive;
Bit16u imgDTASeg;
RealPt imgDTAPtr;
DOS_DTA *imgDTA;
bool killRead;
/* 2 floppys and 2 harddrives, max */
imageDisk *imageDiskList[4];
imageDisk *diskSwap[MAX_SWAPPABLE_DISKS];
Bits swapPosition;
void updateDPT(void) {
Bit32u tmpheads, tmpcyl, tmpsect, tmpsize;
if(imageDiskList[2] != NULL) {
imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize);
real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0)),tmpcyl);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+2,tmpheads);
real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x3,0);
real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x5,-1);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x7,0);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x8,(0xc0 | (((imageDiskList[2]->heads) > 8) << 3)));
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x9,0);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xa,0);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xb,0);
real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xc,tmpcyl);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xe,tmpsect);
}
if(imageDiskList[3] != NULL) {
imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize);
real_writew(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1)),tmpcyl);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1))+2,tmpheads);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1))+0xe,tmpsect);
}
static Bitu INT13_SmallHandler(void) {
switch (reg_ah) {
}
void swapInDisks(void) {
bool allNull = true;
Bits diskcount = 0;
Bits swapPos = swapPosition;
int i;
/* Check to make sure there's atleast one setup image */
for(i=0;i<MAX_SWAPPABLE_DISKS;i++) {
if(diskSwap[i]!=NULL) {
allNull = false;
break;
}
}
/* No disks setup... fail */
if (allNull) return;
/* If only one disk is loaded, this loop will load the same disk in dive A and drive B */
while(diskcount<2) {
if(diskSwap[swapPos] != NULL) {
LOG_MSG("Loaded disk %d from swaplist position %d - \"%s\"", diskcount, swapPos, diskSwap[swapPos]->diskname);
imageDiskList[diskcount] = diskSwap[swapPos];
diskcount++;
}
swapPos++;
if(swapPos>=MAX_SWAPPABLE_DISKS) swapPos=0;
}
}
static void swapInNextDisk(void) {
swapPosition++;
if(diskSwap[swapPosition] == NULL) swapPosition = 0;
swapInDisks();
}
Bit8u imageDisk::Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data) {
Bit32u sectnum;
sectnum = ( (cylinder * heads + head) * sectors ) + sector - 1L;
return Read_AbsoluteSector(sectnum, data);
}
Bit8u imageDisk::Read_AbsoluteSector(Bit32u sectnum, void * data) {
Bit32u bytenum;
bytenum = sectnum * sector_size;
fseek(diskimg,bytenum,SEEK_SET);
fread(data, 1, sector_size, diskimg);
return 0x00;
}
Bit8u imageDisk::Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data) {
Bit32u sectnum;
sectnum = ( (cylinder * heads + head) * sectors ) + sector - 1L;
return Write_AbsoluteSector(sectnum, data);
}
Bit8u imageDisk::Write_AbsoluteSector(Bit32u sectnum, void *data) {
Bit32u bytenum;
bytenum = sectnum * sector_size;
//LOG_MSG("Writing sectors to %ld at bytenum %d", sectnum, bytenum);
fseek(diskimg,bytenum,SEEK_SET);
fwrite(data, sector_size, 1, diskimg);
return 0x00;
}
imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk) {
heads = 0;
cylinders = 0;
sectors = 0;
sector_size = 512;
diskimg = imgFile;
memset(diskname,0,512);
if(strlen((const char *)imgName) > 511) {
memcpy(diskname, imgName, 511);
} else {
strcpy((char *)diskname, (const char *)imgName);
}
active = false;
hardDrive = isHardDisk;
if(!isHardDisk) {
Bitu i=0;
bool founddisk = false;
while (DiskGeometryList[i].ksize!=0x0) {
if (DiskGeometryList[i].ksize==imgSizeK) {
founddisk = true;
active = true;
floppytype = i;
heads = DiskGeometryList[i].headscyl;
cylinders = DiskGeometryList[i].cylcount;
sectors = DiskGeometryList[i].secttrack;
break;
}
i++;
}
if(!founddisk) {
active = false;
}
}
}
void imageDisk::Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize) {
heads = setHeads;
cylinders = setCyl;
sectors = setSect;
sector_size = setSectSize;
active = true;
}
void imageDisk::Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize) {
*getHeads = heads;
*getCyl = cylinders;
*getSect = sectors;
*getSectSize = sector_size;
}
Bit8u imageDisk::GetBiosType(void) {
if(!hardDrive) {
return DiskGeometryList[floppytype].biosval;
} else return 0;
}
Bit32u imageDisk::getSectSize(void) {
return sector_size;
}
static Bitu GetDosDriveNumber(Bitu biosNum) {
switch(biosNum) {
case 0x0:
reg_ah=0x00;
return 0x0;
case 0x1:
return 0x1;
case 0x80:
return 0x2;
case 0x81:
return 0x3;
case 0x82:
return 0x4;
case 0x83:
return 0x5;
default:
return 0x7f;
}
}
static bool driveInactive(Bitu driveNum) {
if(driveNum>=(2 + MAX_HDD_IMAGES)) {
LOG_MSG("Disk %d non-existant", driveNum);
last_status = 0x01;
CALLBACK_SCF(true);
return true;
}
if(imageDiskList[driveNum] == NULL) {
LOG_MSG("Disk %d not active", driveNum);
last_status = 0x01;
CALLBACK_SCF(true);
return true;
}
if(!imageDiskList[driveNum]->active) {
LOG_MSG("Disk %d not active", driveNum);
last_status = 0x01;
CALLBACK_SCF(true);
return true;
}
return false;
}
static Bitu INT13_DiskHandler(void) {
Bit16u segat, bufptr;
Bit8u sectbuf[512];
Bitu drivenum;
Bits readcnt;
int i,t;
last_drive = reg_dl;
drivenum = GetDosDriveNumber(reg_dl);
//drivenum = 0;
//LOG_MSG("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum);
switch(reg_ah) {
case 0x0: /* Reset disk */
if(driveInactive(drivenum)) return CBRET_NONE;
last_status = 0x00;
CALLBACK_SCF(false);
LOG(LOG_BIOS,LOG_NORMAL)("reset disk return succesfull");
break;
case 0x02: /* Read Disk Sectors */
LOG(LOG_BIOS,LOG_NORMAL)("INT13:02:Read Disk Sectors not supported failing");
reg_ah=0x80;
case 0x1: /* Get status of last operation */
if(last_status != 0x00) {
reg_ah = last_status;
CALLBACK_SCF(true);
} else {
reg_ah = 0x00;
CALLBACK_SCF(false);
}
break;
case 0x04:
if(Drives[reg_dl]!=NULL) {
reg_ah=0;
case 0x2: /* Read sectors */
if(driveInactive(drivenum)) {
reg_ah = 0xff;
CALLBACK_SCF(true);
return CBRET_NONE;
}
segat = SegValue(es);
bufptr = reg_bx;
for(i=0;i<reg_al;i++) {
last_status = imageDiskList[drivenum]->Read_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0)<< 2)), (Bit32u)((reg_cl & 63)+i), sectbuf);
if((last_status != 0x00) || (killRead)) {
LOG_MSG("Error in disk read");
killRead = false;
reg_ah = 0x04;
CALLBACK_SCF(true);
return CBRET_NONE;
}
for(t=0;t<512;t++) {
real_writeb(segat,bufptr,sectbuf[t]);
bufptr++;
}
}
reg_ah = 0x00;
CALLBACK_SCF(false);
}
else{
reg_ah=0x80;
CALLBACK_SCF(true);
}
LOG(LOG_BIOS,LOG_NORMAL)("INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah);
break;
case 0x08: /* Get Drive Parameters */
LOG(LOG_BIOS,LOG_NORMAL)("INT13:08:Get Drive parameters not supported failing");
reg_ah=0xff;
CALLBACK_SCF(true);
break;
case 0xff:
case 0x3: /* Write sectors */
if(driveInactive(drivenum)) {
reg_ah = 0xff;
CALLBACK_SCF(true);
return CBRET_NONE;
}
bufptr = reg_bx;
for(i=0;i<reg_al;i++) {
for(t=0;t<imageDiskList[drivenum]->getSectSize();t++) {
sectbuf[t] = real_readb(SegValue(es),bufptr);
bufptr++;
}
last_status = imageDiskList[drivenum]->Write_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0) << 2)), (Bit32u)((reg_cl & 63) + i), &sectbuf[0]);
if(last_status != 0x00) {
CALLBACK_SCF(true);
return CBRET_NONE;
}
}
CALLBACK_SCF(false);
break;
case 0x04: /* Verify sectors */
if(driveInactive(drivenum)) return CBRET_NONE;
/* TODO: Finish coding this section */
/*
segat = SegValue(es);
bufptr = reg_bx;
for(i=0;i<reg_al;i++) {
last_status = imageDiskList[drivenum]->Read_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0)<< 2)), (Bit32u)((reg_cl & 63)+i), sectbuf);
if(last_status != 0x00) {
LOG_MSG("Error in disk read");
CALLBACK_SCF(true);
return CBRET_NONE;
}
for(t=0;t<512;t++) {
real_writeb(segat,bufptr,sectbuf[t]);
bufptr++;
}
}*/
reg_ah = 0x00;
//reg_al = 0x10; /* CRC verify failed */
reg_al = 0x00; /* CRC verify succeeded */
CALLBACK_SCF(false);
break;
case 0x08: /* Get drive parameters */
if(driveInactive(drivenum)) {
last_status = 0x07;
reg_ah = last_status;
CALLBACK_SCF(true);
return CBRET_NONE;
}
reg_ax = 0x00;
reg_bl = imageDiskList[drivenum]->GetBiosType();
Bit32u tmpheads, tmpcyl, tmpsect, tmpsize;
imageDiskList[drivenum]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize);
reg_ch = tmpcyl;
reg_cl = tmpsect;
reg_dh = tmpheads-1;
last_status = 0x00;
reg_dl = 0;
if(imageDiskList[2] != NULL) reg_dl++;
if(imageDiskList[3] != NULL) reg_dl++;
CALLBACK_SCF(false);
break;
case 0x11: /* Recalibrate drive */
reg_ah = 0x00;
CALLBACK_SCF(false);
break;
case 0x17: /* Set disk type for format */
/* Pirates! needs this to load */
killRead = true;
reg_ah = 0x00;
CALLBACK_SCF(false);
break;
default:
LOG(LOG_BIOS,LOG_ERROR)("Illegal int 13h call %2X Fail it",reg_ah);
LOG_MSG("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum);
reg_ah=0xff;
CALLBACK_SCF(true);
}
return CBRET_NONE;
}
void BIOS_SetupDisks(void) {
/* TODO Start the time correctly */
call_int13=CALLBACK_Allocate();
CALLBACK_Setup(call_int13,&INT13_SmallHandler,CB_IRET);
//CALLBACK_Setup(call_int13,&INT13_SmallHandler,CB_IRET);
CALLBACK_Setup(call_int13,&INT13_DiskHandler,CB_IRET);
RealSetVec(0x13,CALLBACK_RealPointer(call_int13));
/* Init the Disk Tables */
last_status=0;
int i;
for(i=0;i<4;i++) {
imageDiskList[i] = NULL;
}
for(i=0;i<MAX_SWAPPABLE_DISKS;i++) {
diskSwap[i] = NULL;
}
diskparm0 = CALLBACK_Allocate();
diskparm1 = CALLBACK_Allocate();
swapPosition = 0;
RealSetVec(0x41,CALLBACK_RealPointer(diskparm0));
RealSetVec(0x46,CALLBACK_RealPointer(diskparm1));
for(i=0;i<16;i++) {
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+i,0);
real_writeb(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1))+i,0);
}
imgDTASeg = 0;
/* Setup the Bios Area */
mem_writeb(BIOS_HARDDISK_COUNT,0);
mem_writeb(BIOS_HARDDISK_COUNT,2);
KEYBOARD_AddEvent(KBD_f4,KBD_MOD_CTRL, swapInNextDisk);
killRead = false;
};