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

Contents of /trunk/pcsx2/CDVD/IsoFS/IsoFS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 7 months ago) by william
File size: 6346 byte(s)
committing r3113 initial commit again...
1 /* 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
19 #include "IsoFS.h"
20 #include "IsoFile.h"
21
22 //////////////////////////////////////////////////////////////////////////
23 // IsoDirectory
24 //////////////////////////////////////////////////////////////////////////
25
26 //u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL
27 //u8 volID[5]; // "CD001"
28
29
30 wxString IsoDirectory::FStype_ToString() const
31 {
32 switch( m_fstype )
33 {
34 case FStype_ISO9660: return L"ISO9660"; break;
35 case FStype_Joliet: return L"Joliet"; break;
36 }
37
38 return wxsFormat( L"Unrecognized Code (0x%x)", m_fstype );
39 }
40
41 // Used to load the Root directory from an image
42 IsoDirectory::IsoDirectory(SectorSource& r)
43 : internalReader(r)
44 {
45 IsoFileDescriptor rootDirEntry;
46 bool isValid = false;
47 bool done = false;
48 uint i = 16;
49
50 m_fstype = FStype_ISO9660;
51
52 while( !done )
53 {
54 u8 sector[2048];
55 internalReader.readSector(sector,i);
56 if( memcmp( &sector[1], "CD001", 5 ) == 0 )
57 {
58 switch (sector[0])
59 {
60 case 0:
61 Console.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Boot partition info.", i );
62 break;
63
64 case 1:
65 Console.WriteLn( "(IsoFS) Block 0x%x: Primary partition info.", i );
66 rootDirEntry.Load( sector+156, 38 );
67 isValid = true;
68 break;
69
70 case 2:
71 // Probably means Joliet (long filenames support), which PCSX2 doesn't care about.
72 Console.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Extended partition info.", i );
73 m_fstype = FStype_Joliet;
74 break;
75
76 case 0xff:
77 // Null terminator. End of partition information.
78 done = true;
79 break;
80
81 default:
82 Console.Error( "(IsoFS) Unknown partition type ID=%d, encountered at block 0x%x", sector[0], i );
83 break;
84 }
85 }
86 else
87 {
88 sector[9] = 0;
89 Console.Error( "(IsoFS) Invalid partition descriptor encountered at block 0x%x: '%s'", i, &sector[1] );
90 break; // if no valid root partition was found, an exception will be thrown below.
91 }
92
93 ++i;
94 }
95
96 if( !isValid )
97 throw Exception::FileNotFound( "IsoFS", "Root directory not found on ISO image." );
98
99 DevCon.WriteLn( L"(IsoFS) Filesystem is " + FStype_ToString() );
100 Init( rootDirEntry );
101 }
102
103 // Used to load a specific directory from a file descriptor
104 IsoDirectory::IsoDirectory(SectorSource& r, IsoFileDescriptor directoryEntry)
105 : internalReader(r)
106 {
107 Init(directoryEntry);
108 }
109
110 IsoDirectory::~IsoDirectory() throw()
111 {
112 }
113
114 void IsoDirectory::Init(const IsoFileDescriptor& directoryEntry)
115 {
116 // parse directory sector
117 IsoFile dataStream (internalReader, directoryEntry);
118
119 files.clear();
120
121 uint remainingSize = directoryEntry.size;
122
123 u8 b[257];
124
125 while(remainingSize>=4) // hm hack :P
126 {
127 b[0] = dataStream.read<u8>();
128
129 if(b[0]==0)
130 {
131 break; // or continue?
132 }
133
134 remainingSize -= b[0];
135
136 dataStream.read(b+1, b[0]-1);
137
138 files.push_back(IsoFileDescriptor(b, b[0]));
139 }
140
141 b[0] = 0;
142 }
143
144 const IsoFileDescriptor& IsoDirectory::GetEntry(int index) const
145 {
146 return files[index];
147 }
148
149 int IsoDirectory::GetIndexOf(const wxString& fileName) const
150 {
151 for(unsigned int i=0;i<files.size();i++)
152 {
153 if(files[i].name == fileName) return i;
154 }
155
156 throw Exception::FileNotFound( fileName );
157 }
158
159 const IsoFileDescriptor& IsoDirectory::GetEntry(const wxString& fileName) const
160 {
161 return GetEntry(GetIndexOf(fileName));
162 }
163
164 IsoFileDescriptor IsoDirectory::FindFile(const wxString& filePath) const
165 {
166 pxAssert( !filePath.IsEmpty() );
167
168 // wxWidgets DOS-style parser should work fine for ISO 9660 path names. Only practical difference
169 // is case sensitivity, and that won't matter for path splitting.
170 wxFileName parts( filePath, wxPATH_DOS );
171 IsoFileDescriptor info;
172 const IsoDirectory* dir = this;
173 ScopedPtr<IsoDirectory> deleteme;
174
175 // walk through path ("." and ".." entries are in the directories themselves, so even if the
176 // path included . and/or .., it still works)
177
178 for(uint i=0; i<parts.GetDirCount(); ++i)
179 {
180 info = dir->GetEntry(parts.GetDirs()[i]);
181 if(info.IsFile()) throw Exception::FileNotFound( filePath );
182
183 dir = deleteme = new IsoDirectory(internalReader, info);
184 }
185
186 if( !parts.GetFullName().IsEmpty() )
187 info = dir->GetEntry(parts.GetFullName());
188
189 return info;
190 }
191
192 bool IsoDirectory::IsFile(const wxString& filePath) const
193 {
194 if( filePath.IsEmpty() ) return false;
195 return (FindFile(filePath).flags&2) != 2;
196 }
197
198 bool IsoDirectory::IsDir(const wxString& filePath) const
199 {
200 if( filePath.IsEmpty() ) return false;
201 return (FindFile(filePath).flags&2) == 2;
202 }
203
204 u32 IsoDirectory::GetFileSize( const wxString& filePath ) const
205 {
206 return FindFile( filePath ).size;
207 }
208
209 IsoFileDescriptor::IsoFileDescriptor()
210 {
211 lba = 0;
212 size = 0;
213 flags = 0;
214 }
215
216 IsoFileDescriptor::IsoFileDescriptor(const u8* data, int length)
217 {
218 Load( data, length );
219 }
220
221 void IsoFileDescriptor::Load( const u8* data, int length )
222 {
223 lba = (u32&)data[2];
224 size = (u32&)data[10];
225
226 date.year = data[18] + 1900;
227 date.month = data[19];
228 date.day = data[20];
229 date.hour = data[21];
230 date.minute = data[22];
231 date.second = data[23];
232 date.gmtOffset = data[24];
233
234 flags = data[25];
235
236 int fileNameLength = data[32];
237
238 if(fileNameLength==1)
239 {
240 u8 c = data[33];
241
242 switch(c)
243 {
244 case 0: name = L"."; break;
245 case 1: name = L".."; break;
246 default: name = (wxChar)c;
247 }
248 }
249 else
250 {
251 // copy string and up-convert from ascii to wxChar
252
253 const u8* fnsrc = data+33;
254 const u8* fnend = fnsrc+fileNameLength;
255
256 while( fnsrc != fnend )
257 {
258 name += (wxChar)*fnsrc;
259 ++fnsrc;
260 }
261 }
262 }

  ViewVC Help
Powered by ViewVC 1.1.22