1 #include "include/usbld.h"
2 #include "include/lang.h"
3 #include "include/gui.h"
4 #include "include/supportbase.h"
5 #include "include/ethsupport.h"
6 #include "include/util.h"
7 #include "include/themes.h"
8 #include "include/textures.h"
9 #include "include/ioman.h"
10 #include "include/system.h"
11 #include "include/smbman.h"
13 extern void *smb_cdvdman_irx
;
14 extern int size_smb_cdvdman_irx
;
16 extern void *smb_pcmcia_cdvdman_irx
;
17 extern int size_smb_pcmcia_cdvdman_irx
;
19 extern void *ps2dev9_irx
;
20 extern int size_ps2dev9_irx
;
22 extern void *smsutils_irx
;
23 extern int size_smsutils_irx
;
25 extern void *smstcpip_irx
;
26 extern int size_smstcpip_irx
;
28 extern void *smsmap_irx
;
29 extern int size_smsmap_irx
;
31 extern void *smbman_irx
;
32 extern int size_smbman_irx
;
35 extern void *smb_mcemu_irx
;
36 extern int size_smb_mcemu_irx
;
39 static char *ethPrefix
= NULL
;
40 static int ethULSizePrev
= -2;
41 static unsigned char ethModifiedCDPrev
[8];
42 static unsigned char ethModifiedDVDPrev
[8];
43 static int ethGameCount
= 0;
44 static base_game_info_t
*ethGames
= NULL
;
46 // forward declaration
47 static item_list_t ethGameList
;
49 static void ethLoadModules(void) {
51 char ipconfig
[IPCONFIG_MAX_LEN
] __attribute__((aligned(64)));
53 LOG("ethLoadModules()\n");
55 ipconfiglen
= sysSetIPConfig(ipconfig
);
59 ret
= sysLoadModuleBuffer(&ps2dev9_irx
, size_ps2dev9_irx
, 0, NULL
);
67 ret
= sysLoadModuleBuffer(&smsutils_irx
, size_smsutils_irx
, 0, NULL
);
74 ret
= sysLoadModuleBuffer(&smstcpip_irx
, size_smstcpip_irx
, 0, NULL
);
82 ret
= sysLoadModuleBuffer(&smsmap_irx
, size_smsmap_irx
, ipconfiglen
, ipconfig
);
90 ret
= sysLoadModuleBuffer(&smbman_irx
, size_smbman_irx
, 0, NULL
);
96 gNetworkStartup
= 0; // ok, all loaded
98 LOG("ethLoadModules: modules loaded\n");
105 sprintf(path
, "%sTHM", ethPrefix
);
106 thmAddElements(path
, "\\", ethGameList
.mode
);
109 sprintf(path
, "%sVMC", ethPrefix
);
110 checkCreateDir(path
);
119 memset(ethModifiedCDPrev
, 0, 8);
120 memset(ethModifiedDVDPrev
, 0, 8);
125 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, ðLoadModules
);
127 ethGameList
.enabled
= 1;
130 item_list_t
* ethGetObject(int initOnly
) {
131 if (initOnly
&& !ethGameList
.enabled
)
136 static int ethNeedsUpdate(void) {
139 if (gNetworkStartup
== 0) {
143 sprintf(path
, "%sCD", ethPrefix
);
144 if (fioGetstat(path
, &stat
) != 0)
145 memset(stat
.mtime
, 0, 8);
146 if (memcmp(ethModifiedCDPrev
, stat
.mtime
, 8)) {
147 memcpy(ethModifiedCDPrev
, stat
.mtime
, 8);
151 sprintf(path
, "%sDVD", ethPrefix
);
152 if (fioGetstat(path
, &stat
) != 0)
153 memset(stat
.mtime
, 0, 8);
154 if (memcmp(ethModifiedDVDPrev
, stat
.mtime
, 8)) {
155 memcpy(ethModifiedDVDPrev
, stat
.mtime
, 8);
159 if (!sbIsSameSize(ethPrefix
, ethULSizePrev
))
165 static int ethUpdateGameList(void) {
166 if (gNetworkStartup
!= 0)
169 sbReadList(ðGames
, ethPrefix
, ðULSizePrev
, ðGameCount
);
173 static int ethGetGameCount(void) {
177 static void* ethGetGame(int id
) {
178 return (void*) ðGames
[id
];
181 static char* ethGetGameName(int id
) {
182 return ethGames
[id
].name
;
185 static int ethGetGameNameLength(int id
) {
186 if (ethGames
[id
].isISO
)
187 return ISO_GAME_NAME_MAX
+ 1;
189 return UL_GAME_NAME_MAX
+ 1;
192 static char* ethGetGameStartup(int id
) {
193 return ethGames
[id
].startup
;
197 static void ethDeleteGame(int id
) {
198 sbDelete(ðGames
, ethPrefix
, "\\", ethGameCount
, id
);
202 static void ethRenameGame(int id
, char* newName
) {
203 sbRename(ðGames
, ethPrefix
, "\\", ethGameCount
, id
, newName
);
208 static int ethGetGameCompatibility(int id
, int *dmaMode
) {
209 return configGetCompatibility(ethGames
[id
].startup
, ethGameList
.mode
, NULL
);
212 static void ethSetGameCompatibility(int id
, int compatMode
, int dmaMode
) {
213 configSetCompatibility(ethGames
[id
].startup
, ethGameList
.mode
, compatMode
, -1);
217 static int ethPrepareMcemu(base_game_info_t
* game
) {
221 int i
, j
, fd
, size_mcemu_irx
= 0;
222 smb_vmc_infos_t smb_vmc_infos
;
223 vmc_superblock_t vmc_superblock
;
225 configGetVMC(game
->startup
, vmc
[0], ETH_MODE
, 0);
226 configGetVMC(game
->startup
, vmc
[1], ETH_MODE
, 1);
229 if(!vmc
[i
][0]) // skip if empty
232 memset(&smb_vmc_infos
, 0, sizeof(smb_vmc_infos_t
));
233 memset(&vmc_superblock
, 0, sizeof(vmc_superblock_t
));
235 snprintf(vmc_path
, 255, "%s\\VMC\\%s.bin", ethPrefix
, vmc
[i
]);
237 fd
= fileXioOpen(vmc_path
, O_RDONLY
, 0666);
240 LOG("%s open\n", vmc_path
);
242 vmc_size
= fileXioLseek(fd
, 0, SEEK_END
);
243 fileXioLseek(fd
, 0, SEEK_SET
);
244 fileXioRead(fd
, (void*)&vmc_superblock
, sizeof(vmc_superblock_t
));
246 LOG("File size : 0x%X\n", vmc_size
);
247 LOG("Magic : %s\n", vmc_superblock
.magic
);
248 LOG("Card type : %d\n", vmc_superblock
.mc_type
);
250 if(!strncmp(vmc_superblock
.magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
.mc_type
== 0x2) {
251 smb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
252 smb_vmc_infos
.flags
|= 0x100;
253 smb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
254 smb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
255 smb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
257 LOG("flags : 0x%X\n", smb_vmc_infos
.flags
);
258 LOG("specs.page_size : 0x%X\n", smb_vmc_infos
.specs
.page_size
);
259 LOG("specs.block_size : 0x%X\n", smb_vmc_infos
.specs
.block_size
);
260 LOG("specs.card_size : 0x%X\n", smb_vmc_infos
.specs
.card_size
);
262 if(vmc_size
== smb_vmc_infos
.specs
.card_size
* smb_vmc_infos
.specs
.page_size
) {
263 smb_vmc_infos
.active
= 1;
264 smb_vmc_infos
.fid
= 0xFFFF;
265 snprintf(vmc_path
, 255, "VMC\\%s.bin", vmc
[i
]);
266 strncpy(smb_vmc_infos
.fname
, vmc_path
, 32); // maybe a too small size here ...
268 LOG("%s is a valid Vmc file\n", smb_vmc_infos
.fname
);
273 for (j
=0; j
<size_smb_mcemu_irx
; j
++) {
274 if (((u32
*)&smb_mcemu_irx
)[j
] == (0xC0DEFAC0 + i
)) {
275 if(smb_vmc_infos
.active
)
276 size_mcemu_irx
= size_smb_mcemu_irx
;
277 memcpy(&((u32
*)&smb_mcemu_irx
)[j
], &smb_vmc_infos
, sizeof(smb_vmc_infos_t
));
282 return size_mcemu_irx
;
286 static void ethLaunchGame(int id
) {
287 if (gNetworkStartup
!= 0) {
288 guiMsgBox(_l(_STR_NETWORK_STARTUP_ERROR
), 0, NULL
);
292 int i
, compatmask
, size_irx
= 0;
294 char isoname
[32], filename
[32];
295 base_game_info_t
* game
= ðGames
[id
];
297 if (gRememberLastPlayed
) {
298 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
299 saveConfig(CONFIG_LAST
, 0);
302 if (sysPcmciaCheck()) {
303 size_irx
= size_smb_pcmcia_cdvdman_irx
;
304 irx
= &smb_pcmcia_cdvdman_irx
;
307 size_irx
= size_smb_cdvdman_irx
;
308 irx
= &smb_cdvdman_irx
;
311 compatmask
= sbPrepare(game
, ethGameList
.mode
, isoname
, size_irx
, irx
, &i
);
313 // For ISO we use the part table to store the "long" name (only for init)
315 memcpy((void*)((u32
)irx
+ i
+ 44), game
->name
, strlen(game
->name
) + 1);
317 for (i
= 0; i
< size_irx
; i
++) {
318 if (!strcmp((const char*)((u32
)irx
+ i
),"xxx.xxx.xxx.xxx")) {
324 int size_mcemu_irx
= ethPrepareMcemu(game
);
325 if (size_mcemu_irx
== -1) {
326 if (guiMsgBox(_l(_STR_ERR_VMC_CONTINUE
), 1, NULL
))
332 // disconnect from the active SMB session
335 char config_str
[255];
336 sprintf(config_str
, "%d.%d.%d.%d", pc_ip
[0], pc_ip
[1], pc_ip
[2], pc_ip
[3]);
337 memcpy((void*)((u32
)irx
+ i
), config_str
, strlen(config_str
) + 1);
338 memcpy((void*)((u32
)irx
+ i
+ 16), &gPCPort
, 4);
339 memcpy((void*)((u32
)irx
+ i
+ 20), gPCShareName
, 32);
340 memcpy((void*)((u32
)irx
+ i
+ 56), gPCUserName
, 32);
341 memcpy((void*)((u32
)irx
+ i
+ 92), gPCPassword
, 32);
343 sprintf(filename
,"%s",game
->startup
);
344 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call ethCleanUp, so ethGames/game will be freed
345 // disconnect from the active SMB session
350 sysLaunchLoaderElf(filename
, "ETH_MODE", size_irx
, irx
, size_mcemu_irx
, &smb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
352 sysLaunchLoaderElf(filename
, "ETH_MODE", size_irx
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
356 static config_set_t
* ethGetConfig(int id
) {
357 return sbPopulateConfig(ðGames
[id
], ethPrefix
, "\\");
360 static int ethGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
363 sprintf(path
, "%s%s\\%s_%s", ethPrefix
, folder
, value
, suffix
);
365 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
366 return texDiscoverLoad(resultTex
, path
, -1, psm
);
369 static void ethCleanUp(int exception
) {
370 if (ethGameList
.enabled
) {
371 LOG("ethCleanUp()\n");
378 static int ethCheckVMC(char* name
, int createSize
) {
379 return sysCheckVMC(ethPrefix
, "\\", name
, createSize
);
383 int ethSMBConnect(void) {
387 smbOpenShare_in_t openshare
;
389 // open tcp connection with the server / logon to SMB server
390 sprintf(logon
.serverIP
, "%d.%d.%d.%d", pc_ip
[0], pc_ip
[1], pc_ip
[2], pc_ip
[3]);
391 logon
.serverPort
= gPCPort
;
393 if (strlen(gPCPassword
) > 0) {
394 smbGetPasswordHashes_in_t passwd
;
395 smbGetPasswordHashes_out_t passwdhashes
;
397 // we'll try to generate hashed password first
398 strncpy(logon
.User
, gPCUserName
, 32);
399 strncpy(passwd
.password
, gPCPassword
, 32);
401 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_GETPASSWORDHASHES
, (void *)&passwd
, sizeof(passwd
), (void *)&passwdhashes
, sizeof(passwdhashes
));
404 // hash generated okay, can use
405 memcpy((void *)logon
.Password
, (void *)&passwdhashes
, sizeof(passwdhashes
));
406 logon
.PasswordType
= HASHED_PASSWORD
;
407 memcpy((void *)openshare
.Password
, (void *)&passwdhashes
, sizeof(passwdhashes
));
408 openshare
.PasswordType
= HASHED_PASSWORD
;
410 // failed hashing, failback to plaintext
411 strncpy(logon
.Password
, gPCPassword
, 32);
412 logon
.PasswordType
= PLAINTEXT_PASSWORD
;
413 strncpy(openshare
.Password
, gPCPassword
, 32);
414 openshare
.PasswordType
= PLAINTEXT_PASSWORD
;
417 strncpy(logon
.User
, gPCUserName
, 32);
418 logon
.PasswordType
= NO_PASSWORD
;
419 openshare
.PasswordType
= NO_PASSWORD
;
422 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_LOGON
, (void *)&logon
, sizeof(logon
), NULL
, 0);
426 // SMB server alive test
427 strcpy(echo
.echo
, "ALIVE ECHO TEST");
428 echo
.len
= strlen("ALIVE ECHO TEST");
430 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_ECHO
, (void *)&echo
, sizeof(echo
), NULL
, 0);
434 // connect to the share
435 strcpy(openshare
.ShareName
, gPCShareName
);
437 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_OPENSHARE
, (void *)&openshare
, sizeof(openshare
), NULL
, 0);
444 int ethSMBDisconnect(void) {
448 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_CLOSESHARE
, NULL
, 0, NULL
, 0);
452 // logoff/close tcp connection from SMB server:
453 ret
= fileXioDevctl(ethPrefix
, SMB_DEVCTL_LOGOFF
, NULL
, 0, NULL
, 0);
460 static item_list_t ethGameList
= {
461 ETH_MODE
, 0, 0, MENU_MIN_INACTIVE_FRAMES
, "ETH Games", _STR_NET_GAMES
, ðInit
, ðNeedsUpdate
,
463 ðUpdateGameList
, ðGetGameCount
, ðGetGame
, ðGetGameName
, ðGetGameNameLength
, ðGetGameStartup
, NULL
, NULL
,
465 ðUpdateGameList
, ðGetGameCount
, ðGetGame
, ðGetGameName
, ðGetGameNameLength
, ðGetGameStartup
, ðDeleteGame
, ðRenameGame
,
468 ðGetGameCompatibility
, ðSetGameCompatibility
, ðLaunchGame
, ðGetConfig
, ðGetImage
, ðCleanUp
, ðCheckVMC
, ETH_ICON
470 ðGetGameCompatibility
, ðSetGameCompatibility
, ðLaunchGame
, ðGetConfig
, ðGetImage
, ðCleanUp
, ETH_ICON