* reverted some changes from rev500, finally crazyc was correct (when he skipped...
[open-ps2-loader.git] / src / ethsupport.c
blobfc32a09c8cbe9f22154e23378bbfee53ab053a73
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 static void ethLaunchGame(int id, config_set_t* configSet) {
276 int i, compatmask, size_irx = 0;
277 void** irx = NULL;
278 char isoname[32], filename[32];
279 base_game_info_t* game = &ethGames[id];
281 #ifdef VMC
282 char vmc_name[32];
283 int vmc_id, size_mcemu_irx = 0;
284 smb_vmc_infos_t smb_vmc_infos;
285 vmc_superblock_t vmc_superblock;
287 for (vmc_id = 0; vmc_id < 2; vmc_id++) {
288 memset(&smb_vmc_infos, 0, sizeof(smb_vmc_infos_t));
289 configGetVMC(configSet, vmc_name, vmc_id);
290 if (vmc_name[0]) {
291 if (sysCheckVMC(ethPrefix, "\\", vmc_name, 0, &vmc_superblock) > 0) {
292 smb_vmc_infos.flags = vmc_superblock.mc_flag & 0xFF;
293 smb_vmc_infos.flags |= 0x100;
294 smb_vmc_infos.specs.page_size = vmc_superblock.page_size;
295 smb_vmc_infos.specs.block_size = vmc_superblock.pages_per_block;
296 smb_vmc_infos.specs.card_size = vmc_superblock.pages_per_cluster * vmc_superblock.clusters_per_card;
297 smb_vmc_infos.active = 1;
298 smb_vmc_infos.fid = 0xFFFF;
299 snprintf(smb_vmc_infos.fname, 64, "VMC\\%s.bin", vmc_name); // may still be too small size here ;) (should add 9)
300 } else {
301 char error[255];
302 snprintf(error, 255, _l(_STR_ERR_VMC_CONTINUE), vmc_name, (vmc_id + 1));
303 if (!guiMsgBox(error, 1, NULL))
304 return;
308 for (i = 0; i < size_smb_mcemu_irx; i++) {
309 if (((u32*)&smb_mcemu_irx)[i] == (0xC0DEFAC0 + vmc_id)) {
310 if (smb_vmc_infos.active)
311 size_mcemu_irx = size_smb_mcemu_irx;
312 memcpy(&((u32*)&smb_mcemu_irx)[i], &smb_vmc_infos, sizeof(smb_vmc_infos_t));
313 break;
317 #endif
319 if (gRememberLastPlayed) {
320 configSetStr(configGetByType(CONFIG_LAST), "last_played", game->startup);
321 saveConfig(CONFIG_LAST, 0);
324 if (sysPcmciaCheck()) {
325 size_irx = size_smb_pcmcia_cdvdman_irx;
326 irx = &smb_pcmcia_cdvdman_irx;
328 else {
329 size_irx = size_smb_cdvdman_irx;
330 irx = &smb_cdvdman_irx;
333 compatmask = sbPrepare(game, configSet, isoname, size_irx, irx, &i);
335 // For ISO we use the part table to store the "long" name (only for init)
336 if (game->isISO)
337 memcpy((void*)((u32)irx + i + 44), game->name, strlen(game->name) + 1);
339 for (i = 0; i < size_irx; i++) {
340 if (!strcmp((const char*)((u32)irx + i),"xxx.xxx.xxx.xxx")) {
341 break;
345 char config_str[255];
346 sprintf(config_str, "%d.%d.%d.%d", pc_ip[0], pc_ip[1], pc_ip[2], pc_ip[3]);
347 memcpy((void*)((u32)irx + i), config_str, strlen(config_str) + 1);
348 memcpy((void*)((u32)irx + i + 16), &gPCPort, 4);
349 memcpy((void*)((u32)irx + i + 20), gPCShareName, 32);
350 memcpy((void*)((u32)irx + i + 56), gPCUserName, 32);
351 memcpy((void*)((u32)irx + i + 92), gPCPassword, 32);
353 // disconnect from the active SMB session
354 ethSMBDisconnect();
356 char *altStartup = NULL;
357 if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
358 strncpy(filename, altStartup, 32);
359 else
360 sprintf(filename, "%s", game->startup);
361 shutdown(NO_EXCEPTION); // CAREFUL: shutdown will call ethCleanUp, so ethGames/game will be freed
362 FlushCache(0);
364 #ifdef VMC
365 sysLaunchLoaderElf(filename, "ETH_MODE", size_irx, irx, size_mcemu_irx, &smb_mcemu_irx, compatmask, compatmask & COMPAT_MODE_1);
366 #else
367 sysLaunchLoaderElf(filename, "ETH_MODE", size_irx, irx, compatmask, compatmask & COMPAT_MODE_1);
368 #endif
371 static config_set_t* ethGetConfig(int id) {
372 return sbPopulateConfig(&ethGames[id], ethPrefix, "\\");
375 static int ethGetImage(char* folder, int isRelative, char* value, char* suffix, GSTEXTURE* resultTex, short psm) {
376 char path[255];
377 if (isRelative)
378 sprintf(path, "%s%s\\%s_%s", ethPrefix, folder, value, suffix);
379 else
380 sprintf(path, "%s%s_%s", folder, value, suffix);
381 return texDiscoverLoad(resultTex, path, -1, psm);
384 static void ethCleanUp(int exception) {
385 if (ethGameList.enabled) {
386 LOG("ethCleanUp()\n");
388 free(ethGames);
392 #ifdef VMC
393 static int ethCheckVMC(char* name, int createSize) {
394 return sysCheckVMC(ethPrefix, "\\", name, createSize, NULL);
396 #endif
398 static item_list_t ethGameList = {
399 ETH_MODE, 0, COMPAT, 0, MENU_MIN_INACTIVE_FRAMES, "ETH Games", _STR_NET_GAMES, &ethInit, &ethNeedsUpdate,
400 #ifdef __CHILDPROOF
401 &ethUpdateGameList, &ethGetGameCount, &ethGetGame, &ethGetGameName, &ethGetGameNameLength, &ethGetGameStartup, NULL, NULL,
402 #else
403 &ethUpdateGameList, &ethGetGameCount, &ethGetGame, &ethGetGameName, &ethGetGameNameLength, &ethGetGameStartup, &ethDeleteGame, &ethRenameGame,
404 #endif
405 #ifdef VMC
406 &ethLaunchGame, &ethGetConfig, &ethGetImage, &ethCleanUp, &ethCheckVMC, ETH_ICON
407 #else
408 &ethLaunchGame, &ethGetConfig, &ethGetImage, &ethCleanUp, ETH_ICON
409 #endif