summaryrefslogtreecommitdiff
path: root/lib/dvdabstract.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dvdabstract.cpp')
-rw-r--r--lib/dvdabstract.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/lib/dvdabstract.cpp b/lib/dvdabstract.cpp
new file mode 100644
index 0000000..582ad90
--- /dev/null
+++ b/lib/dvdabstract.cpp
@@ -0,0 +1,161 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002-2003 Nicolas "Pixel" Noble
+ *
+ * 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: dvdabstract.cpp,v 1.1 2005-11-02 21:34:02 pixel Exp $ */
+
+#include "dvdabstract.h"
+
+dvdabstract::dvdabstract(Handle * h, int _m) : Handle(-1), r(h), v(h->tell()), m(_m) {
+}
+
+off_t dvdabstract::seek(off_t offset, int wheel) throw (GeneralException) {
+ switch (wheel) {
+ case SEEK_SET:
+ v = offset;
+ break;
+ case SEEK_CUR:
+ v += offset;
+ break;
+ case SEEK_END:
+ throw IOGeneral("Can't seek from the end of the dvdabstract...");
+ }
+}
+
+off_t dvdabstract::tell() const {
+ return v;
+}
+
+ssize_t dvdabstract::read(void * _buf, size_t count) throw (GeneralException) {
+ char i_buf[2352], * buf = (char *) _buf;
+ int sector, start, reminder, i_count;
+
+ if (!count) return 0;
+
+ sector = v / 2352;
+ start = v % 2352;
+
+ read_sector(i_buf, sector);
+
+ if ((start + count) < 2352) {
+ memcpy(buf, i_buf + start, count);
+ return count;
+ }
+
+ reminder = 2352 - start;
+ memcpy(buf, i_buf + start, reminder);
+ sector++;
+ i_count = count - reminder;
+ buf += reminder;
+
+ while (i_count >= 2352) {
+ read_sector(buf, sector);
+ i_count -= 2352;
+ sector++;
+ buf += 2352;
+ }
+
+ reminder = i_count;
+
+ if (reminder >= 0) {
+ read_sector(i_buf, sector);
+ memcpy(buf, i_buf, reminder);
+ }
+
+ return count;
+}
+
+ssize_t dvdabstract::write(const void * _buf, size_t count) throw (GeneralException) {
+ char i_buf[2352], * buf = (char *) _buf;
+ int sector, start, reminder, i_count;
+
+ if (!count) return 0;
+
+ sector = v / 2352;
+ start = v % 2352;
+
+ memcpy(i_buf + start, buf, 2352 - start);
+ if (start >= 16) {
+ i_buf[15] = m;
+ if (m == MODE2_FORM1) {
+ i_buf[18] = i_buf[22] = 1;
+ }
+ }
+ write_sector(i_buf, sector);
+
+ if ((start + count) < 2352) {
+ return count;
+ }
+
+ reminder = 2352 - start;
+ sector++;
+ i_count = count - reminder;
+ buf += reminder;
+
+ while (i_count >= 2352) {
+ write_sector(buf, sector);
+ i_count -= 2352;
+ sector++;
+ buf += 2352;
+ }
+
+ reminder = i_count;
+ memcpy(i_buf, buf, reminder);
+ if (reminder >= 0) {
+ memcpy(buf, i_buf, reminder);
+ if (reminder <= 22) {
+ if (reminder <= 15) {
+ i_buf[15] = m;
+ if (m == MODE2_FORM1) {
+ i_buf[18] = i_buf[22] = 1;
+ }
+ } else if (i_buf[15] == MODE2_FORM1) {
+ i_buf[18] = i_buf[22] = 1;
+ }
+ }
+ write_sector(i_buf, sector);
+ }
+
+ return count;
+}
+
+void dvdabstract::read_sector(char * buf, int sector) {
+ r->seek(sector * 2048);
+ r->read(buf + 16, 2048);
+ buf[0] = buf[11] = 0;
+ buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = buf[7] = buf[8] = buf[9] = buf[10] = -1;
+ buf[12] = buf[13] = buf[14] = 0;
+ buf[15] = 1;
+}
+
+void dvdabstract::write_sector(const char * buf, int sector) throw (GeneralException) {
+ r->seek(sector * 2048);
+ switch(buf[15]) {
+ case 0:
+ case 1:
+ r->write(buf + 16, 2048);
+ break;
+ case 2:
+ if ((buf[18] == 1) && (buf[22] == 1)) {
+ r->write(buf + 24, 2048);
+ break;
+ }
+ default:
+ throw GeneralException("dvdabstract::write_sector: unknown sector mode.");
+ }
+}