1 /************************************************************************
2  * This file is part of Wizznic.                                        *
3  * Copyright 2009-2015 Jimmy Christensen <dusted@dusted.dk>             *
4  * Wizznic is free software: you can redistribute it and/or modify      *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation, either version 3 of the License, or    *
7  * (at your option) any later version.                                  *
8  *                                                                      *
9  * Wizznic is distributed in the hope that it will be useful,           *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
12  * GNU General Public License for more details.                         *
13  *                                                                      *
14  * You should have received a copy of the GNU General Public License    *
15  * along with Wizznic.  If not, see <http://www.gnu.org/licenses/>.     *
16  ************************************************************************/
17 
18 #include <math.h>
19 
20 #include "menu.h"
21 
22 #include "userfiles.h"
23 
24 #include "sound.h"
25 #include "ticks.h"
26 #include "input.h"
27 #include "strinput.h"
28 
29 #include "states.h"
30 #include "game.h"
31 #include "levelselector.h"
32 
33 #include "pack.h"
34 #include "strings.h"
35 #include "settings.h"
36 
37 #include "stats.h"
38 #include "mbrowse.h"
39 
40 #include "credits.h"
41 
42 #include "waveimg.h"
43 #include "stats.h"
44 #include "scrollbar.h"
45 #include "about.h"
46 
47 #include "transition.h"
48 
49 #if defined( PLATFORM_SUPPORTS_STATSUPLOAD )
50   #include "bundle.h"
51   #include "platform/libDLC.h"
52 #endif
53 
54 static float rot=0;
55 
56 #define MENUGFXINTRO 0
57 #define MENUGFXHELP 1
58 #define MENUGFXBYE 2
59 #define MENUGFXPACKBOX 3
60 #define MENUGFXNUM 4
61 
62 static SDL_Surface* menuBg[MENUGFXNUM];
63 
64 
65 static int menuState=menuStateIntro;
66 
67 static int menuPosX=0, menuPosY=0;
68 static int menuMaxX, menuMaxY;
69 static int menuChangeX=0,menuChangeY=0; //Is not zero if there's a change
70 
71 static int dir=0;
72 static int countdown=0;
73 
74 static int menuReturnHack=0; //Well, for returning to the right place after entering highscore.
75 
76 static int x,y;
77 
78 static wavingImage_t waving;
79 
80 static aniType* menuYesNo;
81 
82 inpStrState* strStateHighScore;
83 inpStrState* strStateDlcCode;
84 
85 char message[128];
86 
getMenuState()87 int getMenuState() { return(menuState); }
88 
initMenu(SDL_Surface * screen)89 int initMenu(SDL_Surface* screen)
90 {
91   menuBg[MENUGFXINTRO] = loadImg( DATADIR"data/menu/intro.png" );
92   menuBg[MENUGFXHELP] = loadImg( DATADIR""PLATFORM_HELP_FILE );
93 
94   scrollBarInit();
95   aboutInit();
96 
97   menuBg[MENUGFXBYE]=0;
98   menuYesNo=0;
99 
100   menuBg[MENUGFXPACKBOX] = SDL_CreateRGBSurface(SDL_SWSURFACE, 260,42, (setting()->bpp*8), screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0xff000000);
101 
102   setWaving(&waving, screen, menuBg[MENUGFXINTRO], HSCREENW-149,HSCREENH-90,1,15,300);
103   waving.privRotAmount=0; //In case it was nan
104   waving.useOverlay=1;
105   waving.overlaySpeed=1;
106   waving.overlay = loadImg( DATADIR"data/menu/introoverlay.png" );
107   waving.overlayPos=waving.overlay->w+1;
108   waving.mask = loadImg( DATADIR"data/menu/intromask.png");
109 
110   strStateHighScore = inpStrCreate(screen, "Name:", 1,10 );
111   strStateDlcCode = inpStrCreate(screen, "Code:", 1,20 );
112 
113   return(1);
114 }
115 
116 
setMenu(int mstate)117 void setMenu(int mstate)
118 {
119   menuPosY=0;
120   menuPosX=0;
121   menuState=mstate;
122   dir=0;
123   countdown=0;
124 }
125 
setMenuPosX(int x)126 void setMenuPosX(int x)
127 {
128   menuPosX=x;
129 }
setMenuPosY(int Y)130 void setMenuPosY(int Y)
131 {
132   menuPosX=Y;
133 }
134 
decPosX()135 void decPosX()
136 {
137   menuChangeX=1;
138   sndPlay(SND_MENUMOVE, 160);
139 
140   menuPosX--;
141   if(menuPosX < 0)
142     menuPosX=menuMaxX;
143 }
144 
incPosX()145 void incPosX()
146 {
147   menuChangeX=1;
148   sndPlay(SND_MENUMOVE, 160);
149   menuPosX++;
150   if(menuPosX > menuMaxX)
151     menuPosX=0;
152 }
153 
decPosY()154 void decPosY()
155 {
156   menuChangeY=-1;
157   if(!( menuState==menuStatePaused && menuPosY==1 && !player()->gameStarted ))
158     sndPlay(SND_MENUMOVE, 160);
159   countdown=0;
160   dir=0;
161   menuPosY--;
162   if(menuPosY < 0)
163     menuPosY=menuMaxY;
164 }
165 
incPosY()166 void incPosY()
167 {
168   menuChangeY=1;
169   if(!( menuState==menuStatePaused && menuPosY==1 && !player()->gameStarted ))
170     sndPlay(SND_MENUMOVE, 160);
171   countdown=0;
172   dir=0;
173   menuPosY++;
174   if(menuPosY > menuMaxY)
175     menuPosY=0;
176 }
177 
runMenu(SDL_Surface * screen)178 int runMenu(SDL_Surface* screen)
179 {
180   char buf[512];
181   int scroll; //Generic scoll int (for scrolling lists)
182   int ul=0;   //Userlevel (and used for scrolling)
183   psysSet_t ps; //Particle system for particle effects in menu
184   listItem* it;
185   fileListItem_t* fItem;
186   int sb;
187 
188   SDL_Rect r;
189 
190   if( !dir || getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT ) //Nasty little hack to prevent text from blinking when you try to click it
191   {
192     countdown+=getTicks();
193     if(countdown > 250)
194     {
195       countdown=250;
196       dir=1;
197     }
198   } else {
199     countdown-=getTicks();
200     if(countdown < 1)
201     {
202       countdown=0;
203       dir=0;
204     }
205   }
206 
207   if(getButton(C_BTNB))
208     sndPlayOnce(SND_MENUCLICK, 160);
209 
210   if(getButton(C_UP) )
211   {
212     resetBtn(C_UP);
213     getInpPointerState()->timeSinceMoved=POINTER_SHOW_TIMEOUT;
214     decPosY();
215     if( menuState==menuStatePaused && menuPosY==1 && !player()->gameStarted )
216     {
217       decPosY();
218     }
219   }
220   if(getButton(C_DOWN))
221   {
222     resetBtn(C_DOWN);
223     getInpPointerState()->timeSinceMoved=POINTER_SHOW_TIMEOUT;
224     incPosY();
225     if( menuState==menuStatePaused && menuPosY==1 && !player()->gameStarted )
226     {
227       incPosY();
228     }
229   }
230 
231   if(getButton(C_LEFT) )
232   {
233     resetBtn(C_LEFT);
234     getInpPointerState()->timeSinceMoved=POINTER_SHOW_TIMEOUT;
235     decPosX();
236   }
237   if(getButton(C_RIGHT))
238   {
239     resetBtn(C_RIGHT);
240     getInpPointerState()->timeSinceMoved=POINTER_SHOW_TIMEOUT;
241     incPosX();
242   }
243 
244   switch(menuState)
245   {
246     case menuStateIntro:
247 
248 //Intro should no longer crash PSP, will porter please get back to me on this?
249 //Intr not working on PSP.. Skip it untill its fixed.
250 //      #if defined (PSP) && !defined (PSP_DEBUG_INTRO)
251 //        menuState=menuStatePaused;
252 //        SDL_FreeSurface( menuBg[MENUGFXINTRO] );
253 //        menuBg[MENUGFXINTRO]=0;
254 //        menuPosY=0;
255 //        clearParticles();
256 //        clearCredits();
257 //        break;
258 //      #endif
259 
260       //Show background image
261       starField(screen,1);
262 
263       runParticles(screen);
264 
265       runCredits(screen);
266 
267       waveImg(&waving);
268 
269       //Blink "Press B" (NOT dir, it will disappear when mouse is moved)
270       if(!dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+70);
271 
272       //Show version
273       txtWrite(screen, FONTSMALL, VERSION_STRING, HSCREENW+160-((strlen(VERSION_STRING))*9),HSCREENH+106);
274 
275       //Show games played world wide
276       if( setting()->solvedWorldWide )
277       {
278         sprintf(buf, STR_MENU_PUZZLES_WORLDWIDE,setting()->solvedWorldWide);
279         txtWrite(screen, FONTSMALL, buf, HSCREENW-158, HSCREENH+95);
280       }
281 
282       //Wait for keypress
283       if( getButton( C_BTNB ) || isPointerClicked() )
284       {
285         resetBtn( C_BTNB );
286         menuState=menuStatePaused;
287         SDL_FreeSurface( menuBg[MENUGFXINTRO] );
288         SDL_FreeSurface( waving.overlay  );
289         SDL_FreeSurface( waving.mask ) ;
290 
291         startTransition( screen, TRANSITION_TYPE_DISSOLVE, 450 );
292 
293         menuBg[MENUGFXINTRO]=0;
294         menuPosY=0;
295         //clearParticles();
296         clearCredits();
297         #if defined (PLATFORM_SUPPORTS_STATSUPLOAD)
298         if(setting()->firstRun)
299         {
300           setMenu(menuStateUploadDiag);
301           menuPosX=1; //Default to "choose"
302         }
303         if(setting()->session == -1)
304         {
305           menuState=menuStateUpdate;
306         }
307         #endif
308       } else
309       if( getButton( C_BTNY ) )
310       {
311         resetBtn( C_BTNY );
312         ps.layer=PSYS_LAYER_TOP;
313         ps.x=HSCREENW-149;
314         ps.y=HSCREENH;
315         ps.vel=100; // +/- in each dir
316         ps.life=2000;
317         ps.lifeVar=1000;
318         ps.fade=0;
319         ps.gravity=0;
320         ps.bounce=1;      //If 1, particles will bounce off screen borders ( (vel * -1)/2 )
321         ps.fadeColor=0x00;
322         ps.color=PARTICLECOLORRANDOM;
323         ps.srcImg=menuBg[MENUGFXINTRO]; //Getcolors for each particle from this image.
324         ps.srcRect.x=0;
325         ps.srcRect.y=0;
326         ps.srcRect.w=menuBg[MENUGFXINTRO]->w;
327         ps.srcRect.h=menuBg[MENUGFXINTRO]->h;
328         spawnParticleSystem(&ps);
329       }
330 
331     break; //Intro screen
332 
333     case menuStateNewGame: //Start new game (select starting level)
334       starField(screen,1);
335       getInpPointerState()->escEnable=1;
336 
337       menuMaxX = stats()->progress+2;
338 
339       //To make sure that we don't try to show a level that's not there
340       if(menuMaxX > getNumLevels())
341       {
342         menuMaxX=getNumLevels();
343       }
344       if(menuPosX > getNumLevels())
345       {
346         menuPosX = getNumLevels();
347       }
348 
349       if(menuPosX-1 < stats()->progress &&  menuPosX!=getNumLevels())
350       {
351         txtWrite(screen, FONTMEDIUM, ">>", HSCREENW+120,HSCREENH-12);
352         if( isBoxClicked( getTxtBox() ) )
353         {
354           incPosX();
355         }
356       }
357 
358       if(menuPosX > 0)
359       {
360         txtWrite(screen, FONTMEDIUM, "<<", HSCREENW-155, HSCREENH-12);
361         if( isBoxClicked( getTxtBox() ) )
362         {
363           decPosX();
364         }
365       }
366 
367       //The "Finished" image..
368       if(menuPosX == menuMaxX)
369       {
370         levelSelector(screen,menuPosX, 0);
371       } else {
372         levelSelector(screen,menuPosX, 1);
373         txtWriteCenter(screen, FONTMEDIUM, STR_MENU_NEW_GAME, HSCREENW, HSCREENH-100);
374         txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B_PLAY, HSCREENW, HSCREENH+108);
375 
376         if( ( (isPointerClicked() && !isAnyBoxHit()) || getButton(C_BTNB) ) && menuPosX!=getNumLevels())
377         {
378           resetBtn(C_BTNB);
379 
380           initPlayer(); //New game, reset player.
381           player()->levelFile = levelInfo( menuPosX )->file;
382           player()->level = menuPosX;
383 
384           // Show help if it's the first level
385           menuState=menuStateNextLevel;
386         }
387       }
388 
389       if(getButton(C_BTNMENU) || isPointerEscapeClicked() )
390       {
391         resetBtn(C_BTNMENU);
392         menuPosY=0;
393         startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
394 
395         setMenu(menuStatePaused);
396         break;
397       }
398 
399     break; // New game
400 
401     case menuStateNextLevel:
402       starField(screen,0);
403       getInpPointerState()->escEnable=1;
404 
405       levelSelector(screen, player()->level,1);
406 
407 
408       if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B_PLAY, HSCREENW, HSCREENH+108);
409 
410       if( getButton(C_BTNMENU) || isPointerEscapeClicked() )
411       {
412         resetBtn(C_BTNMENU);
413         menuState=menuStateNewGame;
414         if( statsIsHighScore() )
415         {
416           setMenu(menuStateEnterHighScore);
417           menuReturnHack=menuStateNewGame;
418         }
419       } else
420       if(getButton(C_BTNB) || isPointerClicked() )
421       {
422         resetBtn(C_BTNB);
423         resetMouseBtn();
424 
425         if(initGame(screen))
426         {
427           if(player()->level == 0)
428           {
429             setMenu(menuStateHowto);
430           } else {
431             startTransition(screen, TRANSITION_TYPE_ROLL_OUT,500);
432             return(STATEPLAY);
433           }
434         } else {
435           printf("Fatal: Couldn't init game. \n");
436           return(STATEQUIT);
437         }
438       }
439 
440     break;
441 
442     case menuStateFinishedLevel:
443       starField(screen,0);
444       fireWorks(screen);
445       sprintf(buf, "Level %i Done!", player()->level);
446       txtWave(screen, FONTMEDIUM,buf, HSCREENW, HSCREENH-95, &rot);
447 
448       sprintf(buf, "Progress: %.1f%%",  ((100.0f/(float)getNumLevels())*((float)player()->level+1.0f)) );
449       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-60);
450 
451       sprintf(buf, "%i pts total",  player()->campStats.score);
452       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-40);
453 
454       sprintf(buf, "Stats for level %i", player()->level);
455       txtWriteCenter(screen, FONTSMALL, buf,HSCREENW,HSCREENH);
456       txtWrite(screen, FONTSMALL, " Stat      Yours         Best     ", (HSCREENW-153),(HSCREENH+20) );
457       txtWrite(screen, FONTSMALL, "+-----+-------------+------------+", (HSCREENW-153),(HSCREENH+30) );
458       txtWrite(screen, FONTSMALL, "Score :", (HSCREENW-153),(HSCREENH+42) );
459       txtWrite(screen, FONTSMALL, "Time  :", (HSCREENW-153),(HSCREENH+54) );
460       txtWrite(screen, FONTSMALL, "Moves :", (HSCREENW-153),(HSCREENH+68) );
461       txtWrite(screen, FONTSMALL, "Combos:", (HSCREENW-153),(HSCREENH+80) );
462 
463       //levelscore
464       sprintf(buf, "%i", player()->hsEntry.score);
465       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW-32, HSCREENH+42);
466 
467       //best levelscore
468       sprintf(buf, "%i", stats()->cl->score);
469       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW+90, HSCREENH+42);
470 
471       //time
472       sprintf(buf, "%i:%i", player()->hsEntry.time/60,player()->hsEntry.time%60 );
473       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW-32, HSCREENH+54);
474 
475       //best time
476       sprintf(buf, "%i:%i", stats()->cl->time/60,stats()->cl->time%60 );
477       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW+90, HSCREENH+54);
478 
479       //Moves
480       sprintf(buf, "%i", player()->hsEntry.moves);
481       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW-32, HSCREENH+68);
482 
483       //best moves
484       sprintf(buf, "%i", stats()->cl->moves);
485       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW+90, HSCREENH+68);
486 
487       //Combos
488       sprintf(buf, "%i", player()->hsEntry.combos);
489       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW-32, HSCREENH+80);
490       //best moves
491       sprintf(buf, "%i", stats()->cl->combos);
492       txtWriteCenter(screen, FONTSMALL, buf, HSCREENW+90, HSCREENH+80);
493 
494       txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+108);
495 
496       if(getButton(C_BTNB) || isPointerClicked() )
497       {
498         resetBtn(C_BTNB);
499 
500         setMenu( menuStatePrepareNextLevel );
501         return(STATEMENU);
502       }
503 
504     break;
505 
506     case menuStatePrepareNextLevel:
507       //Reset board score
508       player()->hsEntry.score=0;
509 
510       //Check if the player compleated all levels
511       if(player()->level+1 == getNumLevels())
512       {
513         //Go to "Completed pack" image.
514         setMenu(menuStateBeatPack);
515         break;
516       }
517 
518       //Inc to next lvl
519       player()->level++;
520 
521       //Set new level
522       player()->levelFile = levelInfo( player()->level )->file;
523 
524       //Entering screen
525       menuState=menuStateNextLevel;
526     break;
527 
528     case menuStatePaused:
529       menuMaxY = 8;
530       starField(screen,1);
531       if(player()->gameStarted)
532       {
533         txtWave(screen, FONTMEDIUM, STR_MENU_PAUSE_HEADLINE, HSCREENW, HSCREENH-115, &rot);
534       } else {
535         txtWave(screen, FONTMEDIUM, STR_MENU_WIZZNIC_HEADLINE, HSCREENW, HSCREENH-115, &rot);
536       }
537 
538       if(dir || menuPosY!= 0)
539       {
540         txtWriteCenter(screen, FONTSMALL, STR_MENU_NEW_GAME_CHOICE, HSCREENW, HSCREENH-80);
541         if( isBoxClicked( getTxtBox() ) )
542           menuPosY=0;
543       }
544 
545       if( player()->gameStarted && (dir || menuPosY!= 1 ) )
546       {
547         txtWriteCenter(screen, FONTSMALL, STR_MENU_RESUME_CHOICE, HSCREENW, HSCREENH-60);
548         if( isBoxClicked( getTxtBox() ) )
549           menuPosY=1;
550       }
551 
552       if(dir || menuPosY!= 2)
553       {
554         txtWriteCenter(screen, FONTSMALL, STR_MENU_HIGHSCORES_CHOICE, HSCREENW, HSCREENH-40);
555         if( isBoxClicked( getTxtBox() ) )
556           menuPosY=2;
557       }
558 
559       if(dir || menuPosY!= 3)
560       {
561         txtWriteCenter(screen, FONTSMALL, STR_MENU_OPTIONS_CHOICE, HSCREENW, HSCREENH-20);
562         if( isBoxClicked( getTxtBox() ) )
563           menuPosY=3;
564       }
565 
566       if(dir || menuPosY!= 4)
567       {
568         txtWriteCenter(screen, FONTSMALL, STR_MENU_EDITOR_CHOICE, HSCREENW, HSCREENH+0);
569        if( isBoxClicked( getTxtBox() ) )
570        {
571           menuPosY=4;
572        }
573       }
574 
575       if(dir || menuPosY!= 5)
576       {
577         txtWriteCenter(screen, FONTSMALL, STR_MENU_PACK_CHOICE, HSCREENW, HSCREENH+20);
578         if( isBoxClicked( getTxtBox() ) )
579           menuPosY=5;
580       }
581 
582       if(dir || menuPosY!= 6)
583       {
584         txtWriteCenter(screen, FONTSMALL, STR_MENU_ABOUT_CHOICE, HSCREENW, HSCREENH+40);
585         if( isBoxClicked( getTxtBox() ) )
586           menuPosY=6;
587       }
588 
589 
590       if(dir || menuPosY!= 7)
591       {
592         txtWriteCenter(screen, FONTSMALL, STR_MENU_EXIT_CHOICE, HSCREENW, HSCREENH+60);
593         if( isBoxClicked( getTxtBox() ) )
594           menuPosY=7;
595       }
596 
597       if(dir || menuPosY!= 8)
598       {
599         sprintf(buf, STR_MENU_PACK_SHOW, packState()->cp->name);
600         txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+100);
601         if( isBoxClicked( getTxtBox() ) )
602           menuPosY=8;
603       }
604 
605 
606       if( getButton( C_BTNB ) || isAnyBoxHit() )
607       {
608         resetBtn( C_BTNB );
609         resetMouseBtn();
610 
611         switch(menuPosY)
612         {
613           case 0: //Newgame
614             //If in arcade-mode, clear progress before entering level-selection.
615             if(setting()->arcadeMode)
616             {
617               stats()->progress=-1;
618             }
619 
620             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
621             setMenu(menuStateNewGame);
622 
623             //Clean up.
624             if(player()->gameStarted)
625             {
626               cleanUpGame();
627               //Check if highscore, if a game was started
628               if( statsIsHighScore() )
629               {
630                 setMenu(menuStateEnterHighScore);
631                 menuReturnHack=menuStateNewGame;
632               }
633             }
634 
635             //Current selected level.
636             menuPosX=stats()->progress+1;
637           break;
638           case 1: //Resume, unset paused, return to game
639             if(player()->gameStarted)
640             {
641               startTransition(screen, TRANSITION_TYPE_ROLL_OUT,500);
642               return(STATEPLAY);
643             }
644           break;
645           case 2: //Highscores
646             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
647             setMenu(menuStateHighScores);
648           break;
649           case 3: //Options
650             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
651             setMenu(menuStateOptions);
652           break;
653           case 4: //UserLevels
654             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
655             setMenu(menuStateUserLevels);
656             if(player()->gameStarted) cleanUpGame();
657             return(STATEMENU);
658           break;
659           case 6: //Switch to about screen
660             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
661             setMenu(menuStateAbout);
662           break;
663 
664           case 7: //Exit program
665             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
666             if( statsIsHighScore() )
667             {
668               setMenu(menuStateEnterHighScore);
669               menuReturnHack=menuStateOutro;
670             } else {
671               setMenu(menuStateOutro);
672             }
673           break;
674           case 5:
675           case 8: //Pack selection
676             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
677             setMenu(menuStatePackList);
678             menuPosY = packState()->selected;
679           break;
680         }
681       }
682       break;
683 
684       case menuStateHowto:
685         starField(screen,1);
686 
687         #if defined (GP2X) || defined (PSP) || defined (WIZ)
688         //Sprinkle particles
689         if( !dir && countdown < 1 )
690         {
691           ps.layer=PSYS_LAYER_TOP;
692           ps.x=(rand()%109)+107;
693           ps.y=(rand()%40)+78;
694           ps.vel=50; // +/- in each dir
695           ps.life=2000;
696           ps.lifeVar=500;
697           ps.fade=0;
698           ps.gravity=1;
699           ps.bounce=0;      //If 1, particles will bounce off screen borders ( (vel * -1)/2 )
700           ps.fadeColor=0x00;
701           ps.color=PARTICLECOLORRANDOM;
702           ps.srcImg=0; //Don't get colors from an image
703           ps.numParticles=20;
704           spawnParticleSystem(&ps);
705         }
706         runParticles(screen);
707         #else
708         fireWorks(screen);
709         #endif
710 
711         SDL_BlitSurface(menuBg[MENUGFXHELP] , NULL, screen, &(setting()->bgPos) );
712 
713         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B_PLAY, HSCREENW, HSCREENH+108);
714 
715         if( getButton( C_BTNB ) || isPointerClicked() )
716         {
717           resetBtn( C_BTNB );
718 
719           if(player()->gameStarted) //Return to game if allready started
720           {
721             startTransition(screen, TRANSITION_TYPE_ROLL_OUT,800);
722             return(STATEPLAY);
723           } else {
724             startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
725             setMenu(menuStatePaused);
726           }
727 
728         }
729       break;
730 
731       case menuStateAbout:
732         starField(screen, 0);
733         getInpPointerState()->escEnable=1;
734         fireWorks(screen);
735 
736         txtWave(screen, FONTSMALL, STR_MENU_ABOUT_WEBSITE, HSCREENW, HSCREENH-120+12,&rot);
737 
738         menuMaxY = aboutScreen(screen, &menuPosY, menuChangeY);
739 
740 
741         //alt z x z x
742         static int cheat=-1;
743         if( getButton( C_BTNA ) )
744         {
745           cheat=0;
746           resetBtn( C_BTNA );
747         }
748 
749         if( (cheat==0 || cheat==2)  && getButton(C_BTNY) )
750         {
751           resetBtn(C_BTNY);
752           cheat++;
753         }
754         if( (cheat==1 || cheat==3) && getButton(C_BTNX) )
755         {
756           resetBtn(C_BTNX);
757           cheat++;
758         }
759         if(cheat==4)
760         {
761           sndPlay( SND_MENUCLICK, 160 );
762           cheat=-1;
763           stats()->progress = getNumLevels();
764         }
765 
766         if( getButton(C_BTNB) || isPointerEscapeClicked() || getButton(C_BTNMENU) )
767         {
768           resetMouseBtn();
769           resetBtn( C_BTNB );
770           resetBtn( C_BTNMENU );
771           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
772           menuState=menuStatePaused;
773         }
774 
775       break;
776 
777       case menuStateGameOver:
778 
779         starField(screen,0);
780         txtWriteCenter(screen, FONTMEDIUM,STR_MENU_GAMEOVER, HSCREENW, HSCREENH-85);
781         sprintf(buf, STR_MENU_SCORE, player()->campStats.score);
782         txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+108);
783 
784         //If in arcade mode, lose progress
785         if(setting()->arcadeMode)
786         {
787           stats()->progress=-1;
788           statsSave();
789         }
790 
791         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+60);
792 
793         if( getButton(C_BTNB) || isPointerClicked() )
794         {
795           resetMouseBtn();
796           resetBtn( C_BTNB );
797           setMenu(menuStatePaused);
798           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
799 
800           if( statsIsHighScore() )
801           {
802             setMenu(menuStateEnterHighScore);
803             menuReturnHack=menuStatePaused;
804           }
805         }
806       break;
807 
808       case menuStateBeatPack:
809 
810         starField(screen, 1);
811         if( packState()->cp->hasFinishedImg )
812         {
813           if( !packState()->finishedImg )
814           {
815             packState()->finishedImg = loadImg( packGetFile("./","finished.png" ) );
816             if( !packState()->finishedImg )
817             {
818               printf("Error: Can't load pack-finished file '%s'\n", packGetFile("./","finished.png" ) );
819               return(STATEQUIT);
820             }
821           }
822         } else {
823           fireWorks(screen);
824 
825           txtWave(screen, FONTMEDIUM, STR_MENU_BEAT_PACK_HEADLINE, HSCREENW, HSCREENH-108, &rot);
826           txtWrite(screen, FONTSMALL, STR_MENU_BEAT_PACK_RANT, HSCREENW-150, HSCREENH-50);
827         }
828 
829         //Blit image to screen
830         SDL_BlitSurface(packState()->finishedImg , NULL, screen, &(setting()->bgPos) );
831 
832         //bink "press b"
833         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+100);
834 
835         if( getButton(C_BTNB) || isPointerClicked() )
836         {
837           resetBtn(C_BTNB);
838           resetMouseBtn();
839 
840           //Free image
841           SDL_FreeSurface( packState()->finishedImg );
842 
843           //Set img ptr so it knows to load a new next time.
844           packState()->finishedImg=0;
845 
846           //Check if he got a highscore.
847           if( statsIsHighScore() )
848           {
849             setMenu(menuStateEnterHighScore);
850             menuReturnHack=menuStatePackList;
851             menuPosY = packState()->selected;
852           } else {
853             setMenu(menuStatePackList);
854             //Set to first pack in lst when we get there
855             menuPosY=0;
856             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500 );
857 
858           }
859 
860           return(STATEMENU);
861         }
862       break;
863 
864       case menuStateOutro:
865         getInpPointerState()->escEnable=1;
866 
867         //Show background image
868         if(!menuBg[MENUGFXBYE])
869         {
870           menuBg[MENUGFXBYE]=loadImg( DATADIR"data/menu/bye.png");
871         }
872         SDL_BlitSurface(menuBg[MENUGFXBYE] , NULL, screen, &(setting()->bgPos) );
873         //Fireworks?
874         fireWorks(screen);
875 
876         //Blink "Press B"
877         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+60);
878 
879         if( getButton(C_BTNMENU) || isPointerEscapeClicked() )
880         {
881           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500);
882           setMenu(menuStatePaused);
883         }
884 
885         if(getButton(C_BTNB) || isPointerClicked() )
886         {
887           resetBtn(C_BTNB);
888           cleanUpGame();
889           return(STATEQUIT);
890         }
891       break;
892 
893       //The leveleditor submenu.
894       case menuStateUserLevels:
895         getInpPointerState()->escEnable=1;
896         starField(screen, 1);
897         fireWorks(screen);
898 
899         txtWave(screen, FONTMEDIUM, STR_MENU_LVLEDIT_HEADLINE, HSCREENW, HSCREENH-105, &rot);
900         menuMaxY=getNumUserLevels()+1;
901 
902         //Just keep it clean. (This is a reference to a pitchshifter song by the way)
903         if(player()->gameStarted) cleanUpGame();
904 
905         sb = scrollBar(screen, HSCREENW+160-19-15, HSCREENH-120+40, (float)(getNumUserLevels()-1), ((menuPosY<2)?0:menuPosY-2), menuChangeY);
906         if(sb != -1)
907         {
908           menuPosY=sb+2;
909         }
910 
911         //List levels
912         ul=0;   //Userlevel
913         scroll=0; //Generic scoll int
914         if(menuPosY > 10)
915         {
916           ul = menuPosY-10;
917           scroll=ul;
918         }
919 
920 
921         int i=0;
922         while(ul < getNumUserLevels())
923         {
924           i++;
925 
926           if( menuPosY==ul+2)
927           {
928             sprintf(buf, STR_MENU_LVLEDIT_USRLVL_SEL, ul);
929           } else {
930             sprintf(buf, STR_MENU_LVLEDIT_USRLVL, ul);
931           }
932 
933           txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-53+(11*(ul-scroll)));
934 
935           if( isBoxClicked( getTxtBox() ) )
936           {
937             menuPosY=(ul+2); //hackity hack, if menuposy is negative, we click-selected a level
938           }
939 
940           ul++;
941           if( i > 12 )
942           {
943             break;
944           }
945         }
946 
947         //Show keys only if cursor not active
948         if( !(getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT) )
949         {
950           txtWriteCenter(screen, FONTSMALL, STR_MENU_LVLEDIT_USAGE, HSCREENW, HSCREENH+106);
951         } else  {
952           //Show Play Clone Edit buttons for the mouse
953           if( menuPosY > 1)
954           {
955 
956             txtWriteCenter(screen, FONTSMALL, STR_MENU_LVLEDIT_PLAY, HSCREENW-60-48, HSCREENH+106 );
957             if( isBoxClicked( getTxtBox() ) )
958             {
959               resetMouseBtn();
960               ul=-1; //Decided that -1 means "play"
961              // menuPosY=-menuPosY;
962             }
963 
964             txtWriteCenter(screen, FONTSMALL, STR_MENU_LVLEDIT_EDIT, HSCREENW-48, HSCREENH+106 );
965             if( isBoxClicked( getTxtBox() ) )
966             {
967               resetMouseBtn();
968               ul=-2; //Decided that -2 means "edit"
969              // menuPosY=-menuPosY;
970             }
971 
972             txtWriteCenter(screen, FONTSMALL, STR_MENU_LVLEDIT_CLONE, HSCREENW+60-48, HSCREENH+106 );
973             if( isBoxClicked( getTxtBox() ) )
974             {
975               resetMouseBtn();
976               ul=-3; //Decided that -3 means "clone"
977             //  menuPosY=-menuPosY;
978             }
979 
980             txtWriteCenter(screen, FONTSMALL, STR_MENU_LVLEDIT_UPLOAD, HSCREENW+60+24, HSCREENH+106 );
981             if( isBoxClicked( getTxtBox() ) )
982             {
983               resetMouseBtn();
984               ul=-4; //Decided that -4 means "Upload"
985             //  menuPosY=-menuPosY;
986             }
987 
988           }
989         }
990 
991 
992         //Show Create and Exit menu-points.
993         if( (!dir || menuPosY!=0)|| (getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT)) txtWriteCenter(screen, FONTSMALL, STR_LVLEDIT_CREATE_CHOICE,HSCREENW,HSCREENH-78);
994         if( isBoxClicked( getTxtBox() ) )
995         {
996           resetMouseBtn();
997           menuPosY=0;
998           ul=-5; //No special meaning.
999         }
1000 
1001         if( (!dir || menuPosY!=1)|| (getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT)) txtWriteCenter(screen, FONTSMALL, STR_LVLEDIT_EXIT_CHOICE,HSCREENW,HSCREENH-65);
1002         if( isBoxClicked( getTxtBox() ) )
1003         {
1004           resetMouseBtn();
1005           menuPosY=1;
1006           ul=-5; //No special meaning.
1007         }
1008 
1009         if( menuPosY > -1 )
1010         {
1011 
1012           //Edit levels/select
1013           if(getButton(C_BTNB) || ul < 0 )
1014           {
1015             resetBtn(C_BTNB);
1016             resetMouseBtn();
1017 
1018             if(menuPosY==0) //Load empty, and create new levelname
1019             {
1020               //Load empty, set name to something diffrent
1021               editorLoad( DATADIR"data/empty.wzp",screen);
1022 
1023               sprintf(buf, "%s/level%03i.wzp", getUserLevelDir(), getNumUserLevels());
1024               editorFileName(buf);
1025 
1026               startTransition(screen, TRANSITION_TYPE_ROLL_OUT, 500 );
1027               return(STATEEDIT);
1028             } else if(menuPosY==1)  //Exit from editor
1029             {
1030               player()->inEditor=0;
1031               menuState=menuStatePaused;
1032               startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1033               menuPosY=0;
1034             } else if( ul==-2 || ul>0 )
1035             {
1036               startTransition(screen, TRANSITION_TYPE_ROLL_OUT, 500 );
1037               editorLoad(userLevelFile(menuPosY-2),screen);
1038               return(STATEEDIT);
1039             }
1040           }
1041 
1042 #ifdef PLATFORM_SUPPORTS_STATSUPLOAD
1043           //Attempt upload
1044           if( getButton(C_BTNX) || ul==-4 )
1045           {
1046             ul=-5;
1047             resetBtn(C_BTNX);
1048             resetMouseBtn();
1049 
1050             if( isLevelCompletable(userLevelFile(menuPosY-2)) )
1051             {
1052               if( dlcPushFile( userLevelFile(menuPosY-2), message ) )
1053               {
1054                 menuState=menuStateLevelUploadOk;
1055               } else {
1056                 menuState=menuStateLevelUploadError;
1057               }
1058             } else {
1059               menuState=menuStateLevelUploadError;
1060               sprintf(message, "Complete the level first.");
1061             }
1062           }
1063 #endif
1064 
1065           //Clone a level
1066           if( getButton(C_BTNY) || ul==-3 )
1067           {
1068             resetBtn(C_BTNY);
1069             resetMouseBtn();
1070 
1071             if(menuPosY > 1)
1072             {
1073               //Load the selected level
1074               editorLoad(userLevelFile(menuPosY-2),screen);
1075 
1076               //Make new filename
1077               sprintf(buf, "%s/level%03i.wzp", getUserLevelDir(), getNumUserLevels());
1078               editorFileName(buf);
1079 
1080               //Start editing state
1081               startTransition(screen, TRANSITION_TYPE_ROLL_OUT, 500 );
1082 
1083               return(STATEEDIT);
1084             }
1085           }
1086 
1087           //Play levelfile
1088           if( getButton(C_BTNA) || ul==-1 )
1089           {
1090             resetBtn(C_BTNA);
1091             resetMouseBtn();
1092             if(menuPosY > 1)
1093             {
1094               initPlayer(); //Reset player for editor.
1095               player()->levelFile = userLevelFile(menuPosY-2);
1096               player()->level = 0;
1097               player()->inEditor=1;
1098 
1099               if(initGame(screen))
1100               {
1101                 startTransition(screen, TRANSITION_TYPE_ROLL_OUT, 500 );
1102                 return(STATEPLAY);
1103               } else {
1104                 printf("Editor couldn't init game for the editor.\n");
1105                 return(STATEQUIT);
1106               }
1107             }
1108           }
1109         } //Not a negative number
1110 
1111 
1112         if(isPointerEscapeClicked())
1113         {
1114           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1115           menuState=menuStatePaused;
1116           resetMouseBtn();
1117         }
1118 
1119       break; //< userlevels
1120 
1121       case menuStateLevelUploadOk:
1122         starField(screen, 1);
1123         fireWorks(screen);
1124         getInpPointerState()->escEnable=1;
1125         txtWriteCenter(screen, FONTMEDIUM, "Thanks!", HSCREENW, HSCREENH-106);
1126 
1127         //TODO: Externalize strings
1128         txtWrite(screen, FONTSMALL, "Thanks for uploading your level!", HSCREENW-160+8, HSCREENH-78);
1129         txtWrite(screen, FONTSMALL, "When your level has been reviewed,", HSCREENW-160+8, HSCREENH-78+9);
1130         txtWrite(screen, FONTSMALL, "it will appear on wizznic.org", HSCREENW-160+8, HSCREENH-78+9+9);
1131         txtWrite(screen, FONTSMALL, "Then you can get it with the code;", HSCREENW-160+8, HSCREENH-78+9+9+9);
1132         txtWriteCenter(screen, FONTMEDIUM, message, HSCREENW, HSCREENH-78+9+9+9+9+9);
1133 
1134 
1135 
1136 
1137         if( getButton(C_BTNB) || isPointerEscapeClicked() || getButton(C_BTNMENU) )
1138         {
1139           resetMouseBtn();
1140           resetBtn( C_BTNB );
1141           resetBtn( C_BTNMENU );
1142           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1143           menuState=menuStateUserLevels;
1144         }
1145 
1146         if(dir && !(getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT )) txtWriteCenter(screen, FONTSMALL, "Press Ctrl", HSCREENW, HSCREENH+60);
1147 
1148         break; //< upload level went ok
1149 
1150       case menuStateLevelUploadError:
1151         starField(screen, 0);
1152         getInpPointerState()->escEnable=1;
1153         txtWriteCenter(screen, FONTMEDIUM, "Sorry!", HSCREENW, HSCREENH-106);
1154         txtWrite(screen, FONTSMALL, message, HSCREENW-160+28, HSCREENH-78);
1155 
1156         if( getButton(C_BTNB) || isPointerEscapeClicked() || getButton(C_BTNMENU) )
1157         {
1158           resetMouseBtn();
1159           resetBtn( C_BTNB );
1160           resetBtn( C_BTNMENU );
1161           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1162           menuState=menuStateUserLevels;
1163         }
1164 
1165         if(dir && !(getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT )) txtWriteCenter(screen, FONTSMALL, "Press Ctrl", HSCREENW, HSCREENH+60);
1166 
1167       break; //< something went wrong
1168 
1169       case menuStatePackList:
1170         starField(screen, 1);
1171         fireWorks(screen);
1172         txtWriteCenter(screen, FONTMEDIUM, STR_MENU_SELECT_PACK, HSCREENW, HSCREENH-106);
1173         getInpPointerState()->escEnable=0;
1174         if(dir && !(getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT )) txtWriteCenter(screen, FONTSMALL, STR_MENU_SELECT_PACK_PRESS_CTRL, HSCREENW, HSCREENH-84);
1175         menuMaxY= packState()->numPacks;
1176         ul=0;
1177         scroll=0;
1178         if(menuPosY > 2)
1179         {
1180           ul= menuPosY - 2;
1181           scroll=ul;
1182         }
1183 
1184 
1185         //Clear box
1186         SDL_FillRect(menuBg[MENUGFXPACKBOX],0, SDL_MapRGB(screen->format, 0,255,255));
1187 
1188         int_fast8_t packListItemWasClicked=0;
1189         while(ul < packState()->numPacks+1 && ul-scroll <  4)
1190         {
1191           //The selected box waves
1192           if(menuPosY== ul)
1193           {
1194             drawPackBox(menuBg[MENUGFXPACKBOX], 0,0, ul );
1195             setWaving(&waving, screen, menuBg[MENUGFXPACKBOX], HSCREENW-130,HSCREENH-70+(48*(ul-scroll)),2,4,150);
1196             waveImg(&waving);
1197           } else {
1198             drawPackBox(screen, HSCREENW-130,HSCREENH-70+(48*(ul-scroll)), ul );
1199           }
1200 
1201           //Check if this box was clicked
1202 
1203           r.x = HSCREENW-130;
1204           r.y = HSCREENH-70+(48*(ul-scroll));
1205           r.w = r.x+260; // Size of graphics + position I know-, that
1206           r.h = r.y+42;  // is not how SDL_Rect was intended to be used.
1207 
1208           if( isBoxClicked( &r ) )
1209           {
1210             resetMouseBtn();
1211             if( menuPosY == ul )
1212             {
1213               packListItemWasClicked=1;
1214             } else {
1215               menuPosY=ul;
1216             }
1217           }
1218 
1219           //Increase counter (doh, most obvious comment to date)
1220           ul++;
1221         }
1222 
1223 
1224         sb = scrollBar(screen, HSCREENW+160-19-5, HSCREENH-120+50, (float)(packState()->numPacks), menuPosY, menuChangeY);
1225         if(sb != -1) menuPosY=sb;
1226 
1227         if( getButton(C_BTNB) || packListItemWasClicked )
1228         {
1229           resetBtn(C_BTNB);
1230           resetMouseBtn();
1231           //Check if it's the DLC box
1232           if( menuPosY == packState()->numPacks )
1233           {
1234 #if defined( PLATFORM_SUPPORTS_STATSUPLOAD )
1235             if( setting()->online && dlcGetState()==DLC_READY )
1236             {
1237               startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1238               setMenu(menuStateDLC);
1239             }
1240 #endif
1241           } else {
1242 
1243             packFreeGfx();
1244             //If it's a different pack
1245             if(menuPosY != packState()->selected)
1246             {
1247               //If there's a game started
1248               if(player()->gameStarted)
1249               {
1250                 cleanUpGame();
1251               }
1252 
1253               //Clear the levelselector image (it caches images)
1254               resetLevelSelector();
1255 
1256               //Set selected pack.
1257               packSet(menuPosY);
1258               printf("Selected pack number: %i\n", menuPosY);
1259 
1260               //Save setting
1261               free( setting()->packDir);
1262               setting()->packDir = malloc( sizeof(char)*(strlen(packState()->cp->path)+1) );
1263               strcpy( setting()->packDir, packState()->cp->path );
1264               saveSettings(); //Save
1265               //--
1266 
1267             }
1268             startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1269             //Return to main menu
1270             setMenu(menuStatePaused);
1271           }
1272         }
1273       break;
1274 
1275       case menuStateOptions:
1276         starField(screen, 1);
1277         fireWorks(screen);
1278         txtWave(screen, FONTMEDIUM, STR_MENU_OPTIONS, HSCREENW, HSCREENH-108, &rot);
1279 
1280         //Number of options in list
1281         menuMaxY = 9;
1282 
1283         if(dir || menuPosY!= 0) txtWriteCenter(screen, FONTSMALL, STR_MENU_OPTIONS_EXIT, HSCREENW, HSCREENH-70);
1284         //Save and exit Options menu
1285         if( ( getButton( C_BTNMENU ) || (getButton( C_BTNB ) && menuPosY==0) ) || isBoxClicked( getTxtBox() ) )
1286         {
1287           resetBtn( C_BTNMENU );
1288           resetBtn( C_BTNB );
1289           resetMouseBtn();
1290 
1291           saveSettings();
1292           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500 );
1293 
1294           setMenu(menuStatePaused);
1295         }
1296 
1297         sprintf(buf, STR_MENU_OPTIONS_SOUNDVOL, setting()->soundVol);
1298         if(dir || menuPosY!= 1) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-50);
1299         if( isBoxClicked( getTxtBox() ) )
1300         {
1301           resetMouseBtn();
1302           menuPosY=1;
1303           menuMaxX=16;
1304           menuPosX = setting()->soundVol/8;
1305           incPosX();
1306         }
1307 
1308         //Set posY
1309         if(menuPosY==1)
1310         {
1311           if(menuChangeY)
1312           {
1313             menuMaxX=16;
1314             menuPosX = setting()->soundVol/8;
1315           }
1316           setting()->soundVol = menuPosX*8;
1317 
1318           //Change sound-volume if it changed
1319           if(menuChangeX)
1320           {
1321             applySettings();
1322           }
1323         }
1324 
1325         sprintf(buf, STR_MENU_OPTIONS_MUSICVOL, setting()->musicVol);
1326         if(dir || menuPosY!= 2) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-40);
1327         if( isBoxClicked( getTxtBox() ) )
1328         {
1329           menuPosY=2;
1330           menuMaxX=16;
1331           menuPosX = setting()->musicVol/8;
1332           incPosX();
1333         }
1334 
1335         //Set posY
1336         if(menuPosY==2)
1337         {
1338           if(menuChangeY)
1339           {
1340             menuMaxX=16;
1341             menuPosX = setting()->musicVol/8;
1342           }
1343           setting()->musicVol = menuPosX*8;
1344           //Change music-volume if it changed
1345           if(menuChangeX)
1346           {
1347             applySettings();
1348           }
1349         }
1350 
1351         sprintf(buf, (setting()->userMusic)?"Music: <User selected>":"Music: <Game Music>");
1352         if(dir || menuPosY!=3) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW,HSCREENH-30);
1353         if(  (menuPosY==3  && getButton(C_BTNB)) || isBoxClicked( getTxtBox() ) )
1354         {
1355           resetBtn(C_BTNB);
1356           menuPosY=0;
1357           fileListMake(setting()->musicDir);
1358           setMenu(menuStateSelectMusicDir);
1359         }
1360 
1361         sprintf(buf, (setting()->arcadeMode)?"Game mode: < Arcade >":"Game mode: < Career >");
1362         if(dir || menuPosY!= 4) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH-10);
1363         if( isBoxClicked( getTxtBox() ) )
1364         {
1365           menuPosY=4;
1366           menuMaxX=1;
1367           menuPosX = setting()->arcadeMode;
1368           incPosX();
1369         }
1370 
1371         //Set posy
1372         if(menuPosY==4)
1373         {
1374           if(menuChangeY)
1375           {
1376             menuMaxX=1;
1377             menuPosX = setting()->arcadeMode;
1378           }
1379           setting()->arcadeMode = menuPosX;
1380         }
1381 
1382         sprintf(buf, (setting()->showFps)?"Show FPS: < On >":"Show FPS: < Off >");
1383         if(dir || menuPosY!= 5) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+10);
1384         if( isBoxClicked( getTxtBox() ) )
1385         {
1386           menuPosY=5;
1387           menuMaxX=1;
1388           menuPosX = setting()->showFps;
1389           incPosX();
1390         }
1391 
1392         //Set posy
1393         if(menuPosY==5)
1394         {
1395           if(menuChangeY)
1396           {
1397             menuMaxX=1;
1398             menuPosX = setting()->showFps;
1399           }
1400           setting()->showFps = menuPosX;
1401         }
1402 
1403         sprintf(buf, (setting()->particles)?"Particles: < On >":"Particles: < Off >");
1404         if(dir || menuPosY!= 6) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+20);
1405         if( isBoxClicked( getTxtBox() ) )
1406         {
1407           menuPosY=6;
1408           menuMaxX=1;
1409           menuPosX = setting()->particles;
1410           incPosX();
1411         }
1412         //Set posy
1413         if(menuPosY==6)
1414         {
1415           if(menuChangeY)
1416           {
1417             menuMaxX=1;
1418             menuPosX = setting()->particles;
1419           }
1420           setting()->particles = menuPosX;
1421         }
1422         //Disable music (requires restart)
1423         sprintf(buf, (setting()->disableMusic)?"Load Music: < Disabled >":"Load Music: < Enabled >");
1424         if(dir || menuPosY!= 7) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+30);
1425         if( isBoxClicked( getTxtBox() ) )
1426         {
1427           menuPosY=7;
1428           menuMaxX=1;
1429           menuPosX = setting()->disableMusic;
1430           incPosX();
1431         }
1432         //Set posy
1433         if(menuPosY==7)
1434         {
1435           txtWriteCenter(screen, FONTSMALL, "(Restart required)", HSCREENW, HSCREENH+100);
1436           if(menuChangeY)
1437           {
1438             menuMaxX=1;
1439             menuPosX = setting()->disableMusic;
1440           }
1441           setting()->disableMusic = menuPosX;
1442         }
1443 
1444         #ifdef WIZ // to do for GP2X
1445         sprintf(buf, "Wiz Clock: < %i >", setting()->wizClock);
1446         if(dir || menuPosY!= 8) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+50);
1447         if( isBoxClicked( getTxtBox() ) )
1448         {
1449           menuReturnHack=menuStateOptions;
1450           setMenu(menuStateNoPointerSupport);
1451         }
1452 
1453         //Set posY
1454         if(menuPosY==8)
1455         {
1456           if(menuChangeY)
1457           {
1458             menuMaxX=70;
1459             menuPosX = setting()->wizClock/10;
1460           }
1461 
1462           if( menuPosX < 10 )
1463             menuPosX = 10;
1464 
1465           setting()->wizClock = menuPosX*10;
1466 
1467           //Only clock the wiz when value changes.
1468           if(menuChangeX)
1469           {
1470             WIZ_SetClock( setting()->wizClock );
1471           }
1472         }
1473         #endif
1474 
1475 
1476         //Upload stats?
1477         #ifdef PLATFORM_SUPPORTS_STATSUPLOAD
1478         sprintf(buf, (setting()->uploadStats)?"Allow Online: <Yes>":"Allow Online: <No>");
1479         if(dir || menuPosY!= 8) txtWriteCenter(screen, FONTSMALL, buf, HSCREENW, HSCREENH+50);
1480         if( isBoxClicked( getTxtBox() ) )
1481         {
1482           menuPosY=8;
1483           menuMaxX=1;
1484           menuPosX = setting()->uploadStats;
1485           incPosX();
1486         }
1487 
1488         //Set posY
1489         if(menuPosY==8)
1490         {
1491           if(menuChangeY)
1492           {
1493             menuMaxX=1;
1494             menuPosX=setting()->uploadStats;
1495           }
1496           setting()->uploadStats = menuPosX;
1497           if(menuChangeX)
1498           {
1499             if(setting()->uploadStats && !setting()->online)
1500             {
1501               statsUpload(0,0,0,0,0,"check",1, &(setting()->session) );
1502               dlcCheckOnline();
1503             } else if(!setting()->uploadStats)
1504             {
1505               setting()->online=0;
1506             }
1507           }
1508         }
1509         #endif
1510 
1511         //Reset progress?
1512         if( stats()->progress != -1 || 1)
1513         {
1514           //Disable music (requires restart)
1515 
1516           if(dir || menuPosY!= 9) txtWriteCenter(screen, FONTSMALL, "Clear Progress and High-Scores", HSCREENW, HSCREENH+70);
1517           if(  (menuPosY==9  && getButton(C_BTNB)) || isBoxClicked( getTxtBox() ) )
1518           {
1519             resetBtn(C_BTNB);
1520             setMenu(menuStateConfirmReset);
1521             menuPosX = 1;
1522           }
1523         }
1524 
1525 
1526 
1527       break;
1528 
1529       //Highscore list
1530       case menuStateHighScores:
1531       starField(screen, 0);
1532       fireWorks(screen);
1533       menuMaxY=1;
1534 
1535       statsDrawHs(screen);
1536 
1537 
1538       txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B,HSCREENW,HSCREENH+100);
1539 
1540       if( getButton( C_BTNB ) || isPointerClicked() )
1541       {
1542         resetBtn( C_BTNB );
1543           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500);
1544           setMenu(menuStatePaused);
1545       }
1546 
1547       break;
1548 
1549       case menuStateEnterHighScore:
1550         starField(screen, 0);
1551         INP_GET_STR_LIMITS
1552         txtWriteCenter(screen, FONTMEDIUM, "High score!", HSCREENW,HSCREENH-95);
1553         txtWriteCenter(screen, FONTSMALL, "Enter your name for highscore.", HSCREENW, HSCREENH-70);
1554 
1555         if( inpStrGet(strStateHighScore, menuPosX, menuPosY, dir) )
1556         {
1557           strcpy( setting()->playerName, strStateHighScore->str );
1558 
1559           saveSettings();
1560           //Copy player name.
1561           strcpy(player()->campStats.name, setting()->playerName);
1562           statsSaveHighScore();
1563          // printf("AddingHighscore: %i\n", player()->campStats.score);
1564           startTransition(screen, TRANSITION_TYPE_CURTAIN_DOWN, 500);
1565           menuState=menuReturnHack;
1566           menuPosY=0;
1567         }
1568       break;
1569 
1570       case menuStateSelectMusicDir:
1571 
1572         starField(screen,0);
1573         txtWave(screen, FONTMEDIUM, "Select Music", 160,15, &rot);
1574         if(dir || menuPosY!=0) txtWriteCenter(screen, FONTSMALL, "Play Music From Game", HSCREENW, HSCREENH-70);
1575         if( isBoxClicked( getTxtBox() ) || (menuPosY==0 && getButton(C_BTNB) ) )
1576         {
1577           resetBtn(C_BTNB);
1578           setting()->userMusic=0; //Turn user-selected music off
1579           free(setting()->musicDir);
1580           setting()->musicDir=malloc(sizeof(char)*2 );
1581           strcpy(setting()->musicDir, "."); //This forces musicdir to be set to pwd next load, which is fine if user-music is not used anyway.
1582           saveSettings();
1583           fileListFree();
1584           soundSetMusic(); //Important to set after freeing file list, since this is using that list
1585           setMenu(menuStateOptions);
1586           menuPosX=3;
1587           return(STATEMENU);
1588         }
1589 
1590         if(dir || menuPosY!=1) txtWriteCenter(screen, FONTSMALL, "Play Music From Here", HSCREENW, HSCREENH-60);
1591 
1592         if( isBoxClicked( getTxtBox() ) || (menuPosY==1 && getButton(C_BTNB)) )
1593         {
1594           resetBtn(C_BTNB);
1595 
1596           {
1597             setting()->userMusic=1; //Turn user-selected music on
1598             saveSettings();
1599             fileListFree();
1600             soundSetMusic(); //Important to set after freeing file list, since this is using that list
1601             setMenu(menuStateOptions);
1602             menuPosX=3;
1603             return(STATEMENU);
1604           }
1605         }
1606 
1607         x=0;
1608         y=0;
1609         scroll=0;
1610         if(menuPosY > 10)
1611         {
1612           x = menuPosY-10;
1613           scroll=x;
1614         }
1615         //Run through list
1616         it=&fileList()->begin;
1617 
1618         while( LISTFWD(fileList(), it) )
1619         {
1620           fItem=(fileListItem_t*)it->data;
1621           if(fItem->dir)
1622           {
1623             y++;
1624             if(y>x)
1625             {
1626               if(dir || menuPosY!=x+2) txtWriteCenter(screen, FONTSMALL, fItem->name, HSCREENW, (HSCREENH-40)+((x-scroll)*10));
1627               if( (menuPosY-2==x && getButton(C_BTNB)) || isBoxClicked( getTxtBox() ) )
1628               {
1629                 resetBtn(C_BTNB);
1630 
1631                 if( fItem->fullName == (char*)0 ) //The "Go back" entry.
1632                 {
1633                   char* nmd = malloc( sizeof(char)*(strlen(setting()->musicDir)+1) ); //New directory name.
1634                   #ifdef WIN32
1635                     #define DELIMCHAR '\\'
1636                   #else
1637                     #define DELIMCHAR '/'
1638                   #endif
1639                   nmd = strncpy( nmd, setting()->musicDir, charrpos( setting()->musicDir, DELIMCHAR ) );
1640                   nmd[charrpos( setting()->musicDir, DELIMCHAR )] = 0;
1641                   printf("Went from '%s' to '%s'\n", setting()->musicDir, nmd);
1642                   free( setting()->musicDir );
1643                   setting()->musicDir = nmd;
1644                 } else {
1645                   free(setting()->musicDir);
1646                   setting()->musicDir=malloc(sizeof(char)*(strlen(fItem->fullName)+1));
1647                   strcpy(setting()->musicDir, fItem->fullName);
1648                 }
1649                 fileListMake(setting()->musicDir);
1650                 menuPosY=2;
1651                 return(STATEMENU);
1652               }
1653               x++;
1654             }
1655           }
1656         }
1657 
1658         txtWriteCenter(screen, FONTSMALL, "----- Files -----", HSCREENW, (HSCREENH-40)+(x-scroll)*10);
1659         x++;
1660         menuMaxY=x;
1661 
1662         it=&fileList()->begin;
1663         while( LISTFWD(fileList(), it) )
1664         {
1665           fItem=(fileListItem_t*)it->data;
1666           if(!fItem->dir)
1667           {
1668             if(dir || menuPosY!=x+2) txtWriteCenter(screen, FONTSMALL, fItem->name, HSCREENW, (HSCREENH-40)+(x-scroll)*10);
1669             x++;
1670           }
1671         }
1672 
1673       break;
1674 
1675       #if !defined (GP2X) || !defined (WIZ)
1676       case menuStateUploadDiag:
1677         starField(screen,0);
1678         if( menuYesNo == 0)
1679         {
1680           menuYesNo = mkAni(loadImg( DATADIR"data/menu/yesno.png"), 36,42,0);
1681         }
1682 
1683         r.y = (setting()->bgPos.y)+ 240-64-16;
1684 
1685         menuPosY=0; //Using this as a click-lock
1686         menuMaxY=1;
1687         menuMaxX=2;
1688         txtWrite(screen, FONTSMALL, STR_MENU_UPLOADNAG, HSCREENW-152, HSCREENH-108 );
1689 
1690 
1691         //Set rect for yes
1692         r.x = (setting()->bgPos.x)+ 32;
1693         //Display/blink yes
1694         if(menuPosX == 0 && dir)
1695         {
1696           //SDL_BlitSurface(menuBg[MENUGFXYES] , NULL, screen, &ynpos );
1697           drawSprite(screen, menuYesNo->spr[0], r.x, r.y);
1698         } else {
1699           drawSprite(screen, menuYesNo->spr[1], r.x, r.y);
1700         }
1701         //Detect pointer click on yes
1702         r.w=r.x + menuYesNo->spr[0]->clip.w;
1703         r.h=r.y + menuYesNo->spr[0]->clip.h;
1704         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT &&  isPointerInBox( &r ) )
1705         {
1706           menuPosX=0;
1707           menuPosY=1; //Slightly obscure.. :p
1708         }
1709 
1710         if( menuPosX == 1 && dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_ALLOW_UPLOAD_U, HSCREENW, HSCREENH+100-32-16 );
1711         txtWriteCenter(screen, FONTSMALL, STR_MENU_ALLOW_UPLOAD, HSCREENW, HSCREENH+100-32-16);
1712         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT && isPointerInBox( getTxtBox() ) )
1713         {
1714           menuPosX=1;
1715         }
1716 
1717         //Set rect for no
1718         r.x = (setting()->bgPos.x)+ 320-32-menuYesNo->spr[0]->clip.w;
1719         //Display/blink no
1720         if(menuPosX == 2 && dir)
1721         {
1722          // SDL_BlitSurface(menuBg[MENUGFXNO] , NULL, screen, &ynpos );
1723           drawSprite(screen, menuYesNo->spr[2], r.x, r.y);
1724         } else {
1725           drawSprite(screen, menuYesNo->spr[3], r.x, r.y);
1726         }
1727         //Detect pointer click on no
1728         r.w=r.x + menuYesNo->spr[0]->clip.w;
1729         r.h=r.y + menuYesNo->spr[0]->clip.h;
1730         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT && isPointerInBox( &r ) )
1731         {
1732           menuPosX=2;
1733           menuPosY=1; //Slightly obscure.. :p
1734         }
1735 
1736 
1737         if( getButton( C_BTNB) || (isPointerClicked() && menuPosY==1) )
1738         {
1739           resetBtn( C_BTNB );
1740           resetMouseBtn();
1741           //Enabled
1742           if( menuPosX == 0 )
1743           {
1744             setting()->uploadStats=1;
1745             statsUpload(0,0,0,0,0,"check",1, &(setting()->session));
1746 
1747             #ifdef PLATFORM_SUPPORTS_STATSUPLOAD
1748             dlcCheckOnline();
1749             #endif
1750           }
1751 
1752           //Disabled
1753           if( menuPosX == 2 )
1754           {
1755             setting()->uploadStats=0;
1756             sndPlay(SND_LOSER, 160);
1757           } else {
1758             sndPlay(SND_WINNER, 160);
1759           }
1760 
1761           if( (menuPosX == 0 || menuPosX == 2) )
1762           {
1763             SDL_FreeSurface(menuYesNo->spr[0]->img);
1764             freeAni(menuYesNo);
1765             menuYesNo=0;
1766 
1767             setting()->firstRun=0;
1768             saveSettings();
1769             startTransition(screen, TRANSITION_TYPE_CURTAIN_UP, 500);
1770             setMenu( menuStatePaused );
1771           }
1772         }
1773       break;
1774 
1775       case menuStateUpdate:
1776         starField(screen,1);
1777         fireWorks(screen);
1778         menuMaxY=0;
1779         menuMaxX=2;
1780         txtWrite(screen, FONTSMALL, STR_MENU_UPDATE, HSCREENW-152, HSCREENH-50 );
1781         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+70);
1782         if( getButton( C_BTNB) || isPointerClicked() )
1783         {
1784           resetBtn( C_BTNB );
1785           resetMouseBtn();
1786           menuState=menuStatePaused;
1787         }
1788       break;
1789       #endif
1790 
1791       case menuStateNoPointerSupport:
1792         starField(screen,0);
1793         menuMaxY=0;
1794         menuMaxX=0;
1795         txtWrite(screen, FONTSMALL, STR_MENU_NOPTRSUPPORT, HSCREENW-152, HSCREENH-58 );
1796         if(dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_PRESS_B, HSCREENW, HSCREENH+70);
1797         if( isPointerClicked() )
1798         {
1799           resetMouseBtn();
1800           menuState=menuStatePaused;
1801         } else if( getButton( C_BTNB) )
1802         {
1803           resetBtn( C_BTNB );
1804           menuState=menuReturnHack;
1805         }
1806       break;
1807 
1808       case menuStateConfirmReset:
1809         starField(screen,0);
1810 
1811         menuPosY=0; //Using this as a click-lock
1812         menuMaxY=1;
1813         menuMaxX=2;
1814         txtWriteCenter(screen, FONTMEDIUM, STR_MENU_ARE_YOU_SURE, HSCREENW,HSCREENH-95-16);
1815         sprintf(buf, STR_MENU_CONFIRM_CLEAR_HIGHSCORES, packState()->cp->name);
1816         txtWrite(screen, FONTSMALL, buf, HSCREENW-152, HSCREENH-70-16 );
1817 
1818 
1819         if( menuYesNo == 0)
1820         {
1821           menuYesNo = mkAni(loadImg( DATADIR"data/menu/yesno.png"), 36,42,0);
1822         }
1823 
1824         r.y = (setting()->bgPos.y)+ 240-60;
1825 
1826         //Set rect for yes
1827         r.x = (setting()->bgPos.x)+ 32;
1828         //Display/blink yes
1829         if(menuPosX == 0 && dir)
1830         {
1831           //SDL_BlitSurface(menuBg[MENUGFXYES] , NULL, screen, &ynpos );
1832           drawSprite(screen, menuYesNo->spr[0], r.x, r.y);
1833         } else {
1834           drawSprite(screen, menuYesNo->spr[1], r.x, r.y);
1835         }
1836         //Detect pointer click on yes
1837         r.w=r.x + menuYesNo->spr[0]->clip.w;
1838         r.h=r.y + menuYesNo->spr[0]->clip.h;
1839         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT &&  isPointerInBox( &r ) )
1840         {
1841           menuPosX=0;
1842           menuPosY=1; //Slightly obscure.. :p
1843         }
1844 
1845         if( menuPosX == 1 && dir) txtWriteCenter(screen, FONTSMALL, STR_MENU_ALLOW_RESET_U, HSCREENW, HSCREENH+100-25 );
1846         txtWriteCenter(screen, FONTSMALL, STR_MENU_ALLOW_RESET, HSCREENW, HSCREENH+100-25);
1847         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT && isPointerInBox( getTxtBox() ) )
1848         {
1849           menuPosX=1;
1850         }
1851 
1852         //Set rect for no
1853         r.x = (setting()->bgPos.x)+ 320-32-menuYesNo->spr[0]->clip.w;
1854         //Display/blink no
1855         if(menuPosX == 2 && dir)
1856         {
1857          // SDL_BlitSurface(menuBg[MENUGFXNO] , NULL, screen, &ynpos );
1858           drawSprite(screen, menuYesNo->spr[2], r.x, r.y);
1859         } else {
1860           drawSprite(screen, menuYesNo->spr[3], r.x, r.y);
1861         }
1862         //Detect pointer click on no
1863         r.w=r.x + menuYesNo->spr[0]->clip.w;
1864         r.h=r.y + menuYesNo->spr[0]->clip.h;
1865         if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT && isPointerInBox( &r ) )
1866         {
1867           menuPosX=2;
1868           menuPosY=1; //Slightly obscure.. :p
1869         }
1870 
1871 
1872         if( getButton( C_BTNB) || (isPointerClicked() && menuPosY==1) )
1873         {
1874           SDL_FreeSurface(menuYesNo->spr[0]->img);
1875           freeAni(menuYesNo);
1876           menuYesNo=0;
1877 
1878           resetBtn(C_BTNB);
1879           resetMouseBtn();
1880 
1881           if( menuPosX==0)
1882           {
1883             statsReset();
1884             setMenu(menuStateOptions);
1885           }
1886 
1887           if( menuPosX==2)
1888           {
1889             setMenu(menuStateOptions);
1890           }
1891         }
1892       break;
1893 
1894       #if defined( PLATFORM_SUPPORTS_STATSUPLOAD )
1895       case menuStateDLC:
1896         starField(screen,1);
1897         INP_GET_STR_LIMITS
1898         getInpPointerState()->escEnable=0;
1899 
1900         if( dlcGetState() == DLC_BUSY )
1901         {
1902           fireWorks(screen);
1903           txtWriteCenter(screen, FONTMEDIUM, "Installing..", HSCREENW,HSCREENH-95);
1904           txtWriteCenter(screen, FONTSMALL, "Please wait while installing pack.", HSCREENW, HSCREENH-70);
1905         } else if( dlcGetState() == DLC_INSTALLED )
1906         {
1907           fireWorks(screen);
1908           txtWriteCenter(screen, FONTMEDIUM, "Success!", HSCREENW,HSCREENH-95);
1909           txtWriteCenter(screen, FONTSMALL, "It's ready to play!", HSCREENW, HSCREENH-60);
1910 
1911           if( getChar() == SDLK_RETURN || getButton(C_BTNMENU) || getButton(C_BTNB) || isPointerEscapeClicked() || isPointerClicked() )
1912           {
1913             resetBtn(C_BTNMENU);
1914             resetBtn(C_BTNB);
1915             setMenu( menuStatePackList );
1916             menuPosY = packAdd( bundlePath(), PACK_IS_DLC );
1917             bundlePathReset();
1918             dlcSetReady();
1919           }
1920         } else if( dlcGetState() == DLC_READY )
1921         {
1922           getInpPointerState()->escEnable=1;
1923 
1924           txtWriteCenter(screen, FONTMEDIUM, "Install Puzzles!", HSCREENW,HSCREENH-95);
1925           txtWriteCenter(screen, FONTSMALL, "Please enter the DLC Code", HSCREENW, HSCREENH-70);
1926 
1927 
1928           if( getButton(C_BTNMENU) || isPointerEscapeClicked() )
1929           {
1930             setMenu(menuStatePackList);
1931             resetBtn(C_BTNB);
1932           }
1933 
1934           if( inpStrGet(strStateDlcCode, menuPosX, menuPosY, dir ) )
1935           {
1936             dlcTryInstall(strStateDlcCode->str, getUsrPackDir() );
1937           }
1938 
1939         } else if( dlcGetState() == DLC_FAILED )
1940         {
1941           txtWriteCenter(screen, FONTMEDIUM, "Error", HSCREENW,HSCREENH-95);
1942           txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_DOWNLOAD, HSCREENW-150, HSCREENH-70);
1943 
1944           if( getChar() == SDLK_RETURN || getButton(C_BTNMENU) || getButton(C_BTNB) || isPointerEscapeClicked() || isPointerClicked() )
1945           {
1946             resetMouseBtn();
1947             dlcSetReady();
1948             setMenu(menuStateDLC);
1949           }
1950 
1951         } else if( dlcGetState() == DLC_API_OUTDATED )
1952         {
1953           txtWriteCenter(screen, FONTMEDIUM, "Update Wizznic", HSCREENW,HSCREENH-95);
1954           txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_API_OUTDATED, HSCREENW-150, HSCREENH-70);
1955           if( getChar() == SDLK_RETURN || getButton(C_BTNMENU) || getButton(C_BTNB) || isPointerEscapeClicked() || isPointerClicked() )
1956           {
1957             resetMouseBtn();
1958             setMenu(menuStatePackList);
1959           }
1960         } else if( dlcGetState() == DLC_BUNDLE_ERROR )
1961         {
1962           txtWriteCenter(screen, FONTMEDIUM, "Install Error", HSCREENW,HSCREENH-95);
1963           switch( getBundleError() )
1964           {
1965             case BUNDLE_FAIL_CORRUPT:
1966               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_CORRUPT, HSCREENW-150, HSCREENH-70);
1967               break;
1968             case BUNDLE_FAIL_COULD_NOT_OPEN:
1969               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_COULD_NOT_OPEN, HSCREENW-150, HSCREENH-70);
1970               break;
1971             case BUNDLE_FAIL_DIR_EXISTS:
1972               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_DIR_EXISTS, HSCREENW-150, HSCREENH-70);
1973               break;
1974             case BUNDLE_FAIL_NOT_BUNDLEFILE:
1975               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_NOT_BUNDLEFILE, HSCREENW-150, HSCREENH-70);
1976               break;
1977             case BUNDLE_FAIL_NO_WRITE_PERMISSION:
1978               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_NO_WRITE_PERMISSION, HSCREENW-150, HSCREENH-70);
1979               break;
1980             case BUNDLE_FAIL_UNSUPPORTED_VERSION:
1981               txtWrite(screen, FONTSMALL, STR_MENU_DLC_ERROR_UNSUPPORTED_VERSION, HSCREENW-150, HSCREENH-70);
1982               break;
1983           }
1984           if( getChar() == SDLK_RETURN || getButton(C_BTNMENU) || getButton(C_BTNB) || isPointerEscapeClicked() || isPointerClicked() )
1985           {
1986             resetMouseBtn();
1987             dlcSetReady();
1988             setMenu(menuStatePackList);
1989           }
1990         }
1991 
1992 
1993       break;
1994       #endif
1995   }
1996   menuChangeX=0;
1997   menuChangeY=0;
1998 
1999   return(STATEMENU);
2000 }
2001