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 |
|
|
#include "PrecompiledHeader.h" |
17 |
|
|
#include "Common.h" |
18 |
|
|
|
19 |
|
|
#include "GS.h" // for sending game crc to mtgs |
20 |
|
|
#include "Elfheader.h" |
21 |
|
|
|
22 |
|
|
using namespace std; |
23 |
|
|
|
24 |
|
|
u32 ElfCRC; |
25 |
|
|
u32 ElfEntry; |
26 |
|
|
wxString LastELF; |
27 |
|
|
|
28 |
|
|
#if 0 |
29 |
|
|
// fixme: ELF command line option system. |
30 |
|
|
// It parses a command line and pastes it into PS2 memory, and then points the a0 register at it. |
31 |
|
|
// A user-written ELF can then load the data and respond accordingly. Needs a rewrite using modern |
32 |
|
|
// string parsing utils. :) |
33 |
|
|
|
34 |
|
|
//2002-09-19 (Florin) |
35 |
|
|
char args[256]="ez.m2v"; //to be accessed by other files |
36 |
|
|
uptr args_ptr; //a big value; in fact, it is an address |
37 |
|
|
|
38 |
|
|
static bool isEmpty(int addr) |
39 |
|
|
{ |
40 |
|
|
return ((PS2MEM_BASE[addr] == 0) || (PS2MEM_BASE[addr] == 32)); |
41 |
|
|
} |
42 |
|
|
|
43 |
|
|
//in a0 is passed the address of the command line args, |
44 |
|
|
//i.e. a pointer to an area like this: |
45 |
|
|
//+00 unknown/unused |
46 |
|
|
//+04 argc; number of arguments |
47 |
|
|
//+08 argv[0]; address of the first parameter - program name (char*) - |
48 |
|
|
//+08 argv[1]; address of the second parameter (char*) | |
49 |
|
|
//+0C argv[2]; and so on | |
50 |
|
|
//........ | |
51 |
|
|
//+08+4*argc the program name(first param) <-- |
52 |
|
|
//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args' |
53 |
|
|
// see above 'char args[256];' |
54 |
|
|
|
55 |
|
|
// The results of this function will normally be that it finds an arg at 13 chars, and another at 0. |
56 |
|
|
// It'd probably be easier to 0 out all 256 chars, split args, copy all the arguments in, and note |
57 |
|
|
// the locations of each split... --arcum42 |
58 |
|
|
|
59 |
|
|
static uint parseCommandLine( const wxString& filename ) |
60 |
|
|
{ |
61 |
|
|
if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > (4 + 4 + 256) ) ) |
62 |
|
|
{ |
63 |
|
|
const char *p; |
64 |
|
|
int argc, i, ret = 0; |
65 |
|
|
u32 args_end; |
66 |
|
|
|
67 |
|
|
args_ptr -= 256; |
68 |
|
|
|
69 |
|
|
args[ 255 ] = 0; |
70 |
|
|
|
71 |
|
|
// Copy the parameters into the section of memory at args_ptr, |
72 |
|
|
// then zero out anything past the end of args till 256 chars is reached. |
73 |
|
|
memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 ); |
74 |
|
|
memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) ); |
75 |
|
|
args_end = args_ptr + strlen( args ); |
76 |
|
|
|
77 |
|
|
// Set p to just the filename, no path. |
78 |
|
|
#ifdef _WIN32 |
79 |
|
|
p = strrchr( filename, '\\' ); |
80 |
|
|
#else //linux |
81 |
|
|
p = strrchr( filename, '/' ); |
82 |
|
|
if( p == NULL ) p = strchr(filename, '\\'); |
83 |
|
|
#endif |
84 |
|
|
if (p) |
85 |
|
|
p++; |
86 |
|
|
else |
87 |
|
|
p = filename; |
88 |
|
|
|
89 |
|
|
|
90 |
|
|
args_ptr -= strlen( p ) + 1; |
91 |
|
|
|
92 |
|
|
//fill param 0; i.e. name of the program |
93 |
|
|
strcpy( (char*)&PS2MEM_BASE[ args_ptr ], p ); |
94 |
|
|
|
95 |
|
|
// Start from the end of where we wrote to, not including all the zero'd out area. |
96 |
|
|
for ( i = args_end - args_ptr + 1, argc = 0; i > 0; i-- ) |
97 |
|
|
{ |
98 |
|
|
while (i && isEmpty(args_ptr + i )) { i--; } |
99 |
|
|
|
100 |
|
|
// If the last char is a space, set it to 0. |
101 |
|
|
if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ') PS2MEM_BASE[ args_ptr + i + 1 ] = 0; |
102 |
|
|
|
103 |
|
|
while (i && !isEmpty(args_ptr + i )) { i--; } |
104 |
|
|
|
105 |
|
|
// Now that we've gone back a word, increase the number of arguments, |
106 |
|
|
// and mark the location of the argument. |
107 |
|
|
if (!isEmpty(args_ptr + i )) // i <= 0 |
108 |
|
|
{ |
109 |
|
|
// If the spot we are on is not a space or null , use it. |
110 |
|
|
argc++; |
111 |
|
|
ret = args_ptr - 4 - 4 - argc * 4; |
112 |
|
|
|
113 |
|
|
if (ret < 0 ) return 0; |
114 |
|
|
((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i; |
115 |
|
|
} |
116 |
|
|
else |
117 |
|
|
{ |
118 |
|
|
if (!isEmpty(args_ptr + i + 1)) |
119 |
|
|
{ |
120 |
|
|
// Otherwise, use the next character . |
121 |
|
|
argc++; |
122 |
|
|
ret = args_ptr - 4 - 4 - argc * 4; |
123 |
|
|
|
124 |
|
|
if (ret < 0 ) return 0; |
125 |
|
|
((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1; |
126 |
|
|
} |
127 |
|
|
} |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
// Pass the number of arguments, and if we have arguments. |
131 |
|
|
((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args |
132 |
|
|
((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all |
133 |
|
|
|
134 |
|
|
return ret; |
135 |
|
|
} |
136 |
|
|
|
137 |
|
|
return 0; |
138 |
|
|
} |
139 |
|
|
#endif |
140 |
|
|
//--------------- |
141 |
|
|
|
142 |
|
|
// All of ElfObjects functions. |
143 |
|
|
ElfObject::ElfObject(const wxString& srcfile, IsoFile isofile) |
144 |
|
|
: filename( srcfile ) |
145 |
|
|
|
146 |
|
|
, data( wxULongLong(isofile.getLength()).GetLo(), L"ELF headers" ) |
147 |
|
|
, header( *(ELF_HEADER*)data.GetPtr() ) |
148 |
|
|
, proghead( NULL ) |
149 |
|
|
, secthead( NULL ) |
150 |
|
|
{ |
151 |
|
|
isCdvd = true; |
152 |
|
|
checkElfSize(data.GetSizeInBytes()); |
153 |
|
|
readIso(isofile); |
154 |
|
|
initElfHeaders(); |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
ElfObject::ElfObject( const wxString& srcfile, uint hdrsize ) |
158 |
|
|
: filename( srcfile ) |
159 |
|
|
, data( wxULongLong(hdrsize).GetLo(), L"ELF headers" ) |
160 |
|
|
, header( *(ELF_HEADER*)data.GetPtr() ) |
161 |
|
|
, proghead( NULL ) |
162 |
|
|
, secthead( NULL ) |
163 |
|
|
{ |
164 |
|
|
isCdvd = false; |
165 |
|
|
checkElfSize(data.GetSizeInBytes()); |
166 |
|
|
readFile(); |
167 |
|
|
initElfHeaders(); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
void ElfObject::initElfHeaders() |
171 |
|
|
{ |
172 |
|
|
Console.WriteLn( L"Initializing Elf: %d bytes", data.GetSizeInBytes()); |
173 |
|
|
|
174 |
|
|
if ( header.e_phnum > 0 ) |
175 |
|
|
proghead = (ELF_PHR*)&data[header.e_phoff]; |
176 |
|
|
|
177 |
|
|
if ( header.e_shnum > 0 ) |
178 |
|
|
secthead = (ELF_SHR*)&data[header.e_shoff]; |
179 |
|
|
|
180 |
|
|
if ( ( header.e_shnum > 0 ) && ( header.e_shentsize != sizeof(ELF_SHR) ) ) |
181 |
|
|
Console.Error( "(ELF) Size of section headers is not standard" ); |
182 |
|
|
|
183 |
|
|
if ( ( header.e_phnum > 0 ) && ( header.e_phentsize != sizeof(ELF_PHR) ) ) |
184 |
|
|
Console.Error( "(ELF) Size of program headers is not standard" ); |
185 |
|
|
|
186 |
|
|
//getCRC(); |
187 |
|
|
|
188 |
|
|
const char* elftype = NULL; |
189 |
|
|
switch( header.e_type ) |
190 |
|
|
{ |
191 |
|
|
default: |
192 |
|
|
ELF_LOG( "type: unknown = %x", header.e_type ); |
193 |
|
|
break; |
194 |
|
|
|
195 |
|
|
case 0x0: elftype = "no file type"; break; |
196 |
|
|
case 0x1: elftype = "relocatable"; break; |
197 |
|
|
case 0x2: elftype = "executable"; break; |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
if (elftype != NULL) ELF_LOG( "type: %s", elftype ); |
201 |
|
|
|
202 |
|
|
const char* machine = NULL; |
203 |
|
|
|
204 |
|
|
switch(header.e_machine) |
205 |
|
|
{ |
206 |
|
|
case 1: machine = "AT&T WE 32100"; break; |
207 |
|
|
case 2: machine = "SPARC"; break; |
208 |
|
|
case 3: machine = "Intel 80386"; break; |
209 |
|
|
case 4: machine = "Motorola 68000"; break; |
210 |
|
|
case 5: machine = "Motorola 88000"; break; |
211 |
|
|
case 7: machine = "Intel 80860"; break; |
212 |
|
|
case 8: machine = "mips_rs3000"; break; |
213 |
|
|
|
214 |
|
|
default: |
215 |
|
|
ELF_LOG( "machine: unknown = %x", header.e_machine ); |
216 |
|
|
break; |
217 |
|
|
} |
218 |
|
|
|
219 |
|
|
if (machine != NULL) ELF_LOG( "machine: %s", machine ); |
220 |
|
|
|
221 |
|
|
ELF_LOG("version: %d",header.e_version); |
222 |
|
|
ELF_LOG("entry: %08x",header.e_entry); |
223 |
|
|
ELF_LOG("flags: %08x",header.e_flags); |
224 |
|
|
ELF_LOG("eh size: %08x",header.e_ehsize); |
225 |
|
|
ELF_LOG("ph off: %08x",header.e_phoff); |
226 |
|
|
ELF_LOG("ph entsiz: %08x",header.e_phentsize); |
227 |
|
|
ELF_LOG("ph num: %08x",header.e_phnum); |
228 |
|
|
ELF_LOG("sh off: %08x",header.e_shoff); |
229 |
|
|
ELF_LOG("sh entsiz: %08x",header.e_shentsize); |
230 |
|
|
ELF_LOG("sh num: %08x",header.e_shnum); |
231 |
|
|
ELF_LOG("sh strndx: %08x",header.e_shstrndx); |
232 |
|
|
|
233 |
|
|
ELF_LOG("\n"); |
234 |
|
|
|
235 |
|
|
//applyPatches(); |
236 |
|
|
} |
237 |
|
|
|
238 |
|
|
bool ElfObject::hasProgramHeaders() { return (proghead != NULL); } |
239 |
|
|
bool ElfObject::hasSectionHeaders() { return (secthead != NULL); } |
240 |
|
|
bool ElfObject::hasHeaders() { return (hasProgramHeaders() && hasSectionHeaders()); } |
241 |
|
|
|
242 |
|
|
void ElfObject::readIso(IsoFile file) |
243 |
|
|
{ |
244 |
|
|
int rsize = file.read(data.GetPtr(), data.GetSizeInBytes()); |
245 |
|
|
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename ); |
246 |
|
|
} |
247 |
|
|
|
248 |
|
|
void ElfObject::readFile() |
249 |
|
|
{ |
250 |
|
|
int rsize = 0; |
251 |
|
|
FILE *f; |
252 |
|
|
|
253 |
|
|
f = fopen( filename.ToUTF8(), "rb" ); |
254 |
|
|
if (f == NULL) Exception::FileNotFound( filename ); |
255 |
|
|
|
256 |
|
|
fseek(f, 0, SEEK_SET); |
257 |
|
|
rsize = fread(data.GetPtr(), 1, data.GetSizeInBytes(), f); |
258 |
|
|
fclose( f ); |
259 |
|
|
|
260 |
|
|
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename ); |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
void ElfObject::checkElfSize(s64 elfsize) |
264 |
|
|
{ |
265 |
|
|
if (elfsize > 0xfffffff) |
266 |
|
|
throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 2GB!") ); |
267 |
|
|
|
268 |
|
|
if (elfsize == -1) |
269 |
|
|
throw Exception::BadStream( filename, wxLt("Elf file does not exist! ") ); |
270 |
|
|
|
271 |
|
|
if (elfsize == 0) |
272 |
|
|
throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") ); |
273 |
|
|
} |
274 |
|
|
|
275 |
|
|
u32 ElfObject::getCRC() |
276 |
|
|
{ |
277 |
|
|
u32 CRC = 0; |
278 |
|
|
|
279 |
|
|
const u32* srcdata = (u32*)data.GetPtr(); |
280 |
|
|
for(u32 i=data.GetSizeInBytes()/4; i; --i, ++srcdata) |
281 |
|
|
CRC ^= *srcdata; |
282 |
|
|
|
283 |
|
|
return CRC; |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
void ElfObject::loadProgramHeaders() |
287 |
|
|
{ |
288 |
|
|
if (proghead == NULL) return; |
289 |
|
|
|
290 |
|
|
for( int i = 0 ; i < header.e_phnum ; i++ ) |
291 |
|
|
{ |
292 |
|
|
ELF_LOG( "Elf32 Program Header" ); |
293 |
|
|
ELF_LOG( "type: " ); |
294 |
|
|
|
295 |
|
|
switch(proghead[ i ].p_type) |
296 |
|
|
{ |
297 |
|
|
default: |
298 |
|
|
ELF_LOG( "unknown %x", (int)proghead[ i ].p_type ); |
299 |
|
|
break; |
300 |
|
|
|
301 |
|
|
case 0x1: |
302 |
|
|
{ |
303 |
|
|
ELF_LOG("load"); |
304 |
|
|
const uint elfsize = data.GetLength(); |
305 |
|
|
|
306 |
|
|
if (proghead[ i ].p_offset < elfsize) |
307 |
|
|
{ |
308 |
|
|
int size; |
309 |
|
|
|
310 |
|
|
if ((proghead[ i ].p_filesz + proghead[ i ].p_offset) > elfsize) |
311 |
|
|
size = elfsize - proghead[ i ].p_offset; |
312 |
|
|
else |
313 |
|
|
size = proghead[ i ].p_filesz; |
314 |
|
|
|
315 |
|
|
if (proghead[ i ].p_vaddr != proghead[ i ].p_paddr) |
316 |
|
|
Console.Warning( "ElfProgram different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x", |
317 |
|
|
proghead[ i ].p_paddr, proghead[ i ].p_vaddr); |
318 |
|
|
|
319 |
|
|
// used to be paddr |
320 |
|
|
memcpy_fast( |
321 |
|
|
&PS2MEM_BASE[proghead[ i ].p_vaddr & 0x1ffffff], |
322 |
|
|
data.GetPtr(proghead[ i ].p_offset), size |
323 |
|
|
); |
324 |
|
|
|
325 |
|
|
ELF_LOG("\t*LOADED*"); |
326 |
|
|
} |
327 |
|
|
} |
328 |
|
|
break; |
329 |
|
|
} |
330 |
|
|
|
331 |
|
|
ELF_LOG("\n"); |
332 |
|
|
ELF_LOG("offset: %08x",proghead[i].p_offset); |
333 |
|
|
ELF_LOG("vaddr: %08x",proghead[i].p_vaddr); |
334 |
|
|
ELF_LOG("paddr: %08x",proghead[i].p_paddr); |
335 |
|
|
ELF_LOG("file size: %08x",proghead[i].p_filesz); |
336 |
|
|
ELF_LOG("mem size: %08x",proghead[i].p_memsz); |
337 |
|
|
ELF_LOG("flags: %08x",proghead[i].p_flags); |
338 |
|
|
ELF_LOG("palign: %08x",proghead[i].p_align); |
339 |
|
|
ELF_LOG("\n"); |
340 |
|
|
} |
341 |
|
|
} |
342 |
|
|
|
343 |
|
|
void ElfObject::loadSectionHeaders() |
344 |
|
|
{ |
345 |
|
|
if (secthead == NULL || header.e_shoff > (u32)data.GetLength()) return; |
346 |
|
|
|
347 |
|
|
const u8* sections_names = data.GetPtr( secthead[ (header.e_shstrndx == 0xffff ? 0 : header.e_shstrndx) ].sh_offset ); |
348 |
|
|
|
349 |
|
|
int i_st = -1, i_dt = -1; |
350 |
|
|
|
351 |
|
|
for( int i = 0 ; i < header.e_shnum ; i++ ) |
352 |
|
|
{ |
353 |
|
|
ELF_LOG( "ELF32 Section Header [%x] %s", i, §ions_names[ secthead[ i ].sh_name ] ); |
354 |
|
|
|
355 |
|
|
// used by parseCommandLine |
356 |
|
|
//if ( secthead[i].sh_flags & 0x2 ) |
357 |
|
|
// args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff ); |
358 |
|
|
|
359 |
|
|
ELF_LOG("\n"); |
360 |
|
|
|
361 |
|
|
const char* sectype = NULL; |
362 |
|
|
switch(secthead[ i ].sh_type) |
363 |
|
|
{ |
364 |
|
|
case 0x0: sectype = "null"; break; |
365 |
|
|
case 0x1: sectype = "progbits"; break; |
366 |
|
|
case 0x2: sectype = "symtab"; break; |
367 |
|
|
case 0x3: sectype = "strtab"; break; |
368 |
|
|
case 0x4: sectype = "rela"; break; |
369 |
|
|
case 0x8: sectype = "no bits"; break; |
370 |
|
|
case 0x9: sectype = "rel"; break; |
371 |
|
|
|
372 |
|
|
default: |
373 |
|
|
ELF_LOG("type: unknown %08x",secthead[i].sh_type); |
374 |
|
|
break; |
375 |
|
|
} |
376 |
|
|
|
377 |
|
|
ELF_LOG("type: %s", sectype); |
378 |
|
|
ELF_LOG("flags: %08x", secthead[i].sh_flags); |
379 |
|
|
ELF_LOG("addr: %08x", secthead[i].sh_addr); |
380 |
|
|
ELF_LOG("offset: %08x", secthead[i].sh_offset); |
381 |
|
|
ELF_LOG("size: %08x", secthead[i].sh_size); |
382 |
|
|
ELF_LOG("link: %08x", secthead[i].sh_link); |
383 |
|
|
ELF_LOG("info: %08x", secthead[i].sh_info); |
384 |
|
|
ELF_LOG("addralign: %08x", secthead[i].sh_addralign); |
385 |
|
|
ELF_LOG("entsize: %08x", secthead[i].sh_entsize); |
386 |
|
|
// dump symbol table |
387 |
|
|
|
388 |
|
|
if (secthead[ i ].sh_type == 0x02) |
389 |
|
|
{ |
390 |
|
|
i_st = i; |
391 |
|
|
i_dt = secthead[i].sh_link; |
392 |
|
|
} |
393 |
|
|
} |
394 |
|
|
|
395 |
|
|
if ((i_st >= 0) && (i_dt >= 0)) |
396 |
|
|
{ |
397 |
|
|
const char * SymNames; |
398 |
|
|
Elf32_Sym * eS; |
399 |
|
|
|
400 |
|
|
SymNames = (char*)data.GetPtr(secthead[i_dt].sh_offset); |
401 |
|
|
eS = (Elf32_Sym*)data.GetPtr(secthead[i_st].sh_offset); |
402 |
|
|
Console.WriteLn("found %d symbols", secthead[i_st].sh_size / sizeof(Elf32_Sym)); |
403 |
|
|
|
404 |
|
|
for(uint i = 1; i < (secthead[i_st].sh_size / sizeof(Elf32_Sym)); i++) { |
405 |
|
|
if ((eS[i].st_value != 0) && (ELF32_ST_TYPE(eS[i].st_info) == 2)) |
406 |
|
|
{ |
407 |
|
|
R5900::disR5900AddSym(eS[i].st_value, &SymNames[eS[i].st_name]); |
408 |
|
|
} |
409 |
|
|
} |
410 |
|
|
} |
411 |
|
|
} |
412 |
|
|
|
413 |
|
|
void ElfObject::loadHeaders() |
414 |
|
|
{ |
415 |
|
|
loadProgramHeaders(); |
416 |
|
|
loadSectionHeaders(); |
417 |
|
|
} |
418 |
|
|
|
419 |
|
|
// return value: |
420 |
|
|
// 0 - Invalid or unknown disc. |
421 |
|
|
// 1 - PS1 CD |
422 |
|
|
// 2 - PS2 CD |
423 |
|
|
int GetPS2ElfName( wxString& name ) |
424 |
|
|
{ |
425 |
|
|
int retype = 0; |
426 |
|
|
|
427 |
|
|
try { |
428 |
|
|
IsoFSCDVD isofs; |
429 |
|
|
IsoFile file( isofs, L"SYSTEM.CNF;1"); |
430 |
|
|
|
431 |
|
|
int size = file.getLength(); |
432 |
|
|
if( size == 0 ) return 0; |
433 |
|
|
|
434 |
|
|
|
435 |
|
|
while( !file.eof() ) |
436 |
|
|
{ |
437 |
|
|
wxString original( fromUTF8(file.readLine().c_str()) ); |
438 |
|
|
ParsedAssignmentString parts( original ); |
439 |
|
|
|
440 |
|
|
if( parts.lvalue.IsEmpty() && parts.rvalue.IsEmpty() ) continue; |
441 |
|
|
if( parts.rvalue.IsEmpty() ) |
442 |
|
|
{ |
443 |
|
|
Console.Error( "(GetElfName) Unusual or malformed entry in SYSTEM.CNF ignored:" ); |
444 |
|
|
Console.Indent().WriteLn( original ); |
445 |
|
|
continue; |
446 |
|
|
} |
447 |
|
|
|
448 |
|
|
if( parts.lvalue == L"BOOT2" ) |
449 |
|
|
{ |
450 |
|
|
name = parts.rvalue; |
451 |
|
|
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Detected PS2 Disc = " + name ); |
452 |
|
|
retype = 2; |
453 |
|
|
} |
454 |
|
|
else if( parts.lvalue == L"BOOT" ) |
455 |
|
|
{ |
456 |
|
|
name = parts.rvalue; |
457 |
|
|
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Detected PSX/PSone Disc = " + name ); |
458 |
|
|
retype = 1; |
459 |
|
|
} |
460 |
|
|
else if( parts.lvalue == L"VMODE" ) |
461 |
|
|
{ |
462 |
|
|
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Disc region type = " + parts.rvalue ); |
463 |
|
|
} |
464 |
|
|
else if( parts.lvalue == L"VER" ) |
465 |
|
|
{ |
466 |
|
|
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Software version = " + parts.rvalue ); |
467 |
|
|
} |
468 |
|
|
} |
469 |
|
|
|
470 |
|
|
if( retype == 0 ) |
471 |
|
|
{ |
472 |
|
|
Console.Error("(GetElfName) Disc image is *not* a Playstation or PS2 game!"); |
473 |
|
|
return 0; |
474 |
|
|
} |
475 |
|
|
} |
476 |
|
|
catch (Exception::BadStream&) |
477 |
|
|
{ |
478 |
|
|
return 0; // ISO error |
479 |
|
|
} |
480 |
|
|
catch( Exception::FileNotFound& ) |
481 |
|
|
{ |
482 |
|
|
return 0; // no SYSTEM.CNF, not a PS1/PS2 disc. |
483 |
|
|
} |
484 |
|
|
|
485 |
|
|
#ifdef PCSX2_DEVBUILD |
486 |
|
|
FILE *fp; |
487 |
|
|
int i; |
488 |
|
|
char buffer[512]; |
489 |
|
|
|
490 |
|
|
fp = fopen("System.map", "r"); |
491 |
|
|
if( fp == NULL ) return 2; |
492 |
|
|
|
493 |
|
|
u32 addr; |
494 |
|
|
|
495 |
|
|
Console.WriteLn("Loading System.map..."); |
496 |
|
|
while (!feof(fp)) { |
497 |
|
|
fseek(fp, 8, SEEK_CUR); |
498 |
|
|
buffer[0] = '0'; buffer[1] = 'x'; |
499 |
|
|
for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0; |
500 |
|
|
addr = strtoul(buffer, (char**)NULL, 0); |
501 |
|
|
fseek(fp, 3, SEEK_CUR); |
502 |
|
|
for (i=0; i<512; i++) { |
503 |
|
|
buffer[i] = fgetc(fp); |
504 |
|
|
if (buffer[i] == '\n' || buffer[i] == 0) break; |
505 |
|
|
} |
506 |
|
|
if (buffer[i] == 0) break; |
507 |
|
|
buffer[i] = 0; |
508 |
|
|
|
509 |
|
|
R5900::disR5900AddSym(addr, buffer); |
510 |
|
|
} |
511 |
|
|
fclose(fp); |
512 |
|
|
#endif |
513 |
|
|
|
514 |
|
|
return retype; |
515 |
|
|
} |