74e7d24750652dce6d300ed22a9d468012c0f782
[picodrive.git] / platform / uiq3 / App.cpp
1 /*******************************************************************\r
2  *\r
3  *      File:           App.cpp\r
4  *\r
5  *      Author:         Peter van Sebille (peter@yipton.net)\r
6  *\r
7  *  Modified/adapted for picodriveN by notaz, 2006\r
8  *\r
9  *  (c) Copyright 2006, notaz\r
10  *      (c) Copyright 2002, Peter van Sebille\r
11  *      All Rights Reserved\r
12  *\r
13  *******************************************************************/\r
14 \r
15 #include "app.h"\r
16 // #include "picodriven.mbg" // bitmap identifiers\r
17 #include <PicoDrive.RSG> // resource include\r
18 #include <eikenv.h>\r
19 #include <qbtselectdlg.h>\r
20 //#include <gulutil.h>\r
21 //#include <bautils.h>\r
22 //#include <eikmenub.h> // CEikMenuBar\r
23 #include <apgtask.h> // TApaSystemEvent\r
24 #include <eikstart.h>\r
25 #include <eikedwin.h>\r
26 #include <s32strm.h>\r
27 \r
28 #include <QikAppUi.h>\r
29 #include <QikEditCategoryObserver.h>\r
30 #include <QikSelectFileDlg.h>\r
31 #include <QikCommand.h>\r
32 \r
33 #include "Dialogs.h"\r
34 #include "engine/debug.h"\r
35 \r
36 \r
37 \r
38 ////////////////////////////////////////////////////////////////\r
39 //\r
40 // class CPicolAppView\r
41 //\r
42 ////////////////////////////////////////////////////////////////\r
43 \r
44 // Creates and constructs the view.\r
45 CPicolAppView* CPicolAppView::NewLC(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig)\r
46 {\r
47         CPicolAppView* self = new (ELeave) CPicolAppView(aAppUi, aCurrentConfig);\r
48         CleanupStack::PushL(self);\r
49         return self;\r
50 }\r
51 \r
52 /**\r
53 Constructor for the view.\r
54 Passes the application UI reference to the construction of the super class.\r
55 \r
56 KNullViewId should normally be passed as parent view for the applications \r
57 default view. The parent view is the logical view that is normally activated \r
58 when a go back command is issued. KNullViewId will activate the system \r
59 default view. \r
60 \r
61 @param aAppUi Reference to the application UI\r
62 */\r
63 CPicolAppView::CPicolAppView(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig) \r
64 : CQikViewBase(aAppUi, KNullViewId), iCurrentConfig(aCurrentConfig)\r
65 {\r
66 }\r
67 \r
68 void CPicolAppView::ConstructL()\r
69 {\r
70         BaseConstructL();\r
71 }\r
72 \r
73 CPicolAppView::~CPicolAppView()\r
74 {\r
75 }\r
76 \r
77 \r
78 /**\r
79 Inherited from CQikViewBase and called upon by the UI Framework. \r
80 It creates the view from resource.\r
81 */\r
82 void CPicolAppView::ViewConstructL()\r
83 {\r
84         // Loads information about the UI configurations this view supports\r
85         // together with definition of each view.       \r
86         ViewConstructFromResourceL(R_APP_UI_CONFIGURATIONS);\r
87         UpdateCommandList();\r
88 }\r
89 \r
90 /**\r
91 Returns the view Id\r
92 \r
93 @return Returns the Uid of the view\r
94 */\r
95 TVwsViewId CPicolAppView::ViewId()const\r
96 {\r
97         return TVwsViewId(KUidPicolApp, KUidPicolMainView);\r
98 }\r
99 \r
100 /**\r
101 Handles all commands in the view.\r
102 Called by the UI framework when a command has been issued.\r
103 The command Ids are defined in the .hrh file.\r
104 \r
105 @param aCommand The command to be executed\r
106 @see CQikViewBase::HandleCommandL\r
107 */\r
108 void CPicolAppView::HandleCommandL(CQikCommand& aCommand)\r
109 {\r
110         TInt res;\r
111 \r
112         switch(aCommand.Id())\r
113         {\r
114                 case EEikCmdPicoLoadState:\r
115                         if(iROMLoaded) {\r
116                                 CEikonEnv::Static()->BusyMsgL(_L("Loading State"));\r
117                                 res = CPicoGameSession::Do(PicoMsgLoadState);\r
118                                 CEikonEnv::Static()->BusyMsgCancel();\r
119                                 // emu doesn't start to run if load fails, so we can display this\r
120                                 if(res) CEikonEnv::Static()->InfoMsg(_L("Load Failed"));\r
121                         }\r
122                         break;\r
123 \r
124                 case EEikCmdPicoSaveState:\r
125                         if(iROMLoaded) {\r
126                                 CEikonEnv::Static()->BusyMsgL(_L("Saving State"));\r
127                                 res = CPicoGameSession::Do(PicoMsgSaveState);\r
128                                 CEikonEnv::Static()->BusyMsgCancel();\r
129                                 if(res) CEikonEnv::Static()->InfoMsg(_L("Save Failed"));\r
130                         }\r
131                         break;\r
132 \r
133                 case EEikCmdPicoLoadROM:\r
134                         DisplayOpenROMDialogL();\r
135                         DEBUGPRINT(_L("after DisplayOpenROMDialogL()"));\r
136                         break;\r
137 \r
138                 case EEikCmdPicoResume:\r
139                         CPicoGameSession::Do(PicoMsgResume);\r
140                         break;\r
141 \r
142                 case EEikCmdPicoReset:\r
143                         CPicoGameSession::Do(PicoMsgReset);\r
144                         break;\r
145 \r
146                 case EEikCmdPicoSettings:\r
147                         DisplayConfigDialogL();\r
148                         break;\r
149 \r
150                 case EEikCmdHelpAbout:\r
151                         DisplayAboutDialogL();\r
152                         break;\r
153 \r
154                 case EEikCmdPicoDebugInfo:\r
155                         DisplayDebugDialogL();\r
156                         break;\r
157 \r
158                 case EEikCmdPicoKeys:\r
159                         CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);\r
160                         CPicoGameSession::Do(PicoMsgKeys);\r
161                         break;\r
162 \r
163                 case EEikCmdPicoFrameskipAuto:\r
164                         iCurrentConfig.iFrameskip = TPicoConfig::PFSkipAuto;\r
165                         iQikAppUi.Document()->SaveL();\r
166                         break;\r
167 \r
168                 case EEikCmdPicoFrameskip0:\r
169                         iCurrentConfig.iFrameskip = 0;\r
170                         iQikAppUi.Document()->SaveL();\r
171                         break;\r
172 \r
173                 case EEikCmdPicoFrameskip1:\r
174                         iCurrentConfig.iFrameskip = 1;\r
175                         iQikAppUi.Document()->SaveL();\r
176                         break;\r
177 \r
178                 case EEikCmdPicoFrameskip2:\r
179                         iCurrentConfig.iFrameskip = 2;\r
180                         iQikAppUi.Document()->SaveL();\r
181                         break;\r
182 \r
183                 case EEikCmdPicoFrameskip4:\r
184                         iCurrentConfig.iFrameskip = 4;\r
185                         iQikAppUi.Document()->SaveL();\r
186                         break;\r
187 \r
188                 case EEikCmdPicoFrameskip8:\r
189                         iCurrentConfig.iFrameskip = 8;\r
190                         iQikAppUi.Document()->SaveL();\r
191                         break;\r
192 \r
193                 case EEikCmdExit:\r
194                         iQikAppUi.Document()->SaveL();\r
195                         CPicoGameSession::freeResources();\r
196                         //break; // this is intentional\r
197 \r
198                 default:\r
199                         // Go back and exit command will be passed to the CQikViewBase to handle.\r
200                         CQikViewBase::HandleCommandL(aCommand);\r
201                         break;\r
202         }\r
203 }\r
204 \r
205 void CPicolAppView::DisplayOpenROMDialogL()\r
206 {\r
207         // Array of mimetypes that the dialog shall filter on, if empty all\r
208         // mimetypes will be visible.\r
209         CDesCArray* mimeArray = new (ELeave) CDesCArrayFlat(1);\r
210         CleanupStack::PushL(mimeArray);\r
211         // Array that will be filled with the file paths that are choosen\r
212         // from the dialog. \r
213         CDesCArray* fileArray = new (ELeave) CDesCArraySeg(3);\r
214         CleanupStack::PushL(fileArray);\r
215         _LIT16(KDlgTitle, "Select a ROM file");\r
216 \r
217         if( CQikSelectFileDlg::RunDlgLD( *mimeArray, *fileArray, &KDlgTitle, &iCurrentConfig.iLastROMFile) )\r
218         {\r
219                 CEikonEnv::Static()->BusyMsgL(_L("Loading ROM"));\r
220                 TPtrC16 file = (*fileArray)[0];\r
221                 iCurrentConfig.iLastROMFile.Copy(file);\r
222 \r
223                 // push the config first\r
224                 CPicoGameSession::Do(PicoMsgSetAppView, this);\r
225                 CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);\r
226 \r
227                 TInt res = CPicoGameSession::Do(PicoMsgLoadROM, &file);\r
228 \r
229                 CEikonEnv::Static()->BusyMsgCancel();\r
230 \r
231                 iROMLoaded = EFalse;\r
232                 switch (res)\r
233                 {\r
234                         case PicoErrRomOpenFailed:\r
235                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to open file."));\r
236                                 break;\r
237 \r
238                         case PicoErrOutOfMem:\r
239                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate memory."));\r
240                                 break;\r
241 \r
242                         case PicoErrNotRom:\r
243                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("The file you selected is not a game ROM."));\r
244                                 break;\r
245 \r
246                         case PicoErrNoRomsInArchive:\r
247                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("No game ROMs found in zipfile."));\r
248                                 break;\r
249 \r
250                         case PicoErrUncomp:\r
251                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed while unzipping ROM."));\r
252                                 break;\r
253 \r
254                         case PicoErrEmuThread:\r
255                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to create emulation thread. Try to restart this application."));\r
256                                 break;\r
257 \r
258                         default:\r
259                                 iROMLoaded = ETrue;\r
260                                 break;\r
261                 }\r
262 \r
263                 // errors which leave ROM loaded\r
264                 switch (res)\r
265                 {\r
266                         case PicoErrOutOfMemSnd:\r
267                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate sound buffer, disabled sound."));\r
268                                 break;\r
269 \r
270                         case PicoErrGenSnd:\r
271                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to start soundsystem, disabled sound."));\r
272                                 break;\r
273                 }\r
274                 if(res == 6 || res == 7) iCurrentConfig.iFlags &= ~4;\r
275 \r
276                 if(iROMLoaded) {\r
277                         if(iTitleAdded)\r
278                              ViewContext()->ChangeTextL(EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);\r
279                         else ViewContext()->AddTextL   (EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);\r
280                         iTitleAdded = ETrue;\r
281                         UpdateCommandList();\r
282                 }\r
283         }\r
284         CleanupStack::PopAndDestroy(2, mimeArray);\r
285 }\r
286 \r
287 \r
288 void CPicolAppView::DisplayConfigDialogL()\r
289 {\r
290         CPicoConfigDialog* configDialog = new(ELeave)CPicoConfigDialog(iCurrentConfig);\r
291         configDialog->ExecuteLD(R_PICO_CONFIG);\r
292 \r
293         CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);\r
294         iQikAppUi.Document()->SaveL();\r
295 }\r
296 \r
297 \r
298 void CPicolAppView::DisplayAboutDialogL()\r
299 {\r
300         TInt iButtonRes;\r
301         CAboutDialog* dialog = new (ELeave) CAboutDialog;\r
302 \r
303         dialog->PrepareLC(R_PICO_ABOUT);\r
304         iButtonRes = dialog->RunLD();\r
305 \r
306         if(iButtonRes == EEikCmdPicoAboutCreditsCmd) {\r
307                 CCreditsDialog *creditsDialog = new (ELeave) CCreditsDialog();\r
308                 creditsDialog->PrepareLC(R_PICO_CREDITS);\r
309                 creditsDialog->RunLD();\r
310         }\r
311 }\r
312 \r
313 #ifdef __DEBUG_PRINT\r
314 extern "C" char *debugString();\r
315 #endif\r
316 \r
317 void CPicolAppView::DisplayDebugDialogL()\r
318 {\r
319 #ifdef __DEBUG_PRINT\r
320         CDebugDialog* dialog = new (ELeave) CDebugDialog(debugString());\r
321 \r
322         dialog->PrepareLC(R_PICO_DEBUG);\r
323         dialog->RunLD();\r
324 #endif\r
325 }\r
326 \r
327 void CPicolAppView::UpdateCommandList()\r
328 {\r
329         CQikCommandManager& commandManager = CQikCommandManager::Static(*iCoeEnv);\r
330         CQikCommand *cmd_fs[10];\r
331         Mem::FillZ(cmd_fs, sizeof(CQikCommand*)*10);\r
332 \r
333         CQikCommand* cmd_reset  = commandManager.Command(*this, EEikCmdPicoReset);\r
334         CQikCommand* cmd_savest = commandManager.Command(*this, EEikCmdPicoSaveState);\r
335         CQikCommand* cmd_loadst = commandManager.Command(*this, EEikCmdPicoLoadState);\r
336         CQikCommand* cmd_resume = commandManager.Command(*this, EEikCmdPicoResume);\r
337         cmd_fs[0]  = commandManager.Command(*this, EEikCmdPicoFrameskipAuto);\r
338         cmd_fs[1]  = commandManager.Command(*this, EEikCmdPicoFrameskip0);\r
339         cmd_fs[2]  = commandManager.Command(*this, EEikCmdPicoFrameskip1);\r
340         cmd_fs[3]  = commandManager.Command(*this, EEikCmdPicoFrameskip2);\r
341         cmd_fs[5]  = commandManager.Command(*this, EEikCmdPicoFrameskip4);\r
342         cmd_fs[9]  = commandManager.Command(*this, EEikCmdPicoFrameskip8);\r
343 \r
344         TBool dimmed = !CPicoGameSession::iEmuRunning || !iROMLoaded;\r
345         cmd_reset ->SetDimmed(dimmed);\r
346         cmd_savest->SetDimmed(dimmed);\r
347         cmd_loadst->SetDimmed(dimmed);\r
348         cmd_resume->SetDimmed(dimmed);\r
349 \r
350         // frameskip\r
351         TInt fs_index = iCurrentConfig.iFrameskip + 1;\r
352         if (fs_index >= 0 && fs_index < 10 && cmd_fs[fs_index])\r
353         {\r
354                 cmd_fs[fs_index]->SetChecked(ETrue);\r
355         }\r
356 }\r
357 \r
358 \r
359 ////////////////////////////////////////////////////////////////\r
360 //\r
361 // class CPicolAppUi\r
362 //\r
363 ////////////////////////////////////////////////////////////////\r
364 \r
365 \r
366 void CPicolAppUi::ConstructL()\r
367 {\r
368         BaseConstructL();\r
369 \r
370         // Create the view and add it to the framework\r
371         iAppView = CPicolAppView::NewLC(*this, ((CPicolDocument *)Document())->iCurrentConfig);\r
372         AddViewL(*iAppView);\r
373         CleanupStack::Pop(iAppView);\r
374 }\r
375 \r
376 \r
377 ////////////////////////////////////////////////////////////////\r
378 //\r
379 // CPicolDocument\r
380 //\r
381 ////////////////////////////////////////////////////////////////\r
382 \r
383 \r
384 CPicolDocument::CPicolDocument(CQikApplication& aApp)\r
385 : CQikDocument(aApp)\r
386 {\r
387         iCurrentConfig.SetDefaults();\r
388 }\r
389 \r
390 CQikAppUi* CPicolDocument::CreateAppUiL()\r
391 {\r
392         return new(ELeave) CPicolAppUi;\r
393 }\r
394 \r
395 /**\r
396 Called by the framework when ::SaveL has been called.\r
397 */\r
398 void CPicolDocument::StoreL(CStreamStore& aStore, CStreamDictionary& aStreamDic) const\r
399 {\r
400         RStoreWriteStream stream;\r
401 \r
402         TStreamId preferenceId = stream.CreateLC(aStore);\r
403         aStreamDic.AssignL(KUidPicolStore, preferenceId);\r
404 \r
405         // Externalize preference\r
406         stream << iCurrentConfig;\r
407 \r
408         // Ensures that any buffered data is written to aStore\r
409         stream.CommitL();\r
410         CleanupStack::PopAndDestroy(); // stream\r
411 \r
412 /*\r
413         // tmp\r
414         TInt res;\r
415         RFile logFile;\r
416         res = logFile.Replace(CEikonEnv::Static()->FsSession(), _L("C:\\Shared\\pico.cfg"), EFileWrite|EFileShareAny);\r
417         if(!res) {\r
418                 logFile.Write(TPtr8((TUint8 *)&iCurrentConfig, sizeof(iCurrentConfig), sizeof(iCurrentConfig)));\r
419                 logFile.Close();\r
420         }\r
421 */\r
422 }\r
423 \r
424 /**\r
425 Called by the framework on application start.\r
426 Loads the application data from disk, i.e. domain data and preferences.\r
427 */\r
428 void CPicolDocument::RestoreL(const CStreamStore& aStore, const CStreamDictionary& aStreamDic)\r
429\r
430         // Find the stream ID of the model data from the stream dictionary:\r
431         TStreamId preferenceId(aStreamDic.At(KUidPicolStore));\r
432         RStoreReadStream stream;\r
433         stream.OpenLC(aStore, preferenceId);\r
434         if(preferenceId != KNullStreamId)\r
435         {\r
436                 // Interalize preference and model\r
437                 stream >> iCurrentConfig;\r
438         }\r
439 \r
440         CleanupStack::PopAndDestroy(); // stream\r
441 \r
442 \r
443         // tmp\r
444 /*      TInt res;\r
445         RFile logFile;\r
446         res = logFile.Open(CEikonEnv::Static()->FsSession(), _L("C:\\Shared\\pico.cfg"), EFileRead|EFileShareAny);\r
447         if(!res) {\r
448                 TPtr8 ptr((TUint8 *)&iCurrentConfig, sizeof(iCurrentConfig), sizeof(iCurrentConfig));\r
449                 logFile.Read(ptr);\r
450                 logFile.Close();\r
451         }*/\r
452 }\r
453 \r
454 ////////////////////////////////////////////////////////////////\r
455 //\r
456 // framework\r
457 //\r
458 ////////////////////////////////////////////////////////////////\r
459 \r
460 \r
461 CApaDocument* CPicolApplication::CreateDocumentL()\r
462 {\r
463         return new (ELeave) CPicolDocument(*this);\r
464 }\r
465 \r
466 EXPORT_C CApaApplication* NewApplication()\r
467 {\r
468         return new CPicolApplication;\r
469 }\r
470 \r
471 \r
472 TUid CPicolApplication::AppDllUid() const\r
473 {\r
474         return KUidPicolApp;\r
475 }\r
476 \r
477 \r
478 GLDEF_C TInt E32Main()\r
479 {\r
480         User::SetExceptionHandler(ExceptionHandler, (TUint32) -1);\r
481 \r
482         return EikStart::RunApplication(NewApplication);\r
483 }\r
484 \r
485 \r