From 02ff2737d7aa87f2fe1d2869b4d664beac96944c Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Fri, 13 Aug 2004 19:43:02 +0000 Subject: [PATCH] Add Patch 1001897 by Martin. Disabled modem and ipx networking by default as they depend on libraries not everybody may have. Reduces alarmed firewall people and is nicer on unix hosts as port 23 is a bit tricky Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1904 --- configure.in | 10 + src/dos/Makefile.am | 4 +- src/dos/cdrom.cpp | 10 +- src/dos/cdrom.h | 107 +++++++ src/dos/cdrom_image.cpp | 653 ++++++++++++++++++++++++++++++++++++++++ src/dos/dos_mscdex.cpp | 10 +- src/dos/drive_fat.cpp | 53 +++- src/dos/drive_iso.cpp | 435 ++++++++++++++++++++++++++ src/dos/drive_local.cpp | 11 +- src/dos/drives.h | 110 ++++++- src/dosbox.cpp | 6 +- 11 files changed, 1390 insertions(+), 19 deletions(-) create mode 100644 src/dos/cdrom_image.cpp create mode 100644 src/dos/drive_iso.cpp 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" );