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. dnl Init.
AC_INIT(dosbox,0.74) AC_INIT(dosbox,SVN)
AC_PREREQ(2.50) AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(README) AC_CONFIG_SRCDIR(README)

View File

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

View File

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

View File

@ -352,11 +352,15 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
physAddress+=4; physAddress+=4;
} }
phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax
phys_writew(physAddress+0x01,(Bit16u)0x0eb4); // mov ah, 0x0e phys_writeb(physAddress+0x01,(Bit8u)0x53); // push bx
phys_writew(physAddress+0x03,(Bit16u)0x10cd); // int 10 phys_writew(physAddress+0x02,(Bit16u)0x0eb4); // mov ah, 0x0e
phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x04,(Bit8u)0xbb); // mov bx,
phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction phys_writew(physAddress+0x05,(Bit16u)0x0007); // 0x0007
return (use_cb?0x0b:0x07); 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: case CB_HOOKABLE:
phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near
phys_writeb(physAddress+0x01,(Bit8u)0x03); //offset 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) { 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); phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00);
} }
} }

View File

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

View File

@ -131,7 +131,7 @@ int CDROM_Interface_Image::AudioFile::getLength()
int CDROM_Interface_Image::refCount = 0; int CDROM_Interface_Image::refCount = 0;
CDROM_Interface_Image* CDROM_Interface_Image::images[26]; CDROM_Interface_Image* CDROM_Interface_Image::images[26];
CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = { 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) CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit)
@ -259,6 +259,12 @@ bool CDROM_Interface_Image::StopAudio(void)
return true; 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) bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{ {
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
@ -336,6 +342,16 @@ void CDROM_Interface_Image::CDAudioCallBack(Bitu len)
} }
} }
SDL_mutexV(player.mutex); 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) #if defined(WORDS_BIGENDIAN)
player.channel->AddSamples_s16_nonnative(len/4,(Bit16s *)player.buffer); player.channel->AddSamples_s16_nonnative(len/4,(Bit16s *)player.buffer);
#else #else

View File

@ -175,7 +175,7 @@ bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) {
CDROM_Interface_Ioctl::dxPlayer CDROM_Interface_Ioctl::player = { 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) { CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(cdioctl_cdatype ioctl_cda) {
pathname[0] = 0; pathname[0] = 0;
@ -462,6 +462,12 @@ bool CDROM_Interface_Ioctl::StopAudio(void) {
return bStat>0; 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 CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) {
BOOL bStat; BOOL bStat;
DWORD byteCount; DWORD byteCount;
@ -553,6 +559,16 @@ void CDROM_Interface_Ioctl::dx_CDAudioCallBack(Bitu len) {
} }
} }
SDL_mutexV(player.mutex); 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); player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer);
memmove(player.buffer, &player.buffer[len], player.bufLen - len); memmove(player.buffer, &player.buffer[len], player.bufLen - len);
player.bufLen -= len; player.bufLen -= len;

View File

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

View File

@ -203,6 +203,13 @@ bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) {
bool DOS_ChangeDir(char const * const dir) { bool DOS_ChangeDir(char const * const dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH]; 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 (!DOS_MakeName(dir,fulldir,&drive)) return false;
if (Drives[drive]->TestDir(fulldir)) { if (Drives[drive]->TestDir(fulldir)) {

View File

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

View File

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

View File

@ -67,7 +67,7 @@ DOS_Drive_Cache::DOS_Drive_Cache(void) {
srchNr = 0; srchNr = 0;
label[0] = 0; label[0] = 0;
nextFreeFindFirst = 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); SetDirSort(DIRALPHABETICAL);
updatelabel = true; updatelabel = true;
} }
@ -78,7 +78,7 @@ DOS_Drive_Cache::DOS_Drive_Cache(const char* path) {
srchNr = 0; srchNr = 0;
label[0] = 0; label[0] = 0;
nextFreeFindFirst = 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); SetDirSort(DIRALPHABETICAL);
SetBaseDir(path); SetBaseDir(path);
updatelabel = true; updatelabel = true;
@ -86,11 +86,11 @@ DOS_Drive_Cache::DOS_Drive_Cache(const char* path) {
DOS_Drive_Cache::~DOS_Drive_Cache(void) { DOS_Drive_Cache::~DOS_Drive_Cache(void) {
Clear(); 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) { void DOS_Drive_Cache::Clear(void) {
delete dirBase; dirBase = 0; DeleteFileInfo(dirBase); dirBase = 0;
nextFreeFindFirst = 0; nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) dirSearch[i] = 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; dirBase = new CFileInfo;
save_dir = 0; save_dir = 0;
srchNr = 0; srchNr = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) free[i] = true;
SetBaseDir(basePath); 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) { 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!"); LOG(LOG_FILES,LOG_NORMAL)("DIRCACHE: Too many open directories!");
dir->id=0;
return 0; return 0;
} }
@ -264,7 +271,7 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) {
// delete file objects... // delete file objects...
for(Bit32u i=0; i<dir->fileList.size(); i++) { for(Bit32u i=0; i<dir->fileList.size(); i++) {
if (dirSearch[srchNr]==dir->fileList[i]) dirSearch[srchNr] = 0; 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 // clear lists
dir->fileList.clear(); dir->fileList.clear();
@ -526,7 +533,10 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
strcpy(buffer,dirPath); strcpy(buffer,dirPath);
ReadDir(id,result); ReadDir(id,result);
strcpy(dirPath,buffer); 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); strcpy(buffer,dirPath);
ReadDir(id,result); ReadDir(id,result);
strcpy(dirPath,buffer); 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.. // Reset it..
close_directory(dirp); close_directory(dirp);
strcpy(dirPath,expandcopy); strcpy(dirPath,expandcopy);
free[id] = false;
return true; return true;
} }
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
}; };
return false; return false;
} }
@ -661,7 +677,10 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
// Try to open directory // Try to open directory
dir_information* dirp = open_directory(dirPath); dir_information* dirp = open_directory(dirPath);
if (!dirp) { if (!dirp) {
free[id] = true; if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
}
return false; return false;
} }
// Read complete directory // 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; 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; 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 this->nextFreeFindFirst = 1; //the next free one after this search
for(Bitu n=0; n<MAX_OPENDIRS;n++) { for(Bitu n=0; n<MAX_OPENDIRS;n++) {
// Clear and reuse slot // Clear and reuse slot
delete dirFindFirst[n]; DeleteFileInfo(dirFindFirst[n]);
dirFindFirst[n]=0; dirFindFirst[n]=0;
} }
@ -767,8 +789,25 @@ bool DOS_Drive_Cache::FindNext(Bit16u id, char* &result) {
} }
if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) { if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) {
// free slot // free slot
delete dirFindFirst[id]; dirFindFirst[id] = 0; DeleteFileInfo(dirFindFirst[id]); dirFindFirst[id] = 0;
return false; return false;
} }
return true; 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; else findAttr |= DOS_ATTR_ARCHIVE;
if (IS_HIDDEN(de.fileFlags)) findAttr |= DOS_ATTR_HIDDEN; 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))) { && !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) {
/* file is okay, setup everything to be copied in DTA Block */ /* 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 // look for the current path element
int dirIterator = GetDirIterator(de); int dirIterator = GetDirIterator(de);
while (!found && GetNextDirEntry(dirIterator, 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; found = true;
} }
} }

View File

@ -41,6 +41,7 @@ public:
Bit16u GetInformation(void); Bit16u GetInformation(void);
bool UpdateDateTimeFromHost(void); bool UpdateDateTimeFromHost(void);
void FlagReadOnlyMedium(void); void FlagReadOnlyMedium(void);
void Flush(void);
private: private:
FILE * fhandle; FILE * fhandle;
bool read_only_medium; bool read_only_medium;
@ -95,6 +96,22 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
dirCache.ExpandName(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); FILE * hand=fopen(newname,type);
// Bit32u err=errno; // Bit32u err=errno;
if (!hand) { if (!hand) {
@ -541,6 +558,13 @@ bool localFile::UpdateDateTimeFromHost(void) {
return true; return true;
} }
void localFile::Flush(void) {
if (last_action==WRITE) {
fseek(fhandle,ftell(fhandle),SEEK_SET);
last_action=NONE;
}
}
// ******************************************** // ********************************************
// CDROM DRIVE // CDROM DRIVE

View File

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

View File

@ -504,6 +504,8 @@ static void GenerateDMASound(Bitu size) {
sb.dma.left-=read; sb.dma.left-=read;
if (!sb.dma.left) { if (!sb.dma.left) {
PIC_RemoveEvents(END_DMA_Event); 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) { if (!sb.dma.autoinit) {
LOG(LOG_SB,LOG_NORMAL)("Single cycle transfer ended"); LOG(LOG_SB,LOG_NORMAL)("Single cycle transfer ended");
sb.mode=MODE_NONE; sb.mode=MODE_NONE;
@ -515,8 +517,6 @@ static void GenerateDMASound(Bitu size) {
sb.mode=MODE_NONE; 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; return ret;
case 0x82: /* IRQ Status */ case 0x82: /* IRQ Status */
return (sb.irq.pending_8bit ? 0x1 : 0) | 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: default:
if ( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ 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 */ (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. 10h and 14h.
*/ */
break; 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 (!IS_VGA_ARCH) val&=0x1f; // not really correct, but should do it
if ((attr(mode_control) ^ val) & 0x80) { Bitu difference = attr(mode_control)^val;
attr(mode_control)^=0x80; attr(mode_control)=(Bit8u)val;
for (Bit8u i=0;i<0x10;i++) {
if (difference & 0x80) {
for (Bit8u i=0;i<0x10;i++)
VGA_ATTR_SetPalette(i,vga.attr.palette[i]); VGA_ATTR_SetPalette(i,vga.attr.palette[i]);
} }
} if (difference & 0x08)
if ((attr(mode_control) ^ val) & 0x08) {
VGA_SetBlinking(val & 0x8); 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();
}
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;
}
}
/* /*
0 Graphics mode if set, Alphanumeric mode else. 0 Graphics mode if set, Alphanumeric mode else.
1 Monochrome mode if set, color mode else. 1 Monochrome mode if set, color mode else.
@ -113,6 +120,7 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
used. used.
*/ */
break; break;
}
case 0x11: /* Overscan Color Register */ case 0x11: /* Overscan Color Register */
attr(overscan_color)=(Bit8u)val; attr(overscan_color)=(Bit8u)val;
/* 0-5 Color of screen border. Color is defined as in the palette registers. */ /* 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; attr(horizontal_pel_panning)=val & 0xF;
switch (vga.mode) { switch (vga.mode) {
case M_TEXT: case M_TEXT:
if ((val==0x7) && (svgaCard==SVGA_None)) vga.config.pel_panning=7; if (val > 7)
if (val>0x7) vga.config.pel_panning=0; vga.config.pel_panning=0;
else vga.config.pel_panning=(Bit8u)(val+1); 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; break;
case M_VGA: case M_VGA:
case M_LIN8: case M_LIN8:
@ -146,6 +157,9 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
default: default:
vga.config.pel_panning=(val & 0x7); 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 0-3 Indicates number of pixels to shift the display left
Value 9bit textmode 256color mode Other modes Value 9bit textmode 256color mode Other modes

View File

@ -197,14 +197,6 @@ static Bit8u * VGA_Draw_Xlat16_Linear_Line(Bitu vidstart, Bitu /*line*/) {
temps[i]=vga.dac.xlat16[ret[i]]; temps[i]=vga.dac.xlat16[ret[i]];
} }
return TempLine; 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 //Test version, might as well keep it
@ -446,167 +438,121 @@ static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) {
skip_cursor: skip_cursor:
return TempLine; 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) { // combined 8/9-dot wide text mode 8bpp line drawing function
Bits font_addr; static Bit8u* VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) {
Bit8u * draw=(Bit8u *)TempLine; // keep it aligned:
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; Bit8u* draw = ((Bit8u*)TempLine) + 16 - vga.draw.panning;
Bit8u pel_pan=(Bit8u)vga.draw.panning; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart); // pointer to chars+attribs
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; Bitu blocks = vga.draw.blocks;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart); if (vga.draw.panning) blocks++; // if the text is panned part of an
Bit8u chr=vidmem[0]; // additional character becomes visible
Bit8u col=vidmem[1]; while (blocks--) { // for each character in the line
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan; Bitu chr = *vidmem++;
if (underline && ((col&0x07) == 0x01)) font=0xff; Bitu attr = *vidmem++;
Bit8u fg=col&0xf; // the font pattern
Bit8u bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); Bitu font = vga.draw.font_tables[(attr >> 3)&1][(chr<<5)+line];
Bitu draw_blocks=vga.draw.blocks;
draw_blocks++; Bitu background = attr >> 4;
for (Bitu cx=1;cx<draw_blocks;cx++) { // if blinking is enabled bit7 is not mapped to attributes
if (pel_pan) { if (vga.draw.blinking) background &= ~0x8;
chr=vidmem[cx*2]; // choose foreground color if blinking not set for this cell or blink on
col=vidmem[cx*2+1]; Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
if (underline && ((col&0x07) == 0x01)) font|=0xff>>(8-pel_pan); (attr&0xf):background;
else font|=vga.draw.font_tables[(col >> 3)&1][chr*32+line]>>(8-pel_pan); // underline: all foreground [freevga: 0x77, previous 0x7]
fg=col&0xf; if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); (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 { } else {
chr=vidmem[(cx-1)*2]; for (Bitu n = 0; n < 8; n++) {
col=vidmem[(cx-1)*2+1]; *draw++ = (font&0x80)? foreground:background;
if (underline && ((col&0x07) == 0x01)) font=0xff; font <<= 1;
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;
} }
} }
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;
} }
skip_cursor: // draw the text mode cursor if needed
return TempLine; 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;
}
}
}
return TempLine+16;
} }
*/ */
// 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];
static Bit8u * VGA_TEXT_Xlat16_Draw_Line_9(Bitu vidstart, Bitu line) { Bitu background = attr >> 4;
Bits font_addr; // if blinking is enabled bit7 is not mapped to attributes
Bit16u * draw=(Bit16u *)TempLine; if (vga.draw.blinking) background &= ~0x8;
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; // choose foreground color if blinking not set for this cell or blink on
Bit8u pel_pan=(Bit8u)vga.draw.panning; Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; (attr&0xf):background;
const Bit8u* vidmem = VGA_Text_Memwrap(vidstart); // underline: all foreground [freevga: 0x77, previous 0x7]
Bit8u chr=vidmem[0]; if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
Bit8u col=vidmem[1]; (vga.crtc.underline_location&0x1f)==line))
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan; background = foreground;
if (underline && ((col&0x07) == 0x01)) font=0xff; if (vga.draw.char9dot) {
Bit8u fg=col&0xf; font <<=1; // 9 pixels
Bit8u bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); // extend to the 9th pixel if needed
Bitu draw_blocks=vga.draw.blocks; if ((font&0x2) && (vga.attr.mode_control&0x04) &&
draw_blocks++; (chr>=0xc0) && (chr<=0xdf)) font |= 1;
for (Bitu cx=1;cx<draw_blocks;cx++) { for (Bitu n = 0; n < 9; n++) {
if (pel_pan) { *draw++ = vga.dac.xlat16[(font&0x100)? foreground:background];
chr=vidmem[cx*2]; font <<= 1;
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);
} else { } else {
chr=vidmem[(cx-1)*2]; for (Bitu n = 0; n < 8; n++) {
col=vidmem[(cx-1)*2+1]; *draw++ = vga.dac.xlat16[(font&0x80)? foreground:background];
if (underline && ((col&0x07) == 0x01)) font=0xff; font <<= 1;
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;
} }
} }
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];
} }
//if(underline && ((col&0x07) == 0x01)) // draw the text mode cursor if needed
// *draw = vga.dac.xlat16[fg]; 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];
} }
skip_cursor: }
return TempLine; }
return TempLine+32;
} }
#ifdef VGA_KEEP_CHANGES #ifdef VGA_KEEP_CHANGES
@ -628,14 +574,17 @@ static INLINE void VGA_ChangesEnd(void ) {
static void VGA_ProcessSplit() { static void VGA_ProcessSplit() {
// On the EGA the address is always reset to 0. if (vga.attr.mode_control&0x20) {
if ((vga.attr.mode_control&0x20) || (machine==MCH_EGA)) {
vga.draw.address=0; 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 { } else {
// In text mode only the characters are shifted by panning, not the address; // In text mode only the characters are shifted by panning, not the address;
// this is done in the text line draw function. // this is done in the text line draw function.
vga.draw.address = vga.draw.byte_panning_shift*vga.draw.bytes_skip; 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; vga.draw.address_line=0;
} }
@ -662,6 +611,29 @@ static void VGA_DrawSingleLine(Bitu /*blah*/) {
} else RENDER_EndUpdate(false); } 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) { static void VGA_DrawPart(Bitu lines) {
while (lines--) { while (lines--) {
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
@ -771,7 +743,6 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
VGA_DisplayStartLatch(0); VGA_DisplayStartLatch(0);
break; break;
case MCH_VGA: case MCH_VGA:
case MCH_EGA:
PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrstart); PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrstart);
PIC_AddEvent(VGA_PanningLatch, (float)vga.draw.delay.vrend); PIC_AddEvent(VGA_PanningLatch, (float)vga.draw.delay.vrend);
// EGA: 82c435 datasheet: interrupt happens at display end // 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 // 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)); PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005));
break; 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: default:
E_Exit("This new machine needs implementation in VGA_VerticalTimer too."); E_Exit("This new machine needs implementation in VGA_VerticalTimer too.");
break; break;
@ -798,7 +773,11 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
vga.draw.address = vga.config.real_start; vga.draw.address = vga.config.real_start;
vga.draw.byte_panning_shift = 0; vga.draw.byte_panning_shift = 0;
// go figure... // 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); // if (machine==MCH_EGA) vga.draw.split_line = ((((vga.config.line_compare&0x5ff)+1)*2-1)/vga.draw.lines_scaled);
#ifdef VGA_KEEP_CHANGES #ifdef VGA_KEEP_CHANGES
bool startaddr_changed=false; bool startaddr_changed=false;
@ -811,7 +790,7 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
vga.draw.byte_panning_shift = 8; vga.draw.byte_panning_shift = 8;
vga.draw.address += vga.draw.bytes_skip; vga.draw.address += vga.draw.bytes_skip;
vga.draw.address *= vga.draw.byte_panning_shift; 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 #ifdef VGA_KEEP_CHANGES
startaddr_changed=true; startaddr_changed=true;
#endif #endif
@ -851,6 +830,10 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
/* check for blinking and blinking change delay */ /* check for blinking and blinking change delay */
FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ? FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ?
0 : 0xffffffff; 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; break;
case M_HERC_GFX: case M_HERC_GFX:
break; 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); PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts + draw_skip,vga.draw.parts_lines);
break; break;
case LINE: case LINE:
case EGALINE:
if (GCC_UNLIKELY(vga.draw.lines_done < vga.draw.lines_total)) { if (GCC_UNLIKELY(vga.draw.lines_done < vga.draw.lines_total)) {
LOG(LOG_VGAMISC,LOG_NORMAL)( "Lines left: %d", LOG(LOG_VGAMISC,LOG_NORMAL)( "Lines left: %d",
vga.draw.lines_total-vga.draw.lines_done); 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); RENDER_EndUpdate(true);
} }
vga.draw.lines_done = 0; 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; break;
//case EGALINE:
} }
} }
@ -982,6 +968,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
case MCH_PCJR: case MCH_PCJR:
vga.draw.mode = LINE; vga.draw.mode = LINE;
break; break;
case MCH_EGA:
// Note: The Paradise SVGA uses the same panning mechanism as EGA
vga.draw.mode = EGALINE;
break;
case MCH_VGA: case MCH_VGA:
if (svgaCard==SVGA_None) { if (svgaCard==SVGA_None) {
vga.draw.mode = LINE; vga.draw.mode = LINE;
@ -1300,6 +1290,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
vga.draw.blocks = width; vga.draw.blocks = width;
width<<=3; width<<=3;
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) { if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
// This would also be required for EGA in Spacepigs Megademo
bpp=16; bpp=16;
VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line; VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line;
} else VGA_DrawLine=VGA_Draw_Linear_Line; } else VGA_DrawLine=VGA_Draw_Linear_Line;
@ -1329,17 +1320,22 @@ void VGA_SetupDrawing(Bitu /*val*/) {
aspect_ratio=1.0; aspect_ratio=1.0;
vga.draw.blocks=width; vga.draw.blocks=width;
doublewidth=(vga.seq.clocking_mode & 0x8) > 0; 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;
bpp=16;
// VGA_DrawLine=VGA_TEXT_Draw_Line_9;
} else {
width<<=3; /* 8 bit wide text font */
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) { 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; VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line;
bpp=16; bpp=16;
} else VGA_DrawLine=VGA_TEXT_Draw_Line; } else {
// 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; break;
case M_HERC_GFX: case M_HERC_GFX:
@ -1442,8 +1438,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
} }
// LOG_MSG("ht %d vt %d ratio %f", htotal, vtotal, aspect_ratio ); // LOG_MSG("ht %d vt %d ratio %f", htotal, vtotal, aspect_ratio );
bool fps_changed = false;
// need to change the vertical timing? // need to change the vertical timing?
if (fabs(vga.draw.delay.vtotal - 1000.0 / fps) > 0.0001) { if (fabs(vga.draw.delay.vtotal - 1000.0 / fps) > 0.0001) {
fps_changed = true;
vga.draw.delay.vtotal = 1000.0 / fps; vga.draw.delay.vtotal = 1000.0 / fps;
VGA_KillDrawing(); VGA_KillDrawing();
PIC_RemoveEvents(VGA_Other_VertInterrupt); PIC_RemoveEvents(VGA_Other_VertInterrupt);
@ -1470,7 +1468,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
(vga.draw.doublewidth != doublewidth) || (vga.draw.doublewidth != doublewidth) ||
(vga.draw.doubleheight != doubleheight) || (vga.draw.doubleheight != doubleheight) ||
(fabs(aspect_ratio - vga.draw.aspect_ratio) > 0.0001) || (fabs(aspect_ratio - vga.draw.aspect_ratio) > 0.0001) ||
(vga.draw.bpp != bpp)) { (vga.draw.bpp != bpp) || fps_changed) {
VGA_KillDrawing(); VGA_KillDrawing();
@ -1494,6 +1492,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
void VGA_KillDrawing(void) { void VGA_KillDrawing(void) {
PIC_RemoveEvents(VGA_DrawPart); PIC_RemoveEvents(VGA_DrawPart);
PIC_RemoveEvents(VGA_DrawSingleLine); PIC_RemoveEvents(VGA_DrawSingleLine);
PIC_RemoveEvents(VGA_DrawEGASingleLine);
vga.draw.parts_left = 0; vga.draw.parts_left = 0;
vga.draw.lines_done = ~0; vga.draw.lines_done = ~0;
RENDER_EndUpdate(true); RENDER_EndUpdate(true);

View File

@ -516,7 +516,12 @@ static void write_hercules(Bitu port,Bitu val,Bitu /*iolen*/) {
break; break;
} }
case 0x3bf: 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; break;
} }
} }

View File

@ -869,7 +869,7 @@ public:
if (IS_TANDY_ARCH) { if (IS_TANDY_ARCH) {
/* reduce reported memory size for the Tandy (32k graphics memory /* reduce reported memory size for the Tandy (32k graphics memory
at the end of the conventional 640k) */ 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); else mem_writew(BIOS_MEMORY_SIZE,640);
mem_writew(BIOS_TRUE_MEMORY_SIZE,640); mem_writew(BIOS_TRUE_MEMORY_SIZE,640);
} else mem_writew(BIOS_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); reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
break; break;
case 0x10: /* Palette functions */ case 0x10: /* Palette functions */
if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x02))) break; if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x03))) break;
//TODO: subfunction 0x03 for ega
switch (reg_al) { switch (reg_al) {
case 0x00: /* SET SINGLE PALETTE REGISTER */ case 0x00: /* SET SINGLE PALETTE REGISTER */
INT10_SetSinglePaletteRegister(reg_bl,reg_bh); INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
@ -302,14 +301,9 @@ graphics_chars:
break; break;
} }
if ((reg_bh<=7) || (svgaCard==SVGA_TsengET4K)) { 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_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
} }
}
break; break;
default: default:
LOG(LOG_INT10,LOG_ERROR)("Function 11:Unsupported character generator call %2X",reg_al); LOG(LOG_INT10,LOG_ERROR)("Function 11:Unsupported character generator call %2X",reg_al);

View File

@ -67,8 +67,20 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
IO_Write(base,0x9); IO_Write(base,0x9);
IO_Write(base+1,(IO_Read(base+1) & 0xe0)|(height-1)); 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 //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); real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit8u)height);
//TODO Reprogram cursor size? //TODO Reprogram cursor size?
} }

View File

@ -96,6 +96,7 @@ void INT10_SetAllPaletteRegisters(PhysPt data) {
} }
void INT10_ToggleBlinkingBit(Bit8u state) { void INT10_ToggleBlinkingBit(Bit8u state) {
if(IS_VGA_ARCH) {
Bit8u value; Bit8u value;
// state&=0x01; // state&=0x01;
if ((state>1) && (svgaCard==SVGA_S3Trio)) return; if ((state>1) && (svgaCard==SVGA_S3Trio)) return;
@ -118,6 +119,22 @@ void INT10_ToggleBlinkingBit(Bit8u state) {
if (state) msrval|=0x20; if (state) msrval|=0x20;
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,msrval); 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);
}
} }
void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) { void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) {

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_PAUSE_HELP","Waits for 1 keystroke to continue.\n");
MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\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_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"); 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 #ifdef HW_RVL

View File

@ -945,17 +945,22 @@ void DOS_Shell::CMD_SUBST (char * args) {
CommandLine command(0,args); CommandLine command(0,args);
if (command.GetCount() != 2) throw 0 ; 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); command.FindCommand(1,arg);
if( (arg.size()>1) && arg[1] !=':') throw(0); if( (arg.size()>1) && arg[1] !=':') throw(0);
temp_str[0]=(char)toupper(args[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 if(Drives[temp_str[0]-'A'] ) throw 0; //targetdrive in use
strcat(mountstring,temp_str); strcat(mountstring,temp_str);
strcat(mountstring," "); strcat(mountstring," ");
command.FindCommand(2,arg);
Bit8u drive;char fulldir[DOS_PATHLENGTH]; Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(const_cast<char*>(arg.c_str()),fulldir,&drive)) throw 0; if (!DOS_MakeName(const_cast<char*>(arg.c_str()),fulldir,&drive)) throw 0;