/[pcsx2_0.9.7]/trunk/pcsx2/CDVD/IsoFileFormats.cpp
ViewVC logotype

Annotation of /trunk/pcsx2/CDVD/IsoFileFormats.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 7 months ago) by william
File size: 10296 byte(s)
committing r3113 initial commit again...
1 william 31 /* PCSX2 - PS2 Emulator for PCs
2     * Copyright (C) 2002-2010 PCSX2 Dev Team
3     *
4     * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5     * of the GNU Lesser General Public License as published by the Free Software Found-
6     * ation, either version 3 of the License, or (at your option) any later version.
7     *
8     * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10     * PURPOSE. See the GNU General Public License for more details.
11     *
12     * You should have received a copy of the GNU General Public License along with PCSX2.
13     * If not, see <http://www.gnu.org/licenses/>.
14     */
15    
16    
17     #include "PrecompiledHeader.h"
18     #include "IopCommon.h"
19    
20     #include <stdio.h>
21     #include <fcntl.h>
22     #include <errno.h>
23    
24     #include "IsoFileFormats.h"
25    
26     static bool detect(isoFile *iso)
27     {
28     u8 buf[2456];
29     u8* pbuf;
30    
31     if (!isoReadBlock(iso, buf, 16)) return false; // Not readable
32    
33     pbuf = (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
34    
35     if (strncmp((char*)(pbuf+1), "CD001", 5)) return false; // Not ISO 9660 compliant
36    
37     if (*(u16*)(pbuf+166) == 2048)
38     iso->type = ISOTYPE_CD;
39     else
40     iso->type = ISOTYPE_DVD;
41    
42     return true; // We can deal with this.
43     }
44    
45     static bool _isoReadDtable(isoFile *iso)
46     {
47     uint ret;
48    
49     _seekfile(iso->handle, 0, SEEK_END);
50     iso->dtablesize = (_tellfile(iso->handle) - 16) / (iso->blocksize + 4);
51     iso->dtable = (u32*)malloc(iso->dtablesize * 4);
52    
53     for (int i = 0; i < iso->dtablesize; i++)
54     {
55     _seekfile(iso->handle, 16 + (iso->blocksize + 4) * i, SEEK_SET);
56     ret = _readfile(iso->handle, &iso->dtable[i], 4);
57     if (ret < 4) return false;
58     }
59    
60     return true;
61     }
62    
63     static bool tryIsoType(isoFile *iso, u32 size, s32 offset, s32 blockofs)
64     {
65     iso->blocksize = size;
66     iso->offset = offset;
67     iso->blockofs = blockofs;
68    
69     return detect(iso);
70     }
71    
72     // based on florin's CDVDbin detection code :)
73     // Returns true if the image is valid/known/supported, or false if not (iso->type == ISOTYPE_ILLEGAL).
74     bool isoDetect(isoFile *iso)
75     {
76     char buf[32];
77     int len;
78    
79     iso->type = ISOTYPE_ILLEGAL;
80    
81     len = strlen(iso->filename);
82    
83     _seekfile(iso->handle, 0, SEEK_SET);
84     _readfile(iso->handle, buf, 4);
85    
86     if (strncmp(buf, "BDV2", 4) == 0)
87     {
88     iso->flags = ISOFLAGS_BLOCKDUMP_V2;
89     _readfile(iso->handle, &iso->blocksize, 4);
90     _readfile(iso->handle, &iso->blocks, 4);
91     _readfile(iso->handle, &iso->blockofs, 4);
92     _isoReadDtable(iso);
93     return (detect(iso));
94     }
95     else if (strncmp(buf, "BDV3", 4) == 0)
96     {
97     iso->flags = ISOFLAGS_BLOCKDUMP_V3;
98     _readfile(iso->handle, &iso->blocksize, 4);
99     _readfile(iso->handle, &iso->blocks, 4);
100     _readfile(iso->handle, &iso->blockofs, 4);
101     _isoReadDtable(iso);
102     return (detect(iso));
103     }
104     else
105     {
106     iso->blocks = 16;
107     }
108    
109     if (tryIsoType(iso, 2048, 0, 24)) return true; // ISO 2048
110     if (tryIsoType(iso, 2336, 0, 16)) return true; // RAW 2336
111     if (tryIsoType(iso, 2352, 0, 0)) return true; // RAW 2352
112     if (tryIsoType(iso, 2448, 0, 0)) return true; // RAWQ 2448
113     if (tryIsoType(iso, 2048, 150 * 2048, 24)) return true; // NERO ISO 2048
114     if (tryIsoType(iso, 2352, 150 * 2048, 0)) return true; // NERO RAW 2352
115     if (tryIsoType(iso, 2448, 150 * 2048, 0)) return true; // NERO RAWQ 2448
116     if (tryIsoType(iso, 2048, -8, 24)) return true; // ISO 2048
117     if (tryIsoType(iso, 2352, -8, 0)) return true; // RAW 2352
118     if (tryIsoType(iso, 2448, -8, 0)) return true; // RAWQ 2448
119    
120     iso->offset = 0;
121     iso->blocksize = CD_FRAMESIZE_RAW;
122     iso->blockofs = 0;
123     iso->type = ISOTYPE_AUDIO;
124     return true;
125     }
126    
127     isoFile *isoOpen(const char *filename)
128     {
129     isoFile *iso;
130    
131     iso = (isoFile*)malloc(sizeof(isoFile));
132     if (iso == NULL) return NULL;
133    
134     memzero( *iso );
135     strcpy(iso->filename, filename);
136    
137     iso->handle = _openfile( iso->filename, O_RDONLY);
138     if (iso->handle == NULL)
139     {
140     Console.Error("error loading %s", iso->filename);
141     return NULL;
142     }
143    
144     if (!isoDetect(iso)) return NULL;
145    
146     Console.WriteLn("detected blocksize = %u", iso->blocksize);
147    
148     if ((strlen(iso->filename) > 3) && strncmp(iso->filename + (strlen(iso->filename) - 3), "I00", 3) == 0)
149     {
150     int i;
151    
152     _closefile(iso->handle);
153     iso->flags |= ISOFLAGS_MULTI;
154     iso->blocks = 0;
155    
156     for (i = 0; i < 8; i++)
157     {
158     iso->filename[strlen(iso->filename) - 1] = '0' + i;
159     iso->multih[i].handle = _openfile(iso->filename, O_RDONLY);
160    
161     if (iso->multih[i].handle == NULL)
162     {
163     break;
164     }
165    
166     iso->multih[i].slsn = iso->blocks;
167     _seekfile(iso->multih[i].handle, 0, SEEK_END);
168     iso->blocks += (u32)((_tellfile(iso->multih[i].handle) - iso->offset) / (iso->blocksize));
169     iso->multih[i].elsn = iso->blocks - 1;
170     }
171    
172     if (i == 0)
173     {
174     return NULL;
175     }
176     }
177    
178     if (iso->flags == 0)
179     {
180     _seekfile(iso->handle, 0, SEEK_END);
181     iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / (iso->blocksize));
182     }
183    
184     switch(iso->type)
185     {
186     case ISOTYPE_CD: Console.Write("isoOpen(CD): "); break;
187     case ISOTYPE_DVD: Console.Write("isoOpen(DVD): "); break;
188     case ISOTYPE_AUDIO: Console.Write("isoOpen(Audio CD): "); break;
189     case ISOTYPE_DVDDL: Console.Write("isoOpen(DVDDL): "); break;
190     case ISOTYPE_ILLEGAL:
191     default: Console.Write("isoOpen(illegal media): "); break;
192     }
193     Console.WriteLn("%s ok.", iso->filename);
194     Console.WriteLn("The iso has %u blocks (size %u).", iso->blocks, iso->blocksize);
195     Console.WriteLn("The isos offset is %d, and the block offset is %d.", iso->offset, iso->blockofs);
196    
197     return iso;
198     }
199    
200     isoFile *isoCreate(const char *filename, int flags)
201     {
202     isoFile *iso;
203     char Zfile[256];
204    
205     iso = (isoFile*)malloc(sizeof(isoFile));
206     if (iso == NULL) return NULL;
207    
208     memset(iso, 0, sizeof(isoFile));
209     strcpy(iso->filename, filename);
210    
211     iso->flags = flags;
212     iso->offset = 0;
213     iso->blockofs = 24;
214     iso->blocksize = 2048;
215    
216     if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BZ2))
217     {
218     sprintf(Zfile, "%s.table", iso->filename);
219     iso->htable = _openfile(Zfile, O_WRONLY);
220    
221     if (iso->htable == NULL) return NULL;
222     }
223    
224     iso->handle = _openfile(iso->filename, O_WRONLY | O_CREAT);
225    
226     if (iso->handle == NULL)
227     {
228     Console.Error("Error loading %s", iso->filename);
229     return NULL;
230     }
231    
232     Console.WriteLn("isoCreate: %s ok", iso->filename);
233     Console.WriteLn("offset = %d", iso->offset);
234    
235     return iso;
236     }
237    
238     bool isoSetFormat(isoFile *iso, int blockofs, uint blocksize, uint blocks)
239     {
240     iso->blocksize = blocksize;
241     iso->blocks = blocks;
242     iso->blockofs = blockofs;
243    
244     Console.WriteLn("blockofs = %d", iso->blockofs);
245     Console.WriteLn("blocksize = %u", iso->blocksize);
246     Console.WriteLn("blocks = %u", iso->blocks);
247    
248     if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
249     {
250     if (_writefile(iso->handle, "BDV2", 4) < 4) return false;
251     if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
252     if (_writefile(iso->handle, &blocks, 4) < 4) return false;
253     if (_writefile(iso->handle, &blockofs, 4) < 4) return false;
254     }
255     else if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
256     {
257     if (_writefile(iso->handle, "BDV3", 4) < 4) return false;
258     if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
259     if (_writefile(iso->handle, &blocks, 4) < 4) return false;
260     }
261    
262     return true;
263     }
264    
265     bool _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
266     {
267     u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
268    
269     memset(dst, 0, iso->blockofs);
270     _seekfile(iso->handle, ofs, SEEK_SET);
271    
272     uint ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
273    
274     if (ret < iso->blocksize)
275     {
276     Console.Error("read error in _isoReadBlock." );
277     return false;
278     }
279    
280     return true;
281     }
282    
283     bool _isoReadBlockD(isoFile *iso, u8 *dst, uint lsn)
284     {
285     uint ret;
286    
287     // Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
288    
289     memset(dst, 0, iso->blockofs);
290     for (int i = 0; i < iso->dtablesize; i++)
291     {
292     if (iso->dtable[i] != lsn) continue;
293    
294     _seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
295     ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
296    
297     if (ret < iso->blocksize) return false;
298    
299     return true;
300     }
301     Console.WriteLn("Block %u not found in dump", lsn);
302    
303     return false;
304     }
305    
306     bool _isoReadBlockM(isoFile *iso, u8 *dst, uint lsn)
307     {
308     u64 ofs;
309     uint ret, i;
310    
311     for (i = 0; i < 8; i++)
312     {
313     if ((lsn >= iso->multih[i].slsn) && (lsn <= iso->multih[i].elsn))
314     {
315     break;
316     }
317     }
318    
319     if (i == 8) return false;
320    
321     ofs = (u64)(lsn - iso->multih[i].slsn) * iso->blocksize + iso->offset;
322    
323     // Console.WriteLn("_isoReadBlock %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
324    
325     memset(dst, 0, iso->blockofs);
326     _seekfile(iso->multih[i].handle, ofs, SEEK_SET);
327     ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize);
328    
329     if (ret < iso->blocksize)
330     {
331     Console.Error("read error in _isoReadBlockM");
332     return false;
333     }
334    
335     return true;
336     }
337    
338     bool isoReadBlock(isoFile *iso, u8 *dst, uint lsn)
339     {
340     bool ret;
341    
342     if (lsn > iso->blocks)
343     {
344     Console.WriteLn("isoReadBlock: %u > %u", lsn, iso->blocks);
345     return false;
346     }
347    
348     if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
349     ret = _isoReadBlockD(iso, dst, lsn);
350     else if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
351     ret = _isoReadBlockD(iso, dst, lsn);
352     else if (iso->flags & ISOFLAGS_MULTI)
353     ret = _isoReadBlockM(iso, dst, lsn);
354     else
355     ret = _isoReadBlock(iso, dst, lsn);
356    
357     if (!ret) return false;
358    
359     if (iso->type == ISOTYPE_CD)
360     {
361     lsn_to_msf(dst + 12, lsn);
362     dst[15] = 2;
363     }
364    
365     return true;
366     }
367    
368    
369     bool _isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
370     {
371     uint ret;
372     u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
373    
374     _seekfile(iso->handle, ofs, SEEK_SET);
375     ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
376     if (ret < iso->blocksize) return false;
377    
378     return true;
379     }
380    
381     bool _isoWriteBlockD(isoFile *iso, u8 *src, uint lsn)
382     {
383     uint ret;
384    
385     ret = _writefile(iso->handle, &lsn, 4);
386     if (ret < 4) return false;
387     ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
388    
389     if (ret < iso->blocksize) return false;
390    
391     return true;
392     }
393    
394     bool isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
395     {
396     if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
397     return _isoWriteBlockD(iso, src, lsn);
398     else
399     return _isoWriteBlock(iso, src, lsn);
400     }
401    
402     void isoClose(isoFile *iso)
403     {
404     if (iso == NULL ) return;
405     if (iso->handle) _closefile(iso->handle);
406     if (iso->htable) _closefile(iso->htable);
407     safe_free( iso->buffer );
408     safe_free( iso->dtable );
409     safe_free( iso );
410     }
411    

  ViewVC Help
Powered by ViewVC 1.1.22