bugfix
[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 "rsc/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 #include "../common/emu.h"\r
36 #include "emu.h"\r
37 \r
38 extern "C" char menuErrorMsg[];\r
39 \r
40 ////////////////////////////////////////////////////////////////\r
41 //\r
42 // class CPicolAppView\r
43 //\r
44 ////////////////////////////////////////////////////////////////\r
45 \r
46 // Creates and constructs the view.\r
47 CPicolAppView* CPicolAppView::NewLC(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig)\r
48 {\r
49         CPicolAppView* self = new (ELeave) CPicolAppView(aAppUi, aCurrentConfig);\r
50         CleanupStack::PushL(self);\r
51         return self;\r
52 }\r
53 \r
54 /**\r
55 Constructor for the view.\r
56 Passes the application UI reference to the construction of the super class.\r
57 \r
58 KNullViewId should normally be passed as parent view for the applications \r
59 default view. The parent view is the logical view that is normally activated \r
60 when a go back command is issued. KNullViewId will activate the system \r
61 default view. \r
62 \r
63 @param aAppUi Reference to the application UI\r
64 */\r
65 CPicolAppView::CPicolAppView(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig) \r
66 : CQikViewBase(aAppUi, KNullViewId), iCurrentConfig(aCurrentConfig)\r
67 {\r
68 }\r
69 \r
70 void CPicolAppView::ConstructL()\r
71 {\r
72         BaseConstructL();\r
73 }\r
74 \r
75 CPicolAppView::~CPicolAppView()\r
76 {\r
77 }\r
78 \r
79 \r
80 /**\r
81 Inherited from CQikViewBase and called upon by the UI Framework. \r
82 It creates the view from resource.\r
83 */\r
84 void CPicolAppView::ViewConstructL()\r
85 {\r
86         // Loads information about the UI configurations this view supports\r
87         // together with definition of each view.       \r
88         ViewConstructFromResourceL(R_APP_UI_CONFIGURATIONS);\r
89         UpdateCommandList();\r
90 }\r
91 \r
92 /**\r
93 Returns the view Id\r
94 \r
95 @return Returns the Uid of the view\r
96 */\r
97 TVwsViewId CPicolAppView::ViewId()const\r
98 {\r
99         return TVwsViewId(KUidPicolApp, KUidPicolMainView);\r
100 }\r
101 \r
102 /**\r
103 Handles all commands in the view.\r
104 Called by the UI framework when a command has been issued.\r
105 The command Ids are defined in the .hrh file.\r
106 \r
107 @param aCommand The command to be executed\r
108 @see CQikViewBase::HandleCommandL\r
109 */\r
110 void CPicolAppView::HandleCommandL(CQikCommand& aCommand)\r
111 {\r
112         TInt res;\r
113 \r
114         switch(aCommand.Id())\r
115         {\r
116                 case EEikCmdPicoLoadState:\r
117                         if(iROMLoaded) {\r
118                                 CEikonEnv::Static()->BusyMsgL(_L("Loading State"));\r
119                                 res = CPicoGameSession::Do(PicoMsgLoadState);\r
120                                 CEikonEnv::Static()->BusyMsgCancel();\r
121                                 // emu doesn't start to run if load fails, so we can display this\r
122                                 if(res) CEikonEnv::Static()->InfoMsg(_L("Load Failed"));\r
123                         }\r
124                         break;\r
125 \r
126                 case EEikCmdPicoSaveState:\r
127                         if(iROMLoaded) {\r
128                                 CEikonEnv::Static()->BusyMsgL(_L("Saving State"));\r
129                                 res = CPicoGameSession::Do(PicoMsgSaveState);\r
130                                 CEikonEnv::Static()->BusyMsgCancel();\r
131                                 if(res) CEikonEnv::Static()->InfoMsg(_L("Save Failed"));\r
132                         }\r
133                         break;\r
134 \r
135                 case EEikCmdPicoLoadROM:\r
136                         DisplayOpenROMDialogL();\r
137                         DEBUGPRINT(_L("after DisplayOpenROMDialogL()"));\r
138                         break;\r
139 \r
140                 case EEikCmdPicoResume:\r
141                         CPicoGameSession::Do(PicoMsgResume);\r
142                         break;\r
143 \r
144                 case EEikCmdPicoReset:\r
145                         CPicoGameSession::Do(PicoMsgReset);\r
146                         break;\r
147 \r
148                 case EEikCmdPicoSettings:\r
149                         DisplayConfigDialogL();\r
150                         break;\r
151 \r
152                 case EEikCmdHelpAbout:\r
153                         DisplayAboutDialogL();\r
154                         break;\r
155 \r
156                 case EEikCmdPicoDebugInfo:\r
157                         DisplayDebugDialogL();\r
158                         break;\r
159 \r
160                 case EEikCmdPicoKeys:\r
161                         CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);\r
162                         CPicoGameSession::Do(PicoMsgKeys);\r
163                         break;\r
164 \r
165                 case EEikCmdPicoFrameskipAuto:\r
166                         currentConfig.Frameskip = -1;\r
167                         emu_write_config(0);\r
168                         break;\r
169 \r
170                 case EEikCmdPicoFrameskip0:\r
171                         currentConfig.Frameskip = 0;\r
172                         emu_write_config(0);\r
173                         break;\r
174 \r
175                 case EEikCmdPicoFrameskip1:\r
176                         currentConfig.Frameskip = 1;\r
177                         emu_write_config(0);\r
178                         break;\r
179 \r
180                 case EEikCmdPicoFrameskip2:\r
181                         currentConfig.Frameskip = 2;\r
182                         emu_write_config(0);\r
183                         break;\r
184 \r
185                 case EEikCmdPicoFrameskip4:\r
186                         currentConfig.Frameskip = 4;\r
187                         emu_write_config(0);\r
188                         break;\r
189 \r
190                 case EEikCmdPicoFrameskip8:\r
191                         currentConfig.Frameskip = 8;\r
192                         emu_write_config(0);\r
193                         break;\r
194 \r
195                 case EEikCmdExit:\r
196                         emu_Deinit();\r
197                         CPicoGameSession::freeResources();\r
198                         //break; // this is intentional\r
199 \r
200                 default:\r
201                         // Go back and exit command will be passed to the CQikViewBase to handle.\r
202                         CQikViewBase::HandleCommandL(aCommand);\r
203                         break;\r
204         }\r
205 }\r
206 \r
207 void CPicolAppView::DisplayOpenROMDialogL()\r
208 {\r
209         // Array of mimetypes that the dialog shall filter on, if empty all\r
210         // mimetypes will be visible.\r
211         CDesCArray* mimeArray = new (ELeave) CDesCArrayFlat(1);\r
212         CleanupStack::PushL(mimeArray);\r
213         // Array that will be filled with the file paths that are choosen\r
214         // from the dialog. \r
215         CDesCArray* fileArray = new (ELeave) CDesCArraySeg(3);\r
216         CleanupStack::PushL(fileArray);\r
217         _LIT16(KDlgTitle, "Select a ROM file");\r
218 \r
219         TPtrC8 text8((TUint8*) rom_fname_loaded);\r
220         iCurrentConfig.iLastROMFile.Copy(text8);\r
221 \r
222         if( CQikSelectFileDlg::RunDlgLD( *mimeArray, *fileArray, &KDlgTitle, &iCurrentConfig.iLastROMFile) )\r
223         {\r
224                 CEikonEnv::Static()->BusyMsgL(_L("Loading ROM"));\r
225                 TPtrC16 file = (*fileArray)[0];\r
226                 //iCurrentConfig.iLastROMFile.Copy(file);\r
227 \r
228                 // push the config first\r
229                 CPicoGameSession::Do(PicoMsgSetAppView, this);\r
230                 CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);\r
231 \r
232                 TInt res = CPicoGameSession::Do(PicoMsgLoadROM, &file);\r
233 \r
234                 CEikonEnv::Static()->BusyMsgCancel();\r
235 \r
236                 iROMLoaded = EFalse;\r
237                 switch (res)\r
238                 {\r
239                         case PicoErrRomOpenFailed: {\r
240                                 TBuf<64> mErrorBuff;\r
241                                 TPtrC8 buff8((TUint8*) menuErrorMsg);\r
242                                 mErrorBuff.Copy(buff8);\r
243                                 CEikonEnv::Static()->InfoWinL(_L("Error"), mErrorBuff);\r
244                                 break;\r
245                         }\r
246 \r
247                         case PicoErrOutOfMem:\r
248                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate memory."));\r
249                                 break;\r
250 \r
251                         case PicoErrEmuThread:\r
252                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to create emulation thread. Try to restart this application."));\r
253                                 break;\r
254 \r
255                         default:\r
256                                 iROMLoaded = ETrue;\r
257                                 break;\r
258                 }\r
259 \r
260                 // errors which leave ROM loaded\r
261                 switch (res)\r
262                 {\r
263                         case PicoErrOutOfMemSnd:\r
264                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate sound buffer, disabled sound."));\r
265                                 break;\r
266 \r
267                         case PicoErrGenSnd:\r
268                                 CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to start soundsystem, disabled sound."));\r
269                                 break;\r
270                 }\r
271                 if(res == 6 || res == 7) currentConfig.EmuOpt &= ~EOPT_EN_SOUND;\r
272 \r
273                 if(iROMLoaded) {\r
274                         if(iTitleAdded)\r
275                              ViewContext()->ChangeTextL(EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);\r
276                         else ViewContext()->AddTextL   (EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);\r
277                         iTitleAdded = ETrue;\r
278                         UpdateCommandList();\r
279                 }\r
280         }\r
281         CleanupStack::PopAndDestroy(2, mimeArray);\r
282 }\r
283 \r
284 \r
285 void CPicolAppView::DisplayConfigDialogL()\r
286 {\r
287         CPicoConfigDialog* configDialog = new(ELeave)CPicoConfigDialog(currentConfig);\r
288         emu_pack_config();\r
289         configDialog->ExecuteLD(R_PICO_CONFIG);\r
290         emu_unpack_config();\r
291         emu_write_config(0);\r
292 \r
293         CPicoGameSession::Do(PicoMsgConfigChange, &currentConfig);\r
294 }\r
295 \r
296 \r
297 void CPicolAppView::DisplayAboutDialogL()\r
298 {\r
299         TInt iButtonRes;\r
300         CAboutDialog* dialog = new (ELeave) CAboutDialog;\r
301 \r
302         dialog->PrepareLC(R_PICO_ABOUT);\r
303         iButtonRes = dialog->RunLD();\r
304 \r
305         if(iButtonRes == EEikCmdPicoAboutCreditsCmd) {\r
306                 CCreditsDialog *creditsDialog = new (ELeave) CCreditsDialog();\r
307                 creditsDialog->PrepareLC(R_PICO_CREDITS);\r
308                 creditsDialog->RunLD();\r
309         }\r
310 }\r
311 \r
312 #ifdef __DEBUG_PRINT\r
313 extern "C" char *PDebugMain();\r
314 #endif\r
315 \r
316 void CPicolAppView::DisplayDebugDialogL()\r
317 {\r
318 #ifdef __DEBUG_PRINT\r
319         CDebugDialog* dialog = new (ELeave) CDebugDialog(PDebugMain());\r
320 \r
321         dialog->PrepareLC(R_PICO_DEBUG);\r
322         dialog->RunLD();\r
323 #endif\r
324 }\r
325 \r
326 void CPicolAppView::UpdateCommandList()\r
327 {\r
328         CQikCommandManager& commandManager = CQikCommandManager::Static(*iCoeEnv);\r
329         CQikCommand *cmd_fs[10];\r
330         Mem::FillZ(cmd_fs, sizeof(CQikCommand*)*10);\r
331 \r
332         CQikCommand* cmd_reset  = commandManager.Command(*this, EEikCmdPicoReset);\r
333         CQikCommand* cmd_savest = commandManager.Command(*this, EEikCmdPicoSaveState);\r
334         CQikCommand* cmd_loadst = commandManager.Command(*this, EEikCmdPicoLoadState);\r
335         CQikCommand* cmd_resume = commandManager.Command(*this, EEikCmdPicoResume);\r
336         cmd_fs[0]  = commandManager.Command(*this, EEikCmdPicoFrameskipAuto);\r
337         cmd_fs[1]  = commandManager.Command(*this, EEikCmdPicoFrameskip0);\r
338         cmd_fs[2]  = commandManager.Command(*this, EEikCmdPicoFrameskip1);\r
339         cmd_fs[3]  = commandManager.Command(*this, EEikCmdPicoFrameskip2);\r
340         cmd_fs[5]  = commandManager.Command(*this, EEikCmdPicoFrameskip4);\r
341         cmd_fs[9]  = commandManager.Command(*this, EEikCmdPicoFrameskip8);\r
342 \r
343         TBool dimmed = !CPicoGameSession::iEmuRunning || !iROMLoaded;\r
344         cmd_reset ->SetDimmed(dimmed);\r
345         cmd_savest->SetDimmed(dimmed);\r
346         cmd_loadst->SetDimmed(dimmed);\r
347         cmd_resume->SetDimmed(dimmed);\r
348 \r
349         // frameskip\r
350         TInt fs_index = currentConfig.Frameskip + 1;\r
351         if (fs_index >= 0 && fs_index < 10 && cmd_fs[fs_index])\r
352         {\r
353                 cmd_fs[fs_index]->SetChecked(ETrue);\r
354         }\r
355 }\r
356 \r
357 \r
358 ////////////////////////////////////////////////////////////////\r
359 //\r
360 // class CPicolAppUi\r
361 //\r
362 ////////////////////////////////////////////////////////////////\r
363 \r
364 \r
365 void CPicolAppUi::ConstructL()\r
366 {\r
367         BaseConstructL();\r
368 \r
369         // Create the view and add it to the framework\r
370         iAppView = CPicolAppView::NewLC(*this, ((CPicolDocument *)Document())->iCurrentConfig);\r
371         AddViewL(*iAppView);\r
372         CleanupStack::Pop(iAppView);\r
373 }\r
374 \r
375 \r
376 ////////////////////////////////////////////////////////////////\r
377 //\r
378 // CPicolDocument\r
379 //\r
380 ////////////////////////////////////////////////////////////////\r
381 \r
382 \r
383 CPicolDocument::CPicolDocument(CQikApplication& aApp)\r
384 : CQikDocument(aApp)\r
385 {\r
386 }\r
387 \r
388 CQikAppUi* CPicolDocument::CreateAppUiL()\r
389 {\r
390         return new(ELeave) CPicolAppUi;\r
391 }\r
392 \r
393 /**\r
394 Called by the framework when ::SaveL has been called.\r
395 */\r
396 void CPicolDocument::StoreL(CStreamStore& aStore, CStreamDictionary& aStreamDic) const\r
397 {\r
398 #if 0\r
399         RStoreWriteStream stream;\r
400 \r
401         TStreamId preferenceId = stream.CreateLC(aStore);\r
402         aStreamDic.AssignL(KUidPicolStore, preferenceId);\r
403 \r
404         // Externalize preference\r
405         stream << iCurrentConfig;\r
406 \r
407         // Ensures that any buffered data is written to aStore\r
408         stream.CommitL();\r
409         CleanupStack::PopAndDestroy(); // stream\r
410 #endif\r
411 /*\r
412         // tmp\r
413         TInt res;\r
414         RFile logFile;\r
415         res = logFile.Replace(CEikonEnv::Static()->FsSession(), _L("C:\\Shared\\pico.cfg"), EFileWrite|EFileShareAny);\r
416         if(!res) {\r
417                 logFile.Write(TPtr8((TUint8 *)&iCurrentConfig, sizeof(iCurrentConfig), sizeof(iCurrentConfig)));\r
418                 logFile.Close();\r
419         }\r
420 */\r
421 }\r
422 \r
423 /**\r
424 Called by the framework on application start.\r
425 Loads the application data from disk, i.e. domain data and preferences.\r
426 */\r
427 void CPicolDocument::RestoreL(const CStreamStore& aStore, const CStreamDictionary& aStreamDic)\r
428\r
429 #if 0\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 #endif\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 extern "C" TInt my_SetExceptionHandler(TInt, TExceptionHandler, TUint32);\r
479 \r
480 GLDEF_C TInt E32Main()\r
481 {\r
482         // doesn't work :(\r
483         User::SetExceptionHandler(ExceptionHandler, (TUint32) -1);\r
484 //      my_SetExceptionHandler(KCurrentThreadHandle, ExceptionHandler, 0xffffffff);\r
485 \r
486         emu_Init();\r
487 \r
488         return EikStart::RunApplication(NewApplication);\r
489 }\r
490 \r
491 \r