sync to dosbox 3635

This commit is contained in:
dborth 2010-08-11 04:08:22 +00:00
parent 2b06327229
commit ce09efba36
25 changed files with 510 additions and 284 deletions

View File

@ -1,5 +1,5 @@
dnl Init.
AC_INIT(dosbox,0.74)
AC_INIT(dosbox,SVN)
AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(README)

View File

@ -156,8 +156,9 @@ public:
public:
CFileInfo(void) {
orgname[0] = shortname[0] = 0;
nextEntry = shortNr = 0;
isDir = false;
id = MAX_OPENDIRS;
nextEntry = shortNr = 0;
}
~CFileInfo(void) {
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
@ -167,6 +168,7 @@ public:
char orgname [CROSS_LEN];
char shortname [DOS_NAMELENGTH_ASCII];
bool isDir;
Bit16u id;
Bitu nextEntry;
Bitu shortNr;
// contents
@ -175,6 +177,8 @@ public:
};
private:
void ClearFileInfo(CFileInfo *dir);
void DeleteFileInfo(CFileInfo *dir);
bool RemoveTrailingDot (char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname);
@ -203,7 +207,6 @@ private:
Bit16u srchNr;
CFileInfo* dirSearch [MAX_OPENDIRS];
char dirSearchName [MAX_OPENDIRS];
bool free [MAX_OPENDIRS];
CFileInfo* dirFindFirst [MAX_OPENDIRS];
Bit16u nextFreeFindFirst;

View File

@ -114,7 +114,7 @@ typedef struct {
typedef enum {
PART,
LINE,
//EGALINE
EGALINE
} Drawmode;
typedef struct {
@ -157,6 +157,8 @@ typedef struct {
Bit8u font[64*1024];
Bit8u * font_tables[2];
Bitu blinking;
bool blink;
bool char9dot;
struct {
Bitu address;
Bit8u sline,eline;

View File

@ -351,12 +351,16 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax
phys_writew(physAddress+0x01,(Bit16u)0x0eb4); // mov ah, 0x0e
phys_writew(physAddress+0x03,(Bit16u)0x10cd); // int 10
phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x0b:0x07);
phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax
phys_writeb(physAddress+0x01,(Bit8u)0x53); // push bx
phys_writew(physAddress+0x02,(Bit16u)0x0eb4); // mov ah, 0x0e
phys_writeb(physAddress+0x04,(Bit8u)0xbb); // mov bx,
phys_writew(physAddress+0x05,(Bit16u)0x0007); // 0x0007
phys_writew(physAddress+0x07,(Bit16u)0x10cd); // int 10
phys_writeb(physAddress+0x09,(Bit8u)0x5b); // pop bx
phys_writeb(physAddress+0x0a,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x0b,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x10:0x0c);
case CB_HOOKABLE:
phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near
phys_writeb(physAddress+0x01,(Bit8u)0x03); //offset
@ -456,7 +460,7 @@ Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr
}
void CALLBACK_RemoveSetup(Bitu callback) {
for (Bitu i = 0;i < 16;i++) {
for (Bitu i = 0;i < CB_SIZE;i++) {
phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00);
}
}

View File

@ -31,6 +31,11 @@ typedef struct SMSF {
unsigned char fr;
} TMSF;
typedef struct SCtrl {
Bit8u out[4]; // output channel
Bit8u vol[4]; // channel volume
} TCtrl;
extern int CDROM_GetMountType(char* path, int force);
class CDROM_Interface
@ -52,6 +57,7 @@ public:
virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0;
virtual bool PauseAudio (bool resume) = 0;
virtual bool StopAudio (void) = 0;
virtual void ChannelControl (TCtrl ctrl) = 0;
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
@ -76,6 +82,7 @@ public:
virtual bool PlayAudioSector (unsigned long start,unsigned long len);
virtual bool PauseAudio (bool resume);
virtual bool StopAudio (void);
virtual void ChannelControl (TCtrl ctrl) { return; };
virtual bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; };
virtual bool LoadUnloadMedia (bool unload);
@ -101,6 +108,7 @@ public:
bool PlayAudioSector (unsigned long /*start*/,unsigned long /*len*/) { return true; };
bool PauseAudio (bool /*resume*/) { return true; };
bool StopAudio (void) { return true; };
void ChannelControl (TCtrl ctrl) { return; };
bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; };
bool LoadUnloadMedia (bool /*unload*/) { return true; };
};
@ -166,6 +174,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
@ -188,6 +197,8 @@ static struct imagePlayer {
int targetFrame;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
TCtrl ctrlData;
} player;
void ClearTracks();
@ -234,6 +245,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl) { return; };
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
@ -284,6 +296,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
@ -338,6 +351,8 @@ private:
int targetFrame;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
TCtrl ctrlData;
} player;
};

View File

@ -131,7 +131,7 @@ int CDROM_Interface_Image::AudioFile::getLength()
int CDROM_Interface_Image::refCount = 0;
CDROM_Interface_Image* CDROM_Interface_Image::images[26];
CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = {
NULL, NULL, NULL, {0}, 0, 0, 0, false, false };
NULL, NULL, NULL, {0}, 0, 0, 0, false, false, false, {0} };
CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit)
@ -259,6 +259,12 @@ bool CDROM_Interface_Image::StopAudio(void)
return true;
}
void CDROM_Interface_Image::ChannelControl(TCtrl ctrl)
{
player.ctrlUsed = (ctrl.out[0]!=0 || ctrl.out[1]!=1 || ctrl.vol[0]<0xfe || ctrl.vol[1]<0xfe);
player.ctrlData = ctrl;
}
bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
@ -336,6 +342,16 @@ void CDROM_Interface_Image::CDAudioCallBack(Bitu len)
}
}
SDL_mutexV(player.mutex);
if (player.ctrlUsed) {
Bit16s sample0,sample1;
Bit16s * samples=(Bit16s *)&player.buffer;
for (Bitu pos=0;pos<len/4;pos++) {
sample0=samples[pos*2+player.ctrlData.out[0]];
sample1=samples[pos*2+player.ctrlData.out[1]];
samples[pos*2+0]=(Bit16s)(sample0*player.ctrlData.vol[0]/255.0);
samples[pos*2+1]=(Bit16s)(sample1*player.ctrlData.vol[1]/255.0);
}
}
#if defined(WORDS_BIGENDIAN)
player.channel->AddSamples_s16_nonnative(len/4,(Bit16s *)player.buffer);
#else

View File

@ -175,7 +175,7 @@ bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) {
CDROM_Interface_Ioctl::dxPlayer CDROM_Interface_Ioctl::player = {
NULL, NULL, NULL, 0, 0, 0, 0, 0, false, false };
NULL, NULL, NULL, {0}, 0, 0, 0, false, false, false, {0} };
CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(cdioctl_cdatype ioctl_cda) {
pathname[0] = 0;
@ -462,6 +462,12 @@ bool CDROM_Interface_Ioctl::StopAudio(void) {
return bStat>0;
}
void CDROM_Interface_Ioctl::ChannelControl(TCtrl ctrl)
{
player.ctrlUsed = (ctrl.out[0]!=0 || ctrl.out[1]!=1 || ctrl.vol[0]<0xfe || ctrl.vol[1]<0xfe);
player.ctrlData = ctrl;
}
bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) {
BOOL bStat;
DWORD byteCount;
@ -553,6 +559,16 @@ void CDROM_Interface_Ioctl::dx_CDAudioCallBack(Bitu len) {
}
}
SDL_mutexV(player.mutex);
if (player.ctrlUsed) {
Bit16s sample0,sample1;
Bit16s * samples=(Bit16s *)&player.buffer;
for (Bitu pos=0;pos<len/4;pos++) {
sample0=samples[pos*2+player.ctrlData.out[0]];
sample1=samples[pos*2+player.ctrlData.out[1]];
samples[pos*2+0]=(Bit16s)(sample0*player.ctrlData.vol[0]/255.0);
samples[pos*2+1]=(Bit16s)(sample1*player.ctrlData.vol[1]/255.0);
}
}
player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer);
memmove(player.buffer, &player.buffer[len], player.bufLen - len);
player.bufLen -= len;

View File

@ -227,10 +227,13 @@ static Bitu DOS_21Handler(void) {
break;
case 0x0c: /* Flush Buffer and read STDIN call */
{
/* flush STDIN-buffer */
Bit8u c;Bit16u n;
while (DOS_GetSTDINStatus()) {
n=1; DOS_ReadFile(STDIN,&c,&n);
/* flush buffer if STDIN is CON */
Bit8u handle=RealHandle(STDIN);
if (handle!=0xFF && Files[handle] && Files[handle]->IsName("CON")) {
Bit8u c;Bit16u n;
while (DOS_GetSTDINStatus()) {
n=1; DOS_ReadFile(STDIN,&c,&n);
}
}
switch (reg_al) {
case 0x1:

View File

@ -203,6 +203,13 @@ bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) {
bool DOS_ChangeDir(char const * const dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
const char * testdir=dir;
if (strlen(testdir) && testdir[1]==':') testdir+=2;
size_t len=strlen(testdir);
if (!len || (len>1 && testdir[len-1]=='\\')) {
DOS_SetError(DOSERR_PATH_NOT_FOUND);
return false;
}
if (!DOS_MakeName(dir,fulldir,&drive)) return false;
if (Drives[drive]->TestDir(fulldir)) {

View File

@ -436,7 +436,7 @@ void DOS_SetupMemory(void) {
if (machine==MCH_TANDY) {
/* memory up to 608k available, the rest (to 640k) is used by
the tandy graphics system's variable mapping of 0xb800 */
mcb.SetSize(0x97FF - DOS_MEM_START - mcb_sizes);
mcb.SetSize(0x9BFF - DOS_MEM_START - mcb_sizes);
} else if (machine==MCH_PCJR) {
/* memory from 128k to 640k is available */
mcb_devicedummy.SetPt((Bit16u)0x2000);

View File

@ -152,6 +152,7 @@ private:
bool locked; // drive locked ?
bool lastResult; // last operation success ?
Bit32u volumeSize; // for media change
TCtrl audioCtrl; // audio channel control
} TDriveInfo;
Bit16u defaultBufSeg;
@ -160,6 +161,9 @@ private:
public:
Bit16u rootDriverHeaderSeg;
bool ChannelControl (Bit8u subUnit, TCtrl ctrl);
bool GetChannelControl (Bit8u subUnit, TCtrl& ctrl);
};
CMscdex::CMscdex(void) {
@ -368,25 +372,34 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit)
devHeader.SetInterrupt(off+5);
}
subUnit = (Bit8u)numDrives;
// Set drive
DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0));
devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1);
if (dinfo[0].drive-1==_drive) {
CDROM_Interface *_cdrom = cdrom[numDrives];
CDROM_Interface_Image *_cdimg = CDROM_Interface_Image::images[numDrives];
for (Bit16u i=GetNumDrives(); i>0; i--) {
dinfo[i] = dinfo[i-1];
cdrom[i] = cdrom[i-1];
CDROM_Interface_Image::images[i] = CDROM_Interface_Image::images[i-1];
}
cdrom[0] = _cdrom;
CDROM_Interface_Image::images[0] = _cdimg;
dinfo[0].drive = (Bit8u)_drive;
dinfo[0].physDrive = (Bit8u)toupper(physicalPath[0]);
subUnit = 0;
} else {
dinfo[numDrives].drive = (Bit8u)_drive;
dinfo[numDrives].physDrive = (Bit8u)toupper(physicalPath[0]);
subUnit = (Bit8u)numDrives;
}
numDrives++;
// init channel control
for (Bit8u chan=0;chan<4;chan++) {
dinfo[subUnit].audioCtrl.out[chan]=chan;
dinfo[subUnit].audioCtrl.vol[chan]=0xff;
}
// stop audio
StopAudio(subUnit);
return result;
@ -459,7 +472,7 @@ bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length)
if (subUnit>=numDrives) return false;
// If value from last stop is used, this is meant as a resume
// better start using resume command
if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart)) {
if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart) && (dinfo[subUnit].audioEnd!=0)) {
dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(true);
} else
dinfo[subUnit].lastResult = cdrom[subUnit]->PlayAudioSector(sector,length);
@ -665,6 +678,7 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph
char entryName[256];
bool foundComplete = false;
bool foundName;
bool nextPart = true;
char* useName = 0;
Bitu entryLength,nameLength;
// clear error
@ -695,14 +709,15 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph
if (!ReadSectors(GetSubUnit(drive),false,dirEntrySector,1,defBuffer)) return false;
// Get string part
foundName = false;
if (searchPos) {
useName = searchPos;
searchPos = strchr(searchPos,'\\');
if (nextPart) {
if (searchPos) {
useName = searchPos;
searchPos = strchr(searchPos,'\\');
}
if (searchPos) { *searchPos = 0; searchPos++; }
else foundComplete = true;
}
if (searchPos) { *searchPos = 0; searchPos++; }
else foundComplete = true;
do {
entryLength = mem_readb(defBuffer+index);
if (entryLength==0) break;
@ -759,10 +774,12 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph
// change directory
dirEntrySector = mem_readd(defBuffer+index+2);
dirSize = mem_readd(defBuffer+index+10);
nextPart = true;
} else {
// continue search in next sector
dirSize -= 2048;
dirEntrySector++;
nextPart = false;
}
};
error = 2; // file not found
@ -796,6 +813,7 @@ Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit)
(dinfo[subUnit].locked << 1) | // Drive is locked ?
(1<<2) | // raw + cooked sectors
(1<<4) | // Can read sudio
(1<<8) | // Can control audio
(1<<9) | // Red book & HSG
((!media) << 11); // Drive is empty ?
return status;
@ -860,6 +878,22 @@ void CMscdex::InitNewMedia(Bit8u subUnit) {
}
}
bool CMscdex::ChannelControl(Bit8u subUnit, TCtrl ctrl) {
if (subUnit>=numDrives) return false;
// adjust strange channel mapping
if (ctrl.out[0]>1) ctrl.out[0]=0;
if (ctrl.out[1]>1) ctrl.out[1]=1;
dinfo[subUnit].audioCtrl=ctrl;
cdrom[subUnit]->ChannelControl(ctrl);
return true;
}
bool CMscdex::GetChannelControl(Bit8u subUnit, TCtrl& ctrl) {
if (subUnit>=numDrives) return false;
ctrl=dinfo[subUnit].audioCtrl;
return true;
}
static CMscdex* mscdex = 0;
static PhysPt curReqheaderPtr = 0;
@ -889,6 +923,14 @@ static Bit16u MSCDEX_IOCTL_Input(PhysPt buffer,Bit8u drive_unit) {
return 0x03; // invalid function
}
}break;
case 0x04 : /* Audio Channel control */
TCtrl ctrl;
if (!mscdex->GetChannelControl(drive_unit,ctrl)) return 0x01;
for (Bit8u chan=0;chan<4;chan++) {
mem_writeb(buffer+chan*2+1,ctrl.out[chan]);
mem_writeb(buffer+chan*2+2,ctrl.vol[chan]);
}
break;
case 0x06 : /* Get Device status */
mem_writed(buffer+1,mscdex->GetDeviceStatus(drive_unit));
break;
@ -980,7 +1022,13 @@ static Bit16u MSCDEX_IOCTL_Optput(PhysPt buffer,Bit8u drive_unit) {
if (!mscdex->LoadUnloadMedia(drive_unit,true)) return 0x02;
break;
case 0x03: //Audio Channel control
MSCDEX_LOG("MSCDEX: Audio Channel Control used. Not handled. Faking succes!");
TCtrl ctrl;
for (Bit8u chan=0;chan<4;chan++) {
ctrl.out[chan]=mem_readb(buffer+chan*2+1);
ctrl.vol[chan]=mem_readb(buffer+chan*2+2);
}
if (!mscdex->ChannelControl(drive_unit,ctrl)) return 0x01;
break;
case 0x01 : // (un)Lock door
// do nothing -> report as success
break;

View File

@ -67,7 +67,7 @@ DOS_Drive_Cache::DOS_Drive_Cache(void) {
srchNr = 0;
label[0] = 0;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; dirFindFirst[i] = 0; };
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; dirFindFirst[i] = 0; };
SetDirSort(DIRALPHABETICAL);
updatelabel = true;
}
@ -78,7 +78,7 @@ DOS_Drive_Cache::DOS_Drive_Cache(const char* path) {
srchNr = 0;
label[0] = 0;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; dirFindFirst[i] = 0; };
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; dirFindFirst[i] = 0; };
SetDirSort(DIRALPHABETICAL);
SetBaseDir(path);
updatelabel = true;
@ -86,11 +86,11 @@ DOS_Drive_Cache::DOS_Drive_Cache(const char* path) {
DOS_Drive_Cache::~DOS_Drive_Cache(void) {
Clear();
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { delete dirFindFirst[i]; dirFindFirst[i]=0; };
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { DeleteFileInfo(dirFindFirst[i]); dirFindFirst[i]=0; };
}
void DOS_Drive_Cache::Clear(void) {
delete dirBase; dirBase = 0;
DeleteFileInfo(dirBase); dirBase = 0;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) dirSearch[i] = 0;
}
@ -101,7 +101,6 @@ void DOS_Drive_Cache::EmptyCache(void) {
dirBase = new CFileInfo;
save_dir = 0;
srchNr = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) free[i] = true;
SetBaseDir(basePath);
}
@ -117,8 +116,16 @@ void DOS_Drive_Cache::SetLabel(const char* vname,bool cdrom,bool allowupdate) {
}
Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir) {
for (Bit16u i=0; i<MAX_OPENDIRS; i++) if (free[i] || (dir==dirSearch[i])) return i;
if (dir->id != MAX_OPENDIRS)
return dir->id;
for (Bit16u i=0; i<MAX_OPENDIRS; i++) {
if (!dirSearch[i]) {
dir->id = i;
return i;
}
}
LOG(LOG_FILES,LOG_NORMAL)("DIRCACHE: Too many open directories!");
dir->id=0;
return 0;
}
@ -264,7 +271,7 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) {
// delete file objects...
for(Bit32u i=0; i<dir->fileList.size(); i++) {
if (dirSearch[srchNr]==dir->fileList[i]) dirSearch[srchNr] = 0;
delete dir->fileList[i]; dir->fileList[i] = 0;
DeleteFileInfo(dir->fileList[i]); dir->fileList[i] = 0;
}
// clear lists
dir->fileList.clear();
@ -526,7 +533,10 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
strcpy(buffer,dirPath);
ReadDir(id,result);
strcpy(dirPath,buffer);
free[id] = true;
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
};
};
@ -556,7 +566,10 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
strcpy(buffer,dirPath);
ReadDir(id,result);
strcpy(dirPath,buffer);
free[id] = true;
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
};
}
};
@ -600,9 +613,12 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) {
// Reset it..
close_directory(dirp);
strcpy(dirPath,expandcopy);
free[id] = false;
return true;
}
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
};
return false;
}
@ -661,7 +677,10 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
// Try to open directory
dir_information* dirp = open_directory(dirPath);
if (!dirp) {
free[id] = true;
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
return false;
}
// Read complete directory
@ -688,7 +707,10 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
};*/
};
if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true;
free[id] = true;
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
return false;
}
@ -732,7 +754,7 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bit16u& id) {
this->nextFreeFindFirst = 1; //the next free one after this search
for(Bitu n=0; n<MAX_OPENDIRS;n++) {
// Clear and reuse slot
delete dirFindFirst[n];
DeleteFileInfo(dirFindFirst[n]);
dirFindFirst[n]=0;
}
@ -767,8 +789,25 @@ bool DOS_Drive_Cache::FindNext(Bit16u id, char* &result) {
}
if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) {
// free slot
delete dirFindFirst[id]; dirFindFirst[id] = 0;
DeleteFileInfo(dirFindFirst[id]); dirFindFirst[id] = 0;
return false;
}
return true;
}
void DOS_Drive_Cache::ClearFileInfo(CFileInfo *dir) {
for(Bit32u i=0; i<dir->fileList.size(); i++) {
if (CFileInfo *info = dir->fileList[i])
ClearFileInfo(info);
}
if (dir->id != MAX_OPENDIRS) {
dirSearch[dir->id] = 0;
dir->id = MAX_OPENDIRS;
}
}
void DOS_Drive_Cache::DeleteFileInfo(CFileInfo *dir) {
if (dir)
ClearFileInfo(dir);
delete dir;
}

View File

@ -289,7 +289,7 @@ bool isoDrive::FindNext(DOS_DTA &dta) {
else findAttr |= DOS_ATTR_ARCHIVE;
if (IS_HIDDEN(de.fileFlags)) findAttr |= DOS_ATTR_HIDDEN;
if (!(isRoot && de.ident[0]=='.') && WildFileCmp((char*)de.ident, pattern)
if (!IS_ASSOC(de.fileFlags) && !(isRoot && de.ident[0]=='.') && WildFileCmp((char*)de.ident, pattern)
&& !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) {
/* file is okay, setup everything to be copied in DTA Block */
@ -541,7 +541,7 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) {
// look for the current path element
int dirIterator = GetDirIterator(de);
while (!found && GetNextDirEntry(dirIterator, de)) {
if (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH)) {
if (!IS_ASSOC(de->fileFlags) && (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH))) {
found = true;
}
}

View File

@ -41,6 +41,7 @@ public:
Bit16u GetInformation(void);
bool UpdateDateTimeFromHost(void);
void FlagReadOnlyMedium(void);
void Flush(void);
private:
FILE * fhandle;
bool read_only_medium;
@ -95,6 +96,22 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
CROSS_FILENAME(newname);
dirCache.ExpandName(newname);
//Flush the buffer of handles for the same file. (Betrayal in Antara)
Bit8u i,drive=DOS_DRIVES;
localFile *lfp;
for (i=0;i<DOS_DRIVES;i++) {
if (Drives[i]==this) {
drive=i;
break;
}
}
for (i=0;i<DOS_FILES;i++) {
if (Files[i] && Files[i]->IsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) {
lfp=dynamic_cast<localFile*>(Files[i]);
if (lfp) lfp->Flush();
}
}
FILE * hand=fopen(newname,type);
// Bit32u err=errno;
if (!hand) {
@ -541,6 +558,13 @@ bool localFile::UpdateDateTimeFromHost(void) {
return true;
}
void localFile::Flush(void) {
if (last_action==WRITE) {
fseek(fhandle,ftell(fhandle),SEEK_SET);
last_action=NONE;
}
}
// ********************************************
// CDROM DRIVE

View File

@ -298,11 +298,13 @@ struct isoDirEntry {
#endif
#define ISO_FRAMESIZE 2048
#define ISO_ASSOCIATED 4
#define ISO_DIRECTORY 2
#define ISO_HIDDEN 1
#define ISO_MAX_FILENAME_LENGTH 37
#define ISO_MAXPATHNAME 256
#define ISO_FIRST_VD 16
#define IS_ASSOC(fileFlags) (fileFlags & ISO_ASSOCIATED)
#define IS_DIR(fileFlags) (fileFlags & ISO_DIRECTORY)
#define IS_HIDDEN(fileFlags) (fileFlags & ISO_HIDDEN)
#define ISO_MAX_HASH_TABLE_SIZE 100

View File

@ -504,6 +504,8 @@ static void GenerateDMASound(Bitu size) {
sb.dma.left-=read;
if (!sb.dma.left) {
PIC_RemoveEvents(END_DMA_Event);
if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16);
else SB_RaiseIRQ(SB_IRQ_8);
if (!sb.dma.autoinit) {
LOG(LOG_SB,LOG_NORMAL)("Single cycle transfer ended");
sb.mode=MODE_NONE;
@ -515,8 +517,6 @@ static void GenerateDMASound(Bitu size) {
sb.mode=MODE_NONE;
}
}
if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16);
else SB_RaiseIRQ(SB_IRQ_8);
}
}
@ -1345,7 +1345,8 @@ static Bit8u CTMIXER_Read(void) {
return ret;
case 0x82: /* IRQ Status */
return (sb.irq.pending_8bit ? 0x1 : 0) |
(sb.irq.pending_16bit ? 0x2 : 0);
(sb.irq.pending_16bit ? 0x2 : 0) |
((sb.type == SBT_16) ? 0x20 : 0);
default:
if ( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */
(sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */

View File

@ -76,26 +76,33 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
10h and 14h.
*/
break;
case 0x10: /* Mode Control Register */
case 0x10: { /* Mode Control Register */
if (!IS_VGA_ARCH) val&=0x1f; // not really correct, but should do it
if ((attr(mode_control) ^ val) & 0x80) {
attr(mode_control)^=0x80;
for (Bit8u i=0;i<0x10;i++) {
Bitu difference = attr(mode_control)^val;
attr(mode_control)=(Bit8u)val;
if (difference & 0x80) {
for (Bit8u i=0;i<0x10;i++)
VGA_ATTR_SetPalette(i,vga.attr.palette[i]);
}
if (difference & 0x08)
VGA_SetBlinking(val & 0x8);
if (difference & 0x41)
VGA_DetermineMode();
if (difference & 0x04) {
// recompute the panning value
if(vga.mode==M_TEXT) {
Bit8u pan_reg = attr(horizontal_pel_panning);
if (pan_reg > 7)
vga.config.pel_panning=0;
else if (val&0x4) // 9-dot wide characters
vga.config.pel_panning=(Bit8u)(pan_reg+1);
else // 8-dot characters
vga.config.pel_panning=(Bit8u)pan_reg;
}
}
if ((attr(mode_control) ^ val) & 0x08) {
VGA_SetBlinking(val & 0x8);
}
if ((attr(mode_control) ^ val) & 0x04) {
attr(mode_control)=(Bit8u)val;
VGA_DetermineMode();
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) VGA_StartResize();
} else {
attr(mode_control)=(Bit8u)val;
VGA_DetermineMode();
}
/*
0 Graphics mode if set, Alphanumeric mode else.
1 Monochrome mode if set, color mode else.
@ -113,6 +120,7 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
used.
*/
break;
}
case 0x11: /* Overscan Color Register */
attr(overscan_color)=(Bit8u)val;
/* 0-5 Color of screen border. Color is defined as in the palette registers. */
@ -134,9 +142,12 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
attr(horizontal_pel_panning)=val & 0xF;
switch (vga.mode) {
case M_TEXT:
if ((val==0x7) && (svgaCard==SVGA_None)) vga.config.pel_panning=7;
if (val>0x7) vga.config.pel_panning=0;
else vga.config.pel_panning=(Bit8u)(val+1);
if (val > 7)
vga.config.pel_panning=0;
else if (vga.attr.mode_control&0x4) // 9-dot wide characters
vga.config.pel_panning=(Bit8u)(val+1);
else // 8-dot characters
vga.config.pel_panning=(Bit8u)val;
break;
case M_VGA:
case M_LIN8:
@ -146,6 +157,9 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
default:
vga.config.pel_panning=(val & 0x7);
}
if (machine==MCH_EGA)
// On the EGA panning can be programmed for every scanline:
vga.draw.panning = vga.config.pel_panning;
/*
0-3 Indicates number of pixels to shift the display left
Value 9bit textmode 256color mode Other modes

View File

@ -155,7 +155,7 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) {
for (; start <= end;start++) {
if ( map[start] & checkMask ) {
Bitu offset = vidstart & vga.draw.linear_mask;
if(vga.draw.linear_mask-offset < vga.draw.line_length)
if (vga.draw.linear_mask-offset < vga.draw.line_length)
memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length);
Bit8u *ret = &vga.draw.linear_base[ offset ];
#if !defined(C_UNALIGNED_MEMORY)
@ -197,14 +197,6 @@ static Bit8u * VGA_Draw_Xlat16_Linear_Line(Bitu vidstart, Bitu /*line*/) {
temps[i]=vga.dac.xlat16[ret[i]];
}
return TempLine;
/*
#if !defined(C_UNALIGNED_MEMORY)
if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) {
memcpy( TempLine, ret, vga.draw.line_length );
return TempLine;
}
#endif
return ret;*/
}
//Test version, might as well keep it
@ -446,167 +438,121 @@ static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) {
skip_cursor:
return TempLine;
}
static Bit8u * VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) {
Bits font_addr;
Bit16u * draw=(Bit16u *)TempLine;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
for (Bitu cx=0;cx<vga.draw.blocks;cx++) {
Bitu chr=vidmem[cx*2];
Bitu col=vidmem[cx*2+1];
Bitu font=vga.draw.font_tables[(col >> 3)&1][chr*32+line];
Bit32u mask1=TXT_Font_Table[font>>4] & FontMask[col >> 7];
Bit32u mask2=TXT_Font_Table[font&0xf] & FontMask[col >> 7];
Bit32u fg=TXT_FG_Table[col&0xf];
Bit32u bg=TXT_BG_Table[col>>4];
mask1=(fg&mask1) | (bg&~mask1);
mask2=(fg&mask2) | (bg&~mask2);
for(int i = 0; i < 4; i++) {
*draw++ = vga.dac.xlat16[(mask1>>8*i)&0xff];
}
for(int i = 0; i < 4; i++) {
*draw++ = vga.dac.xlat16[(mask2>>8*i)&0xff];
}
}
if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor;
font_addr = (vga.draw.cursor.address-vidstart) >> 1;
if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) {
if (line<vga.draw.cursor.sline) goto skip_cursor;
if (line>vga.draw.cursor.eline) goto skip_cursor;
draw=(Bit16u *)&TempLine[font_addr*16];
Bit8u att=(Bit8u)(TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]&0xff);
for(int i = 0; i < 8; i++) {
*draw++ = vga.dac.xlat16[att];
}
}
skip_cursor:
return TempLine;
}
/*
static Bit8u * VGA_TEXT_Draw_Line_9(Bitu vidstart, Bitu line) {
Bits font_addr;
Bit8u * draw=(Bit8u *)TempLine;
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line;
Bit8u pel_pan=(Bit8u)vga.draw.panning;
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
Bit8u chr=vidmem[0];
Bit8u col=vidmem[1];
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
if (underline && ((col&0x07) == 0x01)) font=0xff;
Bit8u fg=col&0xf;
Bit8u bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
Bitu draw_blocks=vga.draw.blocks;
draw_blocks++;
for (Bitu cx=1;cx<draw_blocks;cx++) {
if (pel_pan) {
chr=vidmem[cx*2];
col=vidmem[cx*2+1];
if (underline && ((col&0x07) == 0x01)) font|=0xff>>(8-pel_pan);
else font|=vga.draw.font_tables[(col >> 3)&1][chr*32+line]>>(8-pel_pan);
fg=col&0xf;
bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
// combined 8/9-dot wide text mode 8bpp line drawing function
static Bit8u* VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) {
// keep it aligned:
Bit8u* draw = ((Bit8u*)TempLine) + 16 - vga.draw.panning;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart); // pointer to chars+attribs
Bitu blocks = vga.draw.blocks;
if (vga.draw.panning) blocks++; // if the text is panned part of an
// additional character becomes visible
while (blocks--) { // for each character in the line
Bitu chr = *vidmem++;
Bitu attr = *vidmem++;
// the font pattern
Bitu font = vga.draw.font_tables[(attr >> 3)&1][(chr<<5)+line];
Bitu background = attr >> 4;
// if blinking is enabled bit7 is not mapped to attributes
if (vga.draw.blinking) background &= ~0x8;
// choose foreground color if blinking not set for this cell or blink on
Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
(attr&0xf):background;
// underline: all foreground [freevga: 0x77, previous 0x7]
if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
(vga.crtc.underline_location&0x1f)==line))
background = foreground;
if (vga.draw.char9dot) {
font <<=1; // 9 pixels
// extend to the 9th pixel if needed
if ((font&0x2) && (vga.attr.mode_control&0x04) &&
(chr>=0xc0) && (chr<=0xdf)) font |= 1;
for (Bitu n = 0; n < 9; n++) {
*draw++ = (font&0x100)? foreground:background;
font <<= 1;
}
} else {
chr=vidmem[(cx-1)*2];
col=vidmem[(cx-1)*2+1];
if (underline && ((col&0x07) == 0x01)) font=0xff;
else font=vga.draw.font_tables[(col >> 3)&1][chr*32+line];
fg=col&0xf;
bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
}
if (FontMask[col>>7]==0) font=0;
*draw++=(font&0x80)?fg:bg; *draw++=(font&0x40)?fg:bg;
*draw++=(font&0x20)?fg:bg; *draw++=(font&0x10)?fg:bg;
*draw++=(font&0x08)?fg:bg; *draw++=(font&0x04)?fg:bg;
*draw++=(font&0x02)?fg:bg;
Bit8u last=(font&0x01)?fg:bg;
*draw++=last;
*draw++=((vga.attr.mode_control&0x04) && ((chr<0xc0) || (chr>0xdf))) ? bg : last;
if (pel_pan) {
if (underline && ((col&0x07) == 0x01)) font=0xff;
else font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
for (Bitu n = 0; n < 8; n++) {
*draw++ = (font&0x80)? foreground:background;
font <<= 1;
}
}
}
if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor;
font_addr = (vga.draw.cursor.address-vidstart) >> 1;
if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) {
if (line<vga.draw.cursor.sline) goto skip_cursor;
if (line>vga.draw.cursor.eline) goto skip_cursor;
draw=&TempLine[font_addr*9];
Bit8u fg=vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf;
*draw++=fg; *draw++=fg; *draw++=fg; *draw++=fg;
*draw++=fg; *draw++=fg; *draw++=fg; *draw++=fg;
// draw the text mode cursor if needed
if ((vga.draw.cursor.count&0x8) && (line >= vga.draw.cursor.sline) &&
(line <= vga.draw.cursor.eline) && vga.draw.cursor.enabled) {
// the adress of the attribute that makes up the cell the cursor is in
Bits attr_addr = (vga.draw.cursor.address-vidstart) >> 1;
if (attr_addr >= 0 && attr_addr < (Bits)vga.draw.blocks) {
Bitu index = attr_addr * (vga.draw.char9dot? 9:8);
draw = (Bit8u*)(&TempLine[index]) + 16 - vga.draw.panning;
Bitu foreground = vga.tandy.draw_base[vga.draw.cursor.address+1] & 0xf;
for (Bitu i = 0; i < 8; i++) {
*draw++ = foreground;
}
}
}
skip_cursor:
return TempLine;
return TempLine+16;
}
*/
static Bit8u * VGA_TEXT_Xlat16_Draw_Line_9(Bitu vidstart, Bitu line) {
Bits font_addr;
Bit16u * draw=(Bit16u *)TempLine;
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line;
Bit8u pel_pan=(Bit8u)vga.draw.panning;
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
Bit8u chr=vidmem[0];
Bit8u col=vidmem[1];
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
if (underline && ((col&0x07) == 0x01)) font=0xff;
Bit8u fg=col&0xf;
Bit8u bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
Bitu draw_blocks=vga.draw.blocks;
draw_blocks++;
for (Bitu cx=1;cx<draw_blocks;cx++) {
if (pel_pan) {
chr=vidmem[cx*2];
col=vidmem[cx*2+1];
if (underline && ((col&0x07) == 0x01)) font|=0xff>>(8-pel_pan);
else font|=vga.draw.font_tables[(col >> 3)&1][chr*32+line]>>(8-pel_pan);
fg=col&0xf;
bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
// combined 8/9-dot wide text mode 16bpp line drawing function
static Bit8u* VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) {
// keep it aligned:
Bit16u* draw = ((Bit16u*)TempLine) + 16 - vga.draw.panning;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart); // pointer to chars+attribs
Bitu blocks = vga.draw.blocks;
if (vga.draw.panning) blocks++; // if the text is panned part of an
// additional character becomes visible
while (blocks--) { // for each character in the line
Bitu chr = *vidmem++;
Bitu attr = *vidmem++;
// the font pattern
Bitu font = vga.draw.font_tables[(attr >> 3)&1][(chr<<5)+line];
Bitu background = attr >> 4;
// if blinking is enabled bit7 is not mapped to attributes
if (vga.draw.blinking) background &= ~0x8;
// choose foreground color if blinking not set for this cell or blink on
Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
(attr&0xf):background;
// underline: all foreground [freevga: 0x77, previous 0x7]
if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
(vga.crtc.underline_location&0x1f)==line))
background = foreground;
if (vga.draw.char9dot) {
font <<=1; // 9 pixels
// extend to the 9th pixel if needed
if ((font&0x2) && (vga.attr.mode_control&0x04) &&
(chr>=0xc0) && (chr<=0xdf)) font |= 1;
for (Bitu n = 0; n < 9; n++) {
*draw++ = vga.dac.xlat16[(font&0x100)? foreground:background];
font <<= 1;
}
} else {
chr=vidmem[(cx-1)*2];
col=vidmem[(cx-1)*2+1];
if (underline && ((col&0x07) == 0x01)) font=0xff;
else font=vga.draw.font_tables[(col >> 3)&1][chr*32+line];
fg=col&0xf;
bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff);
}
if (FontMask[col>>7]==0) font=0;
Bit8u mask=0x80;
for (int i = 0; i < 7; i++) {
*draw++=vga.dac.xlat16[font&mask?fg:bg];
mask>>=1;
}
Bit16u lastval=vga.dac.xlat16[font&mask?fg:bg];
*draw++=lastval;
*draw++=(((vga.attr.mode_control&0x04) && ((chr<0xc0) || (chr>0xdf))) &&
!(underline && ((col&0x07) == 0x01))) ?
(vga.dac.xlat16[bg]) : lastval;
if (pel_pan) {
if (underline && ((col&0x07) == 0x01)) font=0xff;
else font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
for (Bitu n = 0; n < 8; n++) {
*draw++ = vga.dac.xlat16[(font&0x80)? foreground:background];
font <<= 1;
}
}
}
if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor;
font_addr = (vga.draw.cursor.address-vidstart) >> 1;
if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) {
if (line<vga.draw.cursor.sline) goto skip_cursor;
if (line>vga.draw.cursor.eline) goto skip_cursor;
draw=(Bit16u*)&TempLine[font_addr*18];
Bit8u fg=vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf;
for(int i = 0; i < 8; i++) {
*draw++ = vga.dac.xlat16[fg];
// draw the text mode cursor if needed
if ((vga.draw.cursor.count&0x8) && (line >= vga.draw.cursor.sline) &&
(line <= vga.draw.cursor.eline) && vga.draw.cursor.enabled) {
// the adress of the attribute that makes up the cell the cursor is in
Bits attr_addr = (vga.draw.cursor.address-vidstart) >> 1;
if (attr_addr >= 0 && attr_addr < (Bits)vga.draw.blocks) {
Bitu index = attr_addr * (vga.draw.char9dot? 18:16);
draw = (Bit16u*)(&TempLine[index]) + 16 - vga.draw.panning;
Bitu foreground = vga.tandy.draw_base[vga.draw.cursor.address+1] & 0xf;
for (Bitu i = 0; i < 8; i++) {
*draw++ = vga.dac.xlat16[foreground];
}
}
//if(underline && ((col&0x07) == 0x01))
// *draw = vga.dac.xlat16[fg];
}
skip_cursor:
return TempLine;
return TempLine+32;
}
#ifdef VGA_KEEP_CHANGES
@ -628,14 +574,17 @@ static INLINE void VGA_ChangesEnd(void ) {
static void VGA_ProcessSplit() {
// On the EGA the address is always reset to 0.
if ((vga.attr.mode_control&0x20) || (machine==MCH_EGA)) {
if (vga.attr.mode_control&0x20) {
vga.draw.address=0;
// reset panning to 0 here so we don't have to check for
// it in the character draw functions. It will be set back
// to its proper value in v-retrace
vga.draw.panning=0;
} else {
// In text mode only the characters are shifted by panning, not the address;
// this is done in the text line draw function.
vga.draw.address = vga.draw.byte_panning_shift*vga.draw.bytes_skip;
if (!(vga.mode==M_TEXT)) vga.draw.address += vga.draw.panning;
if ((vga.mode!=M_TEXT)&&(machine!=MCH_EGA)) vga.draw.address += vga.draw.panning;
}
vga.draw.address_line=0;
}
@ -662,6 +611,29 @@ static void VGA_DrawSingleLine(Bitu /*blah*/) {
} else RENDER_EndUpdate(false);
}
static void VGA_DrawEGASingleLine(Bitu /*blah*/) {
if (GCC_UNLIKELY(vga.attr.disabled)) {
memset(TempLine, 0, sizeof(TempLine));
RENDER_DrawLine(TempLine);
} else {
Bitu address = vga.draw.address;
if (vga.mode!=M_TEXT) address += vga.draw.panning;
Bit8u * data=VGA_DrawLine(address, vga.draw.address_line );
RENDER_DrawLine(data);
}
vga.draw.address_line++;
if (vga.draw.address_line>=vga.draw.address_line_total) {
vga.draw.address_line=0;
vga.draw.address+=vga.draw.address_add;
}
vga.draw.lines_done++;
if (vga.draw.split_line==vga.draw.lines_done) VGA_ProcessSplit();
if (vga.draw.lines_done < vga.draw.lines_total) {
PIC_AddEvent(VGA_DrawEGASingleLine,(float)vga.draw.delay.htotal);
} else RENDER_EndUpdate(false);
}
static void VGA_DrawPart(Bitu lines) {
while (lines--) {
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
@ -771,7 +743,6 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
VGA_DisplayStartLatch(0);
break;
case MCH_VGA:
case MCH_EGA:
PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrstart);
PIC_AddEvent(VGA_PanningLatch, (float)vga.draw.delay.vrend);
// EGA: 82c435 datasheet: interrupt happens at display end
@ -779,6 +750,10 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
// add a little amount of time to make sure the last drawpart has already fired
PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005));
break;
case MCH_EGA:
PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrend);
PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005));
break;
default:
E_Exit("This new machine needs implementation in VGA_VerticalTimer too.");
break;
@ -798,7 +773,11 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
vga.draw.address = vga.config.real_start;
vga.draw.byte_panning_shift = 0;
// go figure...
if (machine==MCH_EGA) vga.draw.split_line*=2;
if (machine==MCH_EGA) {
if (vga.draw.doubleheight) // Spacepigs EGA Megademo
vga.draw.split_line*=2;
vga.draw.split_line++; // EGA adds one buggy scanline
}
// if (machine==MCH_EGA) vga.draw.split_line = ((((vga.config.line_compare&0x5ff)+1)*2-1)/vga.draw.lines_scaled);
#ifdef VGA_KEEP_CHANGES
bool startaddr_changed=false;
@ -811,13 +790,13 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
vga.draw.byte_panning_shift = 8;
vga.draw.address += vga.draw.bytes_skip;
vga.draw.address *= vga.draw.byte_panning_shift;
vga.draw.address += vga.draw.panning;
if (machine!=MCH_EGA) vga.draw.address += vga.draw.panning;
#ifdef VGA_KEEP_CHANGES
startaddr_changed=true;
#endif
break;
case M_VGA:
if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) {
if (vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) {
vga.draw.linear_base = vga.fastmem;
vga.draw.linear_mask = 0xffff;
} else {
@ -851,6 +830,10 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
/* check for blinking and blinking change delay */
FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ?
0 : 0xffffffff;
/* if blinking is enabled, 'blink' will toggle between true
* and false. Otherwise it's true */
vga.draw.blink = ((vga.draw.blinking & (vga.draw.cursor.count >> 4))
|| !vga.draw.blinking) ? true:false;
break;
case M_HERC_GFX:
break;
@ -889,16 +872,19 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts + draw_skip,vga.draw.parts_lines);
break;
case LINE:
case EGALINE:
if (GCC_UNLIKELY(vga.draw.lines_done < vga.draw.lines_total)) {
LOG(LOG_VGAMISC,LOG_NORMAL)( "Lines left: %d",
vga.draw.lines_total-vga.draw.lines_done);
PIC_RemoveEvents(VGA_DrawSingleLine);
if (vga.draw.mode==EGALINE) PIC_RemoveEvents(VGA_DrawEGASingleLine);
else PIC_RemoveEvents(VGA_DrawSingleLine);
RENDER_EndUpdate(true);
}
vga.draw.lines_done = 0;
PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
if (vga.draw.mode==EGALINE)
PIC_AddEvent(VGA_DrawEGASingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
else PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
break;
//case EGALINE:
}
}
@ -982,6 +968,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
case MCH_PCJR:
vga.draw.mode = LINE;
break;
case MCH_EGA:
// Note: The Paradise SVGA uses the same panning mechanism as EGA
vga.draw.mode = EGALINE;
break;
case MCH_VGA:
if (svgaCard==SVGA_None) {
vga.draw.mode = LINE;
@ -1077,13 +1067,13 @@ void VGA_SetupDrawing(Bitu /*val*/) {
htotal*=2;
}
vga.draw.address_line_total=(vga.crtc.maximum_scan_line&0x1f)+1;
if(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) {
if (IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) {
// vgaonly; can't use with CGA because these use address_line for their
// own purposes.
// Set the low resolution modes to have as many lines as are scanned -
// Quite a few demos change the max_scanline register at display time
// to get SFX: Majic12 show, Magic circle, Copper, GBU, Party91
if( vga.crtc.maximum_scan_line&0x80) vga.draw.address_line_total*=2;
if ( vga.crtc.maximum_scan_line&0x80) vga.draw.address_line_total*=2;
vga.draw.double_scan=false;
}
else if (IS_VGA_ARCH) vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0;
@ -1155,10 +1145,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
// on blanking wrap to 0, the first line is not blanked
// this is used by the S3 BIOS and other S3 drivers in some SVGA modes
if((vbend&0x7f)==1) vblank_skip = 0;
if ((vbend&0x7f)==1) vblank_skip = 0;
// it might also cut some lines off the bottom
if(vbstart < vdend) {
if (vbstart < vdend) {
vdend = vbstart;
}
LOG(LOG_VGA,LOG_WARN)("Blanking wrap to line %d", vblank_skip);
@ -1167,7 +1157,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
vblank_skip = vbend;
LOG(LOG_VGA,LOG_WARN)("Upper %d lines of the screen blanked", vblank_skip);
} else if (vbstart < vdend) {
if(vbend < vdend) {
if (vbend < vdend) {
// the game wants a black bar somewhere on the screen
LOG(LOG_VGA,LOG_WARN)("Unsupported blanking: line %d-%d",vbstart,vbend);
} else {
@ -1266,7 +1256,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
case M_LIN8:
if (vga.crtc.mode_control & 0x8)
width >>=1;
else if(svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) {
else if (svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) {
doublewidth=true;
width >>=1;
}
@ -1300,6 +1290,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
vga.draw.blocks = width;
width<<=3;
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
// This would also be required for EGA in Spacepigs Megademo
bpp=16;
VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line;
} else VGA_DrawLine=VGA_Draw_Linear_Line;
@ -1329,17 +1320,22 @@ void VGA_SetupDrawing(Bitu /*val*/) {
aspect_ratio=1.0;
vga.draw.blocks=width;
doublewidth=(vga.seq.clocking_mode & 0x8) > 0;
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None) && !(vga.seq.clocking_mode&0x01)) {
width*=9; /* 9 bit wide text font */
VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line_9;
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
// vgaonly: allow 9-pixel wide fonts
if (vga.seq.clocking_mode&0x01) {
vga.draw.char9dot = false;
width*=8;
} else {
vga.draw.char9dot = true;
width*=9;
}
VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line;
bpp=16;
// VGA_DrawLine=VGA_TEXT_Draw_Line_9;
} else {
width<<=3; /* 8 bit wide text font */
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line;
bpp=16;
} else VGA_DrawLine=VGA_TEXT_Draw_Line;
// not vgaonly: force 8-pixel wide fonts
width*=8; // 8 bit wide text font
vga.draw.char9dot = false;
VGA_DrawLine=VGA_TEXT_Draw_Line;
}
break;
case M_HERC_GFX:
@ -1417,7 +1413,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
}
vga.draw.vblank_skip = vblank_skip;
if(!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) {
if (!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) {
//Only check for extra double height in vga modes
//(line multiplying by address_line_total)
if (!doubleheight && (vga.mode<M_TEXT) && !(vga.draw.address_line_total & 1)) {
@ -1442,8 +1438,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
}
// LOG_MSG("ht %d vt %d ratio %f", htotal, vtotal, aspect_ratio );
bool fps_changed = false;
// need to change the vertical timing?
if (fabs(vga.draw.delay.vtotal - 1000.0 / fps) > 0.0001) {
fps_changed = true;
vga.draw.delay.vtotal = 1000.0 / fps;
VGA_KillDrawing();
PIC_RemoveEvents(VGA_Other_VertInterrupt);
@ -1470,7 +1468,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
(vga.draw.doublewidth != doublewidth) ||
(vga.draw.doubleheight != doubleheight) ||
(fabs(aspect_ratio - vga.draw.aspect_ratio) > 0.0001) ||
(vga.draw.bpp != bpp)) {
(vga.draw.bpp != bpp) || fps_changed) {
VGA_KillDrawing();
@ -1494,6 +1492,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
void VGA_KillDrawing(void) {
PIC_RemoveEvents(VGA_DrawPart);
PIC_RemoveEvents(VGA_DrawSingleLine);
PIC_RemoveEvents(VGA_DrawEGASingleLine);
vga.draw.parts_left = 0;
vga.draw.lines_done = ~0;
RENDER_EndUpdate(true);

View File

@ -516,7 +516,12 @@ static void write_hercules(Bitu port,Bitu val,Bitu /*iolen*/) {
break;
}
case 0x3bf:
vga.herc.enable_bits=(Bit8u)val;
if ( vga.herc.enable_bits ^ val) {
vga.herc.enable_bits=val;
// Bit 1 enables the upper 32k of video memory,
// so update the handlers
VGA_SetupHandlers();
}
break;
}
}

View File

@ -869,7 +869,7 @@ public:
if (IS_TANDY_ARCH) {
/* reduce reported memory size for the Tandy (32k graphics memory
at the end of the conventional 640k) */
if (machine==MCH_TANDY) mem_writew(BIOS_MEMORY_SIZE,608);
if (machine==MCH_TANDY) mem_writew(BIOS_MEMORY_SIZE,624);
else mem_writew(BIOS_MEMORY_SIZE,640);
mem_writew(BIOS_TRUE_MEMORY_SIZE,640);
} else mem_writew(BIOS_MEMORY_SIZE,640);

View File

@ -138,8 +138,7 @@ static Bitu INT10_Handler(void) {
reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
break;
case 0x10: /* Palette functions */
if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x02))) break;
//TODO: subfunction 0x03 for ega
if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x03))) break;
switch (reg_al) {
case 0x00: /* SET SINGLE PALETTE REGISTER */
INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
@ -302,13 +301,8 @@ graphics_chars:
break;
}
if ((reg_bh<=7) || (svgaCard==SVGA_TsengET4K)) {
if (machine==MCH_EGA) {
reg_cx=0x0e;
reg_dl=0x18;
} else {
reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
}
reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
}
break;
default:

View File

@ -66,9 +66,21 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
IO_Write(base,0x9);
IO_Write(base+1,(IO_Read(base+1) & 0xe0)|(height-1));
//Vertical display end bios says, but should stay the same?
// Vertical display end bios says, but should stay the same?
// Not on EGA.
Bitu rows = CurMode->sheight/height;
if (machine==MCH_EGA) {
Bitu displayend = rows*height - 1;
IO_Write(base,0x12);
IO_Write(base+1,(Bit8u)(displayend & 0xff));
IO_Write(base,0x7);
// Note: IBM EGA registers can't be read
Bitu v_overflow = IO_Read(base+1) & ~0x2;
if (displayend & 0x100) v_overflow |= 0x2;
IO_Write(base+1,(Bit8u)v_overflow);
}
//Rows setting in bios segment
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(CurMode->sheight/height)-1);
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,rows-1);
real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit8u)height);
//TODO Reprogram cursor size?
}

View File

@ -96,25 +96,42 @@ void INT10_SetAllPaletteRegisters(PhysPt data) {
}
void INT10_ToggleBlinkingBit(Bit8u state) {
Bit8u value;
// state&=0x01;
if ((state>1) && (svgaCard==SVGA_S3Trio)) return;
ResetACTL();
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
value=IO_Read(VGAREG_ACTL_READ_DATA);
if (state<=1) {
value&=0xf7;
value|=state<<3;
}
if(IS_VGA_ARCH) {
Bit8u value;
// state&=0x01;
if ((state>1) && (svgaCard==SVGA_S3Trio)) return;
ResetACTL();
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
value=IO_Read(VGAREG_ACTL_READ_DATA);
if (state<=1) {
value&=0xf7;
value|=state<<3;
}
ResetACTL();
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
IO_Write(VGAREG_ACTL_WRITE_DATA,value);
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
ResetACTL();
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
IO_Write(VGAREG_ACTL_WRITE_DATA,value);
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
if (state<=1) {
Bit8u msrval=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR)&0xdf;
if (state<=1) {
Bit8u msrval=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR)&0xdf;
if (state) msrval|=0x20;
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,msrval);
}
} else { // EGA
// Usually it reads this from the mode list in ROM
if (CurMode->type!=M_TEXT) return;
Bit8u value = (CurMode->cwidth==9)? 0x4:0x0;
if (state) value |= 0x8;
ResetACTL();
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
IO_Write(VGAREG_ACTL_WRITE_DATA,value);
IO_Write(VGAREG_ACTL_ADDRESS,0x20);
Bit8u msrval=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR)& ~0x20;
if (state) msrval|=0x20;
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,msrval);
}

View File

@ -490,7 +490,7 @@ void SHELL_Init() {
MSG_Add("SHELL_CMD_PAUSE_HELP","Waits for 1 keystroke to continue.\n");
MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\n");
MSG_Add("SHELL_CMD_COPY_SUCCESS"," %d File(s) copied.\n");
MSG_Add("SHELL_CMD_SUBST_NO_REMOVE","Removing drive not supported. Doing nothing.\n");
MSG_Add("SHELL_CMD_SUBST_NO_REMOVE","Unable to remove, drive not in use.\n");
MSG_Add("SHELL_CMD_SUBST_FAILURE","SUBST failed. You either made an error in your commandline or the target drive is already used.\nIt's only possible to use SUBST on Local drives");
#ifdef HW_RVL

View File

@ -945,17 +945,22 @@ void DOS_Shell::CMD_SUBST (char * args) {
CommandLine command(0,args);
if (command.GetCount() != 2) throw 0 ;
command.FindCommand(2,arg);
if((arg=="/D" ) || (arg=="/d")) throw 1; //No removal (one day)
command.FindCommand(1,arg);
if( (arg.size()>1) && arg[1] !=':') throw(0);
temp_str[0]=(char)toupper(args[0]);
command.FindCommand(2,arg);
if((arg=="/D") || (arg=="/d")) {
if(!Drives[temp_str[0]-'A'] ) throw 1; //targetdrive not in use
strcat(mountstring,"-u ");
strcat(mountstring,temp_str);
this->ParseLine(mountstring);
return;
}
if(Drives[temp_str[0]-'A'] ) throw 0; //targetdrive in use
strcat(mountstring,temp_str);
strcat(mountstring," ");
command.FindCommand(2,arg);
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(const_cast<char*>(arg.c_str()),fulldir,&drive)) throw 0;