diff options
Diffstat (limited to 'lib/cdreader.cpp')
-rw-r--r-- | lib/cdreader.cpp | 140 |
1 files changed, 127 insertions, 13 deletions
diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp index d3d315f..5507588 100644 --- a/lib/cdreader.cpp +++ b/lib/cdreader.cpp @@ -14,6 +14,9 @@ #endif #include "cdabstract.h" +#define nsectorsarow 1 +#define cachesize 2048 + bool cdreader::CanWrite() const { return 0; } @@ -57,7 +60,7 @@ ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) { while (count > 0) { size_t n = MIN(2352 - remain, count); - getsector(sector); + fetchsector(sector); bcopy(sector + remain, buf, n); buf = ((char *) buf) + n; itell += n; @@ -72,6 +75,94 @@ void cdreader::sectorseek(int sec) { sector = sec; } +void cdreader::fetchsector(void * buf, int sec) { + if (sec >= 0) + sector = sec; + + if (sectors[sector]) { + actualize(sectors[sector]); + memcpy(buf, sectors[sector]->sector, 2352); + return; + } + + Byte buffers[2352 * nsectorsarow]; + + getsector(buffers, sec = sector, nsectorsarow); + + for (int i = nsectorsarow - 1; i >= 0; i--) { + introduce(buffers + i * 2352, sec + i); + } + + memcpy(buf, buffers, 2352); + + while (nsectors > cachesize) { + removetail(); + } +} + +cdreader::~cdreader() { + while (nsectors) { + removetail(); + } +} + +void cdreader::removetail() { + void * t = (void *) tail; + if (!tail) + return; + + sectors[tail->n] = 0; + + if (head == tail) { + free(t); + head = tail = 0; + nsectors = 0; + } else { + cachedsector * p; + (p = tail->prev)->next = 0; + free(t); + tail = p; + nsectors--; + } +} + +void cdreader::actualize(cachedsector * s) { + if (s == head) + return; + + if (s != tail) { + s->next->prev = s->prev; + } else { + tail = s->prev; + } + s->prev->next = s->next; + + head->prev = s; + s->prev = 0; + s->next = head; + head = s; +} + +void cdreader::introduce(Byte * datas, int n) { + cachedsector * s; + + s = (cachedsector *) malloc(sizeof(cachedsector)); + memcpy(s->sector, datas, 2352); + s->n = n; + + if (head) { + s->next = head; + head->prev = s; + head = s; + } else { + head = tail = s; + s->prev = s->next = 0; + } + sectors[n] = s; + + nsectors++; +} + #ifdef __linux__ #include <unistd.h> #include <sys/ioctl.h> @@ -94,24 +185,35 @@ cdreader::cdreader(const String & no) throw (GeneralException) : if (!S_ISBLK(s.st_mode)) { throw GeneralException(no + " is not a block device."); } + + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } -void cdreader::getsector(void *buf, int sec) throw (GeneralException) { +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { struct cdrom_msf * msf = (struct cdrom_msf *) buf; if (sec >= 0) sector = sec; sector += 150; - msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; - msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; - msf->cdmsf_frame0= sector %CD_FRAMES; - msf->cdmsf_min1 = (sector+1)/CD_SECS /CD_FRAMES; - msf->cdmsf_sec1 = ((sector+1)/CD_FRAMES)%CD_SECS; - msf->cdmsf_frame1= (sector+1)%CD_FRAMES; + msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; + msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; + msf->cdmsf_frame0= sector %CD_FRAMES; + msf->cdmsf_min1 = (sector + nb)/CD_SECS /CD_FRAMES; + msf->cdmsf_sec1 = ((sector + nb)/CD_FRAMES)%CD_SECS; + msf->cdmsf_frame1= (sector + nb)%CD_FRAMES; sector -= 150; @@ -119,7 +221,7 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno)); } - sector++; + sector += nb; } #endif @@ -128,10 +230,20 @@ cdreader::cdreader(const String & no) throw (GeneralException) : Handle(-1), n(no), sector(0) { if (!(hFile = cdabstract::OpenIOCTLFile(no[0]))) throw GeneralException("Error opening device " + no); + for (int i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { - hFile = i.hFile; + hFile = i.hFile; + for (int x = 0; x < 400000; x++) { + sectors[x] = 0; + } + head = tail = 0; + nsectors = 0; } void cdreader::close() throw (GeneralException) { @@ -150,7 +262,7 @@ typedef struct _RAW_READ_INFO { TRACK_MODE_TYPE TrackMode;
} RAW_READ_INFO, *PRAW_READ_INFO; -void cdreader::getsector(void *buf, int sec) throw (GeneralException) { +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { RAW_READ_INFO rawIOCTL;
DWORD dwRet;
BOOL bStat;
@@ -159,14 +271,14 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { sector = sec; rawIOCTL.DiskOffset.QuadPart = sector * 2048;
- rawIOCTL.SectorCount = 1;
+ rawIOCTL.SectorCount = nb;
rawIOCTL.TrackMode = YellowMode2;
while (!done) {
SetLastError(0);
bStat = DeviceIoControl(hFile, IOCTL_CDROM_RAW_READ,
&rawIOCTL, sizeof(RAW_READ_INFO),
- buf, 2352, &dwRet, NULL);
+ buf, 2352 * nb, &dwRet, NULL);
if (!bStat) {
DWORD dwErrCode = GetLastError();
if (dwErrCode == ERROR_INVALID_FUNCTION) {
@@ -192,6 +304,8 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { done = true;
}
}
+
+ sector += nb;
} #endif |