diff --git a/configure.in b/configure.in index 10a097bc..fa8be44d 100644 --- a/configure.in +++ b/configure.in @@ -177,6 +177,16 @@ else AC_MSG_RESULT(no) fi +AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support]) +AC_CHECK_HEADER(SDL/SDL_sound.h,have_SDL_sound_h=yes,) +AC_CHECK_LIB(SDL_sound, Sound_Init, have_SDL_sound_lib=yes,,) +if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_lib = xyes ; then + LIBS="$LIBS -lSDL_sound" + AC_DEFINE(C_SDL_SOUND,1) +else + AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled]) +fi + dnl Some host detection and actions for them case "$target" in *-*-cygwin* | *-*-mingw32*) diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 3659aba3..4d206c7b 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -5,5 +5,5 @@ EXTRA_DIST = scsidefs.h wnaspi32.h libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \ - dev_con.h dos_mscdex.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp + drive_iso.cpp dev_con.h dos_mscdex.cpp \ + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index 77da894d..ecad2179 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -21,6 +21,7 @@ // SDL CDROM // ****************************************************** +#include #include "SDL.h" #include "support.h" #include "cdrom.h" @@ -175,8 +176,13 @@ int CDROM_GetMountType(char* path, int forceCD) cdName = SDL_CDName(i); if (strcmp(buffer,cdName)==0) return 0; }; - // TODO: Detect ISO - return 2; + + // Detect ISO + struct stat file_stat; + stat(path, &file_stat); + if (S_ISREG(file_stat.st_mode)) return 1; + + return 2; }; // ****************************************************** diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h index fe710f0c..bd81474d 100644 --- a/src/dos/cdrom.h +++ b/src/dos/cdrom.h @@ -5,10 +5,17 @@ #define MAX_ASPI_CDROM 5 #include +#include +#include #include "dosbox.h" #include "mem.h" +#include "mixer.h" #include "SDL.h" +#include "SDL_thread.h" +#if defined(C_SDL_SOUND) +#include "SDL_sound.h" +#endif #define RAW_SECTOR_SIZE 2352 #define COOKED_SECTOR_SIZE 2048 @@ -95,6 +102,106 @@ public: bool LoadUnloadMedia (bool unload) { return true; }; }; +class CDROM_Interface_Image : public CDROM_Interface +{ +private: + class TrackFile { + public: + virtual bool read(Bit8u *buffer, int seek, int count) = 0; + virtual int getLength() = 0; + }; + + class BinaryFile : public TrackFile { + public: + BinaryFile(const char *filename, bool &error); + ~BinaryFile(); + bool read(Bit8u *buffer, int seek, int count); + int getLength(); + private: + BinaryFile(); + std::ifstream *file; + }; + + #if defined(C_SDL_SOUND) + class AudioFile : public TrackFile { + public: + AudioFile(const char *filename, bool &error); + ~AudioFile(); + bool read(Bit8u *buffer, int seek, int count); + int getLength(); + private: + AudioFile(); + Sound_Sample *sample; + int lastCount; + int lastSeek; + }; + #endif + + struct Track { + int number; + int attr; + int start; + int length; + int skip; + int sectorSize; + bool mode2; + TrackFile *file; + }; + +public: + CDROM_Interface_Image (Bit8u subUnit); + virtual ~CDROM_Interface_Image (void); + void InitNewMedia (void); + bool SetDevice (char* path, int forceCD); + bool GetUPC (unsigned char& attr, char* upc); + bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); + bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); + bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); + bool GetAudioStatus (bool& playing, bool& pause); + bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); + bool PlayAudioSector (unsigned long start,unsigned long len); + bool PauseAudio (bool resume); + bool StopAudio (void); + 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); + +static CDROM_Interface_Image* images[26]; + +private: + // player +static void CDAudioCallBack(Bit8u *stream, Bit32u len); + int GetTrack(int sector); + +static struct imagePlayer { + CDROM_Interface_Image *cd; + MIXER_Channel *channel; + SDL_mutex *mutex; + Bit8u buffer[8192]; + int bufLen; + int currFrame; + int targetFrame; + bool isPlaying; + bool isPaused; + } player; + + void ClearTracks(); + bool LoadIsoFile(char *filename); + bool CanReadPVD(TrackFile *file, int sectorSize, bool mode2); + // cue sheet processing + bool LoadCueSheet(char *cuefile); + bool GetRealFileName(std::string& filename, std::string& pathname); + bool GetCueKeyword(std::string &keyword, std::istream &in); + bool GetCueFrame(int &frames, std::istream &in); + bool GetCueString(std::string &str, std::istream &in); + bool AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap); + +static int refCount; + std::vector tracks; + std::string mcn; + Bit8u subUnit; +}; + #if defined (WIN32) /* Win 32 */ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp new file mode 100644 index 00000000..ce2a6f0a --- /dev/null +++ b/src/dos/cdrom_image.cpp @@ -0,0 +1,653 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: cdrom_image.cpp,v 1.1 2004-08-13 19:43:02 qbix79 Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cdrom.h" +#include "drives.h" + +#if not defined(WIN32) +#include +#endif + +using namespace std; + +#define MAX_LINE_LENGTH 512 +#define MAX_FILENAME_LENGTH 256 + +CDROM_Interface_Image::BinaryFile::BinaryFile(const char *filename, bool &error) +{ + file = new ifstream(filename, ios::in | ios::binary); + error = (file == NULL) || (file->fail()); +} + +CDROM_Interface_Image::BinaryFile::~BinaryFile() +{ + delete file; +} + +bool CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, int seek, int count) +{ + file->seekg(seek, ios::beg); + file->read((char*)buffer, count); + return !(file->fail()); +} + +int CDROM_Interface_Image::BinaryFile::getLength() +{ + file->seekg(0, ios::end); + int length = file->tellg(); + if (file->fail()) return -1; + return length; +} + +#if defined(C_SDL_SOUND) +CDROM_Interface_Image::AudioFile::AudioFile(const char *filename, bool &error) +{ + Sound_AudioInfo desired = {AUDIO_S16, 2, 44100}; + sample = Sound_NewSampleFromFile(filename, &desired, RAW_SECTOR_SIZE); + lastCount = RAW_SECTOR_SIZE; + lastSeek = 0; + error = (sample == NULL); +} + +CDROM_Interface_Image::AudioFile::~AudioFile() +{ + Sound_FreeSample(sample); +} + +bool CDROM_Interface_Image::AudioFile::read(Bit8u *buffer, int seek, int count) +{ + if (lastCount != count) { + int success = Sound_SetBufferSize(sample, count); + if (!success) return false; + } + if (lastSeek != (seek - count)) { + int success = Sound_Seek(sample, (int)((double)(seek) / 176.4f)); + if (!success) return false; + } + lastSeek = seek; + int bytes = Sound_Decode(sample); + if (bytes < count) { + memcpy(buffer, sample->buffer, bytes); + memset(buffer + bytes, 0, count - bytes); + } else { + memcpy(buffer, sample->buffer, count); + } + + return !(sample->flags & SOUND_SAMPLEFLAG_ERROR); +} + +int CDROM_Interface_Image::AudioFile::getLength() +{ + int time = 1; + int shift = 0; + if (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK)) return -1; + + while (true) { + int success = Sound_Seek(sample, (unsigned int)(shift + time)); + if (!success) { + if (time == 1) return lround((double)shift * 176.4f); + shift += time >> 1; + time = 1; + } else { + if (time > ((numeric_limits::max() - shift) / 2)) return -1; + time = time << 1; + } + } +} +#endif + +// initialize static members +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, 0, false, false }; + + +CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit) +{ + images[subUnit] = this; + if (refCount == 0) { +#if defined(C_SDL_SOUND) + Sound_Init(); +#endif + player.mutex = SDL_CreateMutex(); + if (!player.channel) { + player.channel = MIXER_AddChannel(&CDAudioCallBack, 44100, "CDAUDIO"); + MIXER_SetMode(player.channel, MIXER_16STEREO); + } + MIXER_Enable(player.channel, true); + } + refCount++; +} + +CDROM_Interface_Image::~CDROM_Interface_Image() +{ + refCount--; + if (player.cd == this) player.cd = NULL; + ClearTracks(); + if (refCount == 0) { +#if defined(C_SDL_SOUND) + Sound_Quit(); +#endif + SDL_DestroyMutex(player.mutex); + MIXER_Enable(player.channel, false); + } +} + +void CDROM_Interface_Image::InitNewMedia() +{ +} + +bool CDROM_Interface_Image::SetDevice(char* path, int forceCD) +{ + if (LoadCueSheet(path)) return true; + if (LoadIsoFile(path)) return true; + + // print error message on dosbox console + char buf[MAX_LINE_LENGTH]; + snprintf(buf, MAX_LINE_LENGTH, "Could not load image file: %s\n", path); + Bit16u size = strlen(buf); + DOS_WriteFile(STDOUT, (Bit8u*)buf, &size); + return false; +} + +bool CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc) +{ + attr = 0; + strcpy(upc, this->mcn.c_str()); + return true; +} + +bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) +{ + stTrack = 1; + end = tracks.size() - 1; + FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr); + return true; +} + +bool CDROM_Interface_Image::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) +{ + if (track < 1 || track > tracks.size()) return false; + FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); + attr = tracks[track - 1].attr; + return true; +} + +bool CDROM_Interface_Image::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) +{ + track = GetTrack(player.currFrame); + if (track < 1) return false; + attr = tracks[track - 1].attr; + index = 1; + FRAMES_TO_MSF(player.currFrame + 150, &absPos.min, &absPos.sec, &absPos.fr); + FRAMES_TO_MSF(player.currFrame - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr); + return true; +} + +bool CDROM_Interface_Image::GetAudioStatus(bool& playing, bool& pause) +{ + playing = player.isPlaying; + pause = player.isPaused; + return true; +} + +bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + mediaPresent = true; + mediaChanged = false; + trayOpen = false; + return true; +} + +bool CDROM_Interface_Image::PlayAudioSector(unsigned long start,unsigned long len) +{ + SDL_mutexP(player.mutex); + player.cd = this; + player.currFrame = start; + player.targetFrame = start + len; + player.isPlaying = true; + player.isPaused = false; + SDL_mutexV(player.mutex); + return true; +} + +bool CDROM_Interface_Image::PauseAudio(bool resume) +{ + player.isPaused = !resume; + return true; +} + +bool CDROM_Interface_Image::StopAudio(void) +{ + player.isPlaying = false; + player.isPaused = false; + return true; +} + +bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) +{ + int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; + Bitu buflen = num * sectorSize; + Bit8u* buf = new Bit8u[buflen]; + + bool success; + for(int i = 0; i < num; i++) { + success = ReadSector(&buf[i * sectorSize], raw, sector); + if (!success) break; + } + + MEM_BlockWrite(buffer, buf, buflen); + delete[] buf; + + return success; +} + +bool CDROM_Interface_Image::LoadUnloadMedia(bool unload) +{ + return true; +} + +int CDROM_Interface_Image::GetTrack(int sector) +{ + vector::iterator i = tracks.begin(); + vector::iterator end = tracks.end() - 1; + + while(i != end) { + Track &curr = *i; + Track &next = *(i + 1); + if (curr.start <= sector && sector < next.start) return curr.number; + i++; + } + return -1; +} + +bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) +{ + int track = GetTrack(sector) - 1; + if (track < 0) return false; + + int seek = tracks[track].skip + (sector - tracks[track].start) * tracks[track].sectorSize; + int length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); + if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false; + if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16; + if (tracks[track].mode2 && !raw) seek += 24; + + return tracks[track].file->read(buffer, seek, length); +} + +void CDROM_Interface_Image::CDAudioCallBack(Bit8u *stream, Bit32u len) +{ + len *= 4; // 16 bit, stereo + if (!len) return; + if (!player.isPlaying || player.isPaused) { + memset(stream, 0, len); + return; + } + + SDL_mutexP(player.mutex); + while (player.bufLen < len) { + bool success; + if (player.targetFrame > player.currFrame) + success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame); + else success = false; + + if (success) { + player.currFrame++; + player.bufLen += RAW_SECTOR_SIZE; + } else { + memset(&player.buffer[player.bufLen], 0, len - player.bufLen); + player.bufLen = len; + player.isPlaying = false; + } + } + SDL_mutexV(player.mutex); + + memcpy(stream, player.buffer, len); + memmove(player.buffer, &player.buffer[len], player.bufLen - len); + player.bufLen -= len; +} + +bool CDROM_Interface_Image::LoadIsoFile(char* filename) +{ + tracks.clear(); + + // data track + Track track = {0, 0, 0, 0, 0, 0, false, NULL}; + bool error; + track.file = new BinaryFile(filename, error); + if (error) { + delete track.file; + return false; + } + track.number = 1; + track.attr = 4; + + // try to detect iso type + if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) { + track.sectorSize = COOKED_SECTOR_SIZE; + track.mode2 = false; + } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) { + track.sectorSize = RAW_SECTOR_SIZE; + track.mode2 = false; + } else if (CanReadPVD(track.file, 2336, true)) { + track.sectorSize = 2336; + track.mode2 = true; + } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { + track.sectorSize = RAW_SECTOR_SIZE; + track.mode2 = true; + } else return false; + + track.length = track.file->getLength() / track.sectorSize; + tracks.push_back(track); + + // leadout track + track.number = 2; + track.attr = 0; + track.start = track.length; + track.length = 0; + track.file = NULL; + tracks.push_back(track); + + return true; +} + +bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, int sectorSize, bool mode2) +{ + Bit8u pvd[COOKED_SECTOR_SIZE]; + int seek = 16 * sectorSize; // first vd is located at sector 16 + if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; + if (mode2) seek += 24; + file->read(pvd, seek, COOKED_SECTOR_SIZE); + // pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version + return (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1); +} + +bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) +{ + Track track = {0, 0, 0, 0, 0, 0, false, NULL}; + tracks.clear(); + int shift = 0; + int currPregap = 0; + int totalPregap = 0; + int prestart = 0; + bool success; + bool canAddTrack = false; + char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument + strncpy(tmp, cuefile, MAX_FILENAME_LENGTH); +#if defined(WIN32) + string pathname(""); +#else + string pathname(dirname(tmp)); +#endif + ifstream in; + in.open(cuefile, ios::in); + if (in.fail()) return false; + + while(!in.eof()) { + // get next line + char buf[MAX_LINE_LENGTH]; + in.getline(buf, MAX_LINE_LENGTH); + if (in.fail() && !in.eof()) return false; // probably a binary file + istringstream line(buf); + + string command; + GetCueKeyword(command, line); + + if (command == "TRACK") { + if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); + else success = true; + + track.start = 0; + track.skip = 0; + currPregap = 0; + prestart = 0; + + line >> track.number; + string type; + GetCueKeyword(type, line); + + if (type == "AUDIO") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = 0; + track.mode2 = false; + } else if (type == "MODE1/2048") { + track.sectorSize = COOKED_SECTOR_SIZE; + track.attr = 4; + track.mode2 = false; + } else if (type == "MODE1/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = 4; + track.mode2 = false; + } else if (type == "MODE2/2336") { + track.sectorSize = 2336; + track.attr = 4; + track.mode2 = true; + } else if (type == "MODE2/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = 4; + track.mode2 = true; + } else success = false; + + canAddTrack = true; + } + else if (command == "INDEX") { + int index; + line >> index; + int frame; + success = GetCueFrame(frame, line); + + if (index == 1) track.start = frame; + else if (index == 0) prestart = frame; + // ignore other indices + } + else if (command == "FILE") { + if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); + else success = true; + canAddTrack = false; + + string filename; + GetCueString(filename, line); + GetRealFileName(filename, pathname); + string type; + GetCueKeyword(type, line); + + track.file = NULL; + bool error = true; + if (type == "BINARY") { + track.file = new BinaryFile(filename.c_str(), error); + } +#if defined(C_SDL_SOUND) + else if (type == "WAVE" || type == "AIFF" || type == "MP3") { + track.file = new AudioFile(filename.c_str(), error); + } +#endif + if (error) { + delete track.file; + success = false; + } + } + else if (command == "PREGAP") success = GetCueFrame(currPregap, line); + else if (command == "CATALOG") success = GetCueString(mcn, line); + // ignored commands + else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" + || command == "PERFORMER" || command == "POSTGAP" || command == "REM" + || command == "SONGWRITER" || command == "TITLE" || command == "") success = true; + // failure + else success = false; + + if (!success) return false; + } + // add last track + if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false; + + // add leadout track + track.number++; + track.start = 0; + track.length = 0; + track.file = NULL; + if(!AddTrack(track, shift, 0, totalPregap, 0)) return false; + + return true; +} + +bool CDROM_Interface_Image::AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap) +{ + // frames between index 0(prestart) and 1(curr.start) must be skipped + int skip; + if (prestart > 0) { + if (prestart > curr.start) return false; + skip = curr.start - prestart; + } else skip = 0; + + // first track (track number must be 1) + if (tracks.empty()) { + if (curr.number != 1) return false; + curr.skip = skip * curr.sectorSize; + curr.start += currPregap; + totalPregap = currPregap; + tracks.push_back(curr); + return true; + } + + Track &prev = *(tracks.end() - 1); + + // current track consumes data from the same file as the previous + if (prev.file == curr.file) { + curr.start += shift; + prev.length = curr.start + totalPregap - prev.start - skip; + curr.skip += prev.skip + prev.length * prev.sectorSize + skip * curr.sectorSize; + totalPregap += currPregap; + curr.start += totalPregap; + // current track uses a different file as the previous track + } else { + int tmp = prev.file->getLength() - prev.skip; + prev.length = tmp / prev.sectorSize; + if (tmp % prev.sectorSize != 0) prev.length++; // padding + + curr.start += prev.start + prev.length + currPregap; + curr.skip = skip * curr.sectorSize; + shift += prev.start + prev.length; + totalPregap = currPregap; + } + + // error checks + if (curr.number <= 1) return false; + if (prev.number + 1 != curr.number) return false; + if (curr.start < prev.start + prev.length) return false; + if (curr.length < 0) return false; + + tracks.push_back(curr); + return true; +} + +bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) +{ + // check if file exists + struct stat test; + if (stat(filename.c_str(), &test) == 0) return true; + + // check if file with path relative to cue file exists +#if not defined(WIN32) + string tmpstr(pathname + "/" + filename); + if (stat(tmpstr.c_str(), &test) == 0) { + filename = tmpstr; + return true; + } +#endif + // finally check if file is in a dosbox local drive + char fullname[CROSS_LEN]; + char tmp[CROSS_LEN]; + strncpy(tmp, filename.c_str(), CROSS_LEN); + Bit8u drive; + if (!DOS_MakeName(tmp, fullname, &drive)) return false; + + localDrive *ldp = (localDrive*)Drives[drive]; + ldp->GetSystemFilename(tmp, fullname); + if (stat(tmp, &test) == 0) { + filename = tmp; + return true; + } + + return false; +} + +bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in) +{ + in >> keyword; + for(int i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); + + return true; +} + +bool CDROM_Interface_Image::GetCueFrame(int &frames, istream &in) +{ + string msf; + in >> msf; + int min, sec, fr; + bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3; + frames = MSF_TO_FRAMES(min, sec, fr); + + return success; +} + +bool CDROM_Interface_Image::GetCueString(string &str, istream &in) +{ + int pos = in.tellg(); + in >> str; + if (str[0] == '\"') { + if (str[str.size() - 1] == '\"') { + str.assign(str, 1, str.size() - 2); + } else { + in.seekg(pos, ios::beg); + char buffer[MAX_FILENAME_LENGTH]; + in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip + in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); + str = buffer; + } + } + return true; +} + +void CDROM_Interface_Image::ClearTracks() +{ + vector::iterator i = tracks.begin(); + vector::iterator end = tracks.end(); + + TrackFile* last = NULL; + while(i != end) { + Track &curr = *i; + if (curr.file != last) { + delete curr.file; + last = curr.file; + } + i++; + } + tracks.clear(); +} diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 827cbbc9..c57c8a26 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_mscdex.cpp,v 1.23 2004-08-04 09:12:53 qbix79 Exp $ */ +/* $Id: dos_mscdex.cpp,v 1.24 2004-08-13 19:43:02 qbix79 Exp $ */ #include #include @@ -275,11 +275,9 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) cdrom[numDrives] = new CDROM_Interface_SDL(); LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); } break; - case 0x01 : // iso cdrom interface - // FIXME: Not yet supported - LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Mounting iso file as cdrom: %s" ,physicalPath); - cdrom[numDrives] = new CDROM_Interface_Fake; - return 2; + case 0x01 : // iso cdrom interface + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting iso file as cdrom: %s", physicalPath); + cdrom[numDrives] = new CDROM_Interface_Image((Bit8u)numDrives); break; case 0x02 : // fake cdrom interface (directories) cdrom[numDrives] = new CDROM_Interface_Fake; diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp index e3901572..4c169bff 100644 --- a/src/dos/drive_fat.cpp +++ b/src/dos/drive_fat.cpp @@ -1147,9 +1147,10 @@ public: if (type=="floppy") { mediaid=0xF0; - } else if (type=="cdrom") { + } else if (type=="cdrom" || type=="iso") { str_size="650,127,16513,1700"; mediaid=0xF8; + fstype = "iso"; } cmd->FindString("-size",str_size,true); if ((type=="hdd") && (str_size.size()==0)) { @@ -1170,7 +1171,7 @@ public: } number[index]=0;sizes[count++]=atoi(number); - if(fstype=="fat") { + if(fstype=="fat" || fstype=="iso") { // get the drive letter cmd->FindCommand(1,temp_line); if ((temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) { @@ -1208,8 +1209,25 @@ public: } struct stat test; if (stat(temp_line.c_str(),&test)) { - WriteOut("Image file not found\n"); - return; + // convert dosbox filename to system filename + char fullname[CROSS_LEN]; + char tmp[CROSS_LEN]; + strncpy(tmp, temp_line.c_str(), CROSS_LEN); + + Bit8u drive; + if (!DOS_MakeName(tmp, fullname, &drive)) { + WriteOut("Image file not found\n"); + return; + } + + localDrive *ldp = (localDrive*)Drives[drive]; + ldp->GetSystemFilename(tmp, fullname); + temp_line = tmp; + + if (stat(temp_line.c_str(),&test)) { + WriteOut("Image file not found\n"); + return; + } } if ((test.st_mode & S_IFDIR)) { @@ -1219,6 +1237,22 @@ public: if(fstype=="fat") { newdrive=new fatDrive(temp_line.c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0); + } else if (fstype=="iso") { + int error; + newdrive = new isoDrive(drive, temp_line.c_str(), mediaid, error); + switch (error) { + case 0 : WriteOut(MSG_Get("MSCDEX_SUCCESS")); break; + case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break; + case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break; + case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_PATH")); break; + case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break; + case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; + default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; + }; + if (error) { + delete newdrive; + return; + } } else { FILE *newDisk = fopen(temp_line.c_str(), "rb+"); fseek(newDisk,0L, SEEK_END); @@ -1254,6 +1288,17 @@ public: if(!((fatDrive *)newdrive)->loadedDisk->hardDrive) { imageDiskList[0] = ((fatDrive *)newdrive)->loadedDisk; } + } else if (fstype=="iso") { + if (Drives[drive-'A']) { + WriteOut("Drive already mounted at that letter\n"); + if (newdrive) delete newdrive; + return; + } + if (!newdrive) WriteOut("Can't create drive from file\n"); + Drives[drive-'A']=newdrive; + // Set the correct media byte in the table + mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',mediaid); + WriteOut("Drive %c mounted as %s\n",drive,temp_line.c_str()); } else if (fstype=="none") { if(imageDiskList[drive] != NULL) delete imageDiskList[drive]; imageDiskList[drive] = newImage; diff --git a/src/dos/drive_iso.cpp b/src/dos/drive_iso.cpp new file mode 100644 index 00000000..d58ec954 --- /dev/null +++ b/src/dos/drive_iso.cpp @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: drive_iso.cpp,v 1.1 2004-08-13 19:43:02 qbix79 Exp $ */ + +#include +#include +#include "cdrom.h" +#include "dosbox.h" +#include "dos_system.h" +#include "drives.h" + +using namespace std; + +class isoFile : public DOS_File { +public: + isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u offset, Bit16u info); + bool Read(Bit8u *data, Bit16u *size); + bool Write(Bit8u *data, Bit16u *size); + bool Seek(Bit32u *pos, Bit32u type); + bool Close(); + Bit16u GetInformation(void); +private: + isoDrive *drive; + Bit8u buffer[ISO_FRAMESIZE]; + int cachedSector; + Bit32u fileBegin; + Bit32u filePos; + Bit32u fileEnd; + Bit16u info; +}; + +isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u offset, Bit16u info) +{ + this->drive = drive; + time = stat->time; + date = stat->date; + attr = stat->attr; + size = stat->size; + fileBegin = offset; + filePos = fileBegin; + fileEnd = fileBegin + size; + cachedSector = -1; + open = true; + info = info; + this->name = NULL; + SetName(name); +} + +bool isoFile::Read(Bit8u *data, Bit16u *size) +{ + if (filePos + *size > fileEnd) + *size = fileEnd - filePos; + + Bit16u nowSize = 0; + int sector = filePos / ISO_FRAMESIZE; + Bit16u sectorPos = filePos % ISO_FRAMESIZE; + + if (sector != cachedSector) { + if (drive->readSector(buffer, sector)) cachedSector = sector; + else { *size = 0; cachedSector = -1; } + } + while (nowSize < *size) { + Bit16u remSector = ISO_FRAMESIZE - sectorPos; + Bit16u remSize = *size - nowSize; + if(remSector < remSize) { + memcpy(&data[nowSize], &buffer[sectorPos], remSector); + nowSize += remSector; + sectorPos = 0; + sector++; + cachedSector++; + if (!drive->readSector(buffer, sector)) { + *size = nowSize; + cachedSector = -1; + } + } else { + memcpy(&data[nowSize], &buffer[sectorPos], remSize); + nowSize += remSize; + } + + } + + *size = nowSize; + filePos += *size; + return true; +} + +bool isoFile::Write(Bit8u *data, Bit16u *size) +{ + return false; +} + +bool isoFile::Seek(Bit32u *pos, Bit32u type) +{ + switch (type) { + case DOS_SEEK_SET: + filePos = fileBegin + *pos; + break; + case DOS_SEEK_CUR: + filePos += *pos; + break; + case DOS_SEEK_END: + filePos = fileEnd + *pos; + break; + default: + return false; + } + if (filePos > fileEnd || filePos < fileBegin) + filePos = fileEnd; + + *pos = filePos - fileBegin; + return true; +} + +bool isoFile::Close() +{ + if (refCtr == 1) open = false; + return true; +} + +Bit16u isoFile::GetInformation(void) +{ + return info; +} + +int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); +bool MSCDEX_HasMediaChanged(Bit8u subUnit); +bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); + +isoDrive::isoDrive(char driveLetter, const char *fileName, Bit8u mediaid, int &error) +{ + error = MSCDEX_AddDrive(driveLetter, fileName, subUnit); + + if (!error) { + if (loadImage()) { + strcpy(info, "isoDrive"); + searchCache.clear(); + dirIter = searchCache.end(); + this->mediaid = mediaid; + if (!MSCDEX_GetVolumeName(subUnit, discLabel)) strcpy(discLabel, ""); + } else error = 6; + } +} + +isoDrive::~isoDrive() { } + +bool isoDrive::FileOpen(DOS_File **file, char *name, Bit32u flags) +{ + if (flags == OPEN_WRITE) { + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; + } + + isoDirEntry de; + bool success = lookup(&de, name) && !IS_DIR(de.fileFlags); + + if (success) { + FileStat_Block file_stat; + file_stat.size = DATA_LENGTH(de); + file_stat.attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; + file_stat.date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); + file_stat.time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); + *file = new isoFile(this, name, &file_stat, EXTENT_LOCATION(de) * ISO_FRAMESIZE, 0x202); + (*file)->flags = flags; + } + return success; +} + +bool isoDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +} + +bool isoDrive::FileUnlink(char *name) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +} + +bool isoDrive::RemoveDir(char *dir) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +} + +bool isoDrive::MakeDir(char *dir) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +} + +bool isoDrive::TestDir(char *dir) +{ + isoDirEntry de; + return (lookup(&de, dir) && IS_DIR(de.fileFlags)); +} + +bool isoDrive::FindFirst(char *dir, DOS_DTA &dta, bool fcb_findfirst) +{ + isoDirEntry de; + if (!lookup(&de, dir)) { + DOS_SetError(DOSERR_PATH_NOT_FOUND); + return false; + } + + Bit32u sectorStart = EXTENT_LOCATION(de); + Bit32u sectorEnd = sectorStart + DATA_LENGTH(de) / ISO_FRAMESIZE; + if (DATA_LENGTH(de) % ISO_FRAMESIZE != 0) sectorEnd++; + searchCache.clear(); + + for(Bit32u sector = sectorStart; sector < sectorEnd; sector++) { + Bit8u block[ISO_FRAMESIZE]; + readSector(block, sector); + + Bit32u pos = 0; + while (pos < ISO_FRAMESIZE && block[pos] != 0) { + isoDirEntry tmp; + int length = readDirEntry(&tmp, &block[pos]); + if (length < 0) return false; + searchCache.push_back(tmp); + pos += length; + } + } + dirIter = searchCache.begin(); + + Bit8u attr; + char pattern[ISO_MAXPATHNAME]; + dta.GetSearchParams(attr, pattern); + if ((attr & DOS_ATTR_VOLUME) && ((*dir == 0) || fcb_findfirst)) { + // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + dta.SetResult(discLabel, 0, 0, 0, DOS_ATTR_VOLUME); + return true; + } + return FindNext(dta); +} + +bool isoDrive::FindNext(DOS_DTA &dta) +{ + Bit8u attr; + char pattern[DOS_NAMELENGTH_ASCII]; + dta.GetSearchParams(attr, pattern); + + while (dirIter != searchCache.end()) { + isoDirEntry &de = *dirIter; + Bit8u findAttr; + if (IS_DIR(de.fileFlags)) findAttr = DOS_ATTR_DIRECTORY; + else findAttr = DOS_ATTR_ARCHIVE; + + if (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 */ + char findName[DOS_NAMELENGTH_ASCII]; + if(strlen((char*)de.ident) < DOS_NAMELENGTH_ASCII) { + strcpy(findName, (char*)de.ident); + upcase(findName); + } + Bit32u findSize = DATA_LENGTH(de); + Bit16u findDate = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); + Bit16u findTime = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); + dta.SetResult(findName, findSize, findDate, findTime, findAttr); + + dirIter++; + return true; + } + dirIter++; + } + + DOS_SetError(DOSERR_NO_MORE_FILES); + return false; +} + +bool isoDrive::Rename(char *oldname, char *newname) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +} + +bool isoDrive::GetFileAttr(char *name, Bit16u *attr) +{ + *attr = 0; + isoDirEntry de; + bool success = lookup(&de, name); + if (success) { + *attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; + if (IS_DIR(de.fileFlags)) *attr |= DOS_ATTR_DIRECTORY; + } + return success; +} + +bool isoDrive::AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters) +{ + *bytes_sector = 2048; + *sectors_cluster = 1; // cluster size for cdroms ? + *total_clusters = 60000; + *free_clusters = 0; + return true; +} + +bool isoDrive::FileExists(const char *name) +{ + isoDirEntry de; + return (lookup(&de, name) && !IS_DIR(de.fileFlags)); +} + +bool isoDrive::FileStat(const char *name, FileStat_Block *const stat_block) +{ + isoDirEntry de; + bool success = lookup(&de, name); + + if (success) { + stat_block->date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); + stat_block->time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); + stat_block->size = DATA_LENGTH(de); + stat_block->attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; + if (IS_DIR(de.fileFlags)) stat_block->attr |= DOS_ATTR_DIRECTORY; + } + + return success; +} + +Bit8u isoDrive::GetMediaByte(void) +{ + return mediaid; +} + +bool isoDrive::isRemote(void) +{ + return true; +} + +inline bool isoDrive :: readSector(Bit8u *buffer, Bit32u sector) +{ + return CDROM_Interface_Image::images[subUnit]->ReadSector(buffer, false, sector); +} + +int isoDrive :: readDirEntry(isoDirEntry *de, Bit8u *data) +{ + // copy data into isoDirEntry struct, data[0] = length of DirEntry + memcpy(de, data, data[0]); + + // xa not supported + if (de->extAttrLength != 0) return -1; + // interleaved mode not supported + if (de->fileUnitSize != 0 || de->interleaveGapSize != 0) return -1; + + // modify file identifier for use with dosbox + if (IS_DIR(de->fileFlags)) { + if (de->fileIdentLength == 1 && de->ident[0] == 0) strcpy((char*)de->ident, "."); + else if (de->fileIdentLength == 1 && de->ident[0] == 1) strcpy((char*)de->ident, ".."); + else { + if (de->fileIdentLength > 31) return -1; + de->ident[de->fileIdentLength] = 0; + } + } else { + if (de->fileIdentLength > 37) return -1; + de->ident[de->fileIdentLength] = 0; + // remove any file version identifiers as there are some cdroms that don't have them + strreplace((char*)de->ident, ';', 0); + // if file has no extension remove the trailing dot + int tmp = strlen((char*)de->ident); + if (tmp > 0 && de->ident[tmp - 1] == '.') de->ident[tmp - 1] = 0; + } + return de->length; +} + +bool isoDrive :: loadImage() +{ + isoPVD pvd; + readSector((Bit8u*)(&pvd), ISO_FIRST_VD); + if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false; + return (readDirEntry(&this->rootEntry, pvd.rootEntry)); +} + +bool isoDrive :: lookupSingle(isoDirEntry *de, const char *name, Bit32u start, Bit32u length) +{ + Bit32u end = start + length / ISO_FRAMESIZE; + if (length % ISO_FRAMESIZE != 0) end++; + + for(Bit32u i = start; i < end; i++) { + Bit8u sector[ISO_FRAMESIZE]; + if (!readSector(sector, i)) return false; + + int pos = 0; + while (sector[pos] != 0 && pos < ISO_FRAMESIZE) { + int deLength = readDirEntry(de, §or[pos]); + if (deLength < 1) return false; + pos += deLength; + int tmp = strncasecmp((char*)de->ident, name, 38); + if (tmp == 0) return true; + } + } + return false; +} + +bool isoDrive :: lookup(isoDirEntry *de, const char *path) +{ + *de = this->rootEntry; + if (!strcmp(path, "")) return true; + + char isoPath[ISO_MAXPATHNAME]; + strncpy(isoPath, path, ISO_MAXPATHNAME); + strreplace(isoPath, '\\', '/'); + + int beginPos = 0; + int pos = 0; + while (isoPath[pos] != 0) { + if (isoPath[pos] == '/') { + char name[38]; + strncpy(name, &isoPath[beginPos], pos - beginPos); + name[pos - beginPos] = 0; + beginPos = pos + 1; + if (!IS_DIR(de->fileFlags)) return false; + if (!lookupSingle(de, name, EXTENT_LOCATION(*de), DATA_LENGTH(*de))) return false; + } + pos++; + } + return lookupSingle(de, &isoPath[beginPos], EXTENT_LOCATION(*de), DATA_LENGTH(*de)); +} diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index dffa7cf9..f4fa8b93 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_local.cpp,v 1.50 2004-08-08 12:39:54 qbix79 Exp $ */ +/* $Id: drive_local.cpp,v 1.51 2004-08-13 19:43:02 qbix79 Exp $ */ #include #include @@ -114,6 +114,15 @@ FILE * localDrive::GetSystemFilePtr(char * name, char * type) { return fopen(newname,type); } +bool localDrive::GetSystemFilename(char *sysName, char *dosName) { + + strcpy(sysName, basedir); + strcat(sysName, dosName); + CROSS_FILENAME(sysName); + dirCache.ExpandName(sysName); + return true; +} + bool localDrive::FileUnlink(char * name) { char newname[CROSS_LEN]; strcpy(newname,basedir); diff --git a/src/dos/drives.h b/src/dos/drives.h index b10fa7c4..ecde6b4e 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -16,11 +16,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drives.h,v 1.22 2004-08-04 09:12:53 qbix79 Exp $ */ +/* $Id: drives.h,v 1.23 2004-08-13 19:43:02 qbix79 Exp $ */ #ifndef _DRIVES_H__ #define _DRIVES_H__ +#include #include #include "dos_system.h" #include "shell.h" /* for DOS_Shell */ @@ -33,6 +34,7 @@ public: localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid); virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); virtual FILE *GetSystemFilePtr(char * name, char * type); + virtual bool GetSystemFilename(char *sysName, char *dosName); virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); virtual bool FileUnlink(char * name); virtual bool RemoveDir(char * dir); @@ -202,6 +204,112 @@ private: Bit8u subUnit; }; +#ifdef _MSC_VER +#pragma pack (1) +#endif +struct isoPVD { + Bit8u type; + Bit8u standardIdent[5]; + Bit8u version; + Bit8u unused1; + Bit8u systemIdent[32]; + Bit8u volumeIdent[32]; + Bit8u unused2[8]; + Bit32u volumeSpaceSizeL; + Bit32u volumeSpaceSizeM; + Bit8u unused3[32]; + Bit16u volumeSetSizeL; + Bit16u volumeSetSizeM; + Bit16u volumeSeqNumberL; + Bit16u volumeSeqNumberM; + Bit16u logicBlockSizeL; + Bit16u logicBlockSizeM; + Bit32u pathTableSizeL; + Bit32u pathTableSizeM; + Bit32u locationPathTableL; + Bit32u locationOptPathTableL; + Bit32u locationPathTableM; + Bit32u locationOptPathTableM; + Bit8u rootEntry[34]; + Bit32u unused4[1858]; +} GCC_ATTRIBUTE(packed); + +struct isoDirEntry { + Bit8u length; + Bit8u extAttrLength; + Bit32u extentLocationL; + Bit32u extentLocationM; + Bit32u dataLengthL; + Bit32u dataLengthM; + Bit8u dateYear; + Bit8u dateMonth; + Bit8u dateDay; + Bit8u timeHour; + Bit8u timeMin; + Bit8u timeSec; + Bit8u timeZone; + Bit8u fileFlags; + Bit8u fileUnitSize; + Bit8u interleaveGapSize; + Bit16u VolumeSeqNumberL; + Bit16u VolumeSeqNumberM; + Bit8u fileIdentLength; + Bit8u ident[38]; // can be smaller +} GCC_ATTRIBUTE(packed); + +#ifdef _MSC_VER +#pragma pack () +#endif + +#if defined (WORD_BIGENDIAN) +#define EXTENT_LOCATION(de) ((de).extentLocationM) +#define DATA_LENGTH(de) ((de).dataLengthM) +#else +#define EXTENT_LOCATION(de) ((de).extentLocationL) +#define DATA_LENGTH(de) ((de).dataLengthL) +#endif + +#define ISO_FRAMESIZE 2048 +#define ISO_DIRECTORY 2 +#define ISO_MAXPATHNAME 256 +#define ISO_FIRST_VD 16 +#define IS_DIR(fileFlags) (fileFlags & ISO_DIRECTORY) + +class isoDrive : public DOS_Drive { +public: + isoDrive(char driveLetter, const char* device_name, Bit8u mediaid, int &error); + ~isoDrive(); + virtual bool FileOpen(DOS_File **file, char *name, Bit32u flags); + virtual bool FileCreate(DOS_File **file, char *name, Bit16u attributes); + virtual bool FileUnlink(char *name); + virtual bool RemoveDir(char *dir); + virtual bool MakeDir(char *dir); + virtual bool TestDir(char *dir); + virtual bool FindFirst(char *_dir, DOS_DTA &dta, bool fcb_findfirst); + virtual bool FindNext(DOS_DTA &dta); + virtual bool GetFileAttr(char *name, Bit16u *attr); + virtual bool Rename(char * oldname,char * newname); + virtual bool AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters); + virtual bool FileExists(const char *name); + virtual bool FileStat(const char *name, FileStat_Block *const stat_block); + virtual Bit8u GetMediaByte(void); + virtual void EmptyCache(void){} + virtual bool isRemote(void); + bool readSector(Bit8u *buffer, Bit32u sector); +private: + int readDirEntry(isoDirEntry *de, Bit8u *data); + bool loadImage(); + bool lookupSingle(isoDirEntry *de, const char *name, Bit32u sectorStart, Bit32u length); + bool lookup(isoDirEntry *de, const char *path); + + std::vector searchCache; + std::vector::iterator dirIter; + isoDirEntry rootEntry; + Bit8u mediaid; + Bit8u subUnit; + char discLabel[32]; +}; + struct VFILE_Block; class Virtual_Drive: public DOS_Drive { diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 17bb93cd..7a395993 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dosbox.cpp,v 1.73 2004-08-04 09:12:51 qbix79 Exp $ */ +/* $Id: dosbox.cpp,v 1.74 2004-08-13 19:43:02 qbix79 Exp $ */ #include #include @@ -369,7 +369,7 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&MSCDEX_Init); #if C_MODEM secprop=control->AddSection_prop("modem",&MODEM_Init); - secprop->Add_bool("modem",true); + secprop->Add_bool("modem",false); secprop->Add_hex("comport",2); secprop->Add_int("listenport",23); @@ -400,7 +400,7 @@ void DOSBOX_Init(void) { #endif #if C_IPX secprop=control->AddSection_prop("ipx",&IPX_Init); - secprop->Add_bool("ipx", true); + secprop->Add_bool("ipx", false); MSG_Add("IPX_CONFIGFILE_HELP", "ipx -- Enable ipx over UDP/IP emulation.\n" );