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"
12 extern void *smb_cdvdman_irx
;
13 extern int size_smb_cdvdman_irx
;
15 extern void *smb_pcmcia_cdvdman_irx
;
16 extern int size_smb_pcmcia_cdvdman_irx
;
18 extern void *ps2dev9_irx
;
19 extern int size_ps2dev9_irx
;
21 extern void *smsutils_irx
;
22 extern int size_smsutils_irx
;
24 extern void *smstcpip_irx
;
25 extern int size_smstcpip_irx
;
27 extern void *smsmap_irx
;
28 extern int size_smsmap_irx
;
30 extern void *smbman_irx
;
31 extern int size_smbman_irx
;
34 extern void *smb_mcemu_irx
;
35 extern int size_smb_mcemu_irx
;
38 static char ethPrefix
[40];
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 void ethSMBConnect(void) {
52 smbOpenShare_in_t openshare
;
54 if (gETHPrefix
[0] != '\0')
55 sprintf(ethPrefix
, "%s%s\\", ethBase
, gETHPrefix
);
57 sprintf(ethPrefix
, ethBase
);
59 // open tcp connection with the server / logon to SMB server
60 sprintf(logon
.serverIP
, "%d.%d.%d.%d", pc_ip
[0], pc_ip
[1], pc_ip
[2], pc_ip
[3]);
61 logon
.serverPort
= gPCPort
;
63 if (strlen(gPCPassword
) > 0) {
64 smbGetPasswordHashes_in_t passwd
;
65 smbGetPasswordHashes_out_t passwdhashes
;
67 // we'll try to generate hashed password first
68 strncpy(logon
.User
, gPCUserName
, 32);
69 strncpy(passwd
.password
, gPCPassword
, 32);
71 if (fileXioDevctl(ethBase
, SMB_DEVCTL_GETPASSWORDHASHES
, (void *)&passwd
, sizeof(passwd
), (void *)&passwdhashes
, sizeof(passwdhashes
)) == 0) {
72 // hash generated okay, can use
73 memcpy((void *)logon
.Password
, (void *)&passwdhashes
, sizeof(passwdhashes
));
74 logon
.PasswordType
= HASHED_PASSWORD
;
75 memcpy((void *)openshare
.Password
, (void *)&passwdhashes
, sizeof(passwdhashes
));
76 openshare
.PasswordType
= HASHED_PASSWORD
;
78 // failed hashing, failback to plaintext
79 strncpy(logon
.Password
, gPCPassword
, 32);
80 logon
.PasswordType
= PLAINTEXT_PASSWORD
;
81 strncpy(openshare
.Password
, gPCPassword
, 32);
82 openshare
.PasswordType
= PLAINTEXT_PASSWORD
;
85 strncpy(logon
.User
, gPCUserName
, 32);
86 logon
.PasswordType
= NO_PASSWORD
;
87 openshare
.PasswordType
= NO_PASSWORD
;
90 gNetworkStartup
= ERROR_ETH_SMB_LOGON
;
91 if (fileXioDevctl(ethBase
, SMB_DEVCTL_LOGON
, (void *)&logon
, sizeof(logon
), NULL
, 0) >= 0) {
92 gNetworkStartup
= ERROR_ETH_SMB_ECHO
;
94 // SMB server alive test
95 strcpy(echo
.echo
, "ALIVE ECHO TEST");
96 echo
.len
= strlen("ALIVE ECHO TEST");
98 if (fileXioDevctl(ethBase
, SMB_DEVCTL_ECHO
, (void *)&echo
, sizeof(echo
), NULL
, 0) >= 0) {
99 gNetworkStartup
= ERROR_ETH_SMB_OPENSHARE
;
101 if (gPCShareName
[0]) {
102 // connect to the share
103 strcpy(openshare
.ShareName
, gPCShareName
);
105 if (fileXioDevctl(ethBase
, SMB_DEVCTL_OPENSHARE
, (void *)&openshare
, sizeof(openshare
), NULL
, 0) >= 0) {
115 int ethSMBDisconnect(void) {
119 ret
= fileXioDevctl(ethBase
, SMB_DEVCTL_CLOSESHARE
, NULL
, 0, NULL
, 0);
123 // logoff/close tcp connection from SMB server:
124 ret
= fileXioDevctl(ethBase
, SMB_DEVCTL_LOGOFF
, NULL
, 0, NULL
, 0);
131 static void ethInitSMB(void) {
135 if (gNetworkStartup
== 0) {
138 sprintf(path
, "%sTHM", ethPrefix
);
139 thmAddElements(path
, "\\", ethGameList
.mode
);
141 sprintf(path
, "%sCFG", ethPrefix
);
142 checkCreateDir(path
);
145 sprintf(path
, "%sVMC", ethPrefix
);
146 checkCreateDir(path
);
148 } else if (gPCShareName
[0] || !(gNetworkStartup
>= ERROR_ETH_SMB_OPENSHARE
))
149 setErrorMessage(_STR_NETWORK_STARTUP_ERROR
, gNetworkStartup
);
152 static void ethLoadModules(void) {
154 char ipconfig
[IPCONFIG_MAX_LEN
] __attribute__((aligned(64)));
156 LOG("ETHSUPPORT LoadModules\n");
158 ipconfiglen
= sysSetIPConfig(ipconfig
);
160 gNetworkStartup
= ERROR_ETH_MODULE_PS2DEV9_FAILURE
;
161 if (sysLoadModuleBuffer(&ps2dev9_irx
, size_ps2dev9_irx
, 0, NULL
) >= 0) {
162 gNetworkStartup
= ERROR_ETH_MODULE_SMSUTILS_FAILURE
;
163 if (sysLoadModuleBuffer(&smsutils_irx
, size_smsutils_irx
, 0, NULL
) >= 0) {
164 gNetworkStartup
= ERROR_ETH_MODULE_SMSTCPIP_FAILURE
;
165 if (sysLoadModuleBuffer(&smstcpip_irx
, size_smstcpip_irx
, 0, NULL
) >= 0) {
166 gNetworkStartup
= ERROR_ETH_MODULE_SMSMAP_FAILURE
;
167 if (sysLoadModuleBuffer(&smsmap_irx
, size_smsmap_irx
, ipconfiglen
, ipconfig
) >= 0) {
168 gNetworkStartup
= ERROR_ETH_MODULE_SMBMAN_FAILURE
;
169 if (sysLoadModuleBuffer(&smbman_irx
, size_smbman_irx
, 0, NULL
) >= 0) {
170 LOG("ETHSUPPORT Modules loaded\n");
179 setErrorMessage(_STR_NETWORK_STARTUP_ERROR
, gNetworkStartup
);
183 if (gNetworkStartup
>= ERROR_ETH_SMB_LOGON
) {
184 LOG("ETHSUPPORT Re-Init\n");
188 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, ðInitSMB
);
190 LOG("ETHSUPPORT Init\n");
193 memset(ethModifiedCDPrev
, 0, 8);
194 memset(ethModifiedDVDPrev
, 0, 8);
197 configGetInt(configGetByType(CONFIG_OPL
), "eth_frames_delay", ðGameList
.delay
);
198 gNetworkStartup
= ERROR_ETH_NOT_STARTED
;
199 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, ðLoadModules
);
200 ethGameList
.enabled
= 1;
204 item_list_t
* ethGetObject(int initOnly
) {
205 if (initOnly
&& !ethGameList
.enabled
)
210 static int ethNeedsUpdate(void) {
211 if (ethULSizePrev
== -2)
214 if (gNetworkStartup
== 0) {
218 sprintf(path
, "%sCD", ethPrefix
);
219 if (fioGetstat(path
, &stat
) != 0)
220 memset(stat
.mtime
, 0, 8);
221 if (memcmp(ethModifiedCDPrev
, stat
.mtime
, 8)) {
222 memcpy(ethModifiedCDPrev
, stat
.mtime
, 8);
226 sprintf(path
, "%sDVD", ethPrefix
);
227 if (fioGetstat(path
, &stat
) != 0)
228 memset(stat
.mtime
, 0, 8);
229 if (memcmp(ethModifiedDVDPrev
, stat
.mtime
, 8)) {
230 memcpy(ethModifiedDVDPrev
, stat
.mtime
, 8);
234 if (!sbIsSameSize(ethPrefix
, ethULSizePrev
))
241 static int ethUpdateGameList(void) {
242 if (gPCShareName
[0]) {
243 if (gNetworkStartup
!= 0)
246 sbReadList(ðGames
, ethPrefix
, ðULSizePrev
, ðGameCount
);
249 ShareEntry_t sharelist
[128] __attribute__((aligned(64)));
250 smbGetShareList_in_t getsharelist
;
251 getsharelist
.EE_addr
= (void *)&sharelist
[0];
252 getsharelist
.maxent
= 128;
254 count
= fileXioDevctl(ethBase
, SMB_DEVCTL_GETSHARELIST
, (void *)&getsharelist
, sizeof(getsharelist
), NULL
, 0);
257 ethGames
= (base_game_info_t
*)malloc(sizeof(base_game_info_t
) * count
);
258 for (i
= 0; i
< count
; i
++) {
259 LOG("ETHSUPPORT Share found: %s\n", sharelist
[i
].ShareName
);
260 base_game_info_t
*g
= ðGames
[i
];
261 memcpy(g
->name
, sharelist
[i
].ShareName
, 32);
263 sprintf(g
->startup
, "SHARE");
264 g
->extension
[0] = '\0';
270 ethGameCount
= count
;
276 static int ethGetGameCount(void) {
280 static void* ethGetGame(int id
) {
281 return (void*) ðGames
[id
];
284 static char* ethGetGameName(int id
) {
285 return ethGames
[id
].name
;
288 static int ethGetGameNameLength(int id
) {
289 if (ethGames
[id
].isISO
)
290 return ISO_GAME_NAME_MAX
+ 1;
292 return UL_GAME_NAME_MAX
+ 1;
295 static char* ethGetGameStartup(int id
) {
296 return ethGames
[id
].startup
;
300 static void ethDeleteGame(int id
) {
301 sbDelete(ðGames
, ethPrefix
, "\\", ethGameCount
, id
);
305 static void ethRenameGame(int id
, char* newName
) {
306 sbRename(ðGames
, ethPrefix
, "\\", ethGameCount
, id
, newName
);
311 static void ethLaunchGame(int id
, config_set_t
* configSet
) {
312 int i
, compatmask
, size_irx
= 0;
315 base_game_info_t
* game
= ðGames
[id
];
317 if (!gPCShareName
[0]) {
318 memcpy(gPCShareName
, game
->name
, 32);
321 ioPutRequest(IO_MENU_UPDATE_DEFFERED
, ðGameList
.mode
); // clear the share list
322 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, ðInitSMB
);
323 ioPutRequest(IO_MENU_UPDATE_DEFFERED
, ðGameList
.mode
); // reload the game list
329 int vmc_id
, size_mcemu_irx
= 0;
330 smb_vmc_infos_t smb_vmc_infos
;
331 vmc_superblock_t vmc_superblock
;
333 for (vmc_id
= 0; vmc_id
< 2; vmc_id
++) {
334 memset(&smb_vmc_infos
, 0, sizeof(smb_vmc_infos_t
));
335 configGetVMC(configSet
, vmc_name
, vmc_id
);
337 if (sysCheckVMC(ethPrefix
, "\\", vmc_name
, 0, &vmc_superblock
) > 0) {
338 smb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
339 smb_vmc_infos
.flags
|= 0x100;
340 smb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
341 smb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
342 smb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
343 smb_vmc_infos
.active
= 1;
344 smb_vmc_infos
.fid
= 0xFFFF;
346 snprintf(smb_vmc_infos
.fname
, 64, "%s\\VMC\\%s.bin", gETHPrefix
, vmc_name
); // may still be too small size here ;) (should add 11 char !)
348 snprintf(smb_vmc_infos
.fname
, 64, "VMC\\%s.bin", vmc_name
);
351 snprintf(error
, 255, _l(_STR_ERR_VMC_CONTINUE
), vmc_name
, (vmc_id
+ 1));
352 if (!guiMsgBox(error
, 1, NULL
))
357 for (i
= 0; i
< size_smb_mcemu_irx
; i
++) {
358 if (((u32
*)&smb_mcemu_irx
)[i
] == (0xC0DEFAC0 + vmc_id
)) {
359 if (smb_vmc_infos
.active
)
360 size_mcemu_irx
= size_smb_mcemu_irx
;
361 memcpy(&((u32
*)&smb_mcemu_irx
)[i
], &smb_vmc_infos
, sizeof(smb_vmc_infos_t
));
368 if (gRememberLastPlayed
) {
369 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
370 saveConfig(CONFIG_LAST
, 0);
373 if (sysPcmciaCheck()) {
374 size_irx
= size_smb_pcmcia_cdvdman_irx
;
375 irx
= &smb_pcmcia_cdvdman_irx
;
378 size_irx
= size_smb_cdvdman_irx
;
379 irx
= &smb_cdvdman_irx
;
382 compatmask
= sbPrepare(game
, configSet
, size_irx
, irx
, &i
);
384 // For ISO we use the part table to store the "long" name (only for init)
386 memcpy((void*)((u32
)irx
+ i
), game
->extension
, 5);
387 strcpy((void*)((u32
)irx
+ i
+ 5), game
->startup
);
388 memcpy((void*)((u32
)irx
+ i
+ 44), game
->name
, strlen(game
->name
) + 1);
390 sprintf(filename
, "ul.%08X.%s", USBA_crc32(game
->name
), game
->startup
);
391 memcpy((void*)((u32
)irx
+ i
), filename
, strlen(filename
) + 1);
394 for (i
= 0; i
< size_irx
; i
++) {
395 if (!strcmp((const char*)((u32
)irx
+ i
),"xxx.xxx.xxx.xxx")) {
400 char config_str
[255];
401 sprintf(config_str
, "%d.%d.%d.%d", pc_ip
[0], pc_ip
[1], pc_ip
[2], pc_ip
[3]);
402 memcpy((void*)((u32
)irx
+ i
), config_str
, strlen(config_str
) + 1);
403 memcpy((void*)((u32
)irx
+ i
+ 16), &gPCPort
, 4);
404 memcpy((void*)((u32
)irx
+ i
+ 20), gPCShareName
, 32);
405 memcpy((void*)((u32
)irx
+ i
+ 52), gETHPrefix
, 32);
406 memcpy((void*)((u32
)irx
+ i
+ 84), gPCUserName
, 16);
407 memcpy((void*)((u32
)irx
+ i
+ 100), gPCPassword
, 16);
409 // disconnect from the active SMB session
412 char *altStartup
= NULL
;
413 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
414 strncpy(filename
, altStartup
, 32);
416 sprintf(filename
, "%s", game
->startup
);
417 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call ethCleanUp, so ethGames/game will be freed
421 sysLaunchLoaderElf(filename
, "ETH_MODE", size_irx
, irx
, size_mcemu_irx
, &smb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
423 sysLaunchLoaderElf(filename
, "ETH_MODE", size_irx
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
427 static config_set_t
* ethGetConfig(int id
) {
428 return sbPopulateConfig(ðGames
[id
], ethPrefix
, "\\");
431 static int ethGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
434 sprintf(path
, "%s%s\\%s_%s", ethPrefix
, folder
, value
, suffix
);
436 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
437 return texDiscoverLoad(resultTex
, path
, -1, psm
);
440 static void ethCleanUp(int exception
) {
441 if (ethGameList
.enabled
) {
442 LOG("ETHSUPPORT CleanUp\n");
449 static int ethCheckVMC(char* name
, int createSize
) {
450 return sysCheckVMC(ethPrefix
, "\\", name
, createSize
, NULL
);
454 static item_list_t ethGameList
= {
455 ETH_MODE
, 0, COMPAT
, 0, MENU_MIN_INACTIVE_FRAMES
, "ETH Games", _STR_NET_GAMES
, ðInit
, ðNeedsUpdate
,
457 ðUpdateGameList
, ðGetGameCount
, ðGetGame
, ðGetGameName
, ðGetGameNameLength
, ðGetGameStartup
, NULL
, NULL
,
459 ðUpdateGameList
, ðGetGameCount
, ðGetGame
, ðGetGameName
, ðGetGameNameLength
, ðGetGameStartup
, ðDeleteGame
, ðRenameGame
,
462 ðLaunchGame
, ðGetConfig
, ðGetImage
, ðCleanUp
, ðCheckVMC
, ETH_ICON
464 ðLaunchGame
, ðGetConfig
, ðGetImage
, ðCleanUp
, ETH_ICON