@@ -29,6 +29,7 @@ using std::vector;
2929const char * JSON_URL = " https://raw.githubusercontent.com/Jolty95/TWLoader-update/master/update.json" ;
3030bool updateGUI = false ;
3131bool updateNAND = false ;
32+ bool updateNAND_part2 = false ;
3233bool updateNAND_STG2 = false ;
3334bool updateACE_RPG = false ;
3435bool updateGBARUNNER_2 = false ;
@@ -37,8 +38,13 @@ bool updateR4 = false;
3738// bool doCleanInstall = true;
3839
3940std::string gui_url;
41+ std::string gui_3dsx_url;
42+ std::string gui_smdh_url;
43+ std::string demo_gui_3dsx_url;
44+ std::string demo_gui_smdh_url;
4045std::string nand_url;
41- std::string nand_stg2_url;
46+ std::string nand_part2_url;
47+ std::string nand_twld_url;
4248std::string ace_rpg_url;
4349std::string gbarunner2_url;
4450std::string loadcard_dstt_url;
@@ -211,9 +217,22 @@ struct ReadJson {
211217 std::string strvalue2;
212218 std::string strvalue3;
213219 std::string strvalue4;
220+ std::string strvalue5;
221+ std::string strvalue6;
222+ std::string strvalue7;
223+ std::string strvalue8;
214224};
215225
216- ReadJson internal_json_reader (json_value* json, json_value* val, std::string str1, std::string str2, std::string str3, std::string str4){
226+ ReadJson internal_json_reader (json_value* json, json_value* val,
227+ std::string str1,
228+ std::string str2,
229+ std::string str3,
230+ std::string str4,
231+ std::string str5,
232+ std::string str6,
233+ std::string str7,
234+ std::string str8)
235+ {
217236 ReadJson rj;
218237 for (u32 i = 0 ; i < (json->u .object .length -1 ); i++) {
219238 // Create two variables that will store the values and it size
@@ -229,6 +248,14 @@ ReadJson internal_json_reader(json_value* json, json_value* val, std::string str
229248 rj.strvalue3 = subVal->u .string .ptr ;
230249 } else if (strncmp (name, str4.c_str (), nameLen) == 0 ) {
231250 rj.strvalue4 = subVal->u .string .ptr ;
251+ } else if (strncmp (name, str5.c_str (), nameLen) == 0 ) {
252+ rj.strvalue5 = subVal->u .string .ptr ;
253+ } else if (strncmp (name, str6.c_str (), nameLen) == 0 ) {
254+ rj.strvalue6 = subVal->u .string .ptr ;
255+ } else if (strncmp (name, str7.c_str (), nameLen) == 0 ) {
256+ rj.strvalue7 = subVal->u .string .ptr ;
257+ } else if (strncmp (name, str8.c_str (), nameLen) == 0 ) {
258+ rj.strvalue8 = subVal->u .string .ptr ;
232259 }
233260 }
234261 }
@@ -303,50 +330,70 @@ int checkUpdate(void) {
303330 char read_gui_major[3 ];
304331 char read_gui_minor[3 ];
305332 char read_gui_micro[3 ];
306-
333+
307334 char read_nand_major[3 ];
308335 char read_nand_minor[3 ];
309336 char read_nand_micro[3 ];
310337
338+ char read_nandpart2_major[3 ];
339+ char read_nandpart2_minor[3 ];
340+ char read_nandpart2_micro[3 ];
341+
311342 char read_nandstg2_major[3 ];
312343 char read_nandstg2_minor[3 ];
313344 char read_nandstg2_micro[3 ];
314345
315346
316347 // Search in GUI object
317348 json_value* val = json->u .object .values [0 ].value ;
318- ReadJson result = internal_json_reader (json, val, " latest_major" , " latest_minor" , " latest_micro" , " gui_url" );
349+ ReadJson result = internal_json_reader (json, val, " latest_major" , " latest_minor" , " latest_micro" , " gui_url" , " gui_3dsx_url " , " gui_smdh_url " , " demo_gui_3dsx_url " , " demo_gui_smdh_url " );
319350 strncpy (read_gui_major, result.strvalue1 .c_str (), sizeof (read_gui_major));
320351 strncpy (read_gui_minor, result.strvalue2 .c_str (), sizeof (read_gui_minor));
321352 strncpy (read_gui_micro, result.strvalue3 .c_str (), sizeof (read_gui_micro));
322353 gui_url = result.strvalue4 .c_str ();
354+ gui_3dsx_url = result.strvalue5 .c_str ();
355+ gui_smdh_url = result.strvalue6 .c_str ();
356+ demo_gui_3dsx_url = result.strvalue7 .c_str ();
357+ demo_gui_smdh_url = result.strvalue8 .c_str ();
323358
324359 // Search in NAND object.
325360 val = json->u .object .values [1 ].value ;
326- result = internal_json_reader (json, val, " not_major" , " not_minor" , " not_micro" , " nand_url" );
361+ json_value* val2 = val->u .object .values [0 ].value ;
362+ result = internal_json_reader (json, val2, " not_major" , " not_minor" , " not_micro" , " nand_url" , " nand_null" , " nand_null" , " nand_null" , " nand_null" );
327363 strncpy (read_nand_major, result.strvalue1 .c_str (), sizeof (read_nand_major));
328364 strncpy (read_nand_minor, result.strvalue2 .c_str (), sizeof (read_nand_minor));
329365 strncpy (read_nand_micro, result.strvalue3 .c_str (), sizeof (read_nand_micro));
330366 nand_url = result.strvalue4 .c_str ();
331367
368+ // Search in NAND (part2) object.
369+ val2 = val->u .object .values [1 ].value ;
370+ result = internal_json_reader (json, val2, " p2_not_major" , " p2_not_minor" , " p2_not_micro" , " nand_part2_url" , " part2_null" , " part2_null" , " part2_null" , " part2_null" );
371+ strncpy (read_nandpart2_major, result.strvalue1 .c_str (), sizeof (read_nandpart2_major));
372+ strncpy (read_nandpart2_minor, result.strvalue2 .c_str (), sizeof (read_nandpart2_minor));
373+ strncpy (read_nandpart2_micro, result.strvalue3 .c_str (), sizeof (read_nandpart2_micro));
374+ nand_part2_url = result.strvalue4 .c_str ();
375+
332376 // Search in NAND STG2 object.
333- val = json ->u .object .values [2 ].value ;
334- result = internal_json_reader (json, val , " not_major " , " not_minor " , " not_micro " , " nand_stg2_url " );
377+ val2 = val ->u .object .values [2 ].value ;
378+ result = internal_json_reader (json, val2 , " twld_not_major " , " twld_not_minor " , " twld_not_micro " , " nand_twld_url " , " twld_null " , " twld_null " , " twld_null " , " twld_null " );
335379 strncpy (read_nandstg2_major, result.strvalue1 .c_str (), sizeof (read_nandstg2_major));
336380 strncpy (read_nandstg2_minor, result.strvalue2 .c_str (), sizeof (read_nandstg2_minor));
337381 strncpy (read_nandstg2_micro, result.strvalue3 .c_str (), sizeof (read_nandstg2_micro));
338- nand_stg2_url = result.strvalue4 .c_str ();
382+ nand_twld_url = result.strvalue4 .c_str ();
339383
340384 // Store latest and current version of GUI and NAND.
341385 char latestVersion[16 ];
342386 snprintf (latestVersion, sizeof (latestVersion), " %s.%s.%s" , read_gui_major, read_gui_minor, read_gui_micro);
343-
387+
344388 char currentVersion[16 ];
345389 snprintf (currentVersion, sizeof (currentVersion), " %d.%d.%d" , VERSION_MAJOR , VERSION_MINOR , VERSION_MICRO );
346-
390+
347391 char latestNANDVersion[16 ];
348392 snprintf (latestNANDVersion, sizeof (latestNANDVersion), " %s.%s.%s" , read_nand_major, read_nand_minor, read_nand_micro);
349-
393+
394+ char latestNAND2Version[16 ];
395+ snprintf (latestNAND2Version, sizeof (latestNAND2Version), " %s.%s.%s" , read_nandpart2_major, read_nandpart2_minor, read_nandpart2_micro);
396+
350397 char latestNANDSTG2Version[16 ];
351398 snprintf (latestNANDSTG2Version, sizeof (latestNANDSTG2Version), " %s.%s.%s" , read_nandstg2_major, read_nandstg2_minor, read_nandstg2_micro);
352399
@@ -364,6 +411,10 @@ int checkUpdate(void) {
364411 if (logEnabled) LogFM (" checkUpdate" , " NAND update available." );
365412 updateNAND = true ;
366413 }
414+ if (strcmp (latestNAND2Version, currentVersion) > 0 ) {
415+ if (logEnabled) LogFM (" checkUpdate" , " NAND (part 2) update available." );
416+ updateNAND_part2 = true ;
417+ }
367418 if (strcmp (latestNANDSTG2Version, currentVersion) > 0 ) {
368419 if (logEnabled) LogFM (" checkUpdate" , " NAND SD stage update available." );
369420 updateNAND_STG2 = true ;
@@ -409,7 +460,7 @@ int checkUpdate(void) {
409460 " \n "
410461 " \n "
411462 " \n "
412- " : Close " ;
463+ " : OK " ;
413464 renderText (12 , 16 , 0 .5f , 0 .5f , false , msg);
414465 sf2d_end_frame ();
415466 sf2d_swapbuffers ();
@@ -431,9 +482,9 @@ int checkUpdate(void) {
431482 }
432483
433484 // Search in prebuilds object
434- val = json->u .object .values [3 ].value ;
435- json_value* val2 = val->u .object .values [0 ].value ;
436- result = internal_json_reader (json, val2, " ace_rpg_major" , " ace_rpg_minor" , " ace_rpg_micro" , " ace_rpg_url" );
485+ val = json->u .object .values [2 ].value ;
486+ val2 = val->u .object .values [0 ].value ;
487+ result = internal_json_reader (json, val2, " ace_rpg_major" , " ace_rpg_minor" , " ace_rpg_micro" , " ace_rpg_url" , " ace_rpg_null " , " ace_rpg_null " , " ace_rpg_null " , " ace_rpg_null " );
437488 ace_rpg_url = result.strvalue4 .c_str ();
438489
439490 char ace_rpg_version[16 ];
@@ -444,7 +495,7 @@ int checkUpdate(void) {
444495 }
445496
446497 val2 = val->u .object .values [1 ].value ;
447- result = internal_json_reader (json, val2, " GBARunner2_major" , " GBARunner2_minor" , " GBARunner2_micro" , " GBARunner2_url" );
498+ result = internal_json_reader (json, val2, " GBARunner2_major" , " GBARunner2_minor" , " GBARunner2_micro" , " GBARunner2_url" , " GBARunner2_null " , " GBARunner2_null " , " GBARunner2_null " , " GBARunner2_null " );
448499 gbarunner2_url = result.strvalue4 .c_str ();
449500
450501 char GBARunner2_version[16 ];
@@ -455,7 +506,7 @@ int checkUpdate(void) {
455506 }
456507
457508 val2 = val->u .object .values [2 ].value ;
458- result = internal_json_reader (json, val2, " loadcard_dstt_major" , " loadcard_dstt_minor" , " loadcard_dstt_micro" , " loadcard_dstt_url" );
509+ result = internal_json_reader (json, val2, " loadcard_dstt_major" , " loadcard_dstt_minor" , " loadcard_dstt_micro" , " loadcard_dstt_url" , " loadcard_dstt_null " , " loadcard_dstt_null " , " loadcard_dstt_null " , " loadcard_dstt_null " );
459510 loadcard_dstt_url = result.strvalue4 .c_str ();
460511 char loadcard_dstt_version[16 ];
461512 snprintf (loadcard_dstt_version, sizeof (loadcard_dstt_version), " %s.%s.%s" , result.strvalue1 .c_str (), result.strvalue2 .c_str (), result.strvalue3 .c_str ());
@@ -465,7 +516,7 @@ int checkUpdate(void) {
465516 }
466517
467518 val2 = val->u .object .values [3 ].value ;
468- result = internal_json_reader (json, val2, " r4_major" , " r4_minor" , " r4_micro" , " r4_url" );
519+ result = internal_json_reader (json, val2, " r4_major" , " r4_minor" , " r4_micro" , " r4_url" , " r4_null " , " r4_null " , " r4_null " , " r4_null " );
469520 r4_url = result.strvalue4 .c_str ();
470521
471522 char r4_version[16 ];
@@ -539,42 +590,78 @@ void DownloadTWLoaderCIAs(void) {
539590
540591 if (yestoupdate) {
541592 int resGUI = -1 ;
593+ int resGUI_3DSX = -1 ;
594+ int resGUI_SMDH = -1 ;
542595 int resNAND = -1 ;
596+ int resNAND_part2 = -1 ;
543597 int resNAND_STG2 = -1 ;
544598 struct stat st;
545599 if (updateGUI) {
546- sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
547- if (screenmode == SCREEN_MODE_SETTINGS ) {
548- sf2d_draw_texture (settingstex, 0 , 0 );
549- }
550- sf2d_draw_texture (dialogboxtex, 0 , 0 );
551- static const char gui_msg[] =
552- " Now downloading latest TWLoader version...\n "
553- " (GUI)\n "
554- " \n "
555- " Do not turn off the power.\n " ;
556- renderText (12 , 16 , 0 .5f , 0 .5f , false , gui_msg);
557- sf2d_end_frame ();
558- sf2d_swapbuffers ();
559-
560- if (stat (" sdmc:/cia" ,&st) == 0 ){
561- // Use root/cia folder instead
562- resGUI = downloadFile (gui_url.c_str ()," /cia/TWLoader.cia" , MEDIA_SD_CIA );
563- }else {
564- mkdir (" sdmc:/_nds/twloader/cia" , 0777 ); // Use twloader/cia folder instead
565- resGUI = downloadFile (gui_url.c_str ()," /_nds/twloader/cia/TWLoader.cia" , MEDIA_SD_CIA );
566- }
600+ if (settings.ui .filetype == 0 || settings.ui .filetype == 2 ) {
601+ sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
602+ if (screenmode == SCREEN_MODE_SETTINGS ) {
603+ sf2d_draw_texture (settingstex, 0 , 0 );
604+ }
605+ sf2d_draw_texture (dialogboxtex, 0 , 0 );
606+ static const char gui_msg[] =
607+ " Now downloading latest TWLoader version...\n "
608+ " (GUI, CIA)\n "
609+ " \n "
610+ " Do not turn off the power.\n " ;
611+ renderText (12 , 16 , 0 .5f , 0 .5f , false , gui_msg);
612+ sf2d_end_frame ();
613+ sf2d_swapbuffers ();
567614
568- sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
569- if (screenmode == SCREEN_MODE_SETTINGS ) {
570- sf2d_draw_texture (settingstex, 0 , 0 );
615+ if (stat (" sdmc:/cia" ,&st) == 0 ){
616+ // Use root/cia folder instead
617+ resGUI = downloadFile (gui_url.c_str ()," /cia/TWLoader.cia" , MEDIA_SD_CIA );
618+ }else {
619+ mkdir (" sdmc:/_nds/twloader/cia" , 0777 ); // Use twloader/cia folder instead
620+ resGUI = downloadFile (gui_url.c_str ()," /_nds/twloader/cia/TWLoader.cia" , MEDIA_SD_CIA );
621+ }
622+
623+ sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
624+ if (screenmode == SCREEN_MODE_SETTINGS ) {
625+ sf2d_draw_texture (settingstex, 0 , 0 );
626+ }
627+ sf2d_draw_texture (dialogboxtex, 0 , 0 );
628+ }
629+ if (settings.ui .filetype == 1 || settings.ui .filetype == 2 ) {
630+ sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
631+ if (screenmode == SCREEN_MODE_SETTINGS ) {
632+ sf2d_draw_texture (settingstex, 0 , 0 );
633+ }
634+ sf2d_draw_texture (dialogboxtex, 0 , 0 );
635+ static const char gui_msg[] =
636+ " Now downloading latest TWLoader version...\n "
637+ " (GUI, 3DSX)\n "
638+ " \n "
639+ " Do not turn off the power.\n " ;
640+ renderText (12 , 16 , 0 .5f , 0 .5f , false , gui_msg);
641+ sf2d_end_frame ();
642+ sf2d_swapbuffers ();
643+
644+ if (isDemo) {
645+ mkdir (" sdmc:/3ds/TWLoader_demo" , 0777 );
646+ resGUI_3DSX = downloadFile (demo_gui_3dsx_url.c_str ()," /3ds/TWLoader_demo/TWLoader_demo.3dsx" , MEDIA_SD_FILE );
647+ resGUI_SMDH = downloadFile (demo_gui_smdh_url.c_str ()," /3ds/TWLoader_demo/TWLoader_demo.smdh" , MEDIA_SD_FILE );
648+ } else {
649+ mkdir (" sdmc:/3ds/TWLoader" , 0777 );
650+ resGUI_3DSX = downloadFile (gui_3dsx_url.c_str ()," /3ds/TWLoader/TWLoader.3dsx" , MEDIA_SD_FILE );
651+ resGUI_SMDH = downloadFile (gui_smdh_url.c_str ()," /3ds/TWLoader/TWLoader.smdh" , MEDIA_SD_FILE );
652+ }
653+
654+ sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
655+ if (screenmode == SCREEN_MODE_SETTINGS ) {
656+ sf2d_draw_texture (settingstex, 0 , 0 );
657+ }
658+ sf2d_draw_texture (dialogboxtex, 0 , 0 );
571659 }
572- sf2d_draw_texture (dialogboxtex, 0 , 0 );
573660 }
574661 if (resGUI == 0 && updateNAND) {
575662 static const char twlnand_msg[] =
576663 " Now downloading latest TWLoader version...\n "
577- " (TWLNAND side CIA)\n "
664+ " (TWLNAND side CIA (part 1) )\n "
578665 " \n "
579666 " Do not turn off the power.\n " ;
580667 renderText (12 , 16 , 0 .5f , 0 .5f , false , twlnand_msg);
@@ -599,26 +686,60 @@ void DownloadTWLoaderCIAs(void) {
599686 }
600687 sf2d_draw_texture (dialogboxtex, 0 , 0 );
601688 }
602- if (updateNAND_STG2) {
689+ if (resNAND == 0 && updateNAND_STG2) {
603690 static const char twlnandstg2_msg[] =
604691 " Now downloading latest TWLoader version...\n "
605- " (SD stage of TWLNAND side)\n "
692+ " (SD stage of (part 1 of) TWLNAND side)\n "
606693 " \n "
607694 " Do not turn off the power.\n " ;
608695 renderText (12 , 16 , 0 .5f , 0 .5f , false , twlnandstg2_msg);
609696 sf2d_end_frame ();
610697 sf2d_swapbuffers ();
611698
612- resNAND_STG2 = downloadFile (nand_stg2_url.c_str ()," /_nds/twloader/TWLD.twldr" , MEDIA_SD_FILE );
699+ resNAND_STG2 = downloadFile (nand_twld_url.c_str ()," /_nds/twloader/TWLD.twldr" , MEDIA_SD_FILE );
700+ sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
701+ if (screenmode == SCREEN_MODE_SETTINGS ) {
702+ sf2d_draw_texture (settingstex, 0 , 0 );
703+ }
704+ sf2d_draw_texture (dialogboxtex, 0 , 0 );
705+ }
706+ if (resNAND_STG2 == 0 && updateNAND_part2) {
707+ static const char twlnand2_msg[] =
708+ " Now downloading latest TWLoader version...\n "
709+ " (TWLNAND side CIA (part 2))\n "
710+ " \n "
711+ " Do not turn off the power.\n " ;
712+ renderText (12 , 16 , 0 .5f , 0 .5f , false , twlnand2_msg);
713+ sf2d_end_frame ();
714+ sf2d_swapbuffers ();
715+ // Delete first if installed.
716+ if (checkTWLNANDSide2 ()){
717+ amInit ();
718+ AM_DeleteTitle (MEDIATYPE_NAND , NTRLAUNCHER_TID );
719+ amExit ();
720+ }
721+
722+ if (stat (" sdmc:/cia" ,&st) == 0 ){
723+ // Use root/cia folder instead
724+ resNAND = downloadFile (nand_part2_url.c_str ()," /cia/TWLoader - TWLNAND side (part 2).cia" , MEDIA_NAND_CIA );
725+ }else {
726+ resNAND = downloadFile (nand_part2_url.c_str ()," /_nds/twloader/cia/TWLoader - TWLNAND side (part 2).cia" , MEDIA_NAND_CIA );
727+ }
613728 sf2d_start_frame (GFX_BOTTOM , GFX_LEFT );
614729 if (screenmode == SCREEN_MODE_SETTINGS ) {
615730 sf2d_draw_texture (settingstex, 0 , 0 );
616731 }
617732 sf2d_draw_texture (dialogboxtex, 0 , 0 );
618733 }
619734 // If gui or nand failed, stop before downloading prebuilds.
620- if (resGUI != 0 || (updateNAND && resNAND != 0 ) || (updateNAND_STG2 && resNAND_STG2 != 0 ) ) {
621- DialogBoxDisappear (12 , 16 , " Update failed." );
735+ if (settings.ui .filetype == 0 || settings.ui .filetype == 2 ) {
736+ if (resGUI != 0 || (updateNAND && resNAND != 0 ) || (updateNAND_STG2 && resNAND_STG2 != 0 ) || (updateNAND_part2 && resNAND_part2 != 0 ) ) {
737+ DialogBoxDisappear (12 , 16 , " Update failed." );
738+ }
739+ } else if (settings.ui .filetype == 1 ) {
740+ if (resGUI_3DSX != 0 || (updateNAND && resNAND != 0 ) || (updateNAND_STG2 && resNAND_STG2 != 0 ) || (updateNAND_part2 && resNAND_part2 != 0 ) ) {
741+ DialogBoxDisappear (12 , 16 , " Update failed." );
742+ }
622743 }
623744 if (resGUI == 0 && updateACE_RPG) {
624745 static const char msg[] =
0 commit comments