clarify the gui
[open-ps2-loader.git] / src / ethsupport.c
blobdb751dfe950a163767e744cae5226b79f30401f2
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;
33 #ifdef VMC
34 extern void *smb_mcemu_irx;
35 extern int size_smb_mcemu_irx;
36 #endif
38 static char *ethPrefix = NULL;
39 static int ethULSizePrev = -2;
40 static unsigned char ethModifiedCDPrev[8];
41 static unsigned char ethModifiedDVDPrev[8];
42 static int ethGameCount = 0;
43 static base_game_info_t *ethGames = NULL;
45 // forward declaration
46 static item_list_t ethGameList;
48 void ethSMBConnect(void) {
49 smbLogOn_in_t logon;
50 smbEcho_in_t echo;
51 smbOpenShare_in_t openshare;
53 // open tcp connection with the server / logon to SMB server
54 sprintf(logon.serverIP, "%d.%d.%d.%d", pc_ip[0], pc_ip[1], pc_ip[2], pc_ip[3]);
55 logon.serverPort = gPCPort;
57 if (strlen(gPCPassword) > 0) {
58 smbGetPasswordHashes_in_t passwd;
59 smbGetPasswordHashes_out_t passwdhashes;
61 // we'll try to generate hashed password first
62 strncpy(logon.User, gPCUserName, 32);
63 strncpy(passwd.password, gPCPassword, 32);
65 if (fileXioDevctl(ethPrefix, SMB_DEVCTL_GETPASSWORDHASHES, (void *)&passwd, sizeof(passwd), (void *)&passwdhashes, sizeof(passwdhashes)) == 0) {
66 // hash generated okay, can use
67 memcpy((void *)logon.Password, (void *)&passwdhashes, sizeof(passwdhashes));
68 logon.PasswordType = HASHED_PASSWORD;
69 memcpy((void *)openshare.Password, (void *)&passwdhashes, sizeof(passwdhashes));
70 openshare.PasswordType = HASHED_PASSWORD;
71 } else {
72 // failed hashing, failback to plaintext
73 strncpy(logon.Password, gPCPassword, 32);
74 logon.PasswordType = PLAINTEXT_PASSWORD;
75 strncpy(openshare.Password, gPCPassword, 32);
76 openshare.PasswordType = PLAINTEXT_PASSWORD;
78 } else {
79 strncpy(logon.User, gPCUserName, 32);
80 logon.PasswordType = NO_PASSWORD;
81 openshare.PasswordType = NO_PASSWORD;
84 gNetworkStartup = ERROR_ETH_SMB_LOGON;
85 if (fileXioDevctl(ethPrefix, SMB_DEVCTL_LOGON, (void *)&logon, sizeof(logon), NULL, 0) >= 0) {
86 gNetworkStartup = ERROR_ETH_SMB_ECHO;
88 // SMB server alive test
89 strcpy(echo.echo, "ALIVE ECHO TEST");
90 echo.len = strlen("ALIVE ECHO TEST");
92 if (fileXioDevctl(ethPrefix, SMB_DEVCTL_ECHO, (void *)&echo, sizeof(echo), NULL, 0) >= 0) {
93 gNetworkStartup = ERROR_ETH_SMB_OPENSHARE;
95 // connect to the share
96 strcpy(openshare.ShareName, gPCShareName);
98 if (fileXioDevctl(ethPrefix, SMB_DEVCTL_OPENSHARE, (void *)&openshare, sizeof(openshare), NULL, 0) >= 0) {
100 // everything is ok
101 gNetworkStartup = 0;
107 int ethSMBDisconnect(void) {
108 int ret;
110 // closing share
111 ret = fileXioDevctl(ethPrefix, SMB_DEVCTL_CLOSESHARE, NULL, 0, NULL, 0);
112 if (ret < 0)
113 return -1;
115 // logoff/close tcp connection from SMB server:
116 ret = fileXioDevctl(ethPrefix, SMB_DEVCTL_LOGOFF, NULL, 0, NULL, 0);
117 if (ret < 0)
118 return -2;
120 return 0;
123 static void ethInitSMB(void) {
124 // connect
125 ethSMBConnect();
127 if (gNetworkStartup == 0) {
128 // update Themes
129 char path[255];
130 sprintf(path, "%sTHM", ethPrefix);
131 thmAddElements(path, "\\", ethGameList.mode);
133 sprintf(path, "%sCFG", ethPrefix);
134 checkCreateDir(path);
136 #ifdef VMC
137 sprintf(path, "%sVMC", ethPrefix);
138 checkCreateDir(path);
139 #endif
140 } else
141 setErrorMessage(_STR_NETWORK_STARTUP_ERROR, gNetworkStartup);
144 static void ethLoadModules(void) {
145 int ipconfiglen;
146 char ipconfig[IPCONFIG_MAX_LEN] __attribute__((aligned(64)));
148 LOG("ethLoadModules()\n");
150 ipconfiglen = sysSetIPConfig(ipconfig);
152 gNetworkStartup = ERROR_ETH_MODULE_PS2DEV9_FAILURE;
153 if (sysLoadModuleBuffer(&ps2dev9_irx, size_ps2dev9_irx, 0, NULL) >= 0) {
154 gNetworkStartup = ERROR_ETH_MODULE_SMSUTILS_FAILURE;
155 if (sysLoadModuleBuffer(&smsutils_irx, size_smsutils_irx, 0, NULL) >= 0) {
156 gNetworkStartup = ERROR_ETH_MODULE_SMSTCPIP_FAILURE;
157 if (sysLoadModuleBuffer(&smstcpip_irx, size_smstcpip_irx, 0, NULL) >= 0) {
158 gNetworkStartup = ERROR_ETH_MODULE_SMSMAP_FAILURE;
159 if (sysLoadModuleBuffer(&smsmap_irx, size_smsmap_irx, ipconfiglen, ipconfig) >= 0) {
160 gNetworkStartup = ERROR_ETH_MODULE_SMBMAN_FAILURE;
161 if (sysLoadModuleBuffer(&smbman_irx, size_smbman_irx, 0, NULL) >= 0) {
162 LOG("ethLoadModules: modules loaded\n");
163 ethInitSMB();
164 return;
171 setErrorMessage(_STR_NETWORK_STARTUP_ERROR, gNetworkStartup);
174 void ethInit(void) {
175 LOG("ethInit()\n");
177 if (gNetworkStartup >= ERROR_ETH_SMB_LOGON) {
178 ethULSizePrev = -2;
179 ioPutRequest(IO_CUSTOM_SIMPLEACTION, &ethInitSMB);
180 } else {
181 ethPrefix = "smb0:";
182 ethULSizePrev = -2;
183 memset(ethModifiedCDPrev, 0, 8);
184 memset(ethModifiedDVDPrev, 0, 8);
185 ethGameCount = 0;
186 ethGames = NULL;
187 gNetworkStartup = ERROR_ETH_NOT_STARTED;
189 ioPutRequest(IO_CUSTOM_SIMPLEACTION, &ethLoadModules);
191 ethGameList.enabled = 1;
195 item_list_t* ethGetObject(int initOnly) {
196 if (initOnly && !ethGameList.enabled)
197 return NULL;
198 return &ethGameList;
201 static int ethNeedsUpdate(void) {
202 if (ethULSizePrev == -2)
203 return 1;
205 if (gNetworkStartup == 0) {
206 fio_stat_t stat;
207 char path[255];
209 sprintf(path, "%sCD", ethPrefix);
210 if (fioGetstat(path, &stat) != 0)
211 memset(stat.mtime, 0, 8);
212 if (memcmp(ethModifiedCDPrev, stat.mtime, 8)) {
213 memcpy(ethModifiedCDPrev, stat.mtime, 8);
214 return 1;
217 sprintf(path, "%sDVD", ethPrefix);
218 if (fioGetstat(path, &stat) != 0)
219 memset(stat.mtime, 0, 8);
220 if (memcmp(ethModifiedDVDPrev, stat.mtime, 8)) {
221 memcpy(ethModifiedDVDPrev, stat.mtime, 8);
222 return 1;
225 if (!sbIsSameSize(ethPrefix, ethULSizePrev))
226 return 1;
229 return 0;
232 static int ethUpdateGameList(void) {
233 if (gNetworkStartup != 0)
234 return 0;
236 sbReadList(&ethGames, ethPrefix, &ethULSizePrev, &ethGameCount);
237 return ethGameCount;
240 static int ethGetGameCount(void) {
241 return ethGameCount;
244 static void* ethGetGame(int id) {
245 return (void*) &ethGames[id];
248 static char* ethGetGameName(int id) {
249 return ethGames[id].name;
252 static int ethGetGameNameLength(int id) {
253 if (ethGames[id].isISO)
254 return ISO_GAME_NAME_MAX + 1;
255 else
256 return UL_GAME_NAME_MAX + 1;
259 static char* ethGetGameStartup(int id) {
260 return ethGames[id].startup;
263 #ifndef __CHILDPROOF
264 static void ethDeleteGame(int id) {
265 sbDelete(&ethGames, ethPrefix, "\\", ethGameCount, id);
266 ethULSizePrev = -2;
269 static void ethRenameGame(int id, char* newName) {
270 sbRename(&ethGames, ethPrefix, "\\", ethGameCount, id, newName);
271 ethULSizePrev = -2;
273 #endif
275 #ifdef VMC
276 static int ethPrepareMcemu(base_game_info_t* game, config_set_t* configSet) {
277 char vmc[2][32];
278 char vmc_path[255];
279 u32 vmc_size;
280 int i, j, fd, size_mcemu_irx = 0;
281 smb_vmc_infos_t smb_vmc_infos;
282 vmc_superblock_t vmc_superblock;
284 configGetVMC(configSet, vmc[0], 0);
285 configGetVMC(configSet, vmc[1], 1);
287 for(i=0; i<2; i++) {
288 if(!vmc[i][0]) // skip if empty
289 continue;
291 memset(&smb_vmc_infos, 0, sizeof(smb_vmc_infos_t));
292 memset(&vmc_superblock, 0, sizeof(vmc_superblock_t));
294 snprintf(vmc_path, 255, "%s\\VMC\\%s.bin", ethPrefix, vmc[i]);
296 fd = fileXioOpen(vmc_path, O_RDONLY, 0666);
297 if (fd >= 0) {
298 size_mcemu_irx = -1;
299 LOG("%s open\n", vmc_path);
301 vmc_size = fileXioLseek(fd, 0, SEEK_END);
302 fileXioLseek(fd, 0, SEEK_SET);
303 fileXioRead(fd, (void*)&vmc_superblock, sizeof(vmc_superblock_t));
305 LOG("File size : 0x%X\n", vmc_size);
306 LOG("Magic : %s\n", vmc_superblock.magic);
307 LOG("Card type : %d\n", vmc_superblock.mc_type);
309 if(!strncmp(vmc_superblock.magic, "Sony PS2 Memory Card Format", 27) && vmc_superblock.mc_type == 0x2) {
310 smb_vmc_infos.flags = vmc_superblock.mc_flag & 0xFF;
311 smb_vmc_infos.flags |= 0x100;
312 smb_vmc_infos.specs.page_size = vmc_superblock.page_size;
313 smb_vmc_infos.specs.block_size = vmc_superblock.pages_per_block;
314 smb_vmc_infos.specs.card_size = vmc_superblock.pages_per_cluster * vmc_superblock.clusters_per_card;
316 LOG("flags : 0x%X\n", smb_vmc_infos.flags );
317 LOG("specs.page_size : 0x%X\n", smb_vmc_infos.specs.page_size );
318 LOG("specs.block_size : 0x%X\n", smb_vmc_infos.specs.block_size);
319 LOG("specs.card_size : 0x%X\n", smb_vmc_infos.specs.card_size );
321 if(vmc_size == smb_vmc_infos.specs.card_size * smb_vmc_infos.specs.page_size) {
322 smb_vmc_infos.active = 1;
323 smb_vmc_infos.fid = 0xFFFF;
324 snprintf(vmc_path, 255, "VMC\\%s.bin", vmc[i]);
325 strncpy(smb_vmc_infos.fname, vmc_path, 32); // maybe a too small size here ...
327 LOG("%s is a valid Vmc file\n", smb_vmc_infos.fname );
330 fileXioClose(fd);
332 for (j=0; j<size_smb_mcemu_irx; j++) {
333 if (((u32*)&smb_mcemu_irx)[j] == (0xC0DEFAC0 + i)) {
334 if(smb_vmc_infos.active)
335 size_mcemu_irx = size_smb_mcemu_irx;
336 memcpy(&((u32*)&smb_mcemu_irx)[j], &smb_vmc_infos, sizeof(smb_vmc_infos_t));
337 break;
341 return size_mcemu_irx;
343 #endif
345 static void ethLaunchGame(int id, config_set_t* configSet) {
346 int i, compatmask, size_irx = 0;
347 void** irx = NULL;
348 char isoname[32], filename[32];
349 base_game_info_t* game = &ethGames[id];
351 if (gRememberLastPlayed) {
352 configSetStr(configGetByType(CONFIG_LAST), "last_played", game->startup);
353 saveConfig(CONFIG_LAST, 0);
356 if (sysPcmciaCheck()) {
357 size_irx = size_smb_pcmcia_cdvdman_irx;
358 irx = &smb_pcmcia_cdvdman_irx;
360 else {
361 size_irx = size_smb_cdvdman_irx;
362 irx = &smb_cdvdman_irx;
365 compatmask = sbPrepare(game, configSet, isoname, size_irx, irx, &i);
367 // For ISO we use the part table to store the "long" name (only for init)
368 if (game->isISO)
369 memcpy((void*)((u32)irx + i + 44), game->name, strlen(game->name) + 1);
371 for (i = 0; i < size_irx; i++) {
372 if (!strcmp((const char*)((u32)irx + i),"xxx.xxx.xxx.xxx")) {
373 break;
377 #ifdef VMC
378 int size_mcemu_irx = ethPrepareMcemu(game, configSet);
379 if (size_mcemu_irx == -1) {
380 if (guiMsgBox(_l(_STR_ERR_VMC_CONTINUE), 1, NULL))
381 size_mcemu_irx = 0;
382 else
383 return;
385 #endif
387 char config_str[255];
388 sprintf(config_str, "%d.%d.%d.%d", pc_ip[0], pc_ip[1], pc_ip[2], pc_ip[3]);
389 memcpy((void*)((u32)irx + i), config_str, strlen(config_str) + 1);
390 memcpy((void*)((u32)irx + i + 16), &gPCPort, 4);
391 memcpy((void*)((u32)irx + i + 20), gPCShareName, 32);
392 memcpy((void*)((u32)irx + i + 56), gPCUserName, 32);
393 memcpy((void*)((u32)irx + i + 92), gPCPassword, 32);
395 // disconnect from the active SMB session
396 ethSMBDisconnect();
398 char *altStartup = NULL;
399 if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
400 strncpy(filename, altStartup, 32);
401 else
402 sprintf(filename, "%s", game->startup);
403 shutdown(NO_EXCEPTION); // CAREFUL: shutdown will call ethCleanUp, so ethGames/game will be freed
404 FlushCache(0);
406 #ifdef VMC
407 sysLaunchLoaderElf(filename, "ETH_MODE", size_irx, irx, size_mcemu_irx, &smb_mcemu_irx, compatmask, compatmask & COMPAT_MODE_1);
408 #else
409 sysLaunchLoaderElf(filename, "ETH_MODE", size_irx, irx, compatmask, compatmask & COMPAT_MODE_1);
410 #endif
413 static config_set_t* ethGetConfig(int id) {
414 return sbPopulateConfig(&ethGames[id], ethPrefix, "\\");
417 static int ethGetImage(char* folder, int isRelative, char* value, char* suffix, GSTEXTURE* resultTex, short psm) {
418 char path[255];
419 if (isRelative)
420 sprintf(path, "%s%s\\%s_%s", ethPrefix, folder, value, suffix);
421 else
422 sprintf(path, "%s%s_%s", folder, value, suffix);
423 return texDiscoverLoad(resultTex, path, -1, psm);
426 static void ethCleanUp(int exception) {
427 if (ethGameList.enabled) {
428 LOG("ethCleanUp()\n");
430 free(ethGames);
434 #ifdef VMC
435 static int ethCheckVMC(char* name, int createSize) {
436 return sysCheckVMC(ethPrefix, "\\", name, createSize);
438 #endif
440 static item_list_t ethGameList = {
441 ETH_MODE, 0, COMPAT, 0, MENU_MIN_INACTIVE_FRAMES, "ETH Games", _STR_NET_GAMES, &ethInit, &ethNeedsUpdate,
442 #ifdef __CHILDPROOF
443 &ethUpdateGameList, &ethGetGameCount, &ethGetGame, &ethGetGameName, &ethGetGameNameLength, &ethGetGameStartup, NULL, NULL,
444 #else
445 &ethUpdateGameList, &ethGetGameCount, &ethGetGame, &ethGetGameName, &ethGetGameNameLength, &ethGetGameStartup, &ethDeleteGame, &ethRenameGame,
446 #endif
447 #ifdef VMC
448 &ethLaunchGame, &ethGetConfig, &ethGetImage, &ethCleanUp, &ethCheckVMC, ETH_ICON
449 #else
450 &ethLaunchGame, &ethGetConfig, &ethGetImage, &ethCleanUp, ETH_ICON
451 #endif