summaryrefslogtreecommitdiff
path: root/lib/cdreader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cdreader.cpp')
-rw-r--r--lib/cdreader.cpp140
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