mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-06 15:48:05 -04:00
initial import
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@2 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
2cadbd5e56
commit
cc68a136aa
341 changed files with 180839 additions and 0 deletions
485
platform/uiq3/App.cpp
Normal file
485
platform/uiq3/App.cpp
Normal file
|
@ -0,0 +1,485 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: App.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "app.h"
|
||||
// #include "picodriven.mbg" // bitmap identifiers
|
||||
#include <PicoDrive.RSG> // resource include
|
||||
#include <eikenv.h>
|
||||
#include <qbtselectdlg.h>
|
||||
//#include <gulutil.h>
|
||||
//#include <bautils.h>
|
||||
//#include <eikmenub.h> // CEikMenuBar
|
||||
#include <apgtask.h> // TApaSystemEvent
|
||||
#include <eikstart.h>
|
||||
#include <eikedwin.h>
|
||||
#include <s32strm.h>
|
||||
|
||||
#include <QikAppUi.h>
|
||||
#include <QikEditCategoryObserver.h>
|
||||
#include <QikSelectFileDlg.h>
|
||||
#include <QikCommand.h>
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include "engine/debug.h"
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// class CPicolAppView
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Creates and constructs the view.
|
||||
CPicolAppView* CPicolAppView::NewLC(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig)
|
||||
{
|
||||
CPicolAppView* self = new (ELeave) CPicolAppView(aAppUi, aCurrentConfig);
|
||||
CleanupStack::PushL(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor for the view.
|
||||
Passes the application UI reference to the construction of the super class.
|
||||
|
||||
KNullViewId should normally be passed as parent view for the applications
|
||||
default view. The parent view is the logical view that is normally activated
|
||||
when a go back command is issued. KNullViewId will activate the system
|
||||
default view.
|
||||
|
||||
@param aAppUi Reference to the application UI
|
||||
*/
|
||||
CPicolAppView::CPicolAppView(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig)
|
||||
: CQikViewBase(aAppUi, KNullViewId), iCurrentConfig(aCurrentConfig)
|
||||
{
|
||||
}
|
||||
|
||||
void CPicolAppView::ConstructL()
|
||||
{
|
||||
BaseConstructL();
|
||||
}
|
||||
|
||||
CPicolAppView::~CPicolAppView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Inherited from CQikViewBase and called upon by the UI Framework.
|
||||
It creates the view from resource.
|
||||
*/
|
||||
void CPicolAppView::ViewConstructL()
|
||||
{
|
||||
// Loads information about the UI configurations this view supports
|
||||
// together with definition of each view.
|
||||
ViewConstructFromResourceL(R_APP_UI_CONFIGURATIONS);
|
||||
UpdateCommandList();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the view Id
|
||||
|
||||
@return Returns the Uid of the view
|
||||
*/
|
||||
TVwsViewId CPicolAppView::ViewId()const
|
||||
{
|
||||
return TVwsViewId(KUidPicolApp, KUidPicolMainView);
|
||||
}
|
||||
|
||||
/**
|
||||
Handles all commands in the view.
|
||||
Called by the UI framework when a command has been issued.
|
||||
The command Ids are defined in the .hrh file.
|
||||
|
||||
@param aCommand The command to be executed
|
||||
@see CQikViewBase::HandleCommandL
|
||||
*/
|
||||
void CPicolAppView::HandleCommandL(CQikCommand& aCommand)
|
||||
{
|
||||
TInt res;
|
||||
|
||||
switch(aCommand.Id())
|
||||
{
|
||||
case EEikCmdPicoLoadState:
|
||||
if(iROMLoaded) {
|
||||
CEikonEnv::Static()->BusyMsgL(_L("Loading State"));
|
||||
res = CPicoGameSession::Do(PicoMsgLoadState);
|
||||
CEikonEnv::Static()->BusyMsgCancel();
|
||||
// emu doesn't start to run if load fails, so we can display this
|
||||
if(res) CEikonEnv::Static()->InfoMsg(_L("Load Failed"));
|
||||
}
|
||||
break;
|
||||
|
||||
case EEikCmdPicoSaveState:
|
||||
if(iROMLoaded) {
|
||||
CEikonEnv::Static()->BusyMsgL(_L("Saving State"));
|
||||
res = CPicoGameSession::Do(PicoMsgSaveState);
|
||||
CEikonEnv::Static()->BusyMsgCancel();
|
||||
if(res) CEikonEnv::Static()->InfoMsg(_L("Save Failed"));
|
||||
}
|
||||
break;
|
||||
|
||||
case EEikCmdPicoLoadROM:
|
||||
DisplayOpenROMDialogL();
|
||||
DEBUGPRINT(_L("after DisplayOpenROMDialogL()"));
|
||||
break;
|
||||
|
||||
case EEikCmdPicoResume:
|
||||
CPicoGameSession::Do(PicoMsgResume);
|
||||
break;
|
||||
|
||||
case EEikCmdPicoReset:
|
||||
CPicoGameSession::Do(PicoMsgReset);
|
||||
break;
|
||||
|
||||
case EEikCmdPicoSettings:
|
||||
DisplayConfigDialogL();
|
||||
break;
|
||||
|
||||
case EEikCmdHelpAbout:
|
||||
DisplayAboutDialogL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoDebugInfo:
|
||||
DisplayDebugDialogL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoKeys:
|
||||
CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);
|
||||
CPicoGameSession::Do(PicoMsgKeys);
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskipAuto:
|
||||
iCurrentConfig.iFrameskip = TPicoConfig::PFSkipAuto;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskip0:
|
||||
iCurrentConfig.iFrameskip = 0;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskip1:
|
||||
iCurrentConfig.iFrameskip = 1;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskip2:
|
||||
iCurrentConfig.iFrameskip = 2;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskip4:
|
||||
iCurrentConfig.iFrameskip = 4;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdPicoFrameskip8:
|
||||
iCurrentConfig.iFrameskip = 8;
|
||||
iQikAppUi.Document()->SaveL();
|
||||
break;
|
||||
|
||||
case EEikCmdExit:
|
||||
iQikAppUi.Document()->SaveL();
|
||||
CPicoGameSession::freeResources();
|
||||
//break; // this is intentional
|
||||
|
||||
default:
|
||||
// Go back and exit command will be passed to the CQikViewBase to handle.
|
||||
CQikViewBase::HandleCommandL(aCommand);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CPicolAppView::DisplayOpenROMDialogL()
|
||||
{
|
||||
// Array of mimetypes that the dialog shall filter on, if empty all
|
||||
// mimetypes will be visible.
|
||||
CDesCArray* mimeArray = new (ELeave) CDesCArrayFlat(1);
|
||||
CleanupStack::PushL(mimeArray);
|
||||
// Array that will be filled with the file paths that are choosen
|
||||
// from the dialog.
|
||||
CDesCArray* fileArray = new (ELeave) CDesCArraySeg(3);
|
||||
CleanupStack::PushL(fileArray);
|
||||
_LIT16(KDlgTitle, "Select a ROM file");
|
||||
|
||||
if( CQikSelectFileDlg::RunDlgLD( *mimeArray, *fileArray, &KDlgTitle, &iCurrentConfig.iLastROMFile) )
|
||||
{
|
||||
CEikonEnv::Static()->BusyMsgL(_L("Loading ROM"));
|
||||
TPtrC16 file = (*fileArray)[0];
|
||||
iCurrentConfig.iLastROMFile.Copy(file);
|
||||
|
||||
// push the config first
|
||||
CPicoGameSession::Do(PicoMsgSetAppView, this);
|
||||
CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);
|
||||
|
||||
TInt res = CPicoGameSession::Do(PicoMsgLoadROM, &file);
|
||||
|
||||
CEikonEnv::Static()->BusyMsgCancel();
|
||||
|
||||
iROMLoaded = EFalse;
|
||||
switch (res)
|
||||
{
|
||||
case PicoErrRomOpenFailed:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to open file."));
|
||||
break;
|
||||
|
||||
case PicoErrOutOfMem:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate memory."));
|
||||
break;
|
||||
|
||||
case PicoErrNotRom:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("The file you selected is not a game ROM."));
|
||||
break;
|
||||
|
||||
case PicoErrNoRomsInArchive:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("No game ROMs found in zipfile."));
|
||||
break;
|
||||
|
||||
case PicoErrUncomp:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed while unzipping ROM."));
|
||||
break;
|
||||
|
||||
case PicoErrEmuThread:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to create emulation thread. Try to restart this application."));
|
||||
break;
|
||||
|
||||
default:
|
||||
iROMLoaded = ETrue;
|
||||
break;
|
||||
}
|
||||
|
||||
// errors which leave ROM loaded
|
||||
switch (res)
|
||||
{
|
||||
case PicoErrOutOfMemSnd:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to allocate sound buffer, disabled sound."));
|
||||
break;
|
||||
|
||||
case PicoErrGenSnd:
|
||||
CEikonEnv::Static()->InfoWinL(_L("Error"), _L("Failed to start soundsystem, disabled sound."));
|
||||
break;
|
||||
}
|
||||
if(res == 6 || res == 7) iCurrentConfig.iFlags &= ~4;
|
||||
|
||||
if(iROMLoaded) {
|
||||
if(iTitleAdded)
|
||||
ViewContext()->ChangeTextL(EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);
|
||||
else ViewContext()->AddTextL (EEikCidTitleBarLabel, CPicoGameSession::iRomInternalName);
|
||||
iTitleAdded = ETrue;
|
||||
UpdateCommandList();
|
||||
}
|
||||
}
|
||||
CleanupStack::PopAndDestroy(2, mimeArray);
|
||||
}
|
||||
|
||||
|
||||
void CPicolAppView::DisplayConfigDialogL()
|
||||
{
|
||||
CPicoConfigDialog* configDialog = new(ELeave)CPicoConfigDialog(iCurrentConfig);
|
||||
configDialog->ExecuteLD(R_PICO_CONFIG);
|
||||
|
||||
CPicoGameSession::Do(PicoMsgConfigChange, &iCurrentConfig);
|
||||
iQikAppUi.Document()->SaveL();
|
||||
}
|
||||
|
||||
|
||||
void CPicolAppView::DisplayAboutDialogL()
|
||||
{
|
||||
TInt iButtonRes;
|
||||
CAboutDialog* dialog = new (ELeave) CAboutDialog;
|
||||
|
||||
dialog->PrepareLC(R_PICO_ABOUT);
|
||||
iButtonRes = dialog->RunLD();
|
||||
|
||||
if(iButtonRes == EEikCmdPicoAboutCreditsCmd) {
|
||||
CCreditsDialog *creditsDialog = new (ELeave) CCreditsDialog();
|
||||
creditsDialog->PrepareLC(R_PICO_CREDITS);
|
||||
creditsDialog->RunLD();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __DEBUG_PRINT
|
||||
extern "C" char *debugString();
|
||||
#endif
|
||||
|
||||
void CPicolAppView::DisplayDebugDialogL()
|
||||
{
|
||||
#ifdef __DEBUG_PRINT
|
||||
CDebugDialog* dialog = new (ELeave) CDebugDialog(debugString());
|
||||
|
||||
dialog->PrepareLC(R_PICO_DEBUG);
|
||||
dialog->RunLD();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPicolAppView::UpdateCommandList()
|
||||
{
|
||||
CQikCommandManager& commandManager = CQikCommandManager::Static(*iCoeEnv);
|
||||
CQikCommand *cmd_fs[10];
|
||||
Mem::FillZ(cmd_fs, sizeof(CQikCommand*)*10);
|
||||
|
||||
CQikCommand* cmd_reset = commandManager.Command(*this, EEikCmdPicoReset);
|
||||
CQikCommand* cmd_savest = commandManager.Command(*this, EEikCmdPicoSaveState);
|
||||
CQikCommand* cmd_loadst = commandManager.Command(*this, EEikCmdPicoLoadState);
|
||||
CQikCommand* cmd_resume = commandManager.Command(*this, EEikCmdPicoResume);
|
||||
cmd_fs[0] = commandManager.Command(*this, EEikCmdPicoFrameskipAuto);
|
||||
cmd_fs[1] = commandManager.Command(*this, EEikCmdPicoFrameskip0);
|
||||
cmd_fs[2] = commandManager.Command(*this, EEikCmdPicoFrameskip1);
|
||||
cmd_fs[3] = commandManager.Command(*this, EEikCmdPicoFrameskip2);
|
||||
cmd_fs[5] = commandManager.Command(*this, EEikCmdPicoFrameskip4);
|
||||
cmd_fs[9] = commandManager.Command(*this, EEikCmdPicoFrameskip8);
|
||||
|
||||
TBool dimmed = !CPicoGameSession::iEmuRunning || !iROMLoaded;
|
||||
cmd_reset ->SetDimmed(dimmed);
|
||||
cmd_savest->SetDimmed(dimmed);
|
||||
cmd_loadst->SetDimmed(dimmed);
|
||||
cmd_resume->SetDimmed(dimmed);
|
||||
|
||||
// frameskip
|
||||
TInt fs_index = iCurrentConfig.iFrameskip + 1;
|
||||
if (fs_index >= 0 && fs_index < 10 && cmd_fs[fs_index])
|
||||
{
|
||||
cmd_fs[fs_index]->SetChecked(ETrue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// class CPicolAppUi
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void CPicolAppUi::ConstructL()
|
||||
{
|
||||
BaseConstructL();
|
||||
|
||||
// Create the view and add it to the framework
|
||||
iAppView = CPicolAppView::NewLC(*this, ((CPicolDocument *)Document())->iCurrentConfig);
|
||||
AddViewL(*iAppView);
|
||||
CleanupStack::Pop(iAppView);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPicolDocument
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CPicolDocument::CPicolDocument(CQikApplication& aApp)
|
||||
: CQikDocument(aApp)
|
||||
{
|
||||
iCurrentConfig.SetDefaults();
|
||||
}
|
||||
|
||||
CQikAppUi* CPicolDocument::CreateAppUiL()
|
||||
{
|
||||
return new(ELeave) CPicolAppUi;
|
||||
}
|
||||
|
||||
/**
|
||||
Called by the framework when ::SaveL has been called.
|
||||
*/
|
||||
void CPicolDocument::StoreL(CStreamStore& aStore, CStreamDictionary& aStreamDic) const
|
||||
{
|
||||
RStoreWriteStream stream;
|
||||
|
||||
TStreamId preferenceId = stream.CreateLC(aStore);
|
||||
aStreamDic.AssignL(KUidPicolStore, preferenceId);
|
||||
|
||||
// Externalize preference
|
||||
stream << iCurrentConfig;
|
||||
|
||||
// Ensures that any buffered data is written to aStore
|
||||
stream.CommitL();
|
||||
CleanupStack::PopAndDestroy(); // stream
|
||||
|
||||
/*
|
||||
// tmp
|
||||
TInt res;
|
||||
RFile logFile;
|
||||
res = logFile.Replace(CEikonEnv::Static()->FsSession(), _L("C:\\Shared\\pico.cfg"), EFileWrite|EFileShareAny);
|
||||
if(!res) {
|
||||
logFile.Write(TPtr8((TUint8 *)&iCurrentConfig, sizeof(iCurrentConfig), sizeof(iCurrentConfig)));
|
||||
logFile.Close();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
Called by the framework on application start.
|
||||
Loads the application data from disk, i.e. domain data and preferences.
|
||||
*/
|
||||
void CPicolDocument::RestoreL(const CStreamStore& aStore, const CStreamDictionary& aStreamDic)
|
||||
{
|
||||
// Find the stream ID of the model data from the stream dictionary:
|
||||
TStreamId preferenceId(aStreamDic.At(KUidPicolStore));
|
||||
RStoreReadStream stream;
|
||||
stream.OpenLC(aStore, preferenceId);
|
||||
if(preferenceId != KNullStreamId)
|
||||
{
|
||||
// Interalize preference and model
|
||||
stream >> iCurrentConfig;
|
||||
}
|
||||
|
||||
CleanupStack::PopAndDestroy(); // stream
|
||||
|
||||
|
||||
// tmp
|
||||
/* TInt res;
|
||||
RFile logFile;
|
||||
res = logFile.Open(CEikonEnv::Static()->FsSession(), _L("C:\\Shared\\pico.cfg"), EFileRead|EFileShareAny);
|
||||
if(!res) {
|
||||
TPtr8 ptr((TUint8 *)&iCurrentConfig, sizeof(iCurrentConfig), sizeof(iCurrentConfig));
|
||||
logFile.Read(ptr);
|
||||
logFile.Close();
|
||||
}*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// framework
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CApaDocument* CPicolApplication::CreateDocumentL()
|
||||
{
|
||||
return new (ELeave) CPicolDocument(*this);
|
||||
}
|
||||
|
||||
EXPORT_C CApaApplication* NewApplication()
|
||||
{
|
||||
return new CPicolApplication;
|
||||
}
|
||||
|
||||
|
||||
TUid CPicolApplication::AppDllUid() const
|
||||
{
|
||||
return KUidPicolApp;
|
||||
}
|
||||
|
||||
|
||||
GLDEF_C TInt E32Main()
|
||||
{
|
||||
User::SetExceptionHandler(ExceptionHandler, (TUint32) -1);
|
||||
|
||||
return EikStart::RunApplication(NewApplication);
|
||||
}
|
||||
|
||||
|
112
platform/uiq3/App.h
Normal file
112
platform/uiq3/App.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: App.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2001, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __APP_H
|
||||
#define __APP_H
|
||||
|
||||
#include <coecntrl.h>
|
||||
#include <coeccntx.h>
|
||||
#include <coemain.h>
|
||||
|
||||
#include <qikappui.h>
|
||||
#include <QikApplication.h>
|
||||
#include <QikViewBase.h>
|
||||
//#include <eikapp.h>
|
||||
#include <QikDocument.h>
|
||||
|
||||
#include "Engine.h"
|
||||
#include "picodrive.hrh"
|
||||
|
||||
const TUid KUidPicolApp = { 0xA00010F3 };
|
||||
const TUid KUidPicolMainView = { 0x00000001 };
|
||||
//const TUid KUidPicolFOView = { 0x1000C194 };
|
||||
//const TUid KUidPicolFCView = { 0x1000C195 };
|
||||
const TUid KUidPicolStore = { 0x00000011 }; // store stream UID
|
||||
|
||||
//enum
|
||||
//{
|
||||
// EScreenModeFlipOpen = 0,
|
||||
// EScreenModeFlipClosed
|
||||
//};
|
||||
|
||||
|
||||
|
||||
class CPicolAppView : public CQikViewBase
|
||||
{
|
||||
public:
|
||||
static CPicolAppView* NewLC(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig);
|
||||
~CPicolAppView();
|
||||
|
||||
// from CQikViewBase
|
||||
TVwsViewId ViewId()const;
|
||||
void HandleCommandL(CQikCommand& aCommand);
|
||||
void UpdateCommandList();
|
||||
|
||||
protected:
|
||||
// from CQikViewBase
|
||||
void ViewConstructL();
|
||||
|
||||
private:
|
||||
CPicolAppView(CQikAppUi& aAppUi, TPicoConfig& aCurrentConfig);
|
||||
void ConstructL();
|
||||
|
||||
protected: // new stuf
|
||||
void DisplayAboutDialogL();
|
||||
void DisplayOpenROMDialogL();
|
||||
void DisplayConfigDialogL();
|
||||
void DisplayDebugDialogL();
|
||||
|
||||
/* void StopGame();
|
||||
void RunGameL();*/
|
||||
|
||||
private:
|
||||
TPicoConfig& iCurrentConfig;
|
||||
TBool iROMLoaded;
|
||||
TBool iTitleAdded;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CPicolAppUi : public CQikAppUi
|
||||
{
|
||||
public:
|
||||
// CPicolAppUi();
|
||||
void ConstructL();
|
||||
|
||||
CPicolAppView* iAppView;
|
||||
};
|
||||
|
||||
|
||||
class CPicolDocument : public CQikDocument
|
||||
{
|
||||
public:
|
||||
CPicolDocument(CQikApplication& aApp);
|
||||
void StoreL(CStreamStore& aStore, CStreamDictionary& aStreamDic) const;
|
||||
void RestoreL(const CStreamStore& aStore, const CStreamDictionary& aStreamDic);
|
||||
|
||||
TPicoConfig iCurrentConfig;
|
||||
|
||||
private: // from CQikDocument
|
||||
CQikAppUi* CreateAppUiL();
|
||||
};
|
||||
|
||||
|
||||
class CPicolApplication : public CQikApplication
|
||||
{
|
||||
private: // from CApaApplication
|
||||
CApaDocument* CreateDocumentL();
|
||||
TUid AppDllUid() const;
|
||||
};
|
||||
|
||||
#endif
|
477
platform/uiq3/CSimpleTextParser.cpp
Normal file
477
platform/uiq3/CSimpleTextParser.cpp
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: CSimpleTextParser.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "CSimpleTextParser.h"
|
||||
|
||||
enum
|
||||
{
|
||||
EBadTag,
|
||||
EBadZeroLengthTag,
|
||||
EBadIntegerParam,
|
||||
EBadAlignmentParam,
|
||||
EBadRgbColorParam
|
||||
};
|
||||
|
||||
void Panic(TInt aPanic)
|
||||
{
|
||||
User::Panic(_L("STP"), aPanic);
|
||||
}
|
||||
|
||||
CSimpleTextFormatParser* CSimpleTextFormatParser::NewLC()
|
||||
{
|
||||
CSimpleTextFormatParser* self = new(ELeave)CSimpleTextFormatParser;
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
return self;
|
||||
}
|
||||
|
||||
CSimpleTextFormatParser::~CSimpleTextFormatParser()
|
||||
{
|
||||
delete iParaFormat;
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::ConstructL()
|
||||
{
|
||||
iParaFormat = CParaFormat::NewL();
|
||||
}
|
||||
|
||||
|
||||
void CSimpleTextFormatParser::SetBold(TBool aEnable)
|
||||
{
|
||||
iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(aEnable ? EStrokeWeightBold : EStrokeWeightNormal);
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontStrokeWeight);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetItalic(TBool aEnable)
|
||||
{
|
||||
iCharFormat.iFontSpec.iFontStyle.SetPosture(aEnable ? EPostureItalic : EPostureUpright);
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontPosture);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetUnderLine(TBool aEnable)
|
||||
{
|
||||
iCharFormat.iFontPresentation.iUnderline = aEnable ? EUnderlineOn : EUnderlineOff;
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontUnderline);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetHiddenText(TBool aEnable)
|
||||
{
|
||||
iCharFormat.iFontPresentation.iHiddenText = aEnable;
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontHiddenText);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
TRgb CSimpleTextFormatParser::ForegroundColor()
|
||||
{
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttColor);
|
||||
iRichText->GetCharFormat(iCharFormat, iCharMask, TextPos(), 0);
|
||||
return iCharFormat.iFontPresentation.iTextColor;
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetForegroundColor(const TRgb& aColor)
|
||||
{
|
||||
iCharFormat.iFontPresentation.iTextColor = aColor;
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttColor);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetBackgroundColor(const TRgb& aColor)
|
||||
{
|
||||
iParaFormat->iFillColor = aColor;
|
||||
iParaMask.ClearAll();
|
||||
iParaMask.SetAttrib(EAttFillColor);
|
||||
iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::NewParagraph()
|
||||
{
|
||||
iCurrentPara++;
|
||||
iRichText->AppendParagraphL();
|
||||
AppendTextL(_L(""));
|
||||
}
|
||||
|
||||
|
||||
void CSimpleTextFormatParser::SetAlignment(CParaFormat::TAlignment aAlignment)
|
||||
{
|
||||
iParaFormat->iHorizontalAlignment = aAlignment;
|
||||
iParaMask.ClearAll();
|
||||
iParaMask.SetAttrib(EAttAlignment);
|
||||
iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
|
||||
}
|
||||
|
||||
|
||||
void CSimpleTextFormatParser::SetFontHeight(TInt aHeight)
|
||||
{
|
||||
iCharFormat.iFontSpec.iHeight = (aHeight * KTwipsPerInch)/KPointsPerInch;
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontHeight);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::SetFontName(const TDesC& aName)
|
||||
{
|
||||
iCharFormat.iFontSpec.iTypeface.iName = aName;
|
||||
iCharFormat.iFontSpec.iTypeface.SetAttributes(0);
|
||||
iCharFormat.iFontSpec.iTypeface.SetIsProportional(ETrue);
|
||||
iCharMask.ClearAll();
|
||||
iCharMask.SetAttrib(EAttFontTypeface);
|
||||
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Character formatting:
|
||||
* <b> Bold on
|
||||
* </b> Bold of
|
||||
* <i> Italic on
|
||||
* </i> Italic off
|
||||
* <u> Underline on
|
||||
* </u> Underline off
|
||||
* <h> Hidden text on **doesn't work**
|
||||
* </h> Hidden text off **doesn't work**
|
||||
* <f=name> Fontname: name (type: string)
|
||||
* <s=size> Fontsize: size (type: integer)
|
||||
* <fg=color> Foreground color: color (type: color)
|
||||
* </fg> Restore foreground color
|
||||
*
|
||||
* Paragraph formatting:
|
||||
* <p> New paragraph - will reset both character & paragraph formatting to defaults
|
||||
* <a=align> Alignment: aling (type: alignement)
|
||||
* <bg=color> Background color: color (type: color) **doesn't work**
|
||||
*
|
||||
* Special characters:
|
||||
* </<> The character: <
|
||||
*
|
||||
* Types:
|
||||
* - string:
|
||||
* - integer: Either decimal or hexidecimal value
|
||||
* - color: Either integer specifing rgb value, or (r,g,b) in which r, g and b are of type integer
|
||||
* - align: element of enumeration {center, left, right}
|
||||
*
|
||||
* Comments:
|
||||
* The syntax/parser is fairly simplistic. The parser is not trying to match a tag like
|
||||
* <tag> </tag> as XML/HTML do. Basically, when it encounters a tag (e.g., <b>) it will
|
||||
* simply instruct the the editor to apply the formatting from the current position as
|
||||
* specified by the tag (e.g., enable bold). For example, <b><b>Hello</b>World</b> results
|
||||
* in Hello displayed in a Bold font and World in a normal font.
|
||||
*
|
||||
* The only case where state is maintained is when using <fg=color> and </fg>. The current
|
||||
* fg color is stored when parsing <fg=color> and restored when doing </fg>. Again, <fg> and
|
||||
* </fg> don't have the XML/HTML <tag> </tag> behavior. For example:
|
||||
* <fg=red>Peter<fg=blue>was</fg></fg>here
|
||||
* results in "Peter" displayed in red, "was" displayed in blue and "here" displayed in red.
|
||||
* It literally goes like this:
|
||||
* 1) <fg=red> --> apply editor text color red, previous color = whatever the editor's text color is now
|
||||
* 2) <fg=blue> --> apply editor text color blue, previous color = whatever the editor's text color
|
||||
* is now --> red
|
||||
* 3) </fg> --> apply editor text to previous color --> red
|
||||
* 4) </fg> --> apply editor text to previous color --> red
|
||||
*
|
||||
* What you probably wanted was:
|
||||
* <fg=red>Peter</fg><fg=blue>was</fg>here
|
||||
* Now "Peter" is displayed in red, "was" in blue and "here" in the default editor's color
|
||||
*/
|
||||
|
||||
static TUint32 ParseInteger(const TDesC& aString)
|
||||
{
|
||||
TUint32 val = 0;
|
||||
TBool parsed = EFalse;
|
||||
if (aString.Length() > 2)
|
||||
{
|
||||
if ((aString[0] == '0') && ((aString[0] == 'x') || (aString[0] == 'X')))
|
||||
{
|
||||
TLex lex(aString.Right(aString.Length()-2));
|
||||
if (lex.Val(val, EHex) != KErrNone)
|
||||
{
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
|
||||
}
|
||||
parsed = ETrue;
|
||||
}
|
||||
}
|
||||
if (!parsed)
|
||||
{
|
||||
TLex lex(aString);
|
||||
if (lex.Val(val, EDecimal) != KErrNone)
|
||||
{
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static TRgb ParseColor(const TDesC& aString)
|
||||
{
|
||||
if (aString.Length() > 0)
|
||||
{
|
||||
if (aString[0] == 'R')
|
||||
{
|
||||
if (aString.Compare(_L("RgbBlack")) == 0)
|
||||
return KRgbBlack;
|
||||
else if (aString.Compare(_L("RgbDarkGray")) == 0)
|
||||
return KRgbDarkGray;
|
||||
else if (aString.Compare(_L("RgbDarkRed")) == 0)
|
||||
return KRgbDarkRed;
|
||||
else if (aString.Compare(_L("RgbDarkGreen")) == 0)
|
||||
return KRgbDarkGreen;
|
||||
else if (aString.Compare(_L("RgbDarkYellow")) == 0)
|
||||
return KRgbDarkYellow;
|
||||
else if (aString.Compare(_L("RgbDarkBlue")) == 0)
|
||||
return KRgbDarkBlue;
|
||||
else if (aString.Compare(_L("RgbDarkMagenta")) == 0)
|
||||
return KRgbDarkMagenta;
|
||||
else if (aString.Compare(_L("RgbDarkCyan")) == 0)
|
||||
return KRgbDarkCyan;
|
||||
else if (aString.Compare(_L("RgbRed")) == 0)
|
||||
return KRgbRed;
|
||||
else if (aString.Compare(_L("RgbGreen")) == 0)
|
||||
return KRgbGreen;
|
||||
else if (aString.Compare(_L("RgbYellow")) == 0)
|
||||
return KRgbYellow;
|
||||
else if (aString.Compare(_L("RgbBlue")) == 0)
|
||||
return KRgbBlue;
|
||||
else if (aString.Compare(_L("RgbMagenta")) == 0)
|
||||
return KRgbMagenta;
|
||||
else if (aString.Compare(_L("RgbCyan")) == 0)
|
||||
return KRgbCyan;
|
||||
else if (aString.Compare(_L("RgbGray")) == 0)
|
||||
return KRgbGray;
|
||||
else if (aString.Compare(_L("RgbWhite")) == 0)
|
||||
return KRgbWhite;
|
||||
else
|
||||
{
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
|
||||
}
|
||||
}
|
||||
return ParseInteger(aString);
|
||||
}
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
|
||||
|
||||
return KRgbBlack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static CParaFormat::TAlignment ParseAlignment(const TDesC& aString)
|
||||
{
|
||||
if (aString.Compare(_L("center")) == 0)
|
||||
{
|
||||
return CParaFormat::ECenterAlign;
|
||||
}
|
||||
else if (aString.Compare(_L("left")) == 0)
|
||||
{
|
||||
return CParaFormat::ELeftAlign;
|
||||
}
|
||||
else if (aString.Compare(_L("right")) == 0)
|
||||
{
|
||||
return CParaFormat::ERightAlign;
|
||||
}
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadAlignmentParam));
|
||||
|
||||
return CParaFormat::ECenterAlign;
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::ParseTagL(const TDesC& aTag)
|
||||
{
|
||||
TInt tagLength = aTag.Length();
|
||||
if (tagLength == 0)
|
||||
{
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadZeroLengthTag));
|
||||
return;
|
||||
}
|
||||
|
||||
TPtrC param(_L(""));
|
||||
TInt pos = aTag.Find(_L("="));
|
||||
if (pos>0)
|
||||
{
|
||||
param.Set(aTag.Right(aTag.Length()-pos-1));
|
||||
tagLength = pos;
|
||||
}
|
||||
TPtrC tag = aTag.Left(tagLength);
|
||||
|
||||
// RDebug::Print(_L("tag=%S, param=%S"), &tag, ¶m);
|
||||
|
||||
switch (tagLength)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (tag.Compare(_L("a")) == 0)
|
||||
SetAlignment(ParseAlignment(param));
|
||||
else if (tag.Compare(_L("b")) == 0)
|
||||
SetBold();
|
||||
else if (tag.Compare(_L("f")) == 0)
|
||||
SetFontName(param);
|
||||
else if (tag.Compare(_L("h")) == 0)
|
||||
SetHiddenText();
|
||||
else if (tag.Compare(_L("i")) == 0)
|
||||
SetItalic();
|
||||
else if (tag.Compare(_L("p")) == 0)
|
||||
NewParagraph();
|
||||
else if (tag.Compare(_L("s")) == 0)
|
||||
SetFontHeight(ParseInteger(param));
|
||||
else if (tag.Compare(_L("u")) == 0)
|
||||
SetUnderLine();
|
||||
else
|
||||
{
|
||||
__ASSERT_DEBUG(ETrue, Panic(EBadTag));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (tag.Compare(_L("/b")) == 0)
|
||||
SetBold(EFalse);
|
||||
if (tag.Compare(_L("bg")) == 0)
|
||||
SetBackgroundColor(ParseColor(param));
|
||||
if (tag.Compare(_L("fg")) == 0)
|
||||
{
|
||||
iPrevFgColor = ForegroundColor();
|
||||
SetForegroundColor(ParseColor(param));
|
||||
}
|
||||
else if (tag.Compare(_L("/h")) == 0)
|
||||
SetHiddenText(EFalse);
|
||||
else if (tag.Compare(_L("/i")) == 0)
|
||||
SetItalic(EFalse);
|
||||
else if (tag.Compare(_L("/u")) == 0)
|
||||
SetUnderLine(EFalse);
|
||||
else if (tag.Compare(_L("/<")) == 0)
|
||||
AppendTextL(_L("<"));
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (tag.Compare(_L("/fg")) == 0)
|
||||
SetForegroundColor(iPrevFgColor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleTextFormatParser::ParseL(const TDesC& aSimpleText, CRichText& aRichText)
|
||||
{
|
||||
iRichText = &aRichText;
|
||||
iCurrentPara = 0;
|
||||
|
||||
TBool done = EFalse;
|
||||
TPtrC simpleText(aSimpleText);
|
||||
do
|
||||
{
|
||||
TInt pos = simpleText.Locate('<');
|
||||
if (pos > 0)
|
||||
{
|
||||
AppendTextL(simpleText.Left(pos));
|
||||
simpleText.Set(simpleText.Right(simpleText.Length() - pos));
|
||||
}
|
||||
else if (pos == 0)
|
||||
{
|
||||
pos = simpleText.Locate('>');
|
||||
if (pos<=0)
|
||||
User::Leave(KErrArgument);
|
||||
ParseTagL(simpleText.Mid(1, pos-1));
|
||||
simpleText.Set(simpleText.Right(simpleText.Length() - pos - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendTextL(simpleText);
|
||||
done = ETrue;
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
|
||||
TInt CSimpleTextFormatParser::TextPos()
|
||||
{
|
||||
return iRichText->DocumentLength();
|
||||
#if 0
|
||||
TInt pos, length;
|
||||
pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
|
||||
return pos+length-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
TInt CSimpleTextFormatParser::ParaPos()
|
||||
{
|
||||
return TextPos();
|
||||
#if 0
|
||||
TInt pos, length;
|
||||
pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
|
||||
return pos+length-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CSimpleTextFormatParser::AppendTextL(const TDesC& aText)
|
||||
{
|
||||
// RDebug::Print(_L("text=%S"), &aText);
|
||||
iRichText->InsertL(TextPos(), aText);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void CTestDialog::ShowTextL(CRichText& aRichText)
|
||||
{
|
||||
aRichText.Reset();
|
||||
|
||||
TCharFormat charFormat;
|
||||
TCharFormatMask charMask;
|
||||
aRichText.GetCharFormat(charFormat, charMask, 0, 0);
|
||||
|
||||
TInt para = 0;
|
||||
AppendTextL(_L("http://www.yipton.net"), aRichText);
|
||||
|
||||
para++;
|
||||
aRichText.AppendParagraphL();
|
||||
|
||||
CParaFormat* paraFormat = CParaFormat::NewLC();
|
||||
TParaFormatMask paraMask;
|
||||
aRichText.GetParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
|
||||
paraFormat->iHorizontalAlignment = CParaFormat::ECenterAlign;
|
||||
paraMask.ClearAll();
|
||||
paraMask.SetAttrib(EAttAlignment);
|
||||
aRichText.ApplyParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
|
||||
|
||||
charFormat.iFontPresentation.iUnderline = EUnderlineOn;
|
||||
charFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
|
||||
charMask.ClearAll();
|
||||
charMask.SetAttrib(EAttFontPosture);
|
||||
charMask.SetAttrib(EAttFontUnderline);
|
||||
aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
|
||||
AppendTextL(_L("mailto:Peter is here"), aRichText, para);
|
||||
|
||||
para++;
|
||||
aRichText.AppendParagraphL();
|
||||
|
||||
TFontSpec fontSpec(_L("edmunds"), 20 * KPointsPerInch);
|
||||
// CFont* font = NULL;
|
||||
// iCoeEnv->ScreenDevice()->GetNearestFontInTwips(font, fontSpec);
|
||||
|
||||
charFormat.iFontSpec = fontSpec;
|
||||
charMask.ClearAll();
|
||||
charMask.SetAttrib(EAttFontHeight);
|
||||
charMask.SetAttrib(EAttFontTypeface);
|
||||
aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
|
||||
AppendTextL(_L("mailto:Peter is here"), aRichText, para);
|
||||
|
||||
CleanupStack::PopAndDestroy();
|
||||
}
|
||||
|
||||
#endif
|
59
platform/uiq3/CSimpleTextParser.h
Normal file
59
platform/uiq3/CSimpleTextParser.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: CSimpleTextParser.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __CSIMPLE_TEXT_PARSER_H
|
||||
#define __CSIMPLE_TEXT_PARSER_H
|
||||
|
||||
#include <e32def.h>
|
||||
#include <txtrich.h> // CRichText
|
||||
#include <eikrted.h> // CEikRichTextEditor
|
||||
|
||||
class CSimpleTextFormatParser : public CBase
|
||||
{
|
||||
public:
|
||||
static CSimpleTextFormatParser* NewLC();
|
||||
void ParseL(const TDesC& aPSTText, CRichText& aRichText);
|
||||
|
||||
protected:
|
||||
CSimpleTextFormatParser(){}
|
||||
~CSimpleTextFormatParser();
|
||||
void ConstructL();
|
||||
|
||||
void ParseTagL(const TDesC& aTag);
|
||||
|
||||
TRgb ForegroundColor();
|
||||
void SetBold(TBool aEnable=ETrue);
|
||||
void SetItalic(TBool aEnable=ETrue);
|
||||
void SetUnderLine(TBool aEnable=ETrue);
|
||||
void SetFontHeight(TInt aHeight);
|
||||
void SetFontName(const TDesC& aName);
|
||||
void SetHiddenText(TBool aEnable=ETrue);
|
||||
void SetForegroundColor(const TRgb& aColor);
|
||||
|
||||
void NewParagraph();
|
||||
void SetAlignment(CParaFormat::TAlignment aAlignment);
|
||||
void SetBackgroundColor(const TRgb& aColor);
|
||||
|
||||
void AppendTextL(const TDesC& aText);
|
||||
TInt TextPos();
|
||||
TInt ParaPos();
|
||||
|
||||
|
||||
CRichText* iRichText;
|
||||
TCharFormat iCharFormat;
|
||||
TCharFormatMask iCharMask;
|
||||
CParaFormat* iParaFormat;
|
||||
TParaFormatMask iParaMask;
|
||||
TInt iCurrentPara;
|
||||
TRgb iPrevFgColor;
|
||||
};
|
||||
|
||||
#endif /* __CSIMPLE_TEXT_PARSER_H */
|
324
platform/uiq3/Dialogs.cpp
Normal file
324
platform/uiq3/Dialogs.cpp
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Dialogs.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include "Engine.h"
|
||||
#include "picodrive.hrh"
|
||||
#include <picodrive.rsg>
|
||||
|
||||
#include "version.h"
|
||||
#include "CSimpleTextParser.h"
|
||||
#include <txtrich.h> // CRichText
|
||||
#include <eikrted.h> // CEikRichTextEditor
|
||||
#include <qikvertoptionbuttonlist.h> // CEikHorOptionButtonList
|
||||
#include <eikopbut.h> // CEikOptionButton
|
||||
#include <eikedwin.h> // CEikEdwin
|
||||
#include <QuartzKeys.h> // EQuartzKeyTwoWayDown
|
||||
|
||||
#include <QikCommand.h>
|
||||
|
||||
|
||||
/************************************************
|
||||
*
|
||||
* config Dialog
|
||||
*
|
||||
************************************************/
|
||||
|
||||
CPicoConfigDialog::CPicoConfigDialog(TPicoConfig &cfg) : config(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
void CPicoConfigDialog::PostLayoutDynInitL()
|
||||
{
|
||||
CEikHorOptionButtonList *buttons_rot = (CEikHorOptionButtonList*) Control( ECtlOptRotation );
|
||||
CEikHorOptionButtonList *buttons_disp = (CEikHorOptionButtonList*) Control( ECtlOptScreenMode );
|
||||
CEikCheckBox *chkbox_altrend= (CEikCheckBox*) Control( ECtlOptUseAltRend );
|
||||
CEikCheckBox *chkbox_acctmng= (CEikCheckBox*) Control( ECtlOptUseAccTiming );
|
||||
CEikCheckBox *chkbox_sram = (CEikCheckBox*) Control( ECtlOptUseSRAM );
|
||||
CEikCheckBox *chkbox_fps = (CEikCheckBox*) Control( ECtlOptShowFPS );
|
||||
CEikCheckBox *chkbox_sound = (CEikCheckBox*) Control( ECtlOptEnableSound );
|
||||
CEikCheckBox *chkbox_z80 = (CEikCheckBox*) Control( ECtlOptEmulateZ80 );
|
||||
CEikCheckBox *chkbox_ym2612 = (CEikCheckBox*) Control( ECtlOptEmulateYM2612 );
|
||||
CEikCheckBox *chkbox_sn76496= (CEikCheckBox*) Control( ECtlOptEmulateSN76496 );
|
||||
CEikChoiceListBase *combo_sndq = (CEikChoiceListBase*) Control( ECtlOptSndQuality );
|
||||
CEikCheckBox *chkbox_6bpad = (CEikCheckBox*) Control( ECtlOpt6ButtonPad );
|
||||
CEikCheckBox *chkbox_gzipst = (CEikCheckBox*) Control( ECtlOptGzipStates );
|
||||
CEikCheckBox *chkbox_accsprt= (CEikCheckBox*) Control( ECtlOptUseAccSprites );
|
||||
CEikChoiceListBase *combo_region = (CEikChoiceListBase*) Control( ECtlOptRegion );
|
||||
CEikOptionButton *opt_fit2 = (CEikOptionButton*) buttons_disp->ComponentControl( TPicoConfig::PMFit2 );
|
||||
|
||||
buttons_rot ->SetButtonById(ECtlOptRotation0 + config.iScreenRotation);
|
||||
buttons_disp->SetButtonById(ECtlOptScreenModeCenter + config.iScreenMode);
|
||||
chkbox_sram ->SetState(config.iFlags & 1 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_fps ->SetState(config.iFlags & 2 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_sound ->SetState(config.iFlags & 4 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_gzipst ->SetState(config.iFlags & 0x80 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_z80 ->SetState(config.iPicoOpt & 4 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_ym2612 ->SetState(config.iPicoOpt & 1 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_sn76496->SetState(config.iPicoOpt & 2 ? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_altrend->SetState(config.iPicoOpt & 0x10? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_6bpad ->SetState(config.iPicoOpt & 0x20? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_acctmng->SetState(config.iPicoOpt & 0x40? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
chkbox_accsprt->SetState(config.iPicoOpt & 0x80? CEikButtonBase::ESet : CEikButtonBase::EClear);
|
||||
|
||||
// dim "fit2" if we are not in 0 or 180 mode
|
||||
if(config.iScreenRotation != TPicoConfig::PRot0 && config.iScreenRotation != TPicoConfig::PRot180) opt_fit2->SetDimmed(ETrue);
|
||||
// dim some stuff for alternative renderer
|
||||
if(config.iPicoOpt & 0x10) {
|
||||
// dim accurate sprites
|
||||
chkbox_accsprt->SetState(CEikButtonBase::EClear);
|
||||
chkbox_accsprt->SetDimmed(ETrue);
|
||||
// dim fit
|
||||
if(buttons_rot->LabeledButtonId() == ECtlOptRotation0 || buttons_rot->LabeledButtonId() == ECtlOptRotation180)
|
||||
((CEikOptionButton*)(buttons_disp->ComponentControl(TPicoConfig::PMFit)))->SetDimmed(ETrue);
|
||||
}
|
||||
|
||||
TInt sel = (config.iPicoOpt&8) ? 5 : 0;
|
||||
sel+= (config.iFlags>>3)&7;
|
||||
if (sel >= 10) sel = 0;
|
||||
combo_sndq->SetCurrentItem(sel);
|
||||
switch(config.PicoRegion) {
|
||||
case 1: sel = 4; break;
|
||||
case 2: sel = 3; break;
|
||||
case 4: sel = 2; break;
|
||||
case 8: sel = 1; break;
|
||||
default:sel = 0; // auto
|
||||
}
|
||||
combo_region->SetCurrentItem(sel);
|
||||
}
|
||||
|
||||
TBool CPicoConfigDialog::OkToExitL(TInt aButtonId)
|
||||
{
|
||||
if(aButtonId != EEikBidOk) return ETrue;
|
||||
|
||||
CEikHorOptionButtonList *buttons_rot = (CEikHorOptionButtonList*) Control( ECtlOptRotation );
|
||||
CEikHorOptionButtonList *buttons_disp = (CEikHorOptionButtonList*) Control( ECtlOptScreenMode );
|
||||
CEikCheckBox *chkbox_altrend= (CEikCheckBox*) Control( ECtlOptUseAltRend );
|
||||
CEikCheckBox *chkbox_acctmng= (CEikCheckBox*) Control( ECtlOptUseAccTiming );
|
||||
CEikCheckBox *chkbox_sram = (CEikCheckBox*) Control( ECtlOptUseSRAM );
|
||||
CEikCheckBox *chkbox_fps = (CEikCheckBox*) Control( ECtlOptShowFPS );
|
||||
CEikCheckBox *chkbox_sound = (CEikCheckBox*) Control( ECtlOptEnableSound );
|
||||
CEikCheckBox *chkbox_z80 = (CEikCheckBox*) Control( ECtlOptEmulateZ80 );
|
||||
CEikCheckBox *chkbox_ym2612 = (CEikCheckBox*) Control( ECtlOptEmulateYM2612 );
|
||||
CEikCheckBox *chkbox_sn76496= (CEikCheckBox*) Control( ECtlOptEmulateSN76496 );
|
||||
CEikChoiceListBase *combo_sndq = (CEikChoiceListBase*) Control( ECtlOptSndQuality );
|
||||
CEikCheckBox *chkbox_6bpad = (CEikCheckBox*) Control( ECtlOpt6ButtonPad );
|
||||
CEikCheckBox *chkbox_gzipst = (CEikCheckBox*) Control( ECtlOptGzipStates );
|
||||
CEikCheckBox *chkbox_accsprt= (CEikCheckBox*) Control( ECtlOptUseAccSprites );
|
||||
CEikChoiceListBase *combo_region = (CEikChoiceListBase*) Control( ECtlOptRegion );
|
||||
|
||||
config.iScreenRotation = (TPicoConfig::TPicoScreenRotation) (buttons_rot->LabeledButtonId() - ECtlOptRotation0);
|
||||
config.iScreenMode = (TPicoConfig::TPicoScreenMode) (buttons_disp->LabeledButtonId() - ECtlOptScreenModeCenter);
|
||||
|
||||
if(chkbox_sram ->State() == CEikButtonBase::ESet) config.iFlags |= 1; else config.iFlags &= ~1;
|
||||
if(chkbox_fps ->State() == CEikButtonBase::ESet) config.iFlags |= 2; else config.iFlags &= ~2;
|
||||
if(chkbox_sound ->State() == CEikButtonBase::ESet) config.iFlags |= 4; else config.iFlags &= ~4;
|
||||
if(chkbox_gzipst ->State() == CEikButtonBase::ESet) config.iFlags |= 0x80; else config.iFlags &= ~0x80;
|
||||
if(chkbox_z80 ->State() == CEikButtonBase::ESet) config.iPicoOpt |= 4; else config.iPicoOpt &= ~4;
|
||||
if(chkbox_ym2612 ->State() == CEikButtonBase::ESet) config.iPicoOpt |= 1; else config.iPicoOpt &= ~1;
|
||||
if(chkbox_sn76496->State() == CEikButtonBase::ESet) config.iPicoOpt |= 2; else config.iPicoOpt &= ~2;
|
||||
if(chkbox_altrend->State() == CEikButtonBase::ESet) config.iPicoOpt |= 0x10;else config.iPicoOpt &= ~0x10;
|
||||
if(chkbox_6bpad ->State() == CEikButtonBase::ESet) config.iPicoOpt |= 0x20;else config.iPicoOpt &= ~0x20;
|
||||
if(chkbox_acctmng->State() == CEikButtonBase::ESet) config.iPicoOpt |= 0x40;else config.iPicoOpt &= ~0x40;
|
||||
if(chkbox_accsprt->State() == CEikButtonBase::ESet) config.iPicoOpt |= 0x80;else config.iPicoOpt &= ~0x80;
|
||||
|
||||
TInt sel = combo_sndq->CurrentItem();
|
||||
if(sel >= 5) { config.iPicoOpt |= 8; sel-=5; } else config.iPicoOpt &= ~8;
|
||||
config.iFlags &= ~0x38;
|
||||
config.iFlags |= (sel<<3)&0x38;
|
||||
|
||||
switch(combo_region->CurrentItem()) {
|
||||
case 4: config.PicoRegion = 1; break;
|
||||
case 3: config.PicoRegion = 2; break;
|
||||
case 2: config.PicoRegion = 4; break;
|
||||
case 1: config.PicoRegion = 8; break;
|
||||
default:config.PicoRegion = 0; // auto
|
||||
}
|
||||
|
||||
return ETrue;
|
||||
}
|
||||
|
||||
// simple GUI stuff needs lots of code
|
||||
void CPicoConfigDialog::HandleControlStateChangeL(TInt aControlId)
|
||||
{
|
||||
if(aControlId == ECtlOptEnableSound) {
|
||||
CEikCheckBox *chkbox_sound = (CEikCheckBox*) Control( ECtlOptEnableSound );
|
||||
CEikCheckBox *chkbox_z80 = (CEikCheckBox*) Control( ECtlOptEmulateZ80 );
|
||||
CEikCheckBox *chkbox_ym2612 = (CEikCheckBox*) Control( ECtlOptEmulateYM2612 );
|
||||
CEikCheckBox *chkbox_sn76496= (CEikCheckBox*) Control( ECtlOptEmulateSN76496 );
|
||||
|
||||
if(chkbox_sound->State() == CEikButtonBase::ESet) {
|
||||
// check all sound chips too, but only if they all are not set
|
||||
if((chkbox_z80->State() | chkbox_ym2612->State() | chkbox_sn76496->State()) == CEikButtonBase::EClear) { // (==0)
|
||||
chkbox_z80 ->SetState(CEikButtonBase::ESet);
|
||||
chkbox_ym2612 ->SetState(CEikButtonBase::ESet);
|
||||
chkbox_sn76496->SetState(CEikButtonBase::ESet);
|
||||
chkbox_z80 ->DrawDeferred();
|
||||
chkbox_ym2612 ->DrawDeferred();
|
||||
chkbox_sn76496->DrawDeferred();
|
||||
}
|
||||
} else {
|
||||
// clear everything, but only if everything is set
|
||||
if((chkbox_z80->State() & chkbox_ym2612->State() & chkbox_sn76496->State()) == CEikButtonBase::ESet) { // (==1)
|
||||
chkbox_z80 ->SetState(CEikButtonBase::EClear);
|
||||
chkbox_ym2612 ->SetState(CEikButtonBase::EClear);
|
||||
chkbox_sn76496->SetState(CEikButtonBase::EClear);
|
||||
chkbox_z80 ->DrawDeferred();
|
||||
chkbox_ym2612 ->DrawDeferred();
|
||||
chkbox_sn76496->DrawDeferred();
|
||||
}
|
||||
}
|
||||
} else if(aControlId == ECtlOptUseAltRend || aControlId == ECtlOptRotation) {
|
||||
CEikCheckBox *chkbox_altrend= (CEikCheckBox*) Control( ECtlOptUseAltRend );
|
||||
CEikCheckBox *chkbox_accsprt= (CEikCheckBox*) Control( ECtlOptUseAccSprites );
|
||||
CEikHorOptionButtonList *buttons_rot = (CEikHorOptionButtonList*) Control( ECtlOptRotation );
|
||||
CEikHorOptionButtonList *buttons_disp = (CEikHorOptionButtonList*) Control( ECtlOptScreenMode );
|
||||
CEikOptionButton *opt_fit = (CEikOptionButton*) buttons_disp->ComponentControl( TPicoConfig::PMFit );
|
||||
CEikOptionButton *opt_fit2 = (CEikOptionButton*) buttons_disp->ComponentControl( TPicoConfig::PMFit2 );
|
||||
|
||||
TBool dimmed = chkbox_altrend->State() == CEikButtonBase::ESet;
|
||||
// show/hide more stuff for alternative renderer
|
||||
chkbox_accsprt->SetDimmed(dimmed);
|
||||
if(buttons_rot->LabeledButtonId() == ECtlOptRotation0 || buttons_rot->LabeledButtonId() == ECtlOptRotation180) {
|
||||
opt_fit->SetDimmed(dimmed);
|
||||
if(dimmed && buttons_disp->LabeledButtonId() == ECtlOptScreenModeFit)
|
||||
buttons_disp->SetButtonById(ECtlOptScreenModeFit2);
|
||||
}
|
||||
else opt_fit->SetDimmed(EFalse);
|
||||
chkbox_accsprt->DrawDeferred();
|
||||
buttons_disp->DrawDeferred();
|
||||
|
||||
if(buttons_rot->LabeledButtonId() == ECtlOptRotation0 || buttons_rot->LabeledButtonId() == ECtlOptRotation180) {
|
||||
opt_fit2->SetDimmed(EFalse);
|
||||
} else {
|
||||
if(opt_fit2->State() == CEikButtonBase::ESet) {
|
||||
buttons_disp->SetButtonById(ECtlOptScreenModeFit);
|
||||
buttons_disp->DrawDeferred();
|
||||
}
|
||||
opt_fit2->SetDimmed(ETrue);
|
||||
}
|
||||
opt_fit2->DrawDeferred();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
*
|
||||
* About Dialog
|
||||
*
|
||||
************************************************/
|
||||
|
||||
void CAboutDialog::PostLayoutDynInitL()
|
||||
{
|
||||
TBuf<16> versionText;
|
||||
TBuf<512> text;
|
||||
|
||||
#if (KPicoBuildNumber != 0)
|
||||
versionText.Format(_L("%d.%d%d"), KPicoMajorVersionNumber, KPicoMinorVersionNumber, KPicoBuildNumber);
|
||||
#else
|
||||
versionText.Format(_L("%d.%d"), KPicoMajorVersionNumber, KPicoMinorVersionNumber);
|
||||
#endif
|
||||
|
||||
CEikRichTextEditor* richTextEd = LocateControlByUniqueHandle<CEikRichTextEditor>(ECtlPicoAboutText);
|
||||
User::LeaveIfNull(richTextEd);
|
||||
|
||||
HBufC *aboutFormat = CEikonEnv::Static()->AllocReadResourceLC(R_PICO_TEXT_ABOUT);
|
||||
CSimpleTextFormatParser *parser = CSimpleTextFormatParser::NewLC();
|
||||
|
||||
text.Format(*aboutFormat, &versionText);
|
||||
parser->ParseL(text, *richTextEd->RichText());
|
||||
|
||||
richTextEd->UpdateAllFieldsL(); // Updates all the fields in the document
|
||||
|
||||
CleanupStack::PopAndDestroy(parser);
|
||||
CleanupStack::PopAndDestroy(aboutFormat);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* Credits dialog
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
void CCreditsDialog::PreLayoutDynInitL()
|
||||
{
|
||||
CEikEdwin *edwin = LocateControlByUniqueHandle<CEikEdwin>(ECtlPicoCreditsText);
|
||||
User::LeaveIfNull(edwin);
|
||||
|
||||
CDesCArrayFlat* desArray = CEikonEnv::Static()->ReadDesCArrayResourceL(R_PICO_TBUF_CREDITS);
|
||||
CleanupStack::PushL(desArray);
|
||||
|
||||
edwin->SetTextLimit(2048); // to prevent stupid "too big" warning
|
||||
TInt count = desArray->Count();
|
||||
for (TInt i = 0; i < count; i++)
|
||||
{
|
||||
edwin->Text()->InsertL(edwin->TextLength(), desArray->operator[](i));
|
||||
edwin->Text()->InsertL(edwin->TextLength(), CEditableText::ELineBreak);
|
||||
}
|
||||
CleanupStack::PopAndDestroy(desArray);
|
||||
}
|
||||
|
||||
TKeyResponse CCreditsDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
|
||||
{
|
||||
if (aType == EEventKey)
|
||||
{
|
||||
CEikEdwin *edwin = LocateControlByUniqueHandle<CEikEdwin>(ECtlPicoCreditsText);
|
||||
User::LeaveIfNull(edwin);
|
||||
|
||||
if (aKeyEvent.iCode == EQuartzKeyTwoWayDown)
|
||||
{
|
||||
edwin->MoveDisplayL(TCursorPosition::EFLineDown);
|
||||
edwin->UpdateScrollBarsL();
|
||||
return EKeyWasConsumed;
|
||||
}
|
||||
else if (aKeyEvent.iCode == EQuartzKeyTwoWayUp)
|
||||
{
|
||||
edwin->MoveDisplayL(TCursorPosition::EFLineUp);
|
||||
edwin->UpdateScrollBarsL();
|
||||
return EKeyWasConsumed;
|
||||
}
|
||||
}
|
||||
return CQikSimpleDialog::OfferKeyEventL(aKeyEvent, aType);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* Debug dialog
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
CDebugDialog::CDebugDialog(char *t)
|
||||
{
|
||||
Mem::Copy(iText, t, 1024);
|
||||
iText[1023] = 0;
|
||||
}
|
||||
|
||||
void CDebugDialog::PreLayoutDynInitL()
|
||||
{
|
||||
char *p = iText, *line = iText;
|
||||
TBool end=0;
|
||||
TBuf<128> tbuf;
|
||||
CEikEdwin *editor = LocateControlByUniqueHandle<CEikEdwin>(ECtlPicoCreditsText);
|
||||
|
||||
while(!end) {
|
||||
while(*p && *p != '\r' && *p != '\n') p++;
|
||||
if(!*p) end=1;
|
||||
*p = 0;
|
||||
TPtrC8 ptr((TUint8*) line);
|
||||
tbuf.Copy(ptr);
|
||||
editor->Text()->InsertL(editor->TextLength(), tbuf);
|
||||
editor->Text()->InsertL(editor->TextLength(), CEditableText::ELineBreak);
|
||||
line = ++p;
|
||||
}
|
||||
}
|
94
platform/uiq3/Dialogs.h
Normal file
94
platform/uiq3/Dialogs.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Dialogs.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __DIALOGS_H
|
||||
#define __DIALOGS_H
|
||||
|
||||
#include <eikenv.h>
|
||||
#include <eikdialg.h>
|
||||
#include <eiktxlbx.h>
|
||||
#include <eiktxlbm.h>
|
||||
#include <eikdlgtb.h>
|
||||
#include <eiklabel.h>
|
||||
#include <eikchlst.h>
|
||||
#include <eikchkbx.h>
|
||||
#include <eikedwob.h>
|
||||
|
||||
#include <QikSimpleDialog.h>
|
||||
|
||||
|
||||
/************************************************
|
||||
*
|
||||
* config Dialog
|
||||
*
|
||||
************************************************/
|
||||
|
||||
class TPicoConfig;
|
||||
|
||||
class CPicoConfigDialog : public CEikDialog
|
||||
{
|
||||
public:
|
||||
CPicoConfigDialog(TPicoConfig &cfg);
|
||||
|
||||
protected: // framework
|
||||
void PostLayoutDynInitL();
|
||||
void HandleControlStateChangeL(TInt aControlId);
|
||||
TBool OkToExitL(TInt aButtonId);
|
||||
|
||||
TPicoConfig &config;
|
||||
};
|
||||
|
||||
|
||||
/************************************************
|
||||
*
|
||||
* About Dialog
|
||||
*
|
||||
************************************************/
|
||||
|
||||
class CAboutDialog : public CQikSimpleDialog
|
||||
{
|
||||
protected: // from CQikSimpleDialog
|
||||
void PostLayoutDynInitL();
|
||||
};
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* Credits dialog
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class CCreditsDialog : public CQikSimpleDialog
|
||||
{
|
||||
protected: // from CQikSimpleDialog
|
||||
void PreLayoutDynInitL();
|
||||
TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
|
||||
};
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* Debug dialog
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class CDebugDialog : public CCreditsDialog
|
||||
{
|
||||
public:
|
||||
CDebugDialog(char *t);
|
||||
|
||||
protected:
|
||||
char iText[1024];
|
||||
void PreLayoutDynInitL();
|
||||
};
|
||||
|
||||
#endif // __DIALOGS_H
|
484
platform/uiq3/Engine.cpp
Normal file
484
platform/uiq3/Engine.cpp
Normal file
|
@ -0,0 +1,484 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Engine.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
|
||||
#include "Engine.h"
|
||||
#include <w32std.h>
|
||||
#include <eikenv.h>
|
||||
#include <e32svr.h>
|
||||
#include <e32math.h>
|
||||
#include <e32uid.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "../../pico/picoInt.h"
|
||||
#include "engine/debug.h"
|
||||
#include "app.h"
|
||||
|
||||
// this is where we start to break a bunch of symbian rules
|
||||
extern TInt machineUid;
|
||||
extern int gamestate, gamestate_next;
|
||||
extern TPicoConfig *currentConfig;
|
||||
extern const char *actionNames[];
|
||||
RSemaphore pauseSemaphore;
|
||||
RSemaphore initSemaphore;
|
||||
const char *RomFileName = 0;
|
||||
int pico_was_reset = 0;
|
||||
unsigned char *rom_data = 0;
|
||||
static CPicolAppView *appView = 0;
|
||||
|
||||
|
||||
TInt CPicoGameSession::Do(const TPicoServRqst what, TAny *param)
|
||||
{
|
||||
switch (what) {
|
||||
case PicoMsgLoadState:
|
||||
if(!rom_data) return -1; // no ROM
|
||||
return saveLoadGame(1);
|
||||
|
||||
case PicoMsgSaveState:
|
||||
if(!rom_data) return -1;
|
||||
return saveLoadGame(0);
|
||||
|
||||
case PicoMsgLoadROM:
|
||||
return loadROM((TPtrC16 *)param);
|
||||
|
||||
case PicoMsgResume:
|
||||
DEBUGPRINT(_L("resume with rom %08x"), rom_data);
|
||||
if(rom_data) {
|
||||
return ChangeRunState(PGS_Running);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PicoMsgReset:
|
||||
if(rom_data) {
|
||||
PicoReset(0);
|
||||
pico_was_reset = 1;
|
||||
return ChangeRunState(PGS_Running);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PicoMsgKeys:
|
||||
return ChangeRunState(PGS_KeyConfig);
|
||||
|
||||
case PicoMsgPause:
|
||||
return ChangeRunState(PGS_Paused);
|
||||
|
||||
case PicoMsgQuit:
|
||||
DEBUGPRINT(_L("got quit msg."));
|
||||
return ChangeRunState(PGS_Quit);
|
||||
|
||||
// config change
|
||||
case PicoMsgConfigChange:
|
||||
return changeConfig((TPicoConfig *)param);
|
||||
|
||||
case PicoMsgSetAppView:
|
||||
appView = (CPicolAppView *)param;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
TInt EmuThreadFunction(TAny* anArg);
|
||||
|
||||
TInt CPicoGameSession::StartEmuThread()
|
||||
{
|
||||
TInt res=KErrNone;
|
||||
iEmuRunning = EFalse;
|
||||
|
||||
if (initSemaphore.Handle() > 0)
|
||||
initSemaphore.Close();
|
||||
initSemaphore.CreateLocal(0);
|
||||
if (pauseSemaphore.Handle() <= 0)
|
||||
pauseSemaphore.CreateLocal(0);
|
||||
|
||||
RThread thread;
|
||||
if(iThreadWatcher && (res = thread.Open(iThreadWatcher->iTid)) == KErrNone) {
|
||||
// should be a dead thread in some strange state.
|
||||
DEBUGPRINT(_L("found thread with the same id (id=%i, RequestCount=%i), killing.."),
|
||||
(TInt32)thread.Id(), thread.RequestCount());
|
||||
// what can we do in this situation? Nothing seems to help, it just stays in this state.
|
||||
delete iThreadWatcher;
|
||||
iThreadWatcher = 0;
|
||||
thread.Kill(1);
|
||||
thread.Terminate(1);
|
||||
thread.Close();
|
||||
}
|
||||
|
||||
//semaphore.CreateLocal(0); // create a semaphore so we know when thread init is finished
|
||||
res=thread.Create(_L("PicoEmuThread"), // create new server thread
|
||||
EmuThreadFunction, // thread's main function
|
||||
KDefaultStackSize,
|
||||
KMinHeapSize,
|
||||
KPicoMaxHeapSize,
|
||||
0 // &semaphore // passed as TAny* argument to thread function
|
||||
);
|
||||
|
||||
if(res == KErrNone) { // thread created ok - now start it going
|
||||
thread.SetPriority(EPriorityMore);
|
||||
iEmuRunning = ETrue;
|
||||
if (iThreadWatcher) delete iThreadWatcher;
|
||||
iThreadWatcher = CThreadWatcher::NewL(thread.Id());
|
||||
thread.Resume(); // start it going
|
||||
DEBUGPRINT(_L("initSemaphore.Wait()"));
|
||||
res = initSemaphore.Wait(1000*1000); // wait until it's initialized
|
||||
DEBUGPRINT(_L("initSemaphore resume, ExitReason() == %i"), thread.ExitReason());
|
||||
res |= thread.ExitReason();
|
||||
thread.Close(); // we're no longer interested in the other thread
|
||||
if(res != KErrNone) iEmuRunning = EFalse;
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
TInt CPicoGameSession::ChangeRunState(TPicoGameState newstate, TPicoGameState newstate_next)
|
||||
{
|
||||
if (!iEmuRunning) {
|
||||
gamestate = PGS_Paused;
|
||||
TInt res = StartEmuThread();
|
||||
if(res != KErrNone) DEBUGPRINT(_L("StartEmuThread() returned %i"), res);
|
||||
if (!iEmuRunning) return PicoErrEmuThread;
|
||||
}
|
||||
|
||||
int oldstate = gamestate;
|
||||
gamestate = newstate;
|
||||
gamestate_next = newstate_next ? newstate_next : PGS_Paused;
|
||||
if (oldstate == PGS_Paused) pauseSemaphore.Signal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TInt CPicoGameSession::loadROM(TPtrC16 *pptr)
|
||||
{
|
||||
TInt res, i;
|
||||
char buff[0x31];
|
||||
|
||||
if(rom_data) {
|
||||
// save SRAM for previous ROM
|
||||
if(currentConfig->iFlags & 1)
|
||||
saveLoadGame(0, 1);
|
||||
}
|
||||
|
||||
RomFileName = 0;
|
||||
if(rom_data) {
|
||||
free(rom_data);
|
||||
rom_data = 0;
|
||||
}
|
||||
|
||||
// read the contents of the client pointer into a TPtr.
|
||||
static TBuf8<KMaxFileName> writeBuf;
|
||||
writeBuf.Copy(*pptr);
|
||||
|
||||
// detect wrong extensions (.srm and .mds)
|
||||
TBuf8<5> ext;
|
||||
ext.Copy(writeBuf.Right(4));
|
||||
ext.LowerCase();
|
||||
if(!strcmp((char *)ext.PtrZ(), ".srm") || !strcmp((char *)ext.PtrZ(), "s.gz") || // .mds.gz
|
||||
!strcmp((char *)ext.PtrZ(), ".mds")) {
|
||||
return PicoErrNotRom;
|
||||
}
|
||||
|
||||
FILE *rom = fopen((char *) writeBuf.PtrZ(), "rb");
|
||||
if(!rom) {
|
||||
DEBUGPRINT(_L("failed to open rom."));
|
||||
return PicoErrRomOpenFailed;
|
||||
}
|
||||
|
||||
// make sure emu thread is ok
|
||||
res = ChangeRunState(PGS_Paused);
|
||||
if(res) {
|
||||
fclose(rom);
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int rom_size = 0;
|
||||
// zipfile support
|
||||
if(!strcmp((char *)ext.PtrZ(), ".zip")) {
|
||||
fclose(rom);
|
||||
res = CartLoadZip((const char *) writeBuf.PtrZ(), &rom_data, &rom_size);
|
||||
if(res) {
|
||||
DEBUGPRINT(_L("CartLoadZip() failed (%i)"), res);
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
if( (res = PicoCartLoad(rom, &rom_data, &rom_size)) ) {
|
||||
DEBUGPRINT(_L("PicoCartLoad() failed (%i)"), res);
|
||||
fclose(rom);
|
||||
return PicoErrOutOfMem;
|
||||
}
|
||||
fclose(rom);
|
||||
}
|
||||
|
||||
// detect wrong files (Pico crashes on very small files), also see if ROM EP is good
|
||||
if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 ||
|
||||
((*(TUint16 *)(rom_data+4)<<16)|(*(TUint16 *)(rom_data+6))) >= (int)rom_size) {
|
||||
free(rom_data);
|
||||
rom_data = 0;
|
||||
return PicoErrNotRom;
|
||||
}
|
||||
|
||||
DEBUGPRINT(_L("PicoCartInsert(0x%08X, %d);"), rom_data, rom_size);
|
||||
if(PicoCartInsert(rom_data, rom_size)) {
|
||||
return PicoErrOutOfMem;
|
||||
}
|
||||
|
||||
pico_was_reset = 1;
|
||||
|
||||
// global ROM file name for later use
|
||||
RomFileName = (const char *) writeBuf.PtrZ();
|
||||
|
||||
// name from the ROM itself
|
||||
for(i = 0; i < 0x30; i++)
|
||||
buff[i] = rom_data[0x150 + (i^1)]; // unbyteswap
|
||||
for(buff[i] = 0, i--; i >= 0; i--) {
|
||||
if(buff[i] != ' ') break;
|
||||
buff[i] = 0;
|
||||
}
|
||||
TPtrC8 buff8((TUint8*) buff);
|
||||
iRomInternalName.Copy(buff8);
|
||||
|
||||
// load SRAM for this ROM
|
||||
if(currentConfig->iFlags & 1)
|
||||
saveLoadGame(1, 1);
|
||||
|
||||
// debug
|
||||
#ifdef __DEBUG_PRINT
|
||||
TInt cells = User::CountAllocCells();
|
||||
TInt mem;
|
||||
User::AllocSize(mem);
|
||||
DEBUGPRINT(_L("comm: cels=%d, size=%d KB"), cells, mem/1024);
|
||||
ChangeRunState(PGS_DebugHeap, PGS_Running);
|
||||
#else
|
||||
ChangeRunState(PGS_Running);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TInt CPicoGameSession::changeConfig(TPicoConfig *aConfig)
|
||||
{
|
||||
DEBUGPRINT(_L("got new config."));
|
||||
|
||||
currentConfig = aConfig;
|
||||
|
||||
// set PicoOpt and rate
|
||||
PicoRegionOverride = currentConfig->PicoRegion;
|
||||
PicoOpt = currentConfig->iPicoOpt;
|
||||
switch((currentConfig->iFlags>>3)&7) {
|
||||
case 1: PsndRate=11025; break;
|
||||
case 2: PsndRate=16000; break;
|
||||
case 3: PsndRate=22050; break;
|
||||
case 4: PsndRate=44100; break;
|
||||
default: PsndRate= 8000; break;
|
||||
}
|
||||
|
||||
// 6 button pad, enable XYZM config if needed
|
||||
if(PicoOpt & 0x20) {
|
||||
actionNames[8] = "Z";
|
||||
actionNames[9] = "Y";
|
||||
actionNames[10] = "X";
|
||||
actionNames[11] = "MODE";
|
||||
} else {
|
||||
actionNames[8] = actionNames[9] = actionNames[10] = actionNames[11] = 0;
|
||||
}
|
||||
|
||||
// if we are in center 90||270 modes, we can bind renderer switcher
|
||||
if(currentConfig->iScreenMode == TPicoConfig::PMFit &&
|
||||
(currentConfig->iScreenRotation == TPicoConfig::PRot0 || currentConfig->iScreenRotation == TPicoConfig::PRot180))
|
||||
actionNames[25] = 0;
|
||||
else actionNames[25] = "RENDERER";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void MainOldCleanup(); // from main.cpp
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
extern RMutex logMutex;
|
||||
#endif
|
||||
|
||||
void CPicoGameSession::freeResources()
|
||||
{
|
||||
RThread thread;
|
||||
TInt i;
|
||||
|
||||
DEBUGPRINT(_L("CPicoGameSession::freeResources()"));
|
||||
|
||||
if(iThreadWatcher && thread.Open(iThreadWatcher->iTid) == KErrNone)
|
||||
{
|
||||
// try to stop our emu thread
|
||||
gamestate = PGS_Quit;
|
||||
if(pauseSemaphore.Handle() > 0)
|
||||
pauseSemaphore.Signal();
|
||||
|
||||
if(thread.Handle() > 0)
|
||||
{
|
||||
// tried reopening thread handle here over time intervals to detect if thread is alive,
|
||||
// but would run into handle panics.
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
User::After(100 * 1000);
|
||||
if(thread.ExitReason() != 0) break;
|
||||
}
|
||||
|
||||
if(thread.ExitReason() == 0) {
|
||||
// too late, time to die
|
||||
DEBUGPRINT(_L("thread %i not responding, killing.."), (TInt32) thread.Id());
|
||||
thread.Terminate(1);
|
||||
}
|
||||
thread.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(iThreadWatcher != NULL)
|
||||
{
|
||||
DEBUGPRINT(_L("delete iThreadWatcher"));
|
||||
delete iThreadWatcher;
|
||||
DEBUGPRINT(_L("after delete iThreadWatcher"));
|
||||
iThreadWatcher = NULL;
|
||||
}
|
||||
|
||||
MainOldCleanup();
|
||||
|
||||
if (initSemaphore.Handle() > 0)
|
||||
initSemaphore.Close();
|
||||
if (pauseSemaphore.Handle() > 0)
|
||||
pauseSemaphore.Close();
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
if (logMutex.Handle() > 0)
|
||||
logMutex.Close();
|
||||
#endif
|
||||
}
|
||||
|
||||
TBool CPicoGameSession::iEmuRunning = EFalse;
|
||||
CThreadWatcher *CPicoGameSession::iThreadWatcher = 0;
|
||||
TBuf<0x30> CPicoGameSession::iRomInternalName;
|
||||
|
||||
|
||||
void TPicoConfig::SetDefaults()
|
||||
{
|
||||
iLastROMFile.SetLength(0);
|
||||
iScreenRotation = PRot270;
|
||||
iScreenMode = PMCenter;
|
||||
iFlags = 1; // use_sram
|
||||
iPicoOpt = 0; // all off
|
||||
iFrameskip = PFSkipAuto;
|
||||
|
||||
Mem::FillZ(iKeyBinds, sizeof(iKeyBinds));
|
||||
Mem::FillZ(iAreaBinds, sizeof(iAreaBinds));
|
||||
iKeyBinds[0xd5] = 1<<26; // bind back
|
||||
}
|
||||
|
||||
// load config
|
||||
void TPicoConfig::InternalizeL(RReadStream &aStream)
|
||||
{
|
||||
TInt32 version, fname_len;
|
||||
version = aStream.ReadInt32L();
|
||||
fname_len = aStream.ReadInt32L();
|
||||
|
||||
// not sure if this is safe
|
||||
iLastROMFile.SetMax();
|
||||
aStream.ReadL((TUint8 *) iLastROMFile.Ptr(), KMaxFileName*2);
|
||||
iLastROMFile.SetLength(fname_len);
|
||||
|
||||
iScreenRotation = aStream.ReadInt32L();
|
||||
iScreenMode = aStream.ReadInt32L();
|
||||
iFlags = aStream.ReadUint32L();
|
||||
iPicoOpt = aStream.ReadInt32L();
|
||||
iFrameskip = aStream.ReadInt32L();
|
||||
|
||||
aStream.ReadL((TUint8 *)iKeyBinds, sizeof(iKeyBinds));
|
||||
aStream.ReadL((TUint8 *)iAreaBinds, sizeof(iAreaBinds));
|
||||
|
||||
PicoRegion = aStream.ReadInt32L();
|
||||
}
|
||||
|
||||
// save config
|
||||
void TPicoConfig::ExternalizeL(RWriteStream &aStream) const
|
||||
{
|
||||
TInt version = (KPicoMajorVersionNumber<<24)+(KPicoMinorVersionNumber<<16);
|
||||
|
||||
aStream.WriteInt32L(version);
|
||||
aStream.WriteInt32L(iLastROMFile.Length());
|
||||
aStream.WriteL((const TUint8 *)iLastROMFile.Ptr(), KMaxFileName*2);
|
||||
|
||||
aStream.WriteInt32L(iScreenRotation);
|
||||
aStream.WriteInt32L(iScreenMode);
|
||||
aStream.WriteUint32L(iFlags);
|
||||
aStream.WriteInt32L(iPicoOpt);
|
||||
aStream.WriteInt32L(iFrameskip);
|
||||
|
||||
aStream.WriteL((const TUint8 *)iKeyBinds, sizeof(iKeyBinds));
|
||||
aStream.WriteL((const TUint8 *)iAreaBinds, sizeof(iAreaBinds));
|
||||
|
||||
aStream.WriteInt32L(PicoRegion);
|
||||
}
|
||||
|
||||
|
||||
// CThreadWatcher
|
||||
CThreadWatcher::~CThreadWatcher()
|
||||
{
|
||||
Cancel();
|
||||
DEBUGPRINT(_L("after CThreadWatcher::Cancel();"));
|
||||
}
|
||||
|
||||
CThreadWatcher::CThreadWatcher(const TThreadId& aTid)
|
||||
: CActive(CActive::EPriorityStandard), iTid(aTid)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CThreadWatcher* CThreadWatcher::NewL(const TThreadId& aTid)
|
||||
{
|
||||
CThreadWatcher* self = new(ELeave) CThreadWatcher(aTid);
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
CleanupStack::Pop(); // self
|
||||
return self;
|
||||
}
|
||||
|
||||
void CThreadWatcher::ConstructL()
|
||||
{
|
||||
CActiveScheduler::Add(this);
|
||||
RThread thread;
|
||||
if(thread.Open(iTid) == KErrNone) {
|
||||
thread.Logon(iStatus);
|
||||
thread.Close();
|
||||
SetActive();
|
||||
}
|
||||
}
|
||||
|
||||
void CThreadWatcher::RunL()
|
||||
{
|
||||
DEBUGPRINT(_L("CThreadWatcher::RunL()"));
|
||||
CPicoGameSession::iEmuRunning = EFalse;
|
||||
if(appView) appView->UpdateCommandList();
|
||||
//initSemaphore.Signal(); // no point to do that here, AS can't get here if it is waiting
|
||||
}
|
||||
|
||||
void CThreadWatcher::DoCancel()
|
||||
{
|
||||
RThread thread;
|
||||
DEBUGPRINT(_L("CThreadWatcher::DoCancel()"));
|
||||
if(thread.Open(iTid) == KErrNone) {
|
||||
DEBUGPRINT(_L("thread.LogonCancel(iStatus);"));
|
||||
thread.LogonCancel(iStatus);
|
||||
thread.Close();
|
||||
}
|
||||
}
|
159
platform/uiq3/Engine.h
Normal file
159
platform/uiq3/Engine.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Engine.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __ENGINE_H
|
||||
#define __ENGINE_H
|
||||
|
||||
#include <e32base.h>
|
||||
|
||||
class RReadStream;
|
||||
class RWriteStream;
|
||||
|
||||
|
||||
// engine states
|
||||
enum TPicoGameState {
|
||||
PGS_Running = 1,
|
||||
PGS_Paused,
|
||||
PGS_Quit,
|
||||
PGS_KeyConfig,
|
||||
PGS_DebugHeap,
|
||||
};
|
||||
|
||||
enum TPicoServRqst {
|
||||
PicoMsgLoadState,
|
||||
PicoMsgSaveState,
|
||||
PicoMsgLoadROM,
|
||||
PicoMsgResume,
|
||||
PicoMsgReset,
|
||||
PicoMsgKeys,
|
||||
PicoMsgPause,
|
||||
PicoMsgQuit,
|
||||
PicoMsgConfigChange,
|
||||
PicoMsgSetAppView,
|
||||
kDefaultMessageSlots // this is how many messages we need :)
|
||||
};
|
||||
|
||||
enum TPicoGenErrors { // generic errors
|
||||
PicoErrNoErr = 0, // OK
|
||||
PicoErrRomOpenFailed,
|
||||
PicoErrOutOfMem,
|
||||
PicoErrNotRom,
|
||||
PicoErrNoRomsInArchive,
|
||||
PicoErrUncomp, // 5
|
||||
PicoErrOutOfMemSnd,
|
||||
PicoErrGenSnd, // 7 generic sound system error
|
||||
PicoErrEmuThread
|
||||
};
|
||||
|
||||
|
||||
// needed for creating server thread.
|
||||
const TUint KPicoMaxHeapSize=0x00800000;
|
||||
|
||||
// key config entry (touchpad areas)
|
||||
struct TPicoAreaConfigEntry {
|
||||
TRect rect;
|
||||
//unsigned long actions;
|
||||
};
|
||||
|
||||
struct TPicoKeyConfigEntry
|
||||
{
|
||||
unsigned short keyCode;
|
||||
unsigned char scanCode;
|
||||
unsigned char flags; // lsb->msb: key_down, pulse_only, ?, ?, ?, ?, not_configurable, disabled
|
||||
TInt32 handle1; // for CancelCaptureKeyUpAndDowns()
|
||||
TInt32 handle2; // for CancelCaptureKey()
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
||||
// configuration data
|
||||
class TPicoConfig
|
||||
{
|
||||
public:
|
||||
void SetDefaults();
|
||||
void InternalizeL(RReadStream &aStream);
|
||||
void ExternalizeL(RWriteStream &aStream) const;
|
||||
|
||||
enum TPicoScreenRotation {
|
||||
PRot0,
|
||||
PRot90,
|
||||
PRot180,
|
||||
PRot270
|
||||
};
|
||||
enum TPicoScreenMode {
|
||||
PMCenter,
|
||||
PMFit,
|
||||
PMFit2
|
||||
};
|
||||
enum TPicoFrameSkip {
|
||||
PFSkipAuto = -1,
|
||||
PFSkip0
|
||||
};
|
||||
|
||||
public:
|
||||
TFileName iLastROMFile;
|
||||
|
||||
TInt32 iScreenRotation;
|
||||
TInt32 iScreenMode;
|
||||
TUint32 iFlags; // LSb->MSb: use_sram, show_fps, enable_sound, sound_rate(3bits), gzip_saves{=0x40}, dont_use_mot_vol
|
||||
// enable_ym2612&dac, enable_sn76496, enable_z80, stereo_sound;
|
||||
// alt_renderer, 6button_gamepad, accurate_timing
|
||||
TInt32 iPicoOpt;
|
||||
TInt32 iFrameskip;
|
||||
TUint32 iKeyBinds[256]; // a binding for every keycode
|
||||
TUint32 iAreaBinds[19];
|
||||
TInt32 PicoRegion;
|
||||
};
|
||||
|
||||
|
||||
class CThreadWatcher : public CActive
|
||||
{
|
||||
public:
|
||||
static CThreadWatcher* NewL(const TThreadId& aTid);
|
||||
~CThreadWatcher();
|
||||
|
||||
TThreadId iTid; // thread id
|
||||
|
||||
protected:
|
||||
CThreadWatcher(const TThreadId& aTid);
|
||||
void ConstructL();
|
||||
|
||||
virtual void RunL();
|
||||
virtual void DoCancel();
|
||||
};
|
||||
|
||||
|
||||
class CPicoGameSession
|
||||
{
|
||||
public:
|
||||
static TInt Do(const TPicoServRqst what, TAny *param=0);
|
||||
static void freeResources();
|
||||
|
||||
static TBool iEmuRunning;
|
||||
static TBuf<0x30> iRomInternalName;
|
||||
|
||||
private:
|
||||
// services available
|
||||
static TInt StartEmuThread();
|
||||
static TInt ChangeRunState(TPicoGameState newstate, TPicoGameState newstate_next=(TPicoGameState)0);
|
||||
static TInt loadROM(TPtrC16 *pptr);
|
||||
static TInt changeConfig(TPicoConfig *aConfig);
|
||||
|
||||
static CThreadWatcher *iThreadWatcher;
|
||||
};
|
||||
|
||||
// global
|
||||
int saveLoadGame(int load, int sram=0);
|
||||
|
||||
#endif
|
307
platform/uiq3/Makefile
Normal file
307
platform/uiq3/Makefile
Normal file
|
@ -0,0 +1,307 @@
|
|||
# makefile for GCCE
|
||||
|
||||
# settings
|
||||
#dprint = 1
|
||||
asm_memory = 1
|
||||
asm_render = 1
|
||||
asm_blit = 1
|
||||
#use_musashi = 1
|
||||
#up = 1
|
||||
#sis = 1
|
||||
|
||||
# targets
|
||||
all: $(EPOCROOT2)epoc32 MAKEDIRS RESOURCES PicoDrive.exe
|
||||
|
||||
clean :
|
||||
@perl -S ermdir.pl _build
|
||||
@erase 2>>nul rsc\*.rsc
|
||||
@erase 2>>nul rsc\*.rsg
|
||||
@erase 2>>nul rsc\PicoDrive.mb?
|
||||
|
||||
|
||||
# paths
|
||||
$(EPOCROOT2)epoc32 :
|
||||
@echo Please set EPOCROOT2 environmental variable to full path to your SDK
|
||||
@echo with ending slash (something like C:\Uiq_21\)
|
||||
@cd : 2> NUL # do something stupid to make it silently fail
|
||||
|
||||
# resource compiler hates drive lettered paths
|
||||
EPOCROOT2_NODRV = $(filter \\%,$(subst :, ,$(EPOCROOT2)))
|
||||
EPOCLIB = $(EPOCROOT2)EPOC32\RELEASE\ARMV5
|
||||
|
||||
# C/C++ Compiler
|
||||
CC=arm-none-symbianelf-gcc
|
||||
|
||||
# Linker
|
||||
LD=arm-none-symbianelf-ld
|
||||
|
||||
# Assembler
|
||||
ASM=arm-none-symbianelf-as
|
||||
|
||||
# Archiver
|
||||
AR=arm-none-symbianelf-ar
|
||||
|
||||
# Strip
|
||||
STRIP=arm-none-symbianelf-strip
|
||||
|
||||
# gcc config
|
||||
GCCDEFINES = -DNDEBUG -D_UNICODE -D__GCCE__ -D__SYMBIAN32__ -D__EPOC32__ -D__MARM__ \
|
||||
-D__EABI__ -D__MARM_ARMV5__ -D__EXE__ -D__SUPPORT_CPP_EXCEPTIONS__ \
|
||||
-D__MARM_ARMV5__ -D__PRODUCT_INCLUDE__=\"$(EPOCROOT2)epoc32/include/variant/UIQ_3.0.hrh\"
|
||||
|
||||
GCCDEFINES += -D_UNZIP_SUPPORT -D__BROKEN_FWRITE
|
||||
|
||||
# 'CSL Arm Toolchain' stuff must be specified after Symbian includes
|
||||
GCCINCLUDES = -I "$(EPOCROOT2)epoc32\include\variant" -I "$(EPOCROOT2)EPOC32\INCLUDE" -I "$(EPOCROOT2)EPOC32\INCLUDE\LIBC" \
|
||||
-I "$(EPOCROOT2)\CSL Arm Toolchain\lib\gcc\arm-none-symbianelf\3.4.3\include" -I.
|
||||
|
||||
# -funit-at-a-time is not compatible with SDK, it either has linker problems or does not start on device
|
||||
GCCCOMMFLAGS = -Wall -Wno-unknown-pragmas -fexceptions -march=armv5t -mapcs -pipe -nostdinc -msoft-float \
|
||||
$(GCCINCLUDES) -include "$(EPOCROOT2)EPOC32/INCLUDE/GCCE/GCCE.h" -marm
|
||||
|
||||
GCCCPPFLAGS = -x c++ -Wno-ctor-dtor-privacy -O3 -fno-unit-at-a-time
|
||||
GCCCFLAGS = -x c -O3 -fno-unit-at-a-time
|
||||
|
||||
GCCLDFLAGS = -L"$(EPOCROOT2)CSL Arm Toolchain\arm-none-symbianelf\lib" \
|
||||
-L"$(EPOCROOT2)CSL Arm Toolchain\lib\gcc\arm-none-symbianelf\3.4.3" \
|
||||
--target1-abs --no-undefined -nostdlib -shared -Ttext 0x8000 -Tdata 0x400000 --default-symver
|
||||
|
||||
# libs
|
||||
LIBS = \
|
||||
$(EPOCLIB)\LIB\ESTLIB.dso \
|
||||
$(EPOCLIB)\urel\qikalloc.lib \
|
||||
$(EPOCLIB)\LIB\euser.dso \
|
||||
$(EPOCLIB)\LIB\apparc.dso \
|
||||
$(EPOCLIB)\LIB\cone.dso \
|
||||
$(EPOCLIB)\LIB\eikcore.dso \
|
||||
$(EPOCLIB)\LIB\eikcoctl.dso \
|
||||
$(EPOCLIB)\LIB\qikcore.dso \
|
||||
$(EPOCLIB)\LIB\qikdlg.dso \
|
||||
$(EPOCLIB)\LIB\etext.dso \
|
||||
$(EPOCLIB)\LIB\bafl.dso \
|
||||
$(EPOCLIB)\LIB\efsrv.dso \
|
||||
$(EPOCLIB)\LIB\eikctl.dso \
|
||||
$(EPOCLIB)\LIB\WS32.dso \
|
||||
$(EPOCLIB)\LIB\EIKDLG.dso \
|
||||
$(EPOCLIB)\LIB\GDI.dso \
|
||||
$(EPOCLIB)\LIB\estor.dso \
|
||||
$(EPOCLIB)\LIB\EZLIB.dso \
|
||||
$(EPOCLIB)\LIB\HAL.dso \
|
||||
$(EPOCLIB)\LIB\mediaclient.dso \
|
||||
$(EPOCLIB)\LIB\mediaclientaudiostream.dso
|
||||
|
||||
LIBS += \
|
||||
$(EPOCLIB)\LIB\qikallocdll.dso \
|
||||
$(EPOCLIB)\UREL\usrt2_2.lib \
|
||||
$(EPOCLIB)\LIB\dfpaeabi.dso \
|
||||
$(EPOCLIB)\LIB\dfprvct2_2.dso \
|
||||
$(EPOCLIB)\LIB\drtaeabi.dso \
|
||||
$(EPOCLIB)\LIB\scppnwdl.dso \
|
||||
$(EPOCLIB)\LIB\drtrvct2_2.dso
|
||||
|
||||
|
||||
# objects
|
||||
|
||||
# launcher
|
||||
OBJECTS += _build\App.o _build\Engine.o _build\Dialogs.o _build\CSimpleTextParser.o
|
||||
# engine
|
||||
OBJECTS += _build\main.o _build\vid.o _build\polledas.o _build\audio_mediaserver.o _build\debug.o
|
||||
|
||||
# Pico
|
||||
OBJECTS += _build\Area.o _build\Cart.o _build\Utils.o _build\Memory.o _build\Misc.o \
|
||||
_build\Pico.o _build\Sek.o _build\VideoPort.o _build\Draw2.o _build\Draw.o
|
||||
# asm stuff
|
||||
ifeq "$(asm_render)" "1"
|
||||
GCCDEFINES += -D_ASM_DRAW_C
|
||||
OBJECTS += _build\draw_asm.o _build\draw2_asm.o
|
||||
endif
|
||||
ifeq "$(asm_memory)" "1"
|
||||
GCCDEFINES += -D_ASM_MEMORY_C
|
||||
OBJECTS += _build\memory_asm.o
|
||||
endif
|
||||
# Pico - sound
|
||||
OBJECTS += _build\sound.o _build\sn76496.o _build\ym2612.o
|
||||
# misc
|
||||
OBJECTS += _build\unzip.o _build\gzio_symb.o
|
||||
# CPU cores
|
||||
ifeq "$(use_musashi)" "1"
|
||||
GCCDEFINES += -DEMU_M68K
|
||||
OBJECTS += _build\m68kcpu.o _build\m68kopac.o _build\m68kopdm.o _build\m68kopnz.o _build\m68kops.o
|
||||
else
|
||||
GCCDEFINES += -DEMU_C68K
|
||||
OBJECTS += _build\Cyclone.o
|
||||
endif
|
||||
ifeq "$(asm_blit)" "1"
|
||||
OBJECTS += _build\blit_asm.o
|
||||
else
|
||||
OBJECTS += _build\blit.o
|
||||
endif
|
||||
GCCDEFINES += -D_USE_DRZ80
|
||||
OBJECTS += _build\DrZ80.o
|
||||
GCCDEFINES += -D_ASM_YM2612_C
|
||||
OBJECTS += _build\ym2612_asm.o
|
||||
|
||||
|
||||
|
||||
# dprint
|
||||
ifeq "$(dprint)" "1"
|
||||
GCCDEFINES += -D__DEBUG_PRINT
|
||||
endif
|
||||
|
||||
|
||||
define crule
|
||||
@echo * $<
|
||||
@$(CC) -c $(GCCCOMMFLAGS) $(GCCDEFINES) $(GCCCFLAGS) $< -o $@
|
||||
endef
|
||||
|
||||
define cpprule
|
||||
@echo * $<
|
||||
@$(CC) -c $(GCCCOMMFLAGS) $(GCCDEFINES) $(GCCCPPFLAGS) $< -o $@
|
||||
endef
|
||||
|
||||
define asmrule
|
||||
@echo * $<
|
||||
@$(ASM) -marmv4t -mthumb-interwork -o $@ $^
|
||||
endef
|
||||
|
||||
# object making rules
|
||||
_build\App.o : App.cpp
|
||||
$(cpprule)
|
||||
_build\Engine.o : Engine.cpp
|
||||
$(cpprule)
|
||||
_build\Dialogs.o : Dialogs.cpp
|
||||
$(cpprule)
|
||||
_build\CSimpleTextParser.o : CSimpleTextParser.cpp
|
||||
$(cpprule)
|
||||
|
||||
_build\main.o : engine\main.cpp
|
||||
$(cpprule)
|
||||
_build\vid.o : engine\vid.cpp
|
||||
$(cpprule)
|
||||
_build\polledas.o: engine\polledas.cpp
|
||||
$(cpprule)
|
||||
_build\audio_mediaserver.o : engine\audio_mediaserver.cpp
|
||||
$(cpprule)
|
||||
_build\debug.o : engine\debug.cpp
|
||||
$(cpprule)
|
||||
_build\blit.o : engine\blit.c
|
||||
$(crule)
|
||||
|
||||
_build\Area.o : ..\..\Pico\Area.c
|
||||
$(crule)
|
||||
_build\Cart.o : ..\..\Pico\Cart.c
|
||||
$(crule)
|
||||
_build\Draw.o : ..\..\Pico\Draw.c
|
||||
$(crule)
|
||||
_build\Draw2.o : ..\..\Pico\Draw2.c
|
||||
$(crule)
|
||||
_build\Memory.o : ..\..\Pico\Memory.c
|
||||
$(crule)
|
||||
_build\Misc.o : ..\..\Pico\Misc.c
|
||||
$(crule)
|
||||
_build\Pico.o : ..\..\Pico\Pico.c
|
||||
$(crule)
|
||||
_build\Sek.o : ..\..\Pico\Sek.c
|
||||
$(crule)
|
||||
_build\Utils.o : ..\..\Pico\Utils.c
|
||||
$(crule)
|
||||
_build\VideoPort.o : ..\..\Pico\VideoPort.c
|
||||
$(crule)
|
||||
_build\sound.o : ..\..\Pico\sound\sound.c
|
||||
$(crule)
|
||||
_build\sn76496.o : ..\..\Pico\sound\sn76496.c
|
||||
$(crule)
|
||||
_build\ym2612.o : ..\..\Pico\sound\ym2612.c
|
||||
$(crule)
|
||||
|
||||
_build\unzip.o : ..\..\unzip\unzip.c
|
||||
$(crule)
|
||||
_build\gzio_symb.o : ..\..\zlib\gzio_symb.c
|
||||
$(crule)
|
||||
|
||||
_build\m68kcpu.o : ..\..\musashi\m68kcpu.c
|
||||
$(crule)
|
||||
_build\m68kopac.o : ..\..\musashi\m68kopac.c
|
||||
$(crule)
|
||||
_build\m68kopdm.o : ..\..\musashi\m68kopdm.c
|
||||
$(crule)
|
||||
_build\m68kopnz.o : ..\..\musashi\m68kopnz.c
|
||||
$(crule)
|
||||
_build\m68kops.o : ..\..\musashi\m68kops.c
|
||||
$(crule)
|
||||
|
||||
_build\Cyclone.o : ..\..\cpu\Cyclone\proj\Cyclone.s
|
||||
$(asmrule)
|
||||
_build\DrZ80.o : ..\..\cpu\DrZ80\drz80.s
|
||||
$(asmrule)
|
||||
_build\draw_asm.o : ..\..\Pico\draw.s
|
||||
$(asmrule)
|
||||
_build\draw2_asm.o : ..\..\Pico\draw2.s
|
||||
$(asmrule)
|
||||
_build\memory_asm.o : ..\..\Pico\memory.s
|
||||
$(asmrule)
|
||||
_build\ym2612_asm.o : ..\..\Pico\sound\ym2612.s
|
||||
$(asmrule)
|
||||
_build\blit_asm.o : engine\blit.s
|
||||
$(asmrule)
|
||||
|
||||
|
||||
PicoDrive.exe : $(OBJECTS)
|
||||
@echo * ld
|
||||
@$(LD) $(GCCLDFLAGS) -soname PicoDrive{000a0000}[a00010f3].exe --entry _E32Startup -u _E32Startup \
|
||||
$(EPOCROOT2)EPOC32\RELEASE\ARMV5\UREL\EEXE.LIB -o "_build\PicoDrive_elf.exe" -Map "_build\PicoDrive.exe.map" $(OBJECTS) $(LIBS) -lsupc++ -lgcc
|
||||
# @echo * strip
|
||||
# @$(STRIP) _build\PicoDrive_elf.exe
|
||||
@echo * elf2e32
|
||||
@elf2e32 --sid=0xa00010f3 --heap=0x00000100,0x00800000 --stack=0x00003000 \
|
||||
--uid1=0x1000007a --uid2=0x100039ce --uid3=0xa00010f3 \
|
||||
--capability=none --fpu=softvfp --targettype=EXE --output="$@" \
|
||||
--elfinput="_build\PicoDrive_elf.exe" --linkas=PicoDrive{000a0000}[a00010f3].exe --libpath="$(EPOCLIB)\LIB"
|
||||
ifeq "$(sis)" "1"
|
||||
@make -C _out
|
||||
ifeq "$(up)" "1"
|
||||
@qup.cmd
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
MAKEDIRS : _build
|
||||
|
||||
_build :
|
||||
# @echo * making build dir
|
||||
@perl -S emkdir.pl $@
|
||||
|
||||
|
||||
# BitMap PicoDrive.mbm
|
||||
|
||||
RESOURCES : rsc\PicoDrive.mbm rsc\PicoDrive.RSC rsc\PicoDrive_reg.RSC rsc\PicoDrive_loc.RSC rsc\PicoDrive.mbg
|
||||
|
||||
rsc\PicoDrive.mbg : rsc\PicoDrive.mbm
|
||||
|
||||
rsc\PicoDrive.mbm : rsc\pico18x18.bmp rsc\pico18x18m.bmp rsc\pico40x40.bmp rsc\pico40x40m.bmp rsc\pico64x64.bmp rsc\pico64x64m.bmp
|
||||
@echo * $@
|
||||
@perl -S epocmbm.pl -h"rsc\PicoDrive.mbg" -o"rsc\PicoDrive.mbm" -l"\Z\Resource\Apps\:rsc" \
|
||||
-b"/c24rsc\pico18x18.bmp /8rsc\pico18x18m.bmp /c24rsc\pico40x40.bmp /8rsc\pico40x40m.bmp /c24rsc\pico64x64.bmp /8rsc\pico64x64m.bmp" -l"\Z\Resource\Apps\:rsc"
|
||||
@perl -S ecopyfile.pl "rsc\PicoDrive.mbg" "$(EPOCROOT2)EPOC32\INCLUDE\PicoDrive.mbg"
|
||||
|
||||
# Resource Z\Resource\Apps\PicoDrive.RSC
|
||||
|
||||
rsc\PicoDrive.RSC : rsc\PicoDrive.rss picodrive.hrh
|
||||
@echo * $@
|
||||
@perl -S epocrc.pl -m045,046,047 -I "." -I- -I "$(EPOCROOT2_NODRV)EPOC32\include" -DLANGUAGE_SC -u "rsc\PicoDrive.rss" -o$@ \
|
||||
-h"rsc\PicoDrive.rsg" -t"rsc" -l"Z\Resource\Apps:rsc"
|
||||
@perl -S ecopyfile.pl "rsc\PicoDrive.rsg" "$(EPOCROOT2)EPOC32\INCLUDE\PicoDrive.RSG"
|
||||
|
||||
# Resource Z\private\10003a3f\apps\PicoDrive_reg.RSC
|
||||
|
||||
rsc\PicoDrive_reg.RSC : rsc\PicoDrive_reg.rss
|
||||
@echo * $@
|
||||
@perl -S epocrc.pl -m045,046,047 -I "." -I- -I "$(EPOCROOT2)EPOC32\include" -DLANGUAGE_SC -u "rsc\PicoDrive_reg.rss" -o$@ \
|
||||
-t"rsc" -l"Z\private\10003a3f\apps:rsc"
|
||||
|
||||
# Resource Z\Resource\Apps\PicoDrive_loc.RSC
|
||||
|
||||
rsc\PicoDrive_loc.RSC : rsc\PicoDrive_loc.rss
|
||||
@echo * $@
|
||||
@perl -S epocrc.pl -m045,046,047 -I "." -I- -I "$(EPOCROOT2)EPOC32\include" -DLANGUAGE_SC -u "rsc\PicoDrive_loc.rss" -o$@ \
|
||||
-t"rsc" -l"Z\Resource\Apps:rsc"
|
78
platform/uiq3/PicoDrive.hrh
Normal file
78
platform/uiq3/PicoDrive.hrh
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
enum TAppMenuCommands
|
||||
{
|
||||
// Emu menu
|
||||
EEikCmdPicoMain = 10000,
|
||||
EEikCmdPicoResume,
|
||||
EEikCmdPicoLoadState,
|
||||
EEikCmdPicoSaveState,
|
||||
EEikCmdPicoLoadROM,
|
||||
EEikCmdPicoReset,
|
||||
EEikCmdPicoConfig,
|
||||
EEikCmdPicoKeys,
|
||||
EEikCmdPicoSettings,
|
||||
|
||||
// Frameskip submenu
|
||||
EEikCmdPicoFrameskip,
|
||||
EEikCmdPicoFrameskipAuto,
|
||||
EEikCmdPicoFrameskip0,
|
||||
EEikCmdPicoFrameskip1,
|
||||
EEikCmdPicoFrameskip2,
|
||||
EEikCmdPicoFrameskip4,
|
||||
EEikCmdPicoFrameskip8,
|
||||
|
||||
// Debug menu
|
||||
EEikCmdPicoDebug,
|
||||
// EEikCmdPicoDebugKillEmu,
|
||||
EEikCmdPicoDebugInfo,
|
||||
|
||||
// config Dialog
|
||||
ECtlOptDone,
|
||||
// pages
|
||||
ECtlOptPageMain,
|
||||
ECtlOptPageSound,
|
||||
ECtlOptPageMisc,
|
||||
// main page
|
||||
ECtlOptRotationLabel,
|
||||
ECtlOptRotation,
|
||||
ECtlOptRotation0,
|
||||
ECtlOptRotation90,
|
||||
ECtlOptRotation180,
|
||||
ECtlOptRotation270,
|
||||
ECtlOptScreenModeLabel,
|
||||
ECtlOptScreenMode,
|
||||
ECtlOptScreenModeCenter,
|
||||
ECtlOptScreenModeFit,
|
||||
ECtlOptScreenModeFit2,
|
||||
ECtlOptUseAltRend,
|
||||
ECtlOptUseAccTiming,
|
||||
ECtlOptUseAccSprites,
|
||||
ECtlOptShowFPS,
|
||||
// sound page
|
||||
ECtlOptEnableSound,
|
||||
ECtlOptChipSelLabel,
|
||||
ECtlOptEmulateZ80,
|
||||
ECtlOptEmulateYM2612,
|
||||
ECtlOptEmulateSN76496,
|
||||
ECtlOptSndQLabel,
|
||||
ECtlOptSndQuality,
|
||||
// misc page
|
||||
ECtlOpt6ButtonPad,
|
||||
ECtlOptGzipStates,
|
||||
ECtlOptUseSRAM,
|
||||
ECtlOptMotDontUseVol,
|
||||
ECtlOptRegion,
|
||||
// about dialog
|
||||
EEikCmdPicoAboutDoneCmd,
|
||||
EEikCmdPicoAboutCreditsCmd,
|
||||
ECtlPicoAboutText,
|
||||
// credits
|
||||
ECtlPicoCreditsText,
|
||||
// debug
|
||||
ECtlDebugEdit
|
||||
};
|
||||
|
||||
|
||||
#define ECtlAboutVersion 1
|
||||
#define ECtlAboutLinks 2
|
||||
|
140
platform/uiq3/PicoDrive.mmp
Normal file
140
platform/uiq3/PicoDrive.mmp
Normal file
|
@ -0,0 +1,140 @@
|
|||
TARGET PicoDrive.exe
|
||||
TARGETTYPE exe
|
||||
//TARGETPATH ?
|
||||
UID 0x100039CE 0xA00010F3
|
||||
EPOCSTACKSIZE 0x3000 // required by CQikSelectFileDlg
|
||||
EPOCHEAPSIZE 0x100 0x00800000 // required by large ROMs :)
|
||||
|
||||
// resource
|
||||
SOURCEPATH Rsc
|
||||
START RESOURCE PicoDrive.rss
|
||||
HEADER
|
||||
TARGETPATH \Resource\Apps
|
||||
LANG SC
|
||||
END
|
||||
|
||||
START RESOURCE PicoDrive_reg.rss
|
||||
TARGETPATH \private\10003a3f\apps
|
||||
END
|
||||
|
||||
START RESOURCE PicoDrive_loc.rss
|
||||
TARGETPATH \Resource\Apps
|
||||
LANG SC
|
||||
END
|
||||
|
||||
CAPABILITY none // SwEvent // forbidden
|
||||
|
||||
USERINCLUDE ..\..
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
|
||||
// launcher
|
||||
SOURCEPATH .
|
||||
SYSTEMINCLUDE . // for port_config.h
|
||||
SOURCE App.cpp
|
||||
SOURCE Engine.cpp
|
||||
SOURCE Dialogs.cpp
|
||||
SOURCE CSimpleTextParser.cpp
|
||||
|
||||
// engine
|
||||
SOURCEPATH engine
|
||||
SOURCE main.cpp
|
||||
SOURCE vid.cpp
|
||||
SOURCE polledas.cpp
|
||||
SOURCE debug.cpp
|
||||
SOURCE audio_mediaserver.cpp
|
||||
SOURCE blit.c
|
||||
|
||||
// pico
|
||||
MACRO _UNZIP_SUPPORT
|
||||
SOURCEPATH ..\..\Pico
|
||||
USERINCLUDE ..\..\Pico
|
||||
SOURCE Area.c
|
||||
SOURCE Cart.c
|
||||
SOURCE Draw.c
|
||||
SOURCE Draw2.c
|
||||
SOURCE Memory.c
|
||||
SOURCE Misc.c
|
||||
SOURCE Pico.c
|
||||
SOURCE Sek.c
|
||||
SOURCE Utils.c
|
||||
SOURCE VideoPort.c
|
||||
|
||||
// pico - sound
|
||||
SOURCEPATH ..\..\Pico\Sound
|
||||
SOURCE sound.c
|
||||
SOURCE sn76496.c
|
||||
SOURCE ym2612.c
|
||||
|
||||
// CPU cores
|
||||
MACRO EMU_M68K
|
||||
SOURCEPATH ..\..\cpu\Musashi
|
||||
USERINCLUDE ..\..\cpu\Musashi
|
||||
SOURCE m68kcpu.c
|
||||
SOURCE m68kopac.c
|
||||
SOURCE m68kopdm.c
|
||||
SOURCE m68kopnz.c
|
||||
SOURCE m68kops.c
|
||||
|
||||
//MACRO _USE_MZ80
|
||||
//SOURCEPATH ..\win32\z80
|
||||
//SOURCE mz80_asm.obj
|
||||
|
||||
// misc
|
||||
SOURCEPATH ..\..\unzip
|
||||
USERINCLUDE ..\..\unzip
|
||||
SOURCE unzip.c
|
||||
SOURCEPATH ..\..\zlib
|
||||
USERINCLUDE ..\..\zlib
|
||||
SOURCE gzio_symb.c
|
||||
|
||||
|
||||
// TODO: get rid of unneeded stuff
|
||||
LIBRARY ESTLIB.LIB
|
||||
LIBRARY euser.lib
|
||||
LIBRARY apparc.lib
|
||||
LIBRARY cone.lib
|
||||
LIBRARY eikcore.lib
|
||||
LIBRARY eikcoctl.lib
|
||||
LIBRARY qikcore.lib
|
||||
LIBRARY qikdlg.lib // CQikSelectFileDlg
|
||||
LIBRARY etext.lib // TCharFormat
|
||||
LIBRARY bafl.lib // CDesCArrayFlat
|
||||
LIBRARY efsrv.lib
|
||||
LIBRARY eikctl.lib
|
||||
|
||||
LIBRARY WS32.LIB
|
||||
LIBRARY EIKDLG.LIB
|
||||
//LIBRARY EGUL.LIB // CColorList
|
||||
LIBRARY GDI.LIB // TTypeface
|
||||
LIBRARY estor.lib // RWriteStream
|
||||
|
||||
LIBRARY EZLIB.LIB
|
||||
LIBRARY HAL.LIB
|
||||
|
||||
LIBRARY mediaclient.LIB
|
||||
LIBRARY mediaclientaudiostream.LIB
|
||||
|
||||
|
||||
|
||||
STATICLIBRARY qikalloc.lib
|
||||
LIBRARY qikallocdll.lib
|
||||
|
||||
|
||||
MACRO __DEBUG_PRINT
|
||||
MACRO __BROKEN_FWRITE
|
||||
|
||||
|
||||
USERINCLUDE .
|
||||
START BITMAP PicoDrive.mbm
|
||||
HEADER
|
||||
TARGETPATH \Resource\Apps
|
||||
SOURCEPATH Rsc
|
||||
SOURCE c24 Pico18x18.bmp
|
||||
SOURCE 8 Pico18x18m.bmp
|
||||
SOURCE c24 Pico40x40.bmp
|
||||
SOURCE 8 Pico40x40m.bmp
|
||||
SOURCE c24 Pico64x64.bmp
|
||||
SOURCE 8 Pico64x64m.bmp
|
||||
END
|
7
platform/uiq3/_out/Makefile
Normal file
7
platform/uiq3/_out/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
all: PicoDrive.SIS
|
||||
|
||||
PicoDrive.SIS: ..\PicoDrive.exe ..\rsc\PicoDrive.rsc ..\rsc\PicoDrive.mbm ..\rsc\PicoDrive_loc.rsc ..\rsc\PicoDrive_reg.rsc
|
||||
makesis PicoDrive.pkg
|
||||
|
||||
clean:
|
||||
@erase 2>>nul PicoDrive.pkg
|
25
platform/uiq3/_out/PicoDrive.pkg
Normal file
25
platform/uiq3/_out/PicoDrive.pkg
Normal file
|
@ -0,0 +1,25 @@
|
|||
;
|
||||
|
||||
; List of localised vendor names - one per language. At least one must be provided (English [EN]).
|
||||
; List must correspond to list of languages specified elsewhere in the .pkg
|
||||
%{"notaz"}
|
||||
|
||||
; The non-localised, globally unique vendor name (mandatory)
|
||||
:"notaz"
|
||||
|
||||
; Package header
|
||||
; Name, UID3, Major, Minor, Build, Package-type
|
||||
#{"PicoDrive"}, (0xA00010F3), 0, 96, 0, TYPE=SA
|
||||
|
||||
; ProductID for UIQ 3.0
|
||||
; Product/platform version UID, Major, Minor, Build, Component name
|
||||
(0x101F6300), 3, 0, 0, {"UIQ30ProductID"}
|
||||
|
||||
|
||||
; Files to install for the application
|
||||
; If you move the example to another destination then you also need to change these paths.
|
||||
"..\PicoDrive.exe"-"!:\sys\bin\PicoDrive.exe"
|
||||
"..\rsc\PicoDrive.rsc"-"!:\resource\apps\PicoDrive.rsc"
|
||||
"..\rsc\PicoDrive.mbm"-"!:\resource\apps\PicoDrive.mbm"
|
||||
"..\rsc\PicoDrive_loc.rsc"-"!:\resource\apps\PicoDrive_loc.rsc"
|
||||
"..\rsc\PicoDrive_reg.rsc"-"!:\private\10003a3f\import\apps\PicoDrive_reg.rsc"
|
BIN
platform/uiq3/_out/PicoDrive.zip
Normal file
BIN
platform/uiq3/_out/PicoDrive.zip
Normal file
Binary file not shown.
25
platform/uiq3/_out/PicoDrive_gcce.pkg
Normal file
25
platform/uiq3/_out/PicoDrive_gcce.pkg
Normal file
|
@ -0,0 +1,25 @@
|
|||
;
|
||||
|
||||
; List of localised vendor names - one per language. At least one must be provided (English [EN]).
|
||||
; List must correspond to list of languages specified elsewhere in the .pkg
|
||||
%{"notaz"}
|
||||
|
||||
; The non-localised, globally unique vendor name (mandatory)
|
||||
:"notaz"
|
||||
|
||||
; Package header
|
||||
; Name, UID3, Major, Minor, Build, Package-type
|
||||
#{"PicoDrive"}, (0xA00010F3), 0, 92, 0, TYPE=SA
|
||||
|
||||
; ProductID for UIQ 3.0
|
||||
; Product/platform version UID, Major, Minor, Build, Component name
|
||||
(0x101F6300), 3, 0, 0, {"UIQ30ProductID"}
|
||||
|
||||
|
||||
; Files to install for the application
|
||||
; If you move the example to another destination then you also need to change these paths.
|
||||
"..\..\..\..\..\..\UIQ3SDK\epoc32\release\gcce\urel\PicoDrive.exe"-"!:\sys\bin\PicoDrive.exe"
|
||||
"..\..\..\..\..\..\UIQ3SDK\epoc32\data\Z\Resource\Apps\PicoDrive.rsc"-"!:\resource\apps\PicoDrive.rsc"
|
||||
"..\..\..\..\..\..\UIQ3SDK\epoc32\data\Z\Resource\Apps\PicoDrive_loc.rsc"-"!:\resource\apps\PicoDrive_loc.rsc"
|
||||
"..\..\..\..\..\..\UIQ3SDK\epoc32\data\z\Private\10003a3f\Apps\PicoDrive_reg.rsc"-"!:\private\10003a3f\import\apps\PicoDrive_reg.rsc"
|
||||
"..\..\..\..\..\..\UIQ3SDK\epoc32\data\Z\Resource\Apps\PicoDrive.mbm"-"!:\resource\apps\PicoDrive.mbm"
|
110
platform/uiq3/_out/config.txt
Normal file
110
platform/uiq3/_out/config.txt
Normal file
|
@ -0,0 +1,110 @@
|
|||
1. Keys:
|
||||
|
||||
If it looks confusing to you, check this tutorial first:
|
||||
http://notaz.atspace.com/pico_tut/
|
||||
|
||||
There are no default settings.
|
||||
When you start key configuration mode, black screen with dark-red squares will
|
||||
appear. Also there will be little 'control' on the top with the function
|
||||
name in it, and arrows on the corners of it. You can tap on these corners to
|
||||
select a function. You can also tap on these squares to bind that function to
|
||||
them. This way you can associate touchpad areas with game-controls or functions.
|
||||
I also made a small square in every corner of the screen to be used as a virtual
|
||||
button for some function, like save state. You can bind it as you like. To
|
||||
bind phone buttons, simply select the function you need, and press a button
|
||||
you want. To unbind any key or touchpad area, simply push or tap it again.
|
||||
|
||||
When finished, select 'done' and press any key. You can also press 'Power'
|
||||
to exit.
|
||||
|
||||
You need to bind 'pause emu' function to be able exit game when ROM is loaded.
|
||||
It is bound to 'back' button by default.
|
||||
|
||||
2. Main Settings:
|
||||
|
||||
Here you can set the orientation of screen and the drawing mode. The "fit"
|
||||
option will scale the image so it better fits in the screen, but some detail
|
||||
will be lost. "center" displays the game at the center of the screen, but
|
||||
non-fitting parts are not visible then. "fit2" is simmilar to "fit" but is
|
||||
a bit more stretched (fit modes are only meaningful in 0 or 180 rotation
|
||||
modes).
|
||||
|
||||
"Fast renderer" enables faster rendering method, but it works only with some
|
||||
games (some other have serious glitches or even hang).
|
||||
|
||||
"Accurate timing" is needed for some games to run (like Red Zone). It should
|
||||
be kept off for all other games, because it slows emulation down. Some games
|
||||
also need this option for proper sound, so enable this if game has any
|
||||
glitches.
|
||||
|
||||
"Accurate sprites" fixes sprite priority problems, for example if game
|
||||
character is in front of or behind some object it should not be, this option
|
||||
should fix it. This option does not work in "Fast renderer" mode.
|
||||
|
||||
"Show FPS" shows game frames per second in format XX/YY, where XX is the
|
||||
number of frames shown per previous second, and YY is the number of frames
|
||||
emulated, but not necessarily shown. By calculating YY-XX you get the number
|
||||
of skipped frames per second.
|
||||
|
||||
3. Sound settings:
|
||||
|
||||
Sound emulation is very picky on CPU power (in most cases sound alone uses
|
||||
more CPU power than everything else altogether), but it is still possible to
|
||||
play some games. When using sound, the recommended display modes are "fit 0"
|
||||
and "fit 180", because these are the fastest ones. Also try "Alternative
|
||||
renderer", but it might cause graphical glitches. You must use auto frameskip
|
||||
when using sound, or else you will get stuttering sound. Also, it is
|
||||
recommended to exit all other non-vital apps (you can use SMan for this),
|
||||
disable bluetooth and any other devices your phone may have. I also noticed
|
||||
that simply connecting the phone battery charger strangely slows everything
|
||||
down.
|
||||
|
||||
"Enable sound" tries to enable sound output on your device, but that alone is
|
||||
not enough to get sound. You need to enable the sound chips below:
|
||||
"Z80" is secondary CPU in genesis and is mostly used to control the other 2
|
||||
sound chips. So if you disable Z80, sound will be lost in most games, with
|
||||
some exceptions like Sonic1. It is possible to use Z80 for other things,
|
||||
some games do that and Z80 must be enabled to run them at all.
|
||||
|
||||
"YM2612" is a fairly complex Frequency Modulation (FM) sound synthesis chip.
|
||||
It was the main sound output device in genesis and is horrible CPU hog when
|
||||
is tried to be emulated in software. Disabling it gives large speed
|
||||
improvement, but most of the sound is lost.
|
||||
|
||||
"SN76496" is programmable sound generator (PSG) chip, used for various sound
|
||||
effects and music elements.
|
||||
|
||||
Note: if you change sound settings AFTER loading a ROM, you may need to reset
|
||||
game to get sound. This is because most games initialize sound chips on
|
||||
startup, and this data is lost when sound chips are being enabled/disabled.
|
||||
|
||||
4. Misc:
|
||||
|
||||
"6 button pad" will enable 6 button gamepad emulation and will add additional
|
||||
X, Y, Z and MODE actions to key configuration.
|
||||
Note: if you enable this, games may detect that and use different button
|
||||
configuration, for example A ("high punch") will change to "low punch" in
|
||||
Mortal Kombat and you will need to bind X for "high punch".
|
||||
|
||||
"gzip save states" enables gzip (similar to ordinary zip, but a little
|
||||
different) compression on your save states to save space. The compression
|
||||
ratio is 50-90%, so it's worth to enable this.
|
||||
|
||||
"Use SRAM saves" option enables emulation of batery-backed save RAM some game
|
||||
cartridges had. RPG games used it alot, but there were some others too, like
|
||||
Sonic 3. If this is enabled, <ROMname>.srm files are generated when you exit
|
||||
the emulator or load another ROM. Format is compatible with other popular
|
||||
emulators (like Gens and Fusion).
|
||||
|
||||
"Region" lets you set the region of emulated genesis machine.
|
||||
|
||||
|
||||
5. Frameskip:
|
||||
|
||||
"Auto" option tries to run the game in it's original speed by skipping next
|
||||
frame if the previous was rendered too slow.
|
||||
"0" displays every frame, thus game runs very slow, sound skips.
|
||||
"1" skips every other frame. Use this for a game which is smoother, but a bit
|
||||
too slow (actually depends on display mode you use).
|
||||
"2" also makes the game smoother, but it will be too fast in most areas.
|
||||
"4","8" similar to above, but skips more frames and often becomes choppy.
|
32
platform/uiq3/engine/PolledAS.h
Normal file
32
platform/uiq3/engine/PolledAS.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: PolledAS.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* (c) Copyright 2001, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __POLLED_AS_H
|
||||
#define __POLLED_AS_H
|
||||
|
||||
class CPrivatePolledActiveScheduler;
|
||||
|
||||
class CPolledActiveScheduler : public CBase
|
||||
{
|
||||
public:
|
||||
~CPolledActiveScheduler();
|
||||
static CPolledActiveScheduler* NewL();
|
||||
static CPolledActiveScheduler* Instance();
|
||||
void Schedule();
|
||||
protected:
|
||||
CPolledActiveScheduler(){};
|
||||
void ConstructL();
|
||||
CPrivatePolledActiveScheduler* iPrivatePolledActiveScheduler;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __POLLED_AS_H */
|
||||
|
293
platform/uiq3/engine/audio_mediaserver.cpp
Normal file
293
platform/uiq3/engine/audio_mediaserver.cpp
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Audio_mediaserver.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2001, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "audio_mediaserver.h"
|
||||
#include "debug.h"
|
||||
|
||||
//#undef DEBUGPRINT
|
||||
//#define DEBUGPRINT(x...)
|
||||
|
||||
|
||||
const TInt KUpdatesPerSec = 10;
|
||||
const TInt KBlockTime = 1000000 / KUpdatesPerSec;
|
||||
const TInt KMaxLag = 200000; // max sound lag, lower values increase chance of underflow
|
||||
const TInt KMaxUnderflows = 50; // max underflows/API errors we are going allow in a row (to prevent lockups)
|
||||
|
||||
|
||||
/*******************************************
|
||||
*
|
||||
* CGameAudioMS
|
||||
*
|
||||
*******************************************/
|
||||
|
||||
CGameAudioMS::CGameAudioMS(TInt aRate, TBool aStereo, TInt aWritesPerSec)
|
||||
: iRate(aRate), iStereo(aStereo), iWritesPerSec(aWritesPerSec)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CGameAudioMS* CGameAudioMS::NewL(TInt aRate, TBool aStereo, TInt aWritesPerSec)
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::NewL(%i, %i, %i)"), aRate, aStereo, aWritesPerSec);
|
||||
CGameAudioMS* self = new(ELeave) CGameAudioMS(aRate, aStereo, aWritesPerSec);
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
CleanupStack::Pop(); // self
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
CGameAudioMS::~CGameAudioMS()
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::~CGameAudioMS()"));
|
||||
if(iMdaAudioOutputStream) {
|
||||
iScheduler->Schedule(); // let it finish it's stuff
|
||||
iMdaAudioOutputStream->Stop();
|
||||
delete iMdaAudioOutputStream;
|
||||
}
|
||||
if(iServer) delete iServer;
|
||||
|
||||
for (TInt i=0; i<KSoundBuffers; i++)
|
||||
delete iSoundBuffers[i];
|
||||
|
||||
// Polled AS
|
||||
//if(iScheduler) delete iScheduler;
|
||||
}
|
||||
|
||||
|
||||
void CGameAudioMS::ConstructL()
|
||||
{
|
||||
iServer = CMdaServer::NewL();
|
||||
|
||||
// iScheduler = CPolledActiveScheduler::NewL();
|
||||
iScheduler = CPolledActiveScheduler::Instance();
|
||||
|
||||
switch(iRate) {
|
||||
case 11025: iMdaAudioDataSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate11025Hz; break;
|
||||
case 16000: iMdaAudioDataSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate16000Hz; break;
|
||||
case 22050: iMdaAudioDataSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate22050Hz; break;
|
||||
case 44100: iMdaAudioDataSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate44100Hz; break;
|
||||
default: iMdaAudioDataSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz; break;
|
||||
}
|
||||
|
||||
iMdaAudioDataSettings.iChannels = (iStereo) ? TMdaAudioDataSettings::EChannelsStereo : TMdaAudioDataSettings::EChannelsMono;
|
||||
iMdaAudioDataSettings.iCaps = TMdaAudioDataSettings::ESampleRateFixed | iMdaAudioDataSettings.iSampleRate;
|
||||
iMdaAudioDataSettings.iFlags = TMdaAudioDataSettings::ENoNetworkRouting;
|
||||
|
||||
int pcmFrames = iRate / iWritesPerSec;
|
||||
pcmFrames += iRate - (iRate / iWritesPerSec) * iWritesPerSec; // add division remainder too for our buffer size
|
||||
iBufferedFrames = iWritesPerSec / KUpdatesPerSec;
|
||||
|
||||
TInt bytesPerFrame = pcmFrames << (iStereo?2:1);
|
||||
for (TInt i=0 ; i<KSoundBuffers ; i++)
|
||||
{
|
||||
iSoundBuffers[i] = HBufC8::NewL(bytesPerFrame * iBufferedFrames);
|
||||
iSoundBuffers[i]->Des().FillZ (bytesPerFrame * iBufferedFrames);
|
||||
}
|
||||
|
||||
iCurrentBuffer = 0;
|
||||
iCurrentBufferSize = 0;
|
||||
|
||||
// here we actually test if we can create and open CMdaAudioOutputStream at all, but really create and use it later.
|
||||
iMdaAudioOutputStream = CMdaAudioOutputStream::NewL(iListener, iServer);
|
||||
if(iMdaAudioOutputStream) {
|
||||
iVolume = iMdaAudioOutputStream->MaxVolume();
|
||||
DEBUGPRINT(_L("MaxVolume: %i"), iVolume);
|
||||
delete iMdaAudioOutputStream;
|
||||
iMdaAudioOutputStream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// returns a pointer to buffer for next frame,
|
||||
// to be used when iSoundBuffers are used directly
|
||||
TInt16 *CGameAudioMS::NextFrameL(TInt aPcmFrames)
|
||||
{
|
||||
iCurrentPosition += aPcmFrames << (iStereo?1:0);
|
||||
iCurrentBufferSize += aPcmFrames << (iStereo?2:1);
|
||||
|
||||
if (++iFrameCount == iBufferedFrames)
|
||||
{
|
||||
WriteBlockL();
|
||||
}
|
||||
|
||||
iScheduler->Schedule();
|
||||
|
||||
if(iListener.iUnderflowed) {
|
||||
if(iListener.iUnderflowed > KMaxUnderflows) {
|
||||
delete iMdaAudioOutputStream;
|
||||
iMdaAudioOutputStream = 0;
|
||||
return 0;
|
||||
}
|
||||
UnderflowedL(); // not again!
|
||||
}
|
||||
|
||||
return iCurrentPosition;
|
||||
}
|
||||
|
||||
void CGameAudioMS::WriteBlockL()
|
||||
{
|
||||
iScheduler->Schedule();
|
||||
// do not write until stream is open
|
||||
if(!iListener.iIsOpen) WaitForOpenToCompleteL();
|
||||
//if(!iListener.iHasCopied) WaitForCopyToCompleteL(); // almost never happens anyway and sometimes even deadlocks?
|
||||
//iListener.iHasCopied = EFalse;
|
||||
|
||||
|
||||
if(!iListener.iUnderflowed) {
|
||||
TInt64 delta;
|
||||
// don't write if sound is lagging too much
|
||||
delta = iTime - iMdaAudioOutputStream->Position().Int64();
|
||||
if (delta > MAKE_TINT64(0, KMaxLag))
|
||||
// another query sometimes returns very different result
|
||||
delta = iTime - iMdaAudioOutputStream->Position().Int64();
|
||||
|
||||
if(delta <= MAKE_TINT64(0, KMaxLag)) {
|
||||
//RDebug::Print(_L("delta: %i"), iTime.Low() - iMdaAudioOutputStream->Position().Int64().Low());
|
||||
iSoundBuffers[iCurrentBuffer]->Des().SetLength(iCurrentBufferSize);
|
||||
iMdaAudioOutputStream->WriteL(*iSoundBuffers[iCurrentBuffer]);
|
||||
iTime += KBlockTime;
|
||||
} else {
|
||||
DEBUGPRINT(_L("lag: %i"), I64LOW(delta));
|
||||
}
|
||||
}
|
||||
|
||||
iFrameCount = 0;
|
||||
if (++iCurrentBuffer == KSoundBuffers)
|
||||
iCurrentBuffer = 0;
|
||||
iCurrentPosition = (TInt16*) iSoundBuffers[iCurrentBuffer]->Ptr();
|
||||
iCurrentBufferSize = 0;
|
||||
}
|
||||
|
||||
void CGameAudioMS::Pause()
|
||||
{
|
||||
if(!iMdaAudioOutputStream) return;
|
||||
|
||||
iScheduler->Schedule(); // let it finish it's stuff
|
||||
iMdaAudioOutputStream->Stop();
|
||||
delete iMdaAudioOutputStream;
|
||||
iMdaAudioOutputStream = 0;
|
||||
}
|
||||
|
||||
// call this before doing any playback!
|
||||
TInt16 *CGameAudioMS::ResumeL()
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::Resume()"));
|
||||
iScheduler->Schedule();
|
||||
|
||||
// we act a bit strange here: simulate buffer underflow, which actually starts audio
|
||||
iListener.iIsOpen = ETrue;
|
||||
iListener.iUnderflowed = 1;
|
||||
iListener.iLastError = 0;
|
||||
iFrameCount = 0;
|
||||
iCurrentBufferSize = 0;
|
||||
iCurrentPosition = (TInt16*) iSoundBuffers[iCurrentBuffer]->Ptr();
|
||||
return iCurrentPosition;
|
||||
}
|
||||
|
||||
// handles underflow condition
|
||||
void CGameAudioMS::UnderflowedL()
|
||||
{
|
||||
DEBUGPRINT(_L("UnderflowedL()"));
|
||||
|
||||
if (iListener.iLastError != KErrUnderflow)
|
||||
{
|
||||
// recreate the stream
|
||||
//iMdaAudioOutputStream->Stop();
|
||||
if(iMdaAudioOutputStream) delete iMdaAudioOutputStream;
|
||||
iMdaAudioOutputStream = CMdaAudioOutputStream::NewL(iListener, iServer);
|
||||
iMdaAudioOutputStream->Open(&iMdaAudioDataSettings);
|
||||
iMdaAudioOutputStream->SetAudioPropertiesL(iMdaAudioDataSettings.iSampleRate, iMdaAudioDataSettings.iChannels);
|
||||
iMdaAudioOutputStream->SetVolume(iVolume); // new in UIQ3
|
||||
|
||||
iListener.iIsOpen = EFalse; // wait for it to open
|
||||
//iListener.iHasCopied = ETrue; // but don't wait for last copy to complete
|
||||
// let it open and feed some stuff to make it happy
|
||||
User::After(0);
|
||||
iScheduler->Schedule();
|
||||
iListener.iLastError = 0;
|
||||
if(!iListener.iIsOpen) WaitForOpenToCompleteL();
|
||||
} else {
|
||||
iListener.iLastError = iListener.iUnderflowed = 0;
|
||||
}
|
||||
iTime = iMdaAudioOutputStream->Position().Int64();
|
||||
}
|
||||
|
||||
void CGameAudioMS::WaitForOpenToCompleteL()
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::WaitForOpenToCompleteL"));
|
||||
TInt count = 20; // 2 seconds
|
||||
TInt waitPeriod = 100 * 1000;
|
||||
|
||||
if(!iListener.iIsOpen) {
|
||||
// it is often enough to do this
|
||||
User::After(0);
|
||||
iScheduler->Schedule();
|
||||
}
|
||||
while (!iListener.iIsOpen && --count)
|
||||
{
|
||||
User::After(waitPeriod);
|
||||
iScheduler->Schedule();
|
||||
}
|
||||
if (!iListener.iIsOpen)
|
||||
User::LeaveIfError(KErrNotSupported);
|
||||
}
|
||||
|
||||
void CGameAudioMS::ChangeVolume(TInt aUp)
|
||||
{
|
||||
//DEBUGPRINT(_L("CGameAudioMS::ChangeVolume(%i)"), aUp);
|
||||
|
||||
if (iMdaAudioOutputStream) {
|
||||
if (aUp) {
|
||||
if (iVolume < iMdaAudioOutputStream->MaxVolume()) iVolume+=5;
|
||||
} else {
|
||||
if (iVolume > 0) iVolume-=5;
|
||||
}
|
||||
iMdaAudioOutputStream->SetVolume(iVolume);
|
||||
}
|
||||
}
|
||||
|
||||
void TGameAudioEventListener::MaoscOpenComplete(TInt aError)
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::MaoscOpenComplete, error=%d"), aError);
|
||||
|
||||
iIsOpen = ETrue;
|
||||
if(aError) {
|
||||
iLastError = aError;
|
||||
iUnderflowed++;
|
||||
}
|
||||
else iUnderflowed = 0;
|
||||
}
|
||||
|
||||
void TGameAudioEventListener::MaoscBufferCopied(TInt aError, const TDesC8& aBuffer)
|
||||
{
|
||||
if (aError)
|
||||
DEBUGPRINT(_L("CGameAudioMS::MaoscBufferCopied, error=%d"), aError);
|
||||
|
||||
// iHasCopied = ETrue;
|
||||
|
||||
if(aError) { // shit!
|
||||
iLastError = aError;
|
||||
iUnderflowed++;
|
||||
}
|
||||
}
|
||||
|
||||
void TGameAudioEventListener::MaoscPlayComplete(TInt aError)
|
||||
{
|
||||
DEBUGPRINT(_L("CGameAudioMS::MaoscPlayComplete: %i"), aError);
|
||||
if(aError) {
|
||||
iLastError = aError;
|
||||
iUnderflowed++; // never happened to me while testing, but just in case
|
||||
}
|
||||
}
|
||||
|
85
platform/uiq3/engine/audio_mediaserver.h
Normal file
85
platform/uiq3/engine/audio_mediaserver.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: Audio_mediaserver.h
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* Modified/adapted for picodriveN by notaz, 2006
|
||||
*
|
||||
* (c) Copyright 2006, notaz
|
||||
* (c) Copyright 2001, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __AUDIO_MEDIASERVER_H
|
||||
#define __AUDIO_MEDIASERVER_H
|
||||
|
||||
#include <Mda\Common\Audio.h>
|
||||
#include <MdaAudioOutputStream.h>
|
||||
|
||||
//#include "audio.h"
|
||||
#include "polledas.h"
|
||||
|
||||
const TInt KSoundBuffers = 4;
|
||||
|
||||
|
||||
class TGameAudioEventListener : public MMdaAudioOutputStreamCallback
|
||||
{
|
||||
public: // implements MMdaAudioOutputStreamCallback
|
||||
void MaoscOpenComplete(TInt aError);
|
||||
void MaoscBufferCopied(TInt aError, const TDesC8& );
|
||||
void MaoscPlayComplete(TInt aError);
|
||||
|
||||
TBool iIsOpen;
|
||||
// TBool iHasCopied;
|
||||
TInt iUnderflowed;
|
||||
TInt iLastError;
|
||||
};
|
||||
|
||||
|
||||
class CGameAudioMS // : public IGameAudio // IGameAudio MUST be specified first!
|
||||
{
|
||||
public: // implements IGameAudio
|
||||
TInt16 *NextFrameL(TInt aPcmFrames);
|
||||
TInt16 *ResumeL();
|
||||
void Pause();
|
||||
void ChangeVolume(TInt aUp);
|
||||
|
||||
public:
|
||||
~CGameAudioMS();
|
||||
CGameAudioMS(TInt aRate, TBool aStereo, TInt aWritesPerSec);
|
||||
static CGameAudioMS* NewL(TInt aRate, TBool aStereo, TInt aWritesPerSec);
|
||||
|
||||
protected:
|
||||
void WriteBlockL();
|
||||
void UnderflowedL();
|
||||
void ConstructL();
|
||||
|
||||
protected:
|
||||
void WaitForOpenToCompleteL();
|
||||
|
||||
TInt iRate;
|
||||
TBool iStereo;
|
||||
|
||||
CMdaAudioOutputStream *iMdaAudioOutputStream;
|
||||
TMdaAudioDataSettings iMdaAudioDataSettings;
|
||||
|
||||
TGameAudioEventListener iListener;
|
||||
|
||||
CPolledActiveScheduler *iScheduler;
|
||||
|
||||
HBufC8* iSoundBuffers[KSoundBuffers];
|
||||
TInt iWritesPerSec;
|
||||
TInt iBufferedFrames;
|
||||
TInt16* iCurrentPosition;
|
||||
TInt iCurrentBuffer;
|
||||
TInt iCurrentBufferSize;
|
||||
TInt iFrameCount;
|
||||
CMdaServer* iServer;
|
||||
|
||||
TInt64 iTime;
|
||||
TInt iVolume;
|
||||
};
|
||||
|
||||
#endif /* __AUDIO_MEDIASERVER_H */
|
34
platform/uiq3/engine/blit.c
Normal file
34
platform/uiq3/engine/blit.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
/*
|
||||
void vidConvCpyRGB32 (void *to, void *from, int lines, int p240)
|
||||
{
|
||||
unsigned short *ps = (unsigned short *) from;
|
||||
unsigned long *pd = (unsigned long *) to;
|
||||
int x, y;
|
||||
int to_x = p240 ? 240 : 224;
|
||||
if(!p240) pd += 8;
|
||||
|
||||
for(y = 0; y < lines; y++) // ps < ps_end; ps++)
|
||||
for(x = 0; x < to_x; x++, ps++)
|
||||
// Convert 0000bbb0 ggg0rrr0
|
||||
// to ..0 rrr00000 ggg00000 bbb00000
|
||||
*(pd+y*256+x) = ((*ps&0x000F)<<20) | ((*ps&0x00F0)<<8) | ((*ps&0x0F00)>>4);
|
||||
}
|
||||
*/
|
||||
|
||||
// stubs
|
||||
void vidConvCpyRGB32 (void *to, void *from, int pixels) {}
|
||||
void vidConvCpyRGB32sh(void *to, void *from, int pixels) {}
|
||||
void vidConvCpyRGB32hi(void *to, void *from, int pixels) {}
|
||||
|
||||
void vidConvCpy_90 (void *to, void *from, void *pal, int width) {}
|
||||
void vidConvCpy_270 (void *to, void *from, void *pal, int width) {}
|
||||
void vidConvCpy_center_0 (void *to, void *from, void *pal) {}
|
||||
void vidConvCpy_center_180(void *to, void *from, void *pal) {}
|
||||
void vidConvCpy_center2_40c_0 (void *to, void *from, void *pal, int lines) {}
|
||||
void vidConvCpy_center2_40c_180(void *to, void *from, void *pal, int lines) {}
|
||||
void vidConvCpy_center2_32c_0 (void *to, void *from, void *pal, int lines) {}
|
||||
void vidConvCpy_center2_32c_180(void *to, void *from, void *pal, int lines) {}
|
||||
|
||||
void vidClear(void *to, int lines) {}
|
||||
|
22
platform/uiq3/engine/blit.h
Normal file
22
platform/uiq3/engine/blit.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
// (c) Copyright 2006 notaz, All rights reserved.
|
||||
// Free for non-commercial use.
|
||||
|
||||
// For commercial use, separate licencing terms must be obtained.
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void vidConvCpyRGB32 (void *to, void *from, int pixels);
|
||||
void vidConvCpyRGB32sh(void *to, void *from, int pixels);
|
||||
void vidConvCpyRGB32hi(void *to, void *from, int pixels);
|
||||
|
||||
void vidConvCpy_90 (void *to, void *from, void *pal, int width);
|
||||
void vidConvCpy_270 (void *to, void *from, void *pal, int width);
|
||||
void vidConvCpy_center_0 (void *to, void *from, void *pal);
|
||||
void vidConvCpy_center_180(void *to, void *from, void *pal);
|
||||
void vidConvCpy_center2_40c_0 (void *to, void *from, void *pal, int lines);
|
||||
void vidConvCpy_center2_40c_180(void *to, void *from, void *pal, int lines);
|
||||
void vidConvCpy_center2_32c_0 (void *to, void *from, void *pal, int lines);
|
||||
void vidConvCpy_center2_32c_180(void *to, void *from, void *pal, int lines);
|
||||
|
||||
void vidClear(void *to, int lines);
|
||||
}
|
695
platform/uiq3/engine/blit.s
Normal file
695
platform/uiq3/engine/blit.s
Normal file
|
@ -0,0 +1,695 @@
|
|||
@ some color conversion and blitting routines
|
||||
|
||||
@ (c) Copyright 2006, notaz
|
||||
@ All Rights Reserved
|
||||
|
||||
|
||||
@ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
|
||||
@ to 00000000 rrr00000 ggg00000 bbb00000 ...
|
||||
|
||||
@ lr = 0x00e000e0, out: r3=lower_pix, r2=higher_pix; trashes rin
|
||||
@ if sh==2, r8=0x00404040 (sh!=0 destroys flags!)
|
||||
.macro convRGB32_2 rin sh=0
|
||||
and r2, lr, \rin, lsr #4 @ blue
|
||||
and r3, \rin, lr
|
||||
orr r2, r2, r3, lsl #8 @ g0b0g0b0
|
||||
|
||||
mov r3, r2, lsl #16 @ g0b00000
|
||||
and \rin,lr, \rin, ror #12 @ 00r000r0 (reversed)
|
||||
orr r3, r3, \rin, lsr #16 @ g0b000r0
|
||||
.if \sh == 1
|
||||
mov r3, r3, ror #17 @ shadow mode
|
||||
.elseif \sh == 2
|
||||
adds r3, r3, #0x40000000 @ green
|
||||
orrcs r3, r3, #0xe0000000
|
||||
mov r3, r3, ror #8
|
||||
adds r3, r3, #0x40000000
|
||||
orrcs r3, r3, #0xe0000000
|
||||
mov r3, r3, ror #16
|
||||
adds r3, r3, #0x40000000
|
||||
orrcs r3, r3, #0xe0000000
|
||||
mov r3, r3, ror #24
|
||||
orr r3, r3, r3, lsr #3
|
||||
.else
|
||||
mov r3, r3, ror #16 @ r3=low
|
||||
orr r3, r3, r3, lsr #3
|
||||
.endif
|
||||
|
||||
str r3, [r0], #4
|
||||
|
||||
mov r2, r2, lsr #16
|
||||
orr r2, r2, \rin, lsl #16
|
||||
.if \sh == 1
|
||||
mov r2, r2, lsr #1
|
||||
.elseif \sh == 2
|
||||
mov r2, r2, ror #8
|
||||
adds r2, r2, #0x40000000 @ blue
|
||||
orrcs r2, r2, #0xe0000000
|
||||
mov r2, r2, ror #8
|
||||
adds r2, r2, #0x40000000
|
||||
orrcs r2, r2, #0xe0000000
|
||||
mov r2, r2, ror #8
|
||||
adds r2, r2, #0x40000000
|
||||
orrcs r2, r2, #0xe0000000
|
||||
mov r2, r2, ror #8
|
||||
orr r2, r2, r2, lsr #3
|
||||
.else
|
||||
orr r2, r2, r2, lsr #3
|
||||
.endif
|
||||
|
||||
str r2, [r0], #4
|
||||
.endm
|
||||
|
||||
|
||||
.global vidConvCpyRGB32 @ void *to, void *from, int pixels
|
||||
|
||||
vidConvCpyRGB32:
|
||||
stmfd sp!, {r4-r7,lr}
|
||||
|
||||
mov r12, r2, lsr #3 @ repeats
|
||||
mov lr, #0x00e00000
|
||||
orr lr, lr, #0x00e0
|
||||
|
||||
.loopRGB32:
|
||||
subs r12, r12, #1
|
||||
|
||||
ldmia r1!, {r4-r7}
|
||||
convRGB32_2 r4
|
||||
convRGB32_2 r5
|
||||
convRGB32_2 r6
|
||||
convRGB32_2 r7
|
||||
|
||||
bgt .loopRGB32
|
||||
|
||||
ldmfd sp!, {r4-r7,lr}
|
||||
bx lr
|
||||
|
||||
|
||||
.global vidConvCpyRGB32sh @ void *to, void *from, int pixels
|
||||
|
||||
vidConvCpyRGB32sh:
|
||||
stmfd sp!, {r4-r7,lr}
|
||||
|
||||
mov r12, r2, lsr #3 @ repeats
|
||||
mov lr, #0x00e00000
|
||||
orr lr, lr, #0x00e0
|
||||
|
||||
.loopRGB32sh:
|
||||
subs r12, r12, #1
|
||||
|
||||
ldmia r1!, {r4-r7}
|
||||
convRGB32_2 r4, 1
|
||||
convRGB32_2 r5, 1
|
||||
convRGB32_2 r6, 1
|
||||
convRGB32_2 r7, 1
|
||||
|
||||
bgt .loopRGB32sh
|
||||
|
||||
ldmfd sp!, {r4-r7,lr}
|
||||
bx lr
|
||||
|
||||
|
||||
.global vidConvCpyRGB32hi @ void *to, void *from, int pixels
|
||||
|
||||
vidConvCpyRGB32hi:
|
||||
stmfd sp!, {r4-r7,lr}
|
||||
|
||||
mov r12, r2, lsr #3 @ repeats
|
||||
mov lr, #0x00e00000
|
||||
orr lr, lr, #0x00e0
|
||||
|
||||
.loopRGB32hi:
|
||||
ldmia r1!, {r4-r7}
|
||||
convRGB32_2 r4, 2
|
||||
convRGB32_2 r5, 2
|
||||
convRGB32_2 r6, 2
|
||||
convRGB32_2 r7, 2
|
||||
|
||||
subs r12, r12, #1
|
||||
bgt .loopRGB32hi
|
||||
|
||||
ldmfd sp!, {r4-r7,lr}
|
||||
bx lr
|
||||
|
||||
|
||||
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
@ -------- M2 stuff ---------
|
||||
/*
|
||||
.global vidConvCpy_90 @ void *to, void *from, int width
|
||||
|
||||
vidConvCpy_90:
|
||||
stmfd sp!, {r4-r10,lr}
|
||||
|
||||
mov lr, #0x00F00000
|
||||
orr lr, lr, #0x00F0
|
||||
|
||||
mov r12, #224/4 @ row counter
|
||||
mov r10, r2, lsl #2 @ we do 2 pixel wide copies
|
||||
|
||||
add r8, r0, #256*4 @ parallel line
|
||||
add r1, r1, #0x23000
|
||||
add r1, r1, #0x00B80 @ r1+=328*223*2+8*2
|
||||
mov r9, r1
|
||||
|
||||
mov r4, #0 @ fill bottom border
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
mov r7, #0
|
||||
stmia r0!, {r4-r7}
|
||||
stmia r0!, {r4-r7}
|
||||
stmia r8!, {r4-r7}
|
||||
stmia r8!, {r4-r7}
|
||||
|
||||
.loopM2RGB32_90:
|
||||
subs r12, r12, #1
|
||||
|
||||
@ at first this loop was written differently: src pixels were fetched with ldm's and
|
||||
@ dest was not sequential. It ran nearly 2 times slower. It seems it is very important
|
||||
@ to do sequential memory access on those items, which we have more (to offload addressing bus?).
|
||||
|
||||
ldr r4, [r1], #-328*2
|
||||
ldr r5, [r1], #-328*2
|
||||
ldr r6, [r1], #-328*2
|
||||
ldr r7, [r1], #-328*2
|
||||
|
||||
convRGB32_2 r4, 1
|
||||
convRGB32_2 r5, 1
|
||||
convRGB32_2 r6, 1
|
||||
convRGB32_2 r7, 1
|
||||
|
||||
str r4, [r8], #4
|
||||
str r5, [r8], #4
|
||||
str r6, [r8], #4
|
||||
str r7, [r8], #4
|
||||
|
||||
bne .loopM2RGB32_90
|
||||
|
||||
mov r4, #0 @ top border
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
stmia r0!, {r4-r6,r12}
|
||||
stmia r0!, {r4-r6,r12}
|
||||
stmia r8!, {r4-r6,r12}
|
||||
stmia r8!, {r4-r6,r12}
|
||||
|
||||
subs r10, r10, #1
|
||||
ldmeqfd sp!, {r4-r10,pc} @ return
|
||||
|
||||
add r0, r8, #16*4 @ set new dst pointer
|
||||
add r8, r0, #256*4
|
||||
add r9, r9, #2*2 @ fix src pointer
|
||||
mov r1, r9
|
||||
|
||||
stmia r0!, {r4-r6,r12} @ bottom border
|
||||
stmia r0!, {r4-r6,r12}
|
||||
stmia r8!, {r4-r6,r12}
|
||||
stmia r8!, {r4-r6,r12}
|
||||
|
||||
mov r12, #224/4 @ restore row counter
|
||||
b .loopM2RGB32_90
|
||||
|
||||
|
||||
|
||||
@ converter for vidConvCpy_270
|
||||
@ lr = 0x00F000F0, out: r3=lower_pix, r2=higher_pix; trashes rin
|
||||
.macro convRGB32_3 rin
|
||||
and r2, lr, \rin, lsr #4 @ blue
|
||||
and r3, \rin, lr
|
||||
orr r2, r2, r3, lsl #8 @ g0b0g0b0
|
||||
|
||||
mov r3, r2, lsl #16 @ g0b00000
|
||||
and \rin,lr, \rin, ror #12 @ 00r000r0 (reversed)
|
||||
orr r3, r3, \rin, lsr #16 @ g0b000r0
|
||||
|
||||
mov r2, r2, lsr #16
|
||||
orr r2, r2, \rin, lsl #16
|
||||
str r2, [r0], #4
|
||||
|
||||
mov \rin,r3, ror #16 @ r3=low
|
||||
.endm
|
||||
*/
|
||||
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
|
||||
@ takes byte-sized pixels from r3-r6, fetches from pal and stores to r7,r8,r10,lr
|
||||
@ r2=pal
|
||||
.macro mode2_4pix shift
|
||||
and r7, r11, r3, lsr #\shift
|
||||
ldr r7, [r2, r7, lsl #2]
|
||||
|
||||
and r8, r11, r4, lsr #\shift
|
||||
ldr r8, [r2, r8, lsl #2]
|
||||
|
||||
and r10,r11, r5, lsr #\shift
|
||||
ldr r10,[r2, r10,lsl #2]
|
||||
|
||||
and lr, r11, r6, lsr #\shift
|
||||
ldr lr, [r2, lr, lsl #2]
|
||||
.endm
|
||||
|
||||
@ r2=pal, r11=0xff
|
||||
.macro mode2_4pix_getpix0 dreg sreg
|
||||
and \dreg, r11, \sreg
|
||||
ldr \dreg, [r2, \dreg, lsl #2]
|
||||
.endm
|
||||
|
||||
.macro mode2_4pix_getpix1 dreg sreg
|
||||
and \dreg, r11, \sreg, lsr #8
|
||||
ldr \dreg, [r2, \dreg, lsl #2]
|
||||
.endm
|
||||
|
||||
.macro mode2_4pix_getpix2 dreg sreg
|
||||
and \dreg, r11, \sreg, lsr #16
|
||||
ldr \dreg, [r2, \dreg, lsl #2]
|
||||
.endm
|
||||
|
||||
.macro mode2_4pix_getpix3 dreg sreg
|
||||
and \dreg, r11, \sreg, lsr #24
|
||||
ldr \dreg, [r2, \dreg, lsl #2]
|
||||
.endm
|
||||
|
||||
@ takes byte-sized pixels from reg, fetches from pal and stores to r3-r6
|
||||
@ r11=0xFF, r2=pal
|
||||
.macro mode2_4pix2_0 reg
|
||||
mode2_4pix_getpix0 r3, \reg
|
||||
mode2_4pix_getpix1 r4, \reg
|
||||
mode2_4pix_getpix2 r5, \reg
|
||||
mode2_4pix_getpix3 r6, \reg
|
||||
.endm
|
||||
|
||||
@ ...
|
||||
.macro mode2_4pix2_180 reg
|
||||
mode2_4pix_getpix3 r3, \reg
|
||||
mode2_4pix_getpix2 r4, \reg
|
||||
mode2_4pix_getpix1 r5, \reg
|
||||
mode2_4pix_getpix0 r6, \reg
|
||||
.endm
|
||||
|
||||
@ takes byte-sized pixels from reg, fetches from pal and stores to r3-r5
|
||||
@ r11=0xFF, r2=pal, r10=0xfcfcfc, r6=tmp
|
||||
.macro mode2_4pix_to3 reg is180
|
||||
.if \is180
|
||||
mode2_4pix_getpix3 r3, \reg
|
||||
mode2_4pix_getpix2 r4, \reg
|
||||
.else
|
||||
mode2_4pix_getpix0 r3, \reg @ gathering loads cause a weird-hang
|
||||
mode2_4pix_getpix1 r4, \reg
|
||||
.endif
|
||||
|
||||
sub r3, r3, r3, lsr #2 @ r3 *= 0.75
|
||||
add r3, r3, r4, lsr #2 @ r3 += r4 * 0.25
|
||||
and r3, r3, r10
|
||||
|
||||
.if \is180
|
||||
mode2_4pix_getpix1 r5, \reg
|
||||
mode2_4pix_getpix0 r6, \reg
|
||||
.else
|
||||
mode2_4pix_getpix2 r5, \reg
|
||||
mode2_4pix_getpix3 r6, \reg
|
||||
.endif
|
||||
|
||||
mov r4, r4, lsr #1
|
||||
add r4, r4, r5, lsr #1 @ r4 = (r4 + r5) / 2;
|
||||
@ and r4, r4, r10
|
||||
sub r6, r6, r6, lsr #2 @ r6 *= 0.75
|
||||
add r5, r6, r5, lsr #2 @ r5 = r6 + r5 * 0.25
|
||||
and r5, r5, r10
|
||||
.endm
|
||||
|
||||
|
||||
@ void *to, void *from, void *pal, int width
|
||||
.macro vidConvCpyM2_landscape is270
|
||||
stmfd sp!, {r4-r11,lr}
|
||||
|
||||
mov r11, #0xff
|
||||
|
||||
mov r12, #(224/4-1)<<16 @ row counter
|
||||
orr r12, r12, r3, lsl #1 @ we do 4 pixel wide copies (right to left)
|
||||
|
||||
.if \is270
|
||||
add r1, r1, #324
|
||||
.else
|
||||
add r1, r1, #0x11c00
|
||||
add r1, r1, #0x00308 @ 328*224+8
|
||||
.endif
|
||||
mov r9, r1
|
||||
|
||||
mov r3, #0 @ fill top border
|
||||
mov r4, #0
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
stmia r0!, {r3-r6}
|
||||
stmia r0!, {r3-r6}
|
||||
add r7, r0, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
add r7, r7, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
add r7, r7, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
|
||||
0: @ .loopM2RGB32_270:
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
.if \is270
|
||||
ldr r3, [r1], #328
|
||||
ldr r4, [r1], #328
|
||||
ldr r5, [r1], #328
|
||||
ldr r6, [r1], #328
|
||||
.else
|
||||
ldr r3, [r1, #-328]!
|
||||
ldr r4, [r1, #-328]!
|
||||
ldr r5, [r1, #-328]!
|
||||
ldr r6, [r1, #-328]!
|
||||
.endif
|
||||
|
||||
.if \is270
|
||||
mode2_4pix 24
|
||||
.else
|
||||
mode2_4pix 0
|
||||
.endif
|
||||
stmia r0, {r7,r8,r10,lr}
|
||||
add r0, r0, #256*4
|
||||
|
||||
.if \is270
|
||||
mode2_4pix 16
|
||||
.else
|
||||
mode2_4pix 8
|
||||
.endif
|
||||
stmia r0, {r7,r8,r10,lr}
|
||||
add r0, r0, #256*4
|
||||
|
||||
.if \is270
|
||||
mode2_4pix 8
|
||||
.else
|
||||
mode2_4pix 16
|
||||
.endif
|
||||
stmia r0, {r7,r8,r10,lr}
|
||||
add r0, r0, #256*4
|
||||
|
||||
.if \is270
|
||||
mode2_4pix 0
|
||||
.else
|
||||
mode2_4pix 24
|
||||
.endif
|
||||
stmia r0!,{r7,r8,r10,lr}
|
||||
sub r0, r0, #256*4*3
|
||||
|
||||
bpl 0b @ .loopM2RGB32_270
|
||||
|
||||
mov r3, #0 @ bottom border
|
||||
mov r4, #0
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
stmia r0!, {r3-r6}
|
||||
stmia r0!, {r3-r6}
|
||||
add r0, r0, #256*4-8*4
|
||||
stmia r0!, {r3-r6}
|
||||
stmia r0!, {r3-r6}
|
||||
add r0, r0, #256*4-8*4
|
||||
stmia r0!, {r3-r6}
|
||||
stmia r0!, {r3-r6}
|
||||
add r0, r0, #256*4-8*4
|
||||
stmia r0!, {r3-r6}
|
||||
nop @ phone crashes if this is commented out. Do I stress it too much?
|
||||
stmia r0!, {r3-r6}
|
||||
|
||||
add r12, r12, #1<<16
|
||||
subs r12, r12, #1
|
||||
ldmeqfd sp!, {r4-r11,pc} @ return
|
||||
|
||||
add r0, r0, #16*4
|
||||
.if \is270
|
||||
sub r9, r9, #4 @ fix src pointer
|
||||
.else
|
||||
add r9, r9, #4
|
||||
.endif
|
||||
mov r1, r9
|
||||
|
||||
stmia r0!, {r3-r6} @ top border
|
||||
stmia r0!, {r3-r6}
|
||||
add r7, r0, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
add r7, r7, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
add r7, r7, #256*4-8*4
|
||||
stmia r7!, {r3-r6}
|
||||
stmia r7!, {r3-r6}
|
||||
|
||||
orr r12, r12, #(224/4-1)<<16 @ restore row counter
|
||||
b 0b @ .loopM2RGB32_270
|
||||
.endm
|
||||
|
||||
|
||||
.global vidConvCpy_90 @ void *to, void *from, void *pal, int width
|
||||
|
||||
vidConvCpy_90:
|
||||
vidConvCpyM2_landscape 0
|
||||
|
||||
|
||||
.global vidConvCpy_270 @ void *to, void *from, void *pal, int width
|
||||
|
||||
vidConvCpy_270:
|
||||
vidConvCpyM2_landscape 1
|
||||
|
||||
|
||||
.global vidConvCpy_center_0 @ void *to, void *from, void *pal
|
||||
|
||||
vidConvCpy_center_0:
|
||||
stmfd sp!, {r4-r6,r11,lr}
|
||||
|
||||
mov r11, #0xff
|
||||
add r1, r1, #8 @ not border (centering 32col here)
|
||||
|
||||
mov r12, #(240/4-1)<<16
|
||||
orr r12, r12, #224
|
||||
|
||||
.loopRGB32_c0:
|
||||
ldr lr, [r1], #4
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix2_0 lr
|
||||
stmia r0!, {r3-r6}
|
||||
bpl .loopRGB32_c0
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r6,r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
add r1, r1, #88
|
||||
orr r12, #(240/4-1)<<16
|
||||
b .loopRGB32_c0
|
||||
|
||||
|
||||
.global vidConvCpy_center_180 @ void *to, void *from, void *pal
|
||||
|
||||
vidConvCpy_center_180:
|
||||
stmfd sp!, {r4-r6,r11,lr}
|
||||
|
||||
mov r11, #0xff
|
||||
add r1, r1, #0x11c00
|
||||
add r1, r1, #0x002B8 @ #328*224-72
|
||||
|
||||
mov r12, #(240/4-1)<<16
|
||||
orr r12, r12, #224
|
||||
|
||||
.loopRGB32_c180:
|
||||
ldr lr, [r1, #-4]!
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix2_180 lr
|
||||
stmia r0!, {r3-r6}
|
||||
bpl .loopRGB32_c180
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r6,r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
sub r1, r1, #88
|
||||
orr r12, #(240/4-1)<<16
|
||||
b .loopRGB32_c180
|
||||
|
||||
|
||||
@ note: the following code assumes that (pal[x] & 0x030303) == 0
|
||||
|
||||
.global vidConvCpy_center2_40c_0 @ void *to, void *from, void *pal, int lines
|
||||
|
||||
vidConvCpy_center2_40c_0:
|
||||
stmfd sp!, {r4-r6,r10,r11,lr}
|
||||
|
||||
mov r11, #0xff
|
||||
mov r10, #0xfc
|
||||
orr r10, r10, lsl #8
|
||||
orr r10, r10, lsl #8
|
||||
add r1, r1, #8 @ border
|
||||
|
||||
mov r12, #(240/3-1)<<16
|
||||
orr r12, r12, r3
|
||||
|
||||
.loopRGB32_c2_40c_0:
|
||||
ldr lr, [r1], #4
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix_to3 lr, 0
|
||||
|
||||
stmia r0!, {r3-r5}
|
||||
bpl .loopRGB32_c2_40c_0
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r6,r10,r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
add r1, r1, #8
|
||||
orr r12, #(240/3-1)<<16
|
||||
b .loopRGB32_c2_40c_0
|
||||
|
||||
|
||||
.global vidConvCpy_center2_40c_180 @ void *to, void *from, void *pal, int lines
|
||||
|
||||
vidConvCpy_center2_40c_180:
|
||||
stmfd sp!, {r4-r6,r10,r11,lr}
|
||||
|
||||
mov r11, #0xff
|
||||
mov r10, #0xfc
|
||||
orr r10, r10, lsl #8
|
||||
orr r10, r10, lsl #8
|
||||
|
||||
mov r4, #328
|
||||
mla r1, r3, r4, r1
|
||||
@ add r1, r1, #0x11000
|
||||
@ add r1, r1, #0x00f00 @ #328*224
|
||||
|
||||
mov r12, #(240/3-1)<<16
|
||||
orr r12, r12, r3
|
||||
|
||||
.loop_c2_40c_180:
|
||||
ldr lr, [r1, #-4]!
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix_to3 lr, 1
|
||||
|
||||
stmia r0!, {r3-r5}
|
||||
bpl .loop_c2_40c_180
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r6,r10,r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
sub r1, r1, #8
|
||||
orr r12, #(240/3-1)<<16
|
||||
b .loop_c2_40c_180
|
||||
|
||||
|
||||
.global vidConvCpy_center2_32c_0 @ void *to, void *from, void *pal, int lines
|
||||
|
||||
vidConvCpy_center2_32c_0:
|
||||
stmfd sp!, {r4-r11,lr}
|
||||
|
||||
mov r10, #0xfc
|
||||
orr r10, r10, lsl #8
|
||||
orr r10, r10, lsl #8
|
||||
mov r11, #0xff
|
||||
add r1, r1, #8 @ border
|
||||
|
||||
mov r12, #(240/15-1)<<16
|
||||
orr r12, r12, r3
|
||||
|
||||
.loop_c2_32c_0:
|
||||
ldmia r1!, {r7-r9,lr}
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix2_0 r7
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix2_0 r8
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix2_0 r9
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix_to3 lr, 0
|
||||
stmia r0!, {r3-r5}
|
||||
bpl .loop_c2_32c_0
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
add r1, r1, #64+8
|
||||
orr r12, #(240/15-1)<<16
|
||||
b .loop_c2_32c_0
|
||||
|
||||
|
||||
.global vidConvCpy_center2_32c_180 @ void *to, void *from, void *pal, int lines
|
||||
|
||||
vidConvCpy_center2_32c_180:
|
||||
stmfd sp!, {r4-r11,lr}
|
||||
|
||||
mov r10, #0xfc
|
||||
orr r10, r10, lsl #8
|
||||
orr r10, r10, lsl #8
|
||||
mov r11, #0xff
|
||||
|
||||
mov r4, #328
|
||||
mla r1, r3, r4, r1
|
||||
@ add r1, r1, #0x11000
|
||||
@ add r1, r1, #0x00f00 @ #328*224
|
||||
|
||||
mov r12, #(240/15-1)<<16
|
||||
orr r12, r12, r3
|
||||
|
||||
.loop_c2_32c_180:
|
||||
ldmdb r1!, {r7-r9,lr}
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
mode2_4pix2_180 lr
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix2_180 r9
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix2_180 r8
|
||||
stmia r0!, {r3-r6}
|
||||
mode2_4pix_to3 r7, 1
|
||||
stmia r0!, {r3-r5}
|
||||
bpl .loop_c2_32c_180
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {r4-r11,pc} @ return
|
||||
add r0, r0, #16*4
|
||||
sub r1, r1, #64+8
|
||||
orr r12, #(240/15-1)<<16
|
||||
b .loop_c2_32c_180
|
||||
|
||||
|
||||
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
|
||||
.global vidClear @ void *to, int lines
|
||||
|
||||
vidClear:
|
||||
stmfd sp!, {lr}
|
||||
mov r12, #240/16-1
|
||||
orr r12, r1, r12, lsl #16
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
mov lr, #0
|
||||
|
||||
.loopVidClear:
|
||||
subs r12, r12, #1<<16
|
||||
|
||||
stmia r0!, {r1-r3,lr}
|
||||
stmia r0!, {r1-r3,lr}
|
||||
stmia r0!, {r1-r3,lr}
|
||||
stmia r0!, {r1-r3,lr}
|
||||
bpl .loopVidClear
|
||||
|
||||
sub r12, r12, #1
|
||||
adds r12, r12, #1<<16
|
||||
ldmeqfd sp!, {pc} @ return
|
||||
add r0, r0, #16*4
|
||||
orr r12, #(240/16-1)<<16
|
||||
b .loopVidClear
|
||||
|
259
platform/uiq3/engine/debug.cpp
Normal file
259
platform/uiq3/engine/debug.cpp
Normal file
|
@ -0,0 +1,259 @@
|
|||
|
||||
#include <e32svr.h> // RDebug
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef __WINS__
|
||||
|
||||
void ExceptionHandler(TExcType exc) {}
|
||||
|
||||
#else
|
||||
|
||||
static const wchar_t * const exception_names[] = {
|
||||
L"General",
|
||||
L"IntegerDivideByZero",
|
||||
L"SingleStep",
|
||||
L"BreakPoint",
|
||||
L"IntegerOverflow",
|
||||
L"BoundsCheck",
|
||||
L"InvalidOpCode",
|
||||
L"DoubleFault",
|
||||
L"StackFault",
|
||||
L"AccessViolation",
|
||||
L"PrivInstruction",
|
||||
L"Alignment",
|
||||
L"PageFault",
|
||||
L"FloatDenormal",
|
||||
L"FloatDivideByZero",
|
||||
L"FloatInexactResult",
|
||||
L"FloatInvalidOperation",
|
||||
L"FloatOverflow",
|
||||
L"FloatStackCheck",
|
||||
L"FloatUnderflow",
|
||||
L"Abort",
|
||||
L"Kill",
|
||||
L"DataAbort",
|
||||
L"CodeAbort",
|
||||
L"MaxNumber",
|
||||
L"InvalidVector",
|
||||
L"UserInterrupt",
|
||||
L"Unknown"
|
||||
};
|
||||
|
||||
|
||||
static void getASpace(TUint *code_start, TUint *code_end, TUint *stack_start, TUint *stack_end)
|
||||
{
|
||||
TUint pc, sp;
|
||||
RChunk chunk;
|
||||
TFullName chunkname;
|
||||
TFindChunk findChunk(_L("*"));
|
||||
|
||||
asm volatile ("str pc, %0" : "=m" (pc) );
|
||||
asm volatile ("str sp, %0" : "=m" (sp) );
|
||||
|
||||
while( findChunk.Next(chunkname) != KErrNotFound ) {
|
||||
chunk.Open(findChunk);
|
||||
if((TUint)chunk.Base()+chunk.Bottom() < pc && pc < (TUint)chunk.Base()+chunk.Top()) {
|
||||
if(code_start) *code_start = (TUint)chunk.Base()+chunk.Bottom();
|
||||
if(code_end) *code_end = (TUint)chunk.Base()+chunk.Top();
|
||||
} else
|
||||
if((TUint)chunk.Base()+chunk.Bottom() < sp && sp < (TUint)chunk.Base()+chunk.Top()) {
|
||||
if(stack_start) *stack_start = (TUint)chunk.Base()+chunk.Bottom();
|
||||
if(stack_end) *stack_end = (TUint)chunk.Base()+chunk.Top();
|
||||
}
|
||||
chunk.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// tmp
|
||||
#if defined(__DEBUG_PRINT)
|
||||
extern "C" char *debugString();
|
||||
#endif
|
||||
|
||||
// our very own exception handler
|
||||
void ExceptionHandler(TExcType exc)
|
||||
{
|
||||
TUint lr, sp, i;
|
||||
TUint stack_end = 0; // ending address of our stack chunk
|
||||
TUint code_start = 0, code_end = 0; // starting and ending addresses of our code chunk
|
||||
TUint guessed_address = 0;
|
||||
|
||||
DEBUGPRINT(_L("ExceptionHandler()")); // this seems to never be called
|
||||
|
||||
asm volatile ("str lr, %0" : "=m" (lr) );
|
||||
asm volatile ("str sp, %0" : "=m" (sp) );
|
||||
|
||||
// first get some info about the chunks we live in
|
||||
getASpace(&code_start, &code_end, 0, &stack_end);
|
||||
|
||||
// now we begin some black magic tricks
|
||||
// we go up our stack until we pass our caller address
|
||||
for(; sp < stack_end; sp += 4)
|
||||
if(*(TUint *)sp == lr) break;
|
||||
|
||||
// there might be mirored caller address
|
||||
for(i = sp + 4; i < sp + 0x300 && i < stack_end; i += 4)
|
||||
if(*(TUint *)i == lr) { sp = i; break; }
|
||||
|
||||
// aah, it is always 0x9c bytes away from the caller address in my firmware,
|
||||
// don't know how to detect it in any other way
|
||||
sp += 0x9c;
|
||||
guessed_address = *(TUint *)sp;
|
||||
|
||||
// output the info
|
||||
TUint exec_show = exc;
|
||||
if(exec_show > 27) exec_show = 27;
|
||||
TPtrC ptrExc((TUint16 *) exception_names[exec_show]);
|
||||
|
||||
RDebug::Print(_L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
DEBUGPRINT( _L("!!!Exception %i (%S) @ 0x%08x (guessed; relative=0x%08x)"), exc, &ptrExc, guessed_address, guessed_address - code_start);
|
||||
#endif
|
||||
|
||||
TBuf<148> buff1;
|
||||
TBuf<10> buff2;
|
||||
buff1.Copy(_L(" guessed stack: "));
|
||||
|
||||
for(sp += 4, i = 0; i < 5 && sp < stack_end; sp += 4) {
|
||||
if((*(TUint *)sp >> 28) == 5) {
|
||||
if(i++) buff1.Append(_L(", "));
|
||||
buff2.Format(_L("0x%08x"), *(TUint *)sp);
|
||||
buff1.Append(buff2);
|
||||
}
|
||||
else if(code_start < *(TUint *)sp && *(TUint *)sp < code_end) {
|
||||
if(i++) buff1.Append(_L(", "));
|
||||
buff2.Format(_L("0x%08x"), *(TUint *)sp);
|
||||
buff1.Append(buff2);
|
||||
buff1.Append(_L(" ("));
|
||||
buff2.Format(_L("0x%08x"), *(TUint *)sp - code_start);
|
||||
buff1.Append(buff2);
|
||||
buff1.Append(_L(")"));
|
||||
}
|
||||
}
|
||||
RDebug::Print(_L("%S"), &buff1);
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
DEBUGPRINT(_L("%S"), &buff1);
|
||||
#endif
|
||||
|
||||
// tmp
|
||||
#if defined(__DEBUG_PRINT)
|
||||
char *ps, *cstr = debugString();
|
||||
for(ps = cstr; *ps; ps++) {
|
||||
if(*ps == '\n') {
|
||||
*ps = 0;
|
||||
dprintf(cstr);
|
||||
cstr = ps+1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// RDebug::Print(_L("Stack dump:"));
|
||||
// asm volatile ("str sp, %0" : "=m" (sp) );
|
||||
// for(TUint i = sp+0x400; i >= sp-16; i-=4)
|
||||
// RDebug::Print(_L("%08x: %08x"), i, *(int *)i);
|
||||
|
||||
// more descriptive replacement of "KERN-EXEC 3" panic
|
||||
buff1.Format(_L("K-EX3: %S"), &ptrExc);
|
||||
User::Panic(buff1, exc);
|
||||
}
|
||||
|
||||
#endif // ifdef __WINS__
|
||||
|
||||
|
||||
#if defined(__DEBUG_PRINT) || defined(__WINS__)
|
||||
|
||||
#ifndef __DLL__
|
||||
// c string dumper for RDebug::Print()
|
||||
static TBuf<1024> sTextBuffer;
|
||||
TDesC* DO_CONV(const char* s)
|
||||
{
|
||||
TPtrC8 text8((TUint8*) (s));
|
||||
sTextBuffer.Copy(text8);
|
||||
return &sTextBuffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DEBUG_PRINT_C
|
||||
#include <stdarg.h> // va_*
|
||||
#include <stdio.h> // vsprintf
|
||||
|
||||
// debug print from c code
|
||||
extern "C" void dprintf(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[512];
|
||||
|
||||
va_start(args,format);
|
||||
vsprintf(buffer,format,args);
|
||||
va_end(args);
|
||||
|
||||
DEBUGPRINT(_L("%S"), DO_CONV(buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
#include <f32file.h>
|
||||
|
||||
//static RFile logFile;
|
||||
// static TBool logInited = 0;
|
||||
RMutex logMutex;
|
||||
|
||||
static void debugPrintFileInit()
|
||||
{
|
||||
// try to open
|
||||
logMutex.CreateLocal();
|
||||
RFs fserv;
|
||||
fserv.Connect();
|
||||
RFile logFile;
|
||||
logFile.Replace(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);
|
||||
logFile.Close();
|
||||
fserv.Close();
|
||||
}
|
||||
|
||||
// debug print to file
|
||||
void debugPrintFile(TRefByValue<const TDesC> aFmt, ...)
|
||||
{
|
||||
if (logMutex.Handle() <= 0) debugPrintFileInit();
|
||||
|
||||
logMutex.Wait();
|
||||
RFs fserv;
|
||||
fserv.Connect();
|
||||
|
||||
TTime now; now.UniversalTime();
|
||||
TBuf<512> tmpBuff;
|
||||
TBuf8<512> tmpBuff8;
|
||||
TInt size, res;
|
||||
|
||||
RThread thisThread;
|
||||
RFile logFile;
|
||||
res = logFile.Open(fserv, _L("C:\\logs\\pico.log"), EFileWrite|EFileShareAny);
|
||||
if(res) goto fail1;
|
||||
|
||||
logFile.Size(size); logFile.Seek(ESeekStart, size);
|
||||
|
||||
now.FormatL(tmpBuff, _L("%H:%T:%S.%C: "));
|
||||
tmpBuff8.Copy(tmpBuff);
|
||||
logFile.Write(tmpBuff8);
|
||||
|
||||
tmpBuff8.Format(TPtr8((TUint8 *)"%03i: ", 6, 6), (TInt32) thisThread.Id());
|
||||
logFile.Write(tmpBuff8);
|
||||
|
||||
VA_LIST args;
|
||||
VA_START(args, aFmt);
|
||||
tmpBuff.FormatList(aFmt, args);
|
||||
VA_END(args);
|
||||
tmpBuff8.Copy(tmpBuff);
|
||||
logFile.Write(tmpBuff8);
|
||||
|
||||
logFile.Write(TPtrC8((TUint8 const *) "\n"));
|
||||
logFile.Flush();
|
||||
logFile.Close();
|
||||
fail1:
|
||||
thisThread.Close();
|
||||
fserv.Close();
|
||||
|
||||
logMutex.Signal();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
27
platform/uiq3/engine/debug.h
Normal file
27
platform/uiq3/engine/debug.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <e32std.h>
|
||||
|
||||
#define __DEBUG_PRINT_C
|
||||
#define __DEBUG_PRINT_FILE
|
||||
|
||||
#if defined(__DEBUG_PRINT) || defined(__WINS__)
|
||||
#include <e32svr.h> // RDebug
|
||||
#ifdef __DEBUG_PRINT_FILE
|
||||
void debugPrintFile(TRefByValue<const TDesC> aFmt, ...);
|
||||
#define DEBUGPRINT debugPrintFile
|
||||
#else
|
||||
#define DEBUGPRINT RDebug::Print
|
||||
#endif
|
||||
TDesC* DO_CONV(const char* s);
|
||||
#ifdef __DEBUG_PRINT_C
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
void dprintf(char *format, ...);
|
||||
#endif
|
||||
#else
|
||||
#define DEBUGPRINT(x...)
|
||||
#undef __DEBUG_PRINT_C
|
||||
#undef __DEBUG_PRINT_FILE
|
||||
#endif
|
||||
|
||||
void ExceptionHandler(TExcType exc);
|
999
platform/uiq3/engine/main.cpp
Normal file
999
platform/uiq3/engine/main.cpp
Normal file
|
@ -0,0 +1,999 @@
|
|||
// mainloop with window server event handling
|
||||
// event polling mechnism was taken from
|
||||
// Peter van Sebille's projects
|
||||
|
||||
// (c) Copyright 2006, notaz
|
||||
// All Rights Reserved
|
||||
|
||||
#include <e32base.h>
|
||||
#include <hal.h>
|
||||
#include <e32keys.h>
|
||||
#include <w32std.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "../Engine.h"
|
||||
|
||||
#include "../../../pico/picoInt.h"
|
||||
#include "vid.h"
|
||||
#include "polledAS.h"
|
||||
//#include "audio.h"
|
||||
#include "audio_mediaserver.h"
|
||||
|
||||
#include <EZlib.h>
|
||||
#include "../../../zlib/gzio_symb.h"
|
||||
|
||||
|
||||
//#define BENCHMARK
|
||||
|
||||
|
||||
// scancodes we care about
|
||||
enum TUsedScanCodes {
|
||||
EStdKeyM600JogUp = EStdKeyDevice1,
|
||||
EStdKeyM600JogDown = EStdKeyDevice2,
|
||||
};
|
||||
|
||||
static unsigned char keyFlags[256]; // lsb->msb: key_down, pulse_only, ?, ?, ?, ?, not_configurable, disabled
|
||||
static unsigned char pressedKeys[11]; // List of pressed key scancodes, up to 10
|
||||
|
||||
// list of areas
|
||||
TPicoAreaConfigEntry areaConfig[] = {
|
||||
{ TRect( 0, 0, 0, 0) },
|
||||
// small corner bottons
|
||||
{ TRect( 0, 0, 15, 15) },
|
||||
{ TRect(224, 0, 239, 15) },
|
||||
{ TRect( 0, 304, 15, 319) },
|
||||
{ TRect(224, 304, 239, 319) },
|
||||
// normal buttons
|
||||
{ TRect( 0, 0, 79, 63) },
|
||||
{ TRect( 80, 0, 159, 63) },
|
||||
{ TRect(160, 0, 239, 63) },
|
||||
{ TRect( 0, 64, 79, 127) },
|
||||
{ TRect( 80, 64, 159, 127) },
|
||||
{ TRect(160, 64, 239, 127) },
|
||||
{ TRect( 0, 128, 79, 191) },
|
||||
{ TRect( 80, 128, 159, 191) },
|
||||
{ TRect(160, 128, 239, 191) },
|
||||
{ TRect( 0, 192, 79, 255) },
|
||||
{ TRect( 80, 192, 159, 255) },
|
||||
{ TRect(160, 192, 239, 255) },
|
||||
{ TRect( 0, 256, 79, 319) },
|
||||
{ TRect( 80, 256, 159, 319) },
|
||||
{ TRect(160, 256, 239, 319) },
|
||||
{ TRect( 0, 0, 0, 0) }
|
||||
};
|
||||
|
||||
// PicoPad[] format: SACB RLDU
|
||||
const char *actionNames[] = {
|
||||
"UP", "DOWN", "LEFT", "RIGHT", "B", "C", "A", "START",
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // Z, Y, X, MODE (enabled only when needed), ?, ?, ?, ?
|
||||
0, 0, 0, 0, "VOLUME@UP", "VOLUME@DOWN", "NEXT@SAVE@SLOT", "PREV@SAVE@SLOT", // ?, ?, ?, ?, vol_up, vol_down, next_slot, prev_slot
|
||||
0, 0, "PAUSE@EMU", "SAVE@STATE", "LOAD@STATE", 0, 0, "DONE" // ?, switch_renderer, [...], "FRAMESKIP@8", "AUTO@FRAMESKIP"
|
||||
};
|
||||
|
||||
|
||||
// globals are allowed, so why not to (ab)use them?
|
||||
//TInt machineUid = 0;
|
||||
int gamestate = PGS_Paused, gamestate_next = PGS_Paused;
|
||||
TPicoConfig *currentConfig = 0;
|
||||
static char noticeMsg[64]; // notice msg to draw
|
||||
static timeval noticeMsgTime = { 0, 0 }; // when started showing
|
||||
static CGameAudioMS *gameAudio = 0; // the audio object itself
|
||||
static int reset_timing, pico_was_reset;
|
||||
static int state_slot = 0;
|
||||
extern const char *RomFileName;
|
||||
extern RSemaphore initSemaphore;
|
||||
extern RSemaphore pauseSemaphore;
|
||||
|
||||
// some forward declarations
|
||||
static void MainInit();
|
||||
static void MainExit();
|
||||
static void DumpMemInfo();
|
||||
void MainOldCleanup();
|
||||
|
||||
|
||||
class TPicoDirectScreenAccess : public MDirectScreenAccess
|
||||
{
|
||||
public: // implements MDirectScreenAccess
|
||||
void Restart(RDirectScreenAccess::TTerminationReasons aReason);
|
||||
public: // implements MAbortDirectScreenAccess
|
||||
void AbortNow(RDirectScreenAccess::TTerminationReasons aReason);
|
||||
};
|
||||
|
||||
|
||||
// just for a nicer grouping of WS related stuff
|
||||
class CGameWindow
|
||||
{
|
||||
public:
|
||||
static void ConstructResourcesL(void);
|
||||
static void FreeResources(void);
|
||||
static void DoKeys(void);
|
||||
static void DoKeysConfig(TUint &which);
|
||||
static void RunEvents(TUint32 which);
|
||||
|
||||
static RWsSession* iWsSession;
|
||||
static RWindowGroup iWsWindowGroup;
|
||||
static RWindow iWsWindow;
|
||||
static CWsScreenDevice* iWsScreen;
|
||||
static CWindowGc* iWindowGc;
|
||||
static TRequestStatus iWsEventStatus;
|
||||
// static TThreadId iLauncherThreadId;
|
||||
// static RDirectScreenAccess* iDSA;
|
||||
// static TRequestStatus iDSAstatus;
|
||||
static TPicoDirectScreenAccess iPDSA;
|
||||
static CDirectScreenAccess* iDSA;
|
||||
};
|
||||
|
||||
|
||||
static int snd_excess_add = 0, snd_excess_cnt = 0; // hack
|
||||
|
||||
static void updateSound(void)
|
||||
{
|
||||
int len = PsndLen;
|
||||
|
||||
snd_excess_cnt += snd_excess_add;
|
||||
if (snd_excess_cnt >= 0x10000) {
|
||||
snd_excess_cnt -= 0x10000;
|
||||
if (PicoOpt&8) {
|
||||
PsndOut[len*2] = PsndOut[len*2-2];
|
||||
PsndOut[len*2+1] = PsndOut[len*2-1];
|
||||
} else {
|
||||
PsndOut[len] = PsndOut[len-1];
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
PsndOut = gameAudio->NextFrameL(len);
|
||||
if(!PsndOut) { // sound output problems?
|
||||
strcpy(noticeMsg, "SOUND@OUTPUT@ERROR;@SOUND@DISABLED");
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SkipFrame(void)
|
||||
{
|
||||
PicoSkipFrame=1;
|
||||
PicoFrame();
|
||||
PicoSkipFrame=0;
|
||||
}
|
||||
|
||||
|
||||
static void simpleWait(int thissec, int lim_time)
|
||||
{
|
||||
struct timeval tval;
|
||||
int sleep = 0;
|
||||
|
||||
gettimeofday(&tval, 0);
|
||||
if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
|
||||
|
||||
sleep = lim_time - tval.tv_usec - 2000;
|
||||
if (sleep > 0) {
|
||||
// User::After((sleep = lim_time - tval.tv_usec));
|
||||
User::AfterHighRes(sleep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void TargetEpocGameL()
|
||||
{
|
||||
char buff[24]; // fps count c string
|
||||
struct timeval tval; // timing
|
||||
int thissec = 0, frames_done = 0, frames_shown = 0;
|
||||
int target_fps, target_frametime;
|
||||
int i, lim_time;
|
||||
//TRawEvent blevent;
|
||||
|
||||
MainInit();
|
||||
buff[0] = 0;
|
||||
|
||||
// just to keep the backlight on (works only on UIQ2)
|
||||
//blevent.Set(TRawEvent::EActive);
|
||||
|
||||
// loop?
|
||||
for(;;) {
|
||||
if(gamestate == PGS_Running) {
|
||||
// switch context to other thread
|
||||
User::After(50000);
|
||||
// prepare window and stuff
|
||||
CGameWindow::ConstructResourcesL();
|
||||
|
||||
// if the system has something to do, it should better do it now
|
||||
User::After(50000);
|
||||
//CPolledActiveScheduler::Instance()->Schedule();
|
||||
|
||||
// pal/ntsc might have changed, reset related stuff
|
||||
if(Pico.m.pal) {
|
||||
target_fps = 50;
|
||||
if(!noticeMsgTime.tv_sec) strcpy(noticeMsg, "PAL@SYSTEM@/@50@FPS");
|
||||
} else {
|
||||
target_fps = 60;
|
||||
if(!noticeMsgTime.tv_sec) strcpy(noticeMsg, "NTSC@SYSTEM@/@60@FPS");
|
||||
}
|
||||
target_frametime = 1000000/target_fps;
|
||||
if(!noticeMsgTime.tv_sec && pico_was_reset)
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
|
||||
if (PsndOut) {
|
||||
snd_excess_cnt = 0;
|
||||
snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps;
|
||||
}
|
||||
|
||||
pico_was_reset = 0;
|
||||
reset_timing = 1;
|
||||
|
||||
while(gamestate == PGS_Running) {
|
||||
gettimeofday(&tval, 0);
|
||||
if(reset_timing) {
|
||||
reset_timing = 0;
|
||||
thissec = tval.tv_sec;
|
||||
frames_done = tval.tv_usec/target_frametime;
|
||||
}
|
||||
|
||||
// show notice message?
|
||||
char *notice = 0;
|
||||
if(noticeMsgTime.tv_sec) {
|
||||
if((tval.tv_sec*1000000+tval.tv_usec) - (noticeMsgTime.tv_sec*1000000+noticeMsgTime.tv_usec) > 2000000) // > 2.0 sec
|
||||
noticeMsgTime.tv_sec = noticeMsgTime.tv_usec = 0;
|
||||
else notice = noticeMsg;
|
||||
}
|
||||
|
||||
// second changed?
|
||||
if(thissec != tval.tv_sec) {
|
||||
#ifdef BENCHMARK
|
||||
static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4];
|
||||
if(++bench == 10) {
|
||||
bench = 0;
|
||||
bench_fps_s = bench_fps;
|
||||
bf[bfp++ & 3] = bench_fps;
|
||||
bench_fps = 0;
|
||||
}
|
||||
bench_fps += frames_shown;
|
||||
sprintf(buff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2);
|
||||
#else
|
||||
if(currentConfig->iFlags & 2)
|
||||
sprintf(buff, "%02i/%02i", frames_shown, frames_done);
|
||||
#endif
|
||||
|
||||
|
||||
thissec = tval.tv_sec;
|
||||
|
||||
if(PsndOut == 0 && currentConfig->iFrameskip >= 0) {
|
||||
frames_done = frames_shown = 0;
|
||||
} else {
|
||||
// it is quite common for this implementation to leave 1 fame unfinished
|
||||
// when second changes, but we don't want buffer to starve.
|
||||
if(PsndOut && frames_done < target_fps && frames_done > target_fps-5) {
|
||||
SkipFrame(); frames_done++;
|
||||
}
|
||||
|
||||
frames_done -= target_fps; if (frames_done < 0) frames_done = 0;
|
||||
frames_shown -= target_fps; if (frames_shown < 0) frames_shown = 0;
|
||||
if (frames_shown > frames_done) frames_shown = frames_done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lim_time = (frames_done+1) * target_frametime;
|
||||
if(currentConfig->iFrameskip >= 0) { // frameskip enabled
|
||||
for(i = 0; i < currentConfig->iFrameskip; i++) {
|
||||
CGameWindow::DoKeys();
|
||||
SkipFrame(); frames_done++;
|
||||
if (PsndOut) { // do framelimitting if sound is enabled
|
||||
gettimeofday(&tval, 0);
|
||||
if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
|
||||
if(tval.tv_usec < lim_time) { // we are too fast
|
||||
simpleWait(thissec, lim_time);
|
||||
}
|
||||
}
|
||||
lim_time += target_frametime;
|
||||
}
|
||||
} else if(tval.tv_usec > lim_time) { // auto frameskip
|
||||
// no time left for this frame - skip
|
||||
CGameWindow::DoKeys();
|
||||
SkipFrame(); frames_done++;
|
||||
continue;
|
||||
}
|
||||
|
||||
CGameWindow::DoKeys();
|
||||
PicoFrame();
|
||||
|
||||
// check time
|
||||
gettimeofday(&tval, 0);
|
||||
if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
|
||||
|
||||
// sleep if we are still too fast
|
||||
if(PsndOut != 0 || currentConfig->iFrameskip < 0)
|
||||
{
|
||||
// TODO: check if User::After() is accurate
|
||||
gettimeofday(&tval, 0);
|
||||
if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
|
||||
if(tval.tv_usec < lim_time)
|
||||
{
|
||||
// we are too fast
|
||||
simpleWait(thissec, lim_time);
|
||||
}
|
||||
}
|
||||
|
||||
CPolledActiveScheduler::Instance()->Schedule();
|
||||
|
||||
if (gamestate != PGS_Paused)
|
||||
vidDrawFrame(notice, buff, frames_shown);
|
||||
|
||||
frames_done++; frames_shown++;
|
||||
}
|
||||
|
||||
// save SRAM
|
||||
if((currentConfig->iFlags & 1) && SRam.changed) {
|
||||
saveLoadGame(0, 1);
|
||||
SRam.changed = 0;
|
||||
}
|
||||
CGameWindow::FreeResources();
|
||||
} else if(gamestate == PGS_Paused) {
|
||||
DEBUGPRINT(_L("pausing.."));
|
||||
pauseSemaphore.Wait();
|
||||
} else if(gamestate == PGS_KeyConfig) {
|
||||
// switch context to other thread
|
||||
User::After(50000);
|
||||
// prepare window and stuff
|
||||
CGameWindow::ConstructResourcesL();
|
||||
|
||||
TUint whichAction = 0;
|
||||
while(gamestate == PGS_KeyConfig) {
|
||||
CGameWindow::DoKeysConfig(whichAction);
|
||||
CPolledActiveScheduler::Instance()->Schedule();
|
||||
if (gamestate != PGS_Paused)
|
||||
vidKeyConfigFrame(whichAction);
|
||||
User::After(150000);
|
||||
}
|
||||
|
||||
CGameWindow::FreeResources();
|
||||
} else if(gamestate == PGS_DebugHeap) {
|
||||
#ifdef __DEBUG_PRINT
|
||||
TInt cells = User::CountAllocCells();
|
||||
TInt mem;
|
||||
User::AllocSize(mem);
|
||||
DEBUGPRINT(_L("worker: cels=%d, size=%d KB"), cells, mem/1024);
|
||||
gamestate = gamestate_next;
|
||||
#endif
|
||||
} else if(gamestate == PGS_Quit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MainExit();
|
||||
}
|
||||
|
||||
|
||||
// main initialization
|
||||
static void MainInit()
|
||||
{
|
||||
DEBUGPRINT(_L("\r\n\r\nstarting.."));
|
||||
|
||||
// our thread might have been crashed previously, so many other objects may be still floating around
|
||||
MainOldCleanup();
|
||||
|
||||
DEBUGPRINT(_L("CPolledActiveScheduler::NewL()"));
|
||||
CPolledActiveScheduler::NewL(); // create Polled AS for the sound engine
|
||||
|
||||
// HAL::Get(HALData::EMachineUid, machineUid); // find out the machine UID
|
||||
|
||||
DumpMemInfo();
|
||||
|
||||
// try to start pico
|
||||
DEBUGPRINT(_L("PicoInit();"));
|
||||
PicoInit();
|
||||
PicoDrawSetColorFormat(2);
|
||||
PicoWriteSound = updateSound;
|
||||
|
||||
// if (pauseSemaphore.Handle() <= 0)
|
||||
// pauseSemaphore.CreateLocal(0);
|
||||
DEBUGPRINT(_L("initSemaphore.Signal()"));
|
||||
initSemaphore.Signal();
|
||||
}
|
||||
|
||||
|
||||
// does not return
|
||||
static void MainExit()
|
||||
{
|
||||
RThread thisThread;
|
||||
|
||||
DEBUGPRINT(_L("%i: cleaning up.."), (TInt32) thisThread.Id());
|
||||
|
||||
// save SRAM
|
||||
if((currentConfig->iFlags & 1) && SRam.changed) {
|
||||
saveLoadGame(0, 1);
|
||||
SRam.changed = 0;
|
||||
}
|
||||
|
||||
PicoExit();
|
||||
// pauseSemaphore.Close();
|
||||
|
||||
if(gameAudio) delete gameAudio;
|
||||
|
||||
// Polled AS
|
||||
delete CPolledActiveScheduler::Instance();
|
||||
}
|
||||
|
||||
void MainOldCleanup()
|
||||
{
|
||||
DEBUGPRINT(_L("MainOldCleanup.."));
|
||||
|
||||
// There was previously a handle leak here, so thread stuff was not cleaned
|
||||
// and I thought I would have to do it mself.
|
||||
|
||||
// clean any resources which might be left after a thread crash
|
||||
//CGameWindow::FreeResources(ETrue);
|
||||
|
||||
//if(CPolledActiveScheduler::Instance())
|
||||
// delete CPolledActiveScheduler::Instance();
|
||||
}
|
||||
|
||||
static void DumpMemInfo()
|
||||
{
|
||||
TInt ramSize, ramSizeFree, romSize;
|
||||
|
||||
HAL::Get(HALData::EMemoryRAM, ramSize);
|
||||
HAL::Get(HALData::EMemoryRAMFree, ramSizeFree);
|
||||
HAL::Get(HALData::EMemoryROM, romSize);
|
||||
|
||||
DEBUGPRINT(_L("ram=%dKB, ram_free=%dKB, rom=%dKB"), ramSize/1024, ramSizeFree/1024, romSize/1024);
|
||||
}
|
||||
|
||||
|
||||
TInt EmuThreadFunction(TAny*)
|
||||
{
|
||||
const TUint32 exs = KExceptionAbort|KExceptionKill|KExceptionUserInterrupt|KExceptionFpe|KExceptionFault|KExceptionInteger|KExceptionDebug;
|
||||
|
||||
DEBUGPRINT(_L("EmuThreadFunction()"));
|
||||
User::SetExceptionHandler(ExceptionHandler, exs/*(TUint32) -1*/); // does not work?
|
||||
|
||||
//TInt pc, sp;
|
||||
//asm volatile ("str pc, %0" : "=m" (pc) );
|
||||
//asm volatile ("str sp, %0" : "=m" (sp) );
|
||||
//RDebug::Print(_L("executing @ 0x%08x, sp=0x%08x"), pc, sp);
|
||||
|
||||
/*
|
||||
RDebug::Print(_L("Base Bottom Top Size RW Name"));
|
||||
TBuf<4> l_r(_L("R")), l_w(_L("W")), l_d(_L("-"));
|
||||
RChunk chunk;
|
||||
TFullName chunkname;
|
||||
TFindChunk findChunk(_L("*"));
|
||||
while( findChunk.Next(chunkname) != KErrNotFound ) {
|
||||
chunk.Open(findChunk);
|
||||
RDebug::Print(_L("%08x %08x %08x %08x %S%S %S"), chunk.Base(), chunk.Base()+chunk.Bottom(), chunk.Base()+chunk.Top(), chunk.Size(), chunk.IsReadable() ? &l_r : &l_d, chunk.IsWritable() ? &l_w : &l_d, &chunkname);
|
||||
chunk.Close();
|
||||
}
|
||||
*/
|
||||
|
||||
// can't do that, will crash here
|
||||
// if(cleanup) {
|
||||
// DEBUGPRINT(_L("found old CTrapCleanup, deleting.."));
|
||||
// delete cleanup;
|
||||
// }
|
||||
|
||||
CTrapCleanup *cleanup = CTrapCleanup::New();
|
||||
|
||||
TRAPD(error, TargetEpocGameL());
|
||||
|
||||
__ASSERT_ALWAYS(!error, User::Panic(_L("Picosmall"), error));
|
||||
delete cleanup;
|
||||
|
||||
DEBUGPRINT(_L("exitting.."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void TPicoDirectScreenAccess::Restart(RDirectScreenAccess::TTerminationReasons aReason)
|
||||
{
|
||||
DEBUGPRINT(_L("TPicoDirectScreenAccess::Restart(%i)"), aReason);
|
||||
|
||||
// if (CGameWindow::iDSA) {
|
||||
// TRAPD(error, CGameWindow::iDSA->StartL());
|
||||
// if (error) DEBUGPRINT(_L("iDSA->StartL() error: %i"), error);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void TPicoDirectScreenAccess::AbortNow(RDirectScreenAccess::TTerminationReasons aReason)
|
||||
{
|
||||
DEBUGPRINT(_L("TPicoDirectScreenAccess::AbortNow(%i)"), aReason);
|
||||
|
||||
// the WS wants us to stop, so let's obey
|
||||
gamestate = PGS_Paused;
|
||||
}
|
||||
|
||||
|
||||
void CGameWindow::ConstructResourcesL()
|
||||
{
|
||||
DEBUGPRINT(_L("ConstructResourcesL()"));
|
||||
// connect to window server
|
||||
// tried to create it globally and not re-connect everytime,
|
||||
// but my window started to lose focus strangely
|
||||
iWsSession = new(ELeave) RWsSession();
|
||||
User::LeaveIfError(iWsSession->Connect());
|
||||
|
||||
// * Tell the Window Server not to mess about with our process priority
|
||||
// * Also, because of the way legacy games are written, they never sleep
|
||||
// * and thus never voluntarily yield the CPU. We set our process priority
|
||||
// * to EPriorityForeground and hope that a Telephony application on
|
||||
// * this device runs at EPriorityForeground as well. If not, tough! ;-)
|
||||
|
||||
iWsSession->ComputeMode(RWsSession::EPriorityControlDisabled);
|
||||
RProcess me;
|
||||
me.SetPriority(EPriorityForeground);
|
||||
|
||||
iWsScreen = new(ELeave) CWsScreenDevice(*iWsSession);
|
||||
User::LeaveIfError(iWsScreen->Construct());
|
||||
// User::LeaveIfError(iWsScreen->CreateContext(iWindowGc));
|
||||
|
||||
iWsWindowGroup = RWindowGroup(*iWsSession);
|
||||
User::LeaveIfError(iWsWindowGroup.Construct((TUint32)&iWsWindowGroup));
|
||||
//iWsWindowGroup.SetOrdinalPosition(0);
|
||||
//iWsWindowGroup.SetName(KServerWGName);
|
||||
iWsWindowGroup.EnableScreenChangeEvents(); // flip events (EEventScreenDeviceChanged)
|
||||
iWsWindowGroup.EnableFocusChangeEvents(); // EEventFocusGroupChanged
|
||||
iWsWindowGroup.SetOrdinalPosition(0, 1); // TInt aPos, TInt aOrdinalPriority
|
||||
|
||||
iWsWindow=RWindow(*iWsSession);
|
||||
User::LeaveIfError(iWsWindow.Construct(iWsWindowGroup, (TUint32)&iWsWindow));
|
||||
iWsWindow.SetSize(iWsScreen->SizeInPixels());
|
||||
iWsWindow.PointerFilter(EPointerFilterDrag, 0);
|
||||
iWsWindow.SetPointerGrab(ETrue);
|
||||
iWsWindow.SetVisible(ETrue);
|
||||
iWsWindow.Activate();
|
||||
|
||||
#if 0
|
||||
// request access through RDirectScreenAccess api, but don't care about the result
|
||||
// hangs?
|
||||
RRegion *dsa_region = 0;
|
||||
iDSA = new(ELeave) RDirectScreenAccess(*iWsSession);
|
||||
if(iDSA->Construct() == KErrNone)
|
||||
iDSA->Request(dsa_region, iDSAstatus, iWsWindow);
|
||||
DEBUGPRINT(_L("DSA: %i"), dsa_region ? dsa_region->Count() : -1);
|
||||
#endif
|
||||
|
||||
TInt ret;
|
||||
|
||||
// request access through CDirectScreenAccess
|
||||
iDSA = CDirectScreenAccess::NewL(*iWsSession, *iWsScreen, iWsWindow, iPDSA);
|
||||
|
||||
// now get the screenbuffer
|
||||
TScreenInfoV01 screenInfo;
|
||||
TPckg<TScreenInfoV01> sI(screenInfo);
|
||||
UserSvr::ScreenInfo(sI);
|
||||
|
||||
if(!screenInfo.iScreenAddressValid)
|
||||
User::Leave(KErrNotSupported);
|
||||
|
||||
DEBUGPRINT(_L("framebuffer=0x%08x (%dx%d)"), screenInfo.iScreenAddress,
|
||||
screenInfo.iScreenSize.iWidth, screenInfo.iScreenSize.iHeight);
|
||||
|
||||
// vidInit
|
||||
DEBUGPRINT(_L("vidInit()"));
|
||||
ret = vidInit((void *)screenInfo.iScreenAddress, 0);
|
||||
DEBUGPRINT(_L("vidInit() done (%i)"), ret);
|
||||
|
||||
User::LeaveIfError(ret);
|
||||
|
||||
memset(keyFlags, 0, 256);
|
||||
keyFlags[EStdKeyM600JogUp] = keyFlags[EStdKeyM600JogDown] = 2; // add "pulse only" for jog up/down
|
||||
keyFlags[EStdKeyOff] = 0x40; // not configurable
|
||||
|
||||
// try to start the audio engine
|
||||
static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0;
|
||||
|
||||
if(gamestate == PGS_Running && (currentConfig->iFlags & 4)) {
|
||||
TInt err = 0;
|
||||
if(PsndRate != PsndRate_old || (PicoOpt&11) != (PicoOpt_old&11) || Pico.m.pal != pal_old) {
|
||||
// if rate changed, reset all enabled chips, else reset only those chips, which were recently enabled
|
||||
//sound_reset(PsndRate != PsndRate_old ? PicoOpt : (PicoOpt&(PicoOpt^PicoOpt_old)));
|
||||
sound_rerate();
|
||||
}
|
||||
if(!gameAudio || PsndRate != PsndRate_old || ((PicoOpt&8) ^ (PicoOpt_old&8)) || Pico.m.pal != pal_old) { // rate or stereo or pal/ntsc changed
|
||||
if(gameAudio) delete gameAudio; gameAudio = 0;
|
||||
DEBUGPRINT(_L("starting audio: %i len: %i stereo: %i, pal: %i"), PsndRate, PsndLen, PicoOpt&8, Pico.m.pal);
|
||||
TRAP(err, gameAudio = CGameAudioMS::NewL(PsndRate, (PicoOpt&8) ? 1 : 0, Pico.m.pal ? 50 : 60));
|
||||
}
|
||||
if( gameAudio) {
|
||||
TRAP(err, PsndOut = gameAudio->ResumeL());
|
||||
}
|
||||
if(err) {
|
||||
if(gameAudio) delete gameAudio;
|
||||
gameAudio = 0;
|
||||
PsndOut = 0;
|
||||
strcpy(noticeMsg, "SOUND@STARTUP@FAILED");
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
}
|
||||
PsndRate_old = PsndRate;
|
||||
PicoOpt_old = PicoOpt;
|
||||
pal_old = Pico.m.pal;
|
||||
} else {
|
||||
if(gameAudio) delete gameAudio;
|
||||
gameAudio = 0;
|
||||
PsndOut = 0;
|
||||
}
|
||||
|
||||
CPolledActiveScheduler::Instance()->Schedule();
|
||||
|
||||
// start key WS event polling
|
||||
iWsSession->EventReady(&iWsEventStatus);
|
||||
|
||||
iWsSession->Flush(); // check: short hang in UIQ2
|
||||
User::After(1);
|
||||
|
||||
// I don't know why but the Window server sometimes hangs completely (hanging the phone too) after calling StartL()
|
||||
// Is this a sync broblem? weird bug?
|
||||
TRAP(ret, iDSA->StartL());
|
||||
if (ret) DEBUGPRINT(_L("iDSA->StartL() error: %i"), ret);
|
||||
|
||||
// User::After(1);
|
||||
// CPolledActiveScheduler::Instance()->Schedule();
|
||||
|
||||
DEBUGPRINT(_L("CGameWindow::ConstructResourcesL() finished."));
|
||||
}
|
||||
|
||||
// this may be run even if there is nothing to free
|
||||
void CGameWindow::FreeResources()
|
||||
{
|
||||
if(gameAudio) gameAudio->Pause();
|
||||
|
||||
//DEBUGPRINT(_L("CPolledActiveScheduler::Instance(): %08x"), CPolledActiveScheduler::Instance());
|
||||
if(CPolledActiveScheduler::Instance())
|
||||
CPolledActiveScheduler::Instance()->Schedule();
|
||||
|
||||
#if 0
|
||||
// free RDirectScreenAccess stuff (seems to be deleted automatically after crash?)
|
||||
if(iDSA) {
|
||||
iDSA->Cancel();
|
||||
iDSA->Close();
|
||||
delete iDSA;
|
||||
}
|
||||
iDSA = NULL;
|
||||
#endif
|
||||
if(iDSA) delete iDSA;
|
||||
iDSA = 0;
|
||||
|
||||
if(iWsSession->WsHandle() > 0 && iWsEventStatus != KRequestPending) // TODO: 2 UIQ2 (?)
|
||||
iWsSession->EventReadyCancel();
|
||||
|
||||
if(iWsWindow.WsHandle() > 0)
|
||||
iWsWindow.Close();
|
||||
|
||||
if(iWsWindowGroup.WsHandle() > 0)
|
||||
iWsWindowGroup.Close();
|
||||
|
||||
// these must be deleted before calling iWsSession->Close()
|
||||
if(iWsScreen) {
|
||||
delete iWsScreen;
|
||||
iWsScreen = NULL;
|
||||
}
|
||||
|
||||
if(iWsSession->WsHandle() > 0) {
|
||||
iWsSession->Close();
|
||||
delete iWsSession;
|
||||
}
|
||||
|
||||
vidFree();
|
||||
|
||||
// emu might change renderer by itself, so we may need to sync config
|
||||
if(currentConfig && currentConfig->iPicoOpt != PicoOpt) {
|
||||
currentConfig->iFlags |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGameWindow::DoKeys(void)
|
||||
{
|
||||
TWsEvent iWsEvent;
|
||||
TInt iWsEventType;
|
||||
unsigned long allActions = 0;
|
||||
static unsigned long areaActions = 0, forceUpdate = 0;
|
||||
int i, nEvents;
|
||||
|
||||
for(nEvents = 0; iWsEventStatus != KRequestPending; nEvents++)
|
||||
{
|
||||
iWsSession->GetEvent(iWsEvent);
|
||||
iWsEventType = iWsEvent.Type();
|
||||
|
||||
// pointer events?
|
||||
if(iWsEventType == EEventPointer) {
|
||||
if(iWsEvent.Pointer()->iType == TPointerEvent::EButton1Up) {
|
||||
areaActions = 0; // remove all directionals
|
||||
} else { // if(iWsEvent.Pointer()->iType == TPointerEvent::EButton1Down) {
|
||||
TPoint p = iWsEvent.Pointer()->iPosition;
|
||||
const TPicoAreaConfigEntry *e = areaConfig + 1;
|
||||
for(i = 0; !e->rect.IsEmpty(); e++, i++)
|
||||
if(e->rect.Contains(p)) {
|
||||
areaActions = currentConfig->iAreaBinds[i];
|
||||
break;
|
||||
}
|
||||
//DEBUGPRINT(_L("pointer event: %i %i"), p.iX, p.iY);
|
||||
}
|
||||
}
|
||||
else if(iWsEventType == EEventKeyDown || iWsEventType == EEventKeyUp) {
|
||||
TInt iScanCode = iWsEvent.Key()->iScanCode;
|
||||
//DEBUGPRINT(_L("key event: 0x%02x"), iScanCode);
|
||||
|
||||
if(iScanCode < 256)
|
||||
{
|
||||
if(iWsEventType == EEventKeyDown) {
|
||||
keyFlags[iScanCode] |= 1;
|
||||
for(i=0; i < 10; i++) {
|
||||
if( pressedKeys[i] == (TUint8) iScanCode) break;
|
||||
if(!pressedKeys[i]) { pressedKeys[i] = (TUint8) iScanCode; break; }
|
||||
}
|
||||
} else if(!(keyFlags[iScanCode]&2)) {
|
||||
keyFlags[iScanCode] &= ~1;
|
||||
for(i=0; i < 10; i++) {
|
||||
if(pressedKeys[i] == (TUint8) iScanCode) { pressedKeys[i] = 0; break; }
|
||||
}
|
||||
}
|
||||
|
||||
// power?
|
||||
if(iScanCode == EStdKeyOff) gamestate = PGS_Paused;
|
||||
} else {
|
||||
DEBUGPRINT(_L("weird scancode: 0x%02x"), iScanCode);
|
||||
}
|
||||
}
|
||||
else if(iWsEventType == EEventScreenDeviceChanged) {
|
||||
// ???
|
||||
//User::After(500000);
|
||||
//reset_timing = 1;
|
||||
DEBUGPRINT(_L("EEventScreenDeviceChanged, focus: %i, our: %i"),
|
||||
iWsSession->GetFocusWindowGroup(), iWsWindowGroup.Identifier());
|
||||
}
|
||||
else if(iWsEventType == EEventFocusGroupChanged) {
|
||||
TInt focusGrpId = iWsSession->GetFocusWindowGroup();
|
||||
DEBUGPRINT(_L("EEventFocusGroupChanged: %i, our: %i"),
|
||||
focusGrpId, iWsWindowGroup.Identifier());
|
||||
// if it is not us and not launcher that got focus, pause emu
|
||||
if(focusGrpId != iWsWindowGroup.Identifier())
|
||||
gamestate = PGS_Paused;
|
||||
}
|
||||
|
||||
iWsEventStatus = KRequestPending;
|
||||
iWsSession->EventReady(&iWsEventStatus);
|
||||
}
|
||||
|
||||
if(nEvents || forceUpdate) {
|
||||
allActions = areaActions;
|
||||
forceUpdate = 0;
|
||||
|
||||
// add all pushed button actions
|
||||
for(i = 9; i >= 0; i--) {
|
||||
int scan = pressedKeys[i];
|
||||
if(scan) {
|
||||
if(keyFlags[scan] & 1) allActions |= currentConfig->iKeyBinds[scan];
|
||||
if((keyFlags[scan]& 3)==3) forceUpdate = 1;
|
||||
if(keyFlags[scan] & 2) keyFlags[scan] &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
PicoPad[0] = (unsigned short) allActions;
|
||||
if(allActions & 0xFFFF0000) {
|
||||
RunEvents(allActions >> 16);
|
||||
areaActions = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGameWindow::DoKeysConfig(TUint &which)
|
||||
{
|
||||
TWsEvent iWsEvent;
|
||||
int i;
|
||||
|
||||
while(iWsEventStatus != KRequestPending)
|
||||
{
|
||||
TUint currentActCode = 1 << which;
|
||||
|
||||
iWsSession->GetEvent(iWsEvent);
|
||||
|
||||
// pointer events?
|
||||
if(iWsEvent.Type() == EEventPointer) {
|
||||
TPoint p = iWsEvent.Pointer()->iPosition;
|
||||
TRect prev(56, 0, 120, 26);
|
||||
TRect next(120, 0, 180, 26);
|
||||
|
||||
if(iWsEvent.Pointer()->iType == TPointerEvent::EButton1Down) {
|
||||
if(prev.Contains(p)) do { which = (which-1) & 0x1F; } while(!actionNames[which]);
|
||||
else if(next.Contains(p)) do { which = (which+1) & 0x1F; } while(!actionNames[which]);
|
||||
else if(which == 31) gamestate = PGS_Paused; // done
|
||||
else {
|
||||
const TPicoAreaConfigEntry *e = areaConfig + 1;
|
||||
for(i = 0; e->rect != TRect(0,0,0,0); e++, i++)
|
||||
if(e->rect.Contains(p)) {
|
||||
currentConfig->iAreaBinds[i] ^= currentActCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(iWsEvent.Type() == EEventKeyDown || iWsEvent.Type() == EEventKeyUp)
|
||||
{
|
||||
TUint scan = (TUint) iWsEvent.Key()->iScanCode;
|
||||
|
||||
// key events?
|
||||
if(iWsEvent.Type() == EEventKeyDown) {
|
||||
if(which == 31) {
|
||||
gamestate = PGS_Paused;
|
||||
} else if (scan < 256) {
|
||||
if(!(keyFlags[scan]&0x40)) currentConfig->iKeyBinds[scan] ^= currentActCode;
|
||||
}
|
||||
}
|
||||
|
||||
// power?
|
||||
if(iWsEvent.Key()->iScanCode == EStdKeyOff) gamestate = PGS_Paused;
|
||||
}
|
||||
else if(iWsEvent.Type() == EEventFocusGroupChanged) {
|
||||
TInt focusGrpId = iWsSession->GetFocusWindowGroup();
|
||||
// if we lost focus, exit config mode
|
||||
if(focusGrpId != iWsWindowGroup.Identifier())
|
||||
gamestate = PGS_Paused;
|
||||
}
|
||||
|
||||
// iWsEventStatus = KRequestPending;
|
||||
iWsSession->EventReady(&iWsEventStatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGameWindow::RunEvents(TUint32 which)
|
||||
{
|
||||
if(which & 0x4000) currentConfig->iFrameskip = -1;
|
||||
if(which & 0x2000) currentConfig->iFrameskip = 8;
|
||||
if(which & 0x1800) { // save or load (but not both)
|
||||
if(PsndOut) gameAudio->Pause(); // this may take a while, so we pause sound output
|
||||
|
||||
vidDrawNotice((which & 0x1000) ? "LOADING@GAME" : "SAVING@GAME");
|
||||
saveLoadGame(which & 0x1000);
|
||||
|
||||
if(PsndOut) PsndOut = gameAudio->ResumeL();
|
||||
reset_timing = 1;
|
||||
}
|
||||
if(which & 0x0400) gamestate = PGS_Paused;
|
||||
if(which & 0x0200) { // switch renderer
|
||||
if(!(currentConfig->iScreenMode == TPicoConfig::PMFit &&
|
||||
(currentConfig->iScreenRotation == TPicoConfig::PRot0 || currentConfig->iScreenRotation == TPicoConfig::PRot180))) {
|
||||
|
||||
PicoOpt^=0x10;
|
||||
vidInit(0, 1);
|
||||
|
||||
strcpy(noticeMsg, (PicoOpt&0x10) ? "ALT@RENDERER" : "DEFAULT@RENDERER");
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
}
|
||||
}
|
||||
if(which & 0x00c0) {
|
||||
if(which&0x0080) {
|
||||
state_slot -= 1;
|
||||
if(state_slot < 0) state_slot = 9;
|
||||
} else {
|
||||
state_slot += 1;
|
||||
if(state_slot > 9) state_slot = 0;
|
||||
}
|
||||
sprintf(noticeMsg, "SAVE@SLOT@%i@SELECTED", state_slot);
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
}
|
||||
if(which & 0x0020) if(gameAudio) gameAudio->ChangeVolume(0);
|
||||
if(which & 0x0010) if(gameAudio) gameAudio->ChangeVolume(1);
|
||||
}
|
||||
|
||||
|
||||
// must use wrappers, or else will run into some weird loader error (see pico/area.c)
|
||||
static size_t fRead2(void *p, size_t _s, size_t _n, void *file)
|
||||
{
|
||||
return fread(p, _s, _n, (FILE *) file);
|
||||
}
|
||||
|
||||
static size_t fWrite2(void *p, size_t _s, size_t _n, void *file)
|
||||
{
|
||||
return fwrite(p, _s, _n, (FILE *) file);
|
||||
}
|
||||
|
||||
static size_t gzRead2(void *p, size_t, size_t _n, void *file)
|
||||
{
|
||||
return gzread(file, p, _n);
|
||||
}
|
||||
|
||||
static size_t gzWrite2(void *p, size_t, size_t _n, void *file)
|
||||
{
|
||||
return gzwrite(file, p, _n);
|
||||
}
|
||||
|
||||
|
||||
// this function is shared between both threads
|
||||
int saveLoadGame(int load, int sram)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if(!RomFileName) return -1;
|
||||
|
||||
// make save filename
|
||||
char saveFname[KMaxFileName];
|
||||
strcpy(saveFname, RomFileName);
|
||||
saveFname[KMaxFileName-8] = 0;
|
||||
if(saveFname[strlen(saveFname)-4] == '.') saveFname[strlen(saveFname)-4] = 0;
|
||||
if(sram) strcat(saveFname, ".srm");
|
||||
else {
|
||||
if(state_slot > 0 && state_slot < 10) sprintf(saveFname, "%s.%i", saveFname, state_slot);
|
||||
strcat(saveFname, ".mds");
|
||||
}
|
||||
|
||||
DEBUGPRINT(_L("saveLoad (%i, %i): %S"), load, sram, DO_CONV(saveFname));
|
||||
|
||||
if(sram) {
|
||||
FILE *sramFile;
|
||||
int sram_size = SRam.end-SRam.start+1;
|
||||
if(SRam.reg_back & 4) sram_size=0x2000;
|
||||
if(!SRam.data) return 0; // SRam forcefully disabled for this game
|
||||
if(load) {
|
||||
sramFile = fopen(saveFname, "rb");
|
||||
if(!sramFile) return -1;
|
||||
fread(SRam.data, 1, sram_size, sramFile);
|
||||
fclose(sramFile);
|
||||
} else {
|
||||
// sram save needs some special processing
|
||||
// see if we have anything to save
|
||||
for(; sram_size > 0; sram_size--)
|
||||
if(SRam.data[sram_size-1]) break;
|
||||
|
||||
if(sram_size) {
|
||||
sramFile = fopen(saveFname, "wb");
|
||||
res = fwrite(SRam.data, 1, sram_size, sramFile);
|
||||
res = (res != sram_size) ? -1 : 0;
|
||||
fclose(sramFile);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
void *PmovFile = NULL;
|
||||
// try gzip first
|
||||
if(currentConfig->iFlags & 0x80) {
|
||||
strcat(saveFname, ".gz");
|
||||
if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) {
|
||||
areaRead = gzRead2;
|
||||
areaWrite = gzWrite2;
|
||||
if(!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY);
|
||||
} else
|
||||
saveFname[strlen(saveFname)-3] = 0;
|
||||
}
|
||||
if(!PmovFile) { // gzip failed or was disabled
|
||||
if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) {
|
||||
areaRead = fRead2;
|
||||
areaWrite = fWrite2;
|
||||
}
|
||||
}
|
||||
if(PmovFile) {
|
||||
PmovState(load ? 6 : 5, PmovFile); // load/save
|
||||
strcpy(noticeMsg, load ? "GAME@LOADED" : "GAME@SAVED");
|
||||
if(areaRead == gzRead2)
|
||||
gzclose(PmovFile);
|
||||
else fclose ((FILE *) PmovFile);
|
||||
PmovFile = 0;
|
||||
if (load) Pico.m.dirtyPal=1;
|
||||
} else {
|
||||
strcpy(noticeMsg, load ? "LOAD@FAILED" : "SAVE@FAILED");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
gettimeofday(¬iceMsgTime, 0);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// static class members
|
||||
RWsSession* CGameWindow::iWsSession;
|
||||
RWindowGroup CGameWindow::iWsWindowGroup;
|
||||
RWindow CGameWindow::iWsWindow;
|
||||
CWsScreenDevice* CGameWindow::iWsScreen = NULL;
|
||||
CWindowGc* CGameWindow::iWindowGc = NULL;
|
||||
TRequestStatus CGameWindow::iWsEventStatus = KRequestPending;
|
||||
//RDirectScreenAccess* CGameWindow::iDSA;
|
||||
//TRequestStatus CGameWindow::iDSAstatus = KRequestPending;
|
||||
TPicoDirectScreenAccess CGameWindow::iPDSA;
|
||||
CDirectScreenAccess* CGameWindow::iDSA = NULL;
|
||||
|
269
platform/uiq3/engine/polledas.cpp
Normal file
269
platform/uiq3/engine/polledas.cpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*******************************************************************
|
||||
*
|
||||
* File: PolledAS.cpp
|
||||
*
|
||||
* Author: Peter van Sebille (peter@yipton.net)
|
||||
*
|
||||
* (c) Copyright 2002, Peter van Sebille
|
||||
* All Rights Reserved
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* Oh Lord, forgive me for I have sinned.
|
||||
* In their infinite wisdom, Symbian Engineers have decided that
|
||||
* the Active Scheduler's queue of Active Objects is private
|
||||
* and no getters are provided... sigh.
|
||||
* This mere mortal will have to excercise the power of C pre-processor
|
||||
* once more to circumvent the will of the gods.
|
||||
*/
|
||||
|
||||
|
||||
#include <e32std.h>
|
||||
|
||||
// from e32base.h
|
||||
class CBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Default constructor
|
||||
*/
|
||||
inline CBase() {}
|
||||
IMPORT_C virtual ~CBase();
|
||||
inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW { Mem::FillZ(aBase, aSize); return aBase; }
|
||||
inline TAny* operator new(TUint aSize) __NO_THROW { return User::AllocZ(aSize); }
|
||||
inline TAny* operator new(TUint aSize, TLeave) { return User::AllocZL(aSize); }
|
||||
inline TAny* operator new(TUint aSize, TUint aExtraSize) { return User::AllocZ(aSize + aExtraSize); }
|
||||
inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize) { return User::AllocZL(aSize + aExtraSize); }
|
||||
IMPORT_C static void Delete(CBase* aPtr);
|
||||
protected:
|
||||
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
|
||||
private:
|
||||
CBase(const CBase&);
|
||||
CBase& operator=(const CBase&);
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
class TRequestStatusFaked
|
||||
{
|
||||
public:
|
||||
inline TRequestStatusFaked() : iFlags(0) {};
|
||||
inline TRequestStatusFaked(TInt aVal) : iStatus(aVal), iFlags(aVal==KRequestPending ? TRequestStatusFaked::ERequestPending : 0) {}
|
||||
/* inline TInt operator=(TInt aVal);
|
||||
inline TBool operator==(TInt aVal) const;
|
||||
*/
|
||||
inline TBool operator!=(TInt aVal) const {return(iStatus!=aVal);}
|
||||
/*
|
||||
inline TBool operator>=(TInt aVal) const;
|
||||
inline TBool operator<=(TInt aVal) const;
|
||||
inline TBool operator>(TInt aVal) const;
|
||||
inline TBool operator<(TInt aVal) const;
|
||||
inline TInt Int() const;
|
||||
private:
|
||||
*/
|
||||
enum
|
||||
{
|
||||
EActive = 1, //bit0
|
||||
ERequestPending = 2, //bit1
|
||||
};
|
||||
TInt iStatus;
|
||||
TUint iFlags;
|
||||
friend class CActive;
|
||||
friend class CActiveScheduler;
|
||||
friend class CServer2;
|
||||
};
|
||||
|
||||
|
||||
class CActive : public CBase
|
||||
{
|
||||
public:
|
||||
enum TPriority
|
||||
{
|
||||
EPriorityIdle=-100,
|
||||
EPriorityLow=-20,
|
||||
EPriorityStandard=0,
|
||||
EPriorityUserInput=10,
|
||||
EPriorityHigh=20,
|
||||
};
|
||||
public:
|
||||
IMPORT_C ~CActive();
|
||||
IMPORT_C void Cancel();
|
||||
IMPORT_C void Deque();
|
||||
IMPORT_C void SetPriority(TInt aPriority);
|
||||
inline TBool IsActive() const {return(iStatus.iFlags&TRequestStatus::EActive);}
|
||||
inline TBool IsAdded() const {return(iLink.iNext!=NULL);}
|
||||
inline TInt Priority() const {return iLink.iPriority;}
|
||||
protected:
|
||||
IMPORT_C CActive(TInt aPriority);
|
||||
IMPORT_C void SetActive();
|
||||
virtual void DoCancel() =0;
|
||||
virtual void RunL() =0;
|
||||
IMPORT_C virtual TInt RunError(TInt aError);
|
||||
protected:
|
||||
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
|
||||
public:
|
||||
TRequestStatusFaked iStatus; // hope this will work
|
||||
private:
|
||||
// TBool iActive;
|
||||
TPriQueLink iLink;
|
||||
TAny* iSpare;
|
||||
friend class CActiveScheduler;
|
||||
friend class CServer;
|
||||
friend class CServer2;
|
||||
friend class CPrivatePolledActiveScheduler; // added
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CActiveScheduler : public CBase
|
||||
{
|
||||
friend class CActiveSchedulerWait;
|
||||
public:
|
||||
struct TLoop;
|
||||
typedef TLoop* TLoopOwner;
|
||||
public:
|
||||
IMPORT_C CActiveScheduler();
|
||||
IMPORT_C ~CActiveScheduler();
|
||||
IMPORT_C static void Install(CActiveScheduler* aScheduler);
|
||||
IMPORT_C static CActiveScheduler* Current();
|
||||
IMPORT_C static void Add(CActive* aActive);
|
||||
IMPORT_C static void Start();
|
||||
IMPORT_C static void Stop();
|
||||
IMPORT_C static TBool RunIfReady(TInt& aError, TInt aMinimumPriority);
|
||||
IMPORT_C static CActiveScheduler* Replace(CActiveScheduler* aNewActiveScheduler);
|
||||
IMPORT_C virtual void WaitForAnyRequest();
|
||||
IMPORT_C virtual void Error(TInt aError) const;
|
||||
IMPORT_C void Halt(TInt aExitCode) const;
|
||||
IMPORT_C TInt StackDepth() const;
|
||||
private:
|
||||
static void Start(TLoopOwner* aOwner);
|
||||
IMPORT_C virtual void OnStarting();
|
||||
IMPORT_C virtual void OnStopping();
|
||||
IMPORT_C virtual void Reserved_1();
|
||||
IMPORT_C virtual void Reserved_2();
|
||||
void Run(TLoopOwner* const volatile& aLoop);
|
||||
void DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj);
|
||||
friend class CPrivatePolledActiveScheduler; // added
|
||||
protected:
|
||||
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
|
||||
protected:
|
||||
inline TInt Level() const {return StackDepth();} // deprecated
|
||||
private:
|
||||
TLoop* iStack;
|
||||
TPriQue<CActive> iActiveQ;
|
||||
TAny* iSpare;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TCleanupItem;
|
||||
class CleanupStack
|
||||
{
|
||||
public:
|
||||
IMPORT_C static void PushL(TAny* aPtr);
|
||||
IMPORT_C static void PushL(CBase* aPtr);
|
||||
IMPORT_C static void PushL(TCleanupItem anItem);
|
||||
IMPORT_C static void Pop();
|
||||
IMPORT_C static void Pop(TInt aCount);
|
||||
IMPORT_C static void PopAndDestroy();
|
||||
IMPORT_C static void PopAndDestroy(TInt aCount);
|
||||
IMPORT_C static void Check(TAny* aExpectedItem);
|
||||
inline static void Pop(TAny* aExpectedItem);
|
||||
inline static void Pop(TInt aCount, TAny* aLastExpectedItem);
|
||||
inline static void PopAndDestroy(TAny* aExpectedItem);
|
||||
inline static void PopAndDestroy(TInt aCount, TAny* aLastExpectedItem);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This will declare CPrivatePolledActiveScheduler as a friend
|
||||
* of all classes that define a friend. CPrivatePolledActiveScheduler needs to
|
||||
* be a friend of CActive
|
||||
*/
|
||||
//#define friend friend class CPrivatePolledActiveScheduler; friend
|
||||
|
||||
|
||||
/*
|
||||
* This will change the:
|
||||
* void DoStart();
|
||||
* method in CActiveScheduler to:
|
||||
* void DoStart(); friend class CPrivatePolledActiveScheduler;
|
||||
* We need this to access the private datamembers in CActiveScheduler.
|
||||
*/
|
||||
//#define DoStart() DoStart(); friend class CPrivatePolledActiveScheduler;
|
||||
//#include <e32base.h>
|
||||
#include "PolledAS.h"
|
||||
|
||||
|
||||
class CPrivatePolledActiveScheduler : public CActiveScheduler
|
||||
{
|
||||
public:
|
||||
void Schedule();
|
||||
};
|
||||
|
||||
|
||||
void CPrivatePolledActiveScheduler::Schedule()
|
||||
{
|
||||
TDblQueIter<CActive> q(iActiveQ);
|
||||
q.SetToFirst();
|
||||
FOREVER
|
||||
{
|
||||
CActive *pR=q++;
|
||||
if (pR)
|
||||
{
|
||||
//TRequestStatus::EActive = 1, //bit0
|
||||
//TRequestStatus::ERequestPending = 2, //bit1
|
||||
if (pR->IsActive() && pR->iStatus!=KRequestPending)
|
||||
{
|
||||
// pR->iActive=EFalse; // won't this cause trouble?
|
||||
pR->iStatus.iFlags&=~TRequestStatusFaked::EActive;
|
||||
//debugPrintFile(_L("as: %08x"), pR);
|
||||
TRAPD(r,pR->RunL());
|
||||
//pR->iStatus=TRequestStatus::ERequestPending;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static CPolledActiveScheduler* sPolledActiveScheduler = NULL;
|
||||
|
||||
CPolledActiveScheduler::~CPolledActiveScheduler()
|
||||
{
|
||||
sPolledActiveScheduler = NULL;
|
||||
delete iPrivatePolledActiveScheduler;
|
||||
}
|
||||
|
||||
CPolledActiveScheduler* CPolledActiveScheduler::NewL()
|
||||
{
|
||||
// if (sPolledActiveScheduler == NULL)
|
||||
{
|
||||
sPolledActiveScheduler = new(ELeave)CPolledActiveScheduler;
|
||||
CleanupStack::PushL(sPolledActiveScheduler);
|
||||
sPolledActiveScheduler->ConstructL();
|
||||
CleanupStack::Pop();
|
||||
}
|
||||
return sPolledActiveScheduler;
|
||||
}
|
||||
|
||||
void CPolledActiveScheduler::ConstructL()
|
||||
{
|
||||
iPrivatePolledActiveScheduler = new(ELeave) CPrivatePolledActiveScheduler;
|
||||
iPrivatePolledActiveScheduler->Install(iPrivatePolledActiveScheduler);
|
||||
}
|
||||
|
||||
|
||||
void CPolledActiveScheduler::Schedule()
|
||||
{
|
||||
iPrivatePolledActiveScheduler->Schedule();
|
||||
}
|
||||
|
||||
CPolledActiveScheduler* CPolledActiveScheduler::Instance()
|
||||
{
|
||||
// return (CPolledActiveScheduler*) CActiveScheduler::Current();
|
||||
return sPolledActiveScheduler;
|
||||
}
|
645
platform/uiq3/engine/vid.cpp
Normal file
645
platform/uiq3/engine/vid.cpp
Normal file
|
@ -0,0 +1,645 @@
|
|||
// EmuScan routines for Pico, also simple text and shape drawing routines.
|
||||
|
||||
// (c) Copyright 2006, notaz
|
||||
// All Rights Reserved
|
||||
|
||||
#include "vid.h"
|
||||
#include "../Engine.h"
|
||||
#include "../../../pico/picoInt.h"
|
||||
#include "blit.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// global stuff
|
||||
extern TPicoConfig *currentConfig;
|
||||
extern TPicoAreaConfigEntry areaConfig[];
|
||||
extern const char *actionNames[];
|
||||
|
||||
// main framebuffer
|
||||
static void *screenbuff = 0; // pointer to real device video memory
|
||||
//static
|
||||
extern "C" { unsigned char *framebuff = 0; } // temporary buffer
|
||||
const int framebuffsize = (8+320)*(8+240+8)*2+8*2; // actual framebuffer size (in bytes+to support new rendering mode)
|
||||
|
||||
// drawer function pointers
|
||||
static void (*drawTextFps)(const char *text) = 0;
|
||||
static void (*drawTextNotice)(const char *text) = 0;
|
||||
|
||||
// blitter
|
||||
static void (*vidBlit)(int full) = 0;
|
||||
|
||||
// colors
|
||||
const unsigned short color_red = 0x022F;
|
||||
const unsigned short color_red_dim = 0x0004;
|
||||
const unsigned short color_green = 0x01F1;
|
||||
const unsigned short color_blue = 0x0F11;
|
||||
const unsigned short color_grey = 0x0222;
|
||||
|
||||
// other
|
||||
int txtheight_fit = 138;
|
||||
|
||||
// bitmasks
|
||||
static const unsigned long mask_numbers[] = {
|
||||
0x12244800, // 47 2F /
|
||||
0x69999600, // 48 30 0
|
||||
0x26222200, // 49 31 1
|
||||
0x69168F00, // 50 32 2
|
||||
0x69219600, // 51 33 3
|
||||
0x266AF200, // 52 34 4
|
||||
0xF8E11E00, // 53 35 5
|
||||
0x68E99600, // 54 36 6
|
||||
0x71222200, // 55 37 7
|
||||
0x69699600, // 56 38 8
|
||||
0x69719600, // 57 39 9
|
||||
0x04004000, // 58 3A :
|
||||
0x04004400, // 59 3B ;
|
||||
0x01242100, // 60 3C <
|
||||
0x00707000, // 61 3D =
|
||||
0x04212400, // 62 3E >
|
||||
0x69240400, // 63 3F ?
|
||||
0x00000000, // 64 40 @ [used instead of space for now]
|
||||
0x22579900, // 65 41 A
|
||||
0xE9E99E00, // 66 42 B
|
||||
0x69889600, // 67 43 C
|
||||
0xE9999E00, // 68 44 D
|
||||
0xF8E88F00, // 69 45 E
|
||||
0xF8E88800, // 70 46 F
|
||||
0x698B9700, // 71 47 G
|
||||
0x99F99900, // 72 48 H
|
||||
0x44444400, // 73 49 I
|
||||
0x11119600, // 74 4A J
|
||||
0x9ACCA900, // 75 4B K
|
||||
0x88888F00, // 76 4C L
|
||||
0x9F999900, // 77 4D M
|
||||
0x9DDBB900, // 78 4E N
|
||||
0x69999600, // 79 4F O
|
||||
0xE99E8800, // 80 50 P
|
||||
0x6999A500, // 81 51 Q
|
||||
0xE99E9900, // 82 52 R
|
||||
0x69429600, // 83 53 S
|
||||
0x72222200, // 84 54 T
|
||||
0x99999600, // 85 55 U
|
||||
0x55552200, // 86 56 V
|
||||
0x9999F900, // 87 57 W
|
||||
0x55225500, // 88 58 X
|
||||
0x55222200, // 89 59 Y
|
||||
0xF1248F00, // 90 5A Z
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Cram functions
|
||||
|
||||
static int EmuCramNull(int cram)
|
||||
{
|
||||
User::Panic(_L("Cram called!!"), 0);
|
||||
return cram;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// PicoScan functions
|
||||
|
||||
static int EmuScan8(unsigned int num, void *sdata)
|
||||
{
|
||||
DrawLineDest = framebuff + 328*(num+1) + 328*8 + 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int EmuScanFit0(unsigned int num, void *sdata)
|
||||
{
|
||||
// 0.75, 168 lines
|
||||
|
||||
static int u = 0, num2 = 0;
|
||||
if(!num) u = num2 = 0;
|
||||
|
||||
DrawLineDest = framebuff + 328*(++num2) + 328*8 + 8;
|
||||
|
||||
u += 6666;
|
||||
|
||||
if(u < 10000) {
|
||||
// u += 7500;
|
||||
return 1;
|
||||
}
|
||||
|
||||
u -= 10000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// text drawers
|
||||
// warning: text must be at least 1px away from screen borders
|
||||
|
||||
static void drawTextM2(int x, int y, const char *text)
|
||||
{
|
||||
unsigned char *vidmem = framebuff + 328*8 + 8;
|
||||
int charmask, i, cx = x, cy;
|
||||
unsigned char *l, *le;
|
||||
|
||||
// darken the background (left border)
|
||||
for(l=vidmem+(cx-1)+(y-1)*328, le=l+8*328; l < le; l+=328) *l = 0xE0;
|
||||
|
||||
for(const char *p=text; *p; p++) {
|
||||
cy = y;
|
||||
charmask = *(mask_numbers + (*p - 0x2F));
|
||||
|
||||
for(l = vidmem+cx+(y-1)*328, le = l+8*328; l < le; l+=328-4) {
|
||||
*l = 0xE0; l++; *l = 0xE0; l++;
|
||||
*l = 0xE0; l++; *l = 0xE0; l++;
|
||||
*l = 0xE0;
|
||||
}
|
||||
|
||||
for(i=0; i < 24; i++) {
|
||||
if(charmask&0x80000000) *( vidmem + (cx+(i&3)) + (cy+(i>>2))*328 ) = 0xf0;
|
||||
charmask <<= 1;
|
||||
}
|
||||
cx += 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drawTextM2Fat(int x, int y, const char *text)
|
||||
{
|
||||
unsigned char *vidmem = framebuff + 328*8 + 8;
|
||||
int charmask, i, cx = x&~1, cy;
|
||||
unsigned short *l, *le;
|
||||
|
||||
// darken the background (left border)
|
||||
for(l=(unsigned short *)(vidmem+(cx-2)+(y-1)*328), le=l+8*328/2; l < le; l+=328/2) *l = 0xE0;
|
||||
|
||||
for(const char *p=text; *p; p++) {
|
||||
cy = y;
|
||||
for(l = (unsigned short *)(vidmem+cx+(y-1)*328), le = l+8*328/2; l < le; l+=328/2) {
|
||||
l += 4;
|
||||
*l-- = 0xe0e0; *l-- = 0xe0e0; *l-- = 0xe0e0; *l-- = 0xe0e0; *l = 0xe0e0;
|
||||
}
|
||||
|
||||
charmask = *(mask_numbers + (*p - 0x2F));
|
||||
|
||||
for(i=0; i < 24; i++) {
|
||||
if(charmask&0x80000000) *(unsigned short *)( vidmem + cx+(i&3)*2 + (cy+(i>>2))*328 ) = 0xf0f0;
|
||||
charmask <<= 1;
|
||||
}
|
||||
cx += 5*2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drawTextFpsCenter0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2(214, 216, text);
|
||||
}
|
||||
|
||||
static void drawTextFpsFit0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2Fat((Pico.video.reg[12]&1) ? 256-32 : 224-32, 160, text);
|
||||
}
|
||||
|
||||
static void drawTextFpsFit2_0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2Fat((Pico.video.reg[12]&1) ? 256-32 : 224-32, 216, text);
|
||||
}
|
||||
|
||||
static void drawTextFps0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2((Pico.video.reg[12]&1) ? 256 : 224, 216, text);
|
||||
}
|
||||
|
||||
static void drawTextNoticeCenter0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2(2, 216, text);
|
||||
}
|
||||
|
||||
static void drawTextNoticeFit0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2Fat(2, 160, text);
|
||||
}
|
||||
|
||||
static void drawTextNoticeFit2_0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2Fat(2, 216, text);
|
||||
}
|
||||
|
||||
static void drawTextNotice0(const char *text)
|
||||
{
|
||||
if(!text) return;
|
||||
drawTextM2(2, 216, text);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
static int localPal[0x100];
|
||||
|
||||
static void fillLocalPal(void)
|
||||
{
|
||||
Pico.m.dirtyPal = 0;
|
||||
|
||||
if (PicoOpt&0x10) {
|
||||
// 8bit fast renderer
|
||||
vidConvCpyRGB32(localPal, Pico.cram, 0x40);
|
||||
return;
|
||||
}
|
||||
|
||||
// 8bit accurate renderer
|
||||
if(Pico.video.reg[0xC]&8) { // shadow/hilight mode
|
||||
vidConvCpyRGB32(localPal, Pico.cram, 0x40);
|
||||
vidConvCpyRGB32sh(localPal+0x40, Pico.cram, 0x40);
|
||||
vidConvCpyRGB32hi(localPal+0x80, Pico.cram, 0x40);
|
||||
blockcpy(localPal+0xc0, localPal+0x40, 0x40*4);
|
||||
localPal[0xe0] = 0x00000000; // reserved pixels for OSD
|
||||
localPal[0xf0] = 0x00ee0000;
|
||||
} else if (rendstatus & 0x20) { // mid-frame palette changes
|
||||
vidConvCpyRGB32(localPal, Pico.cram, 0x40);
|
||||
vidConvCpyRGB32(localPal+0x40, HighPal, 0x40);
|
||||
vidConvCpyRGB32(localPal+0x80, HighPal+0x40, 0x40);
|
||||
} else {
|
||||
vidConvCpyRGB32(localPal, Pico.cram, 0x40);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// note: the internal 8 pixel border is taken care by asm code
|
||||
static void vidBlit_90(int full)
|
||||
{
|
||||
unsigned char *ps = framebuff+328*8;
|
||||
unsigned long *pd = (unsigned long *) screenbuff;
|
||||
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_90(pd, ps, localPal, 320/8);
|
||||
else {
|
||||
if(full) vidClear(pd, 32);
|
||||
pd += 256*32;
|
||||
vidConvCpy_90(pd, ps, localPal, 256/8);
|
||||
if(full) vidClear(pd + 256*256, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void vidBlit_270(int full)
|
||||
{
|
||||
unsigned char *ps = framebuff+328*8;
|
||||
unsigned long *pd = (unsigned long *) screenbuff;
|
||||
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_270(pd, ps, localPal, 320/8);
|
||||
else {
|
||||
if(full) vidClear(pd, 32);
|
||||
pd += 256*32;
|
||||
ps -= 64; // the blitter starts copying from the right border, so we need to adjust
|
||||
vidConvCpy_270(pd, ps, localPal, 256/8);
|
||||
if(full) vidClear(pd + 256*256, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitCenter_0(int full)
|
||||
{
|
||||
unsigned char *ps = framebuff+328*8+8;
|
||||
unsigned long *pd = (unsigned long *) screenbuff;
|
||||
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1) ps += 32;
|
||||
vidConvCpy_center_0(pd, ps, localPal);
|
||||
if(full) vidClear(pd + 224*256, 96);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitCenter_180(int full)
|
||||
{
|
||||
unsigned char *ps = framebuff+328*8+8;
|
||||
unsigned long *pd = (unsigned long *) screenbuff;
|
||||
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1) ps += 32;
|
||||
vidConvCpy_center_180(pd, ps, localPal);
|
||||
if(full) vidClear(pd + 224*256, 96);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitFit_0(int full)
|
||||
{
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_center2_40c_0(screenbuff, framebuff+328*8, localPal, 168);
|
||||
else vidConvCpy_center2_32c_0(screenbuff, framebuff+328*8, localPal, 168);
|
||||
if(full) vidClear((unsigned long *)screenbuff + 168*256, 320-168);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitFit_180(int full)
|
||||
{
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_center2_40c_180(screenbuff, framebuff+328*8, localPal, 168);
|
||||
else vidConvCpy_center2_32c_180(screenbuff, framebuff+328*8-64, localPal, 168);
|
||||
if(full) vidClear((unsigned long *)screenbuff + 168*256, 320-168);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitFit2_0(int full)
|
||||
{
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_center2_40c_0(screenbuff, framebuff+328*8, localPal, 224);
|
||||
else vidConvCpy_center2_32c_0(screenbuff, framebuff+328*8, localPal, 224);
|
||||
if(full) vidClear((unsigned long *)screenbuff + 224*256, 96);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitFit2_180(int full)
|
||||
{
|
||||
if (Pico.m.dirtyPal) fillLocalPal();
|
||||
|
||||
if(Pico.video.reg[12]&1)
|
||||
vidConvCpy_center2_40c_180(screenbuff, framebuff+328*8, localPal, 224);
|
||||
else vidConvCpy_center2_32c_180(screenbuff, framebuff+328*8-64, localPal, 224);
|
||||
if(full) vidClear((unsigned long *)screenbuff + 224*256, 96);
|
||||
}
|
||||
|
||||
|
||||
static void vidBlitCfg(void)
|
||||
{
|
||||
unsigned short *ps = (unsigned short *) framebuff;
|
||||
unsigned long *pd = (unsigned long *) screenbuff;
|
||||
int i;
|
||||
|
||||
// hangs randomly (due to repeated ldms/stms?)
|
||||
//for (int i = 1; i < 320; i++, ps += 240, pd += 256)
|
||||
// vidConvCpyRGB32(pd, ps, 240);
|
||||
|
||||
for (i = 0; i < 320; i++, pd += 16)
|
||||
for (int u = 0; u < 240; u++, ps++, pd++)
|
||||
*pd = ((*ps & 0xf) << 20) | ((*ps & 0xf0) << 8) | ((*ps & 0xf00) >> 4);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// main functions
|
||||
|
||||
int vidInit(void *vidmem, int reinit)
|
||||
{
|
||||
if(!reinit) {
|
||||
// prepare framebuffer
|
||||
screenbuff = vidmem;
|
||||
framebuff = (unsigned char *) malloc(framebuffsize);
|
||||
|
||||
if(!screenbuff) return KErrNotSupported;
|
||||
if(!framebuff) return KErrNoMemory;
|
||||
|
||||
memset(framebuff, 0, framebuffsize);
|
||||
|
||||
// Cram function: go and hack Pico so it never gets called
|
||||
PicoCram = EmuCramNull;
|
||||
}
|
||||
|
||||
// select suitable blitters
|
||||
vidBlit = vidBlit_270;
|
||||
PicoScan = EmuScan8;
|
||||
drawTextFps = drawTextFps0;
|
||||
drawTextNotice = drawTextNotice0;
|
||||
|
||||
memset(localPal, 0, 0x100*4);
|
||||
localPal[0xe0] = 0x00000000; // reserved pixels for OSD
|
||||
localPal[0xf0] = 0x00ee0000;
|
||||
|
||||
// setup all orientation related stuff
|
||||
if(currentConfig->iScreenRotation == TPicoConfig::PRot0) {
|
||||
if(currentConfig->iScreenMode == TPicoConfig::PMCenter) {
|
||||
vidBlit = vidBlitCenter_0;
|
||||
drawTextFps = drawTextFpsCenter0;
|
||||
drawTextNotice = drawTextNoticeCenter0;
|
||||
} else if(currentConfig->iScreenMode == TPicoConfig::PMFit2) {
|
||||
vidBlit = vidBlitFit2_0;
|
||||
drawTextFps = drawTextFpsFit2_0;
|
||||
drawTextNotice = drawTextNoticeFit2_0;
|
||||
} else {
|
||||
vidBlit = vidBlitFit_0;
|
||||
drawTextFps = drawTextFpsFit0;
|
||||
drawTextNotice = drawTextNoticeFit0;
|
||||
PicoScan = EmuScanFit0;
|
||||
}
|
||||
} else if(currentConfig->iScreenRotation == TPicoConfig::PRot90) {
|
||||
vidBlit = vidBlit_90;
|
||||
} else if(currentConfig->iScreenRotation == TPicoConfig::PRot180) {
|
||||
if(currentConfig->iScreenMode == TPicoConfig::PMCenter) {
|
||||
vidBlit = vidBlitCenter_180;
|
||||
drawTextFps = drawTextFpsCenter0;
|
||||
drawTextNotice = drawTextNoticeCenter0;
|
||||
} else if(currentConfig->iScreenMode == TPicoConfig::PMFit2) {
|
||||
vidBlit = vidBlitFit2_180;
|
||||
drawTextFps = drawTextFpsFit2_0;
|
||||
drawTextNotice = drawTextNoticeFit2_0;
|
||||
} else {
|
||||
vidBlit = vidBlitFit_180;
|
||||
drawTextFps = drawTextFpsFit0;
|
||||
drawTextNotice = drawTextNoticeFit0;
|
||||
PicoScan = EmuScanFit0;
|
||||
}
|
||||
} else if(currentConfig->iScreenRotation == TPicoConfig::PRot270) {
|
||||
vidBlit = vidBlit_270;
|
||||
}
|
||||
|
||||
vidBlit(1);
|
||||
PicoOpt |= 0x100;
|
||||
Pico.m.dirtyPal = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vidFree()
|
||||
{
|
||||
free(framebuff);
|
||||
framebuff = 0;
|
||||
}
|
||||
|
||||
void vidDrawFrame(char *noticeStr, char *fpsStr, int num)
|
||||
{
|
||||
DrawLineDest = framebuff + 328*8 + 8;
|
||||
|
||||
// PicoFrame(); // moved to main loop
|
||||
if(currentConfig->iFlags & 2)
|
||||
drawTextFps(fpsStr);
|
||||
drawTextNotice(noticeStr);
|
||||
|
||||
vidBlit(!num); // copy full frame once a second
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
static void drawText0(int x, int y, const char *text, long color)
|
||||
{
|
||||
unsigned short *vidmem=(unsigned short *)framebuff;
|
||||
int charmask, i, cx = x, cy;
|
||||
unsigned short *l, *le, dmask=0x0333;
|
||||
|
||||
// darken the background (left border)
|
||||
for(l=vidmem+(cx-1)+(y-1)*240, le=vidmem+(cx-1)+(y+7)*240; l < le; l+=240)
|
||||
*l = (*l >> 2) & dmask;
|
||||
|
||||
for(const char *p=text; *p; p++) {
|
||||
cy = y;
|
||||
charmask = *(mask_numbers + (*p - 0x2F));
|
||||
|
||||
for(l = vidmem+cx+(y-1)*240, le = vidmem+cx+(y+7)*240; l < le; l+=240-4) {
|
||||
*l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
|
||||
*l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
|
||||
*l = (*l >> 2) & dmask;
|
||||
}
|
||||
|
||||
for(i=0; i < 24; i++) {
|
||||
// draw dot. Is this fast?
|
||||
if(charmask&0x80000000) *( vidmem + (cx+(i&3)) + (cy+(i>>2))*240 ) = color;
|
||||
charmask <<= 1;
|
||||
}
|
||||
cx += 5;
|
||||
}
|
||||
}
|
||||
|
||||
// draws rect with width - 1 and height - 1
|
||||
static void drawRect(const TRect &rc, unsigned short color)
|
||||
{
|
||||
unsigned short *vidmem=(unsigned short *)framebuff;
|
||||
|
||||
if(rc.iTl.iX - rc.iBr.iX && rc.iTl.iY - rc.iBr.iY) {
|
||||
int stepX = rc.iTl.iX < rc.iBr.iX ? 1 : -1;
|
||||
int stepY = rc.iTl.iY < rc.iBr.iY ? 1 : -1;
|
||||
|
||||
for(int x = rc.iTl.iX;; x += stepX) {
|
||||
*(vidmem + rc.iTl.iY*240 + x) = *(vidmem + (rc.iBr.iY - stepY)*240 + x) = color;
|
||||
if(x == rc.iBr.iX - stepX) break;
|
||||
}
|
||||
|
||||
for(int y = rc.iTl.iY;; y += stepY) {
|
||||
*(vidmem + y*240 + rc.iTl.iX) = *(vidmem + y*240 + rc.iBr.iX - stepX) = color;
|
||||
if(y == rc.iBr.iY - stepY) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draws fullsize filled rect
|
||||
static void drawRectFilled(const TRect rc, unsigned short color)
|
||||
{
|
||||
unsigned short *vidmem=(unsigned short *)framebuff;
|
||||
|
||||
if(rc.iTl.iX - rc.iBr.iX && rc.iTl.iY - rc.iBr.iY) {
|
||||
int stepX = rc.iTl.iX < rc.iBr.iX ? 1 : -1;
|
||||
int stepY = rc.iTl.iY < rc.iBr.iY ? 1 : -1;
|
||||
|
||||
for(int y = rc.iTl.iY;; y += stepY) {
|
||||
for(int x = rc.iTl.iX;; x += stepX) {
|
||||
*(vidmem + y*240 + x) = *(vidmem + y*240 + x) = color;
|
||||
if(x == rc.iBr.iX) break;
|
||||
}
|
||||
if(y == rc.iBr.iY) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// direction: -1 left, 1 right
|
||||
static void drawArrow0(TPoint p, int direction, unsigned short color)
|
||||
{
|
||||
unsigned short *vidmem=(unsigned short *)framebuff;
|
||||
int width = 15;
|
||||
int x = p.iX;
|
||||
int y = p.iY;
|
||||
|
||||
for(; width > 0; x+=direction, y++, width -=2)
|
||||
for(int i=0; i < width; i++)
|
||||
*(vidmem + x + y*240 + i*240) = color;
|
||||
}
|
||||
|
||||
static char *vidGetScanName(int scan)
|
||||
{
|
||||
static char buff[32];
|
||||
|
||||
if((scan >= '0' && scan <= '9') || (scan >= 'A' && scan <= 'Z')) {
|
||||
buff[0] = (char) scan; buff[1] = 0;
|
||||
} else {
|
||||
switch(scan) {
|
||||
case 0x01: strcpy(buff, "BSPACE"); break;
|
||||
case 0x03: strcpy(buff, "OK"); break;
|
||||
case 0x05: strcpy(buff, "SPACE"); break;
|
||||
case 0x0e: strcpy(buff, "AST"); break;
|
||||
case 0x0f: strcpy(buff, "HASH"); break;
|
||||
case 0x12: strcpy(buff, "SHIFT"); break;
|
||||
case 0x19: strcpy(buff, "ALT"); break;
|
||||
case 0x79: strcpy(buff, "PLUS"); break;
|
||||
case 0x7a: strcpy(buff, "DOT"); break;
|
||||
case 0xa5: strcpy(buff, "JOG@UP"); break;
|
||||
case 0xa6: strcpy(buff, "JOG@DOWN"); break;
|
||||
case 0xb5: strcpy(buff, "INET"); break;
|
||||
case 0xd4: strcpy(buff, "JOG@PUSH"); break;
|
||||
case 0xd5: strcpy(buff, "BACK"); break;
|
||||
default: sprintf(buff, "KEY@%02X", scan); break;
|
||||
}
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
void vidKeyConfigFrame(const TUint whichAction)
|
||||
{
|
||||
int i;
|
||||
char buttonNames[128];
|
||||
buttonNames[0] = 0;
|
||||
memset(framebuff, 0, framebuffsize);
|
||||
|
||||
unsigned long currentActCode = 1 << whichAction;
|
||||
|
||||
// draw all "buttons" in reverse order
|
||||
const TPicoAreaConfigEntry *e = areaConfig + 1; i = 0;
|
||||
while(e->rect != TRect(0,0,0,0)) { e++; i++; }
|
||||
for(e--, i--; e->rect != TRect(0,0,0,0); e--, i--)
|
||||
drawRect(e->rect, (currentConfig->iAreaBinds[i] & currentActCode) ? color_red : color_red_dim);
|
||||
|
||||
// action name control
|
||||
drawRectFilled(TRect(72, 2, 168, 20), color_grey); // 96x14
|
||||
drawArrow0(TPoint(80, 3), -1, color_green);
|
||||
drawArrow0(TPoint(160, 3), 1, color_green);
|
||||
|
||||
drawText0(86, 9, actionNames[whichAction], color_red);
|
||||
|
||||
// draw active button names if there are any
|
||||
for(i = 0; i < 256; i++) {
|
||||
if(currentConfig->iKeyBinds[i] & currentActCode) {
|
||||
if(buttonNames[0]) strcat(buttonNames, ";@");
|
||||
strcat(buttonNames, vidGetScanName(i));
|
||||
}
|
||||
}
|
||||
|
||||
if(buttonNames[0]) {
|
||||
buttonNames[61] = 0; // only 60 chars fit
|
||||
drawText0(6, 48, buttonNames, color_blue);
|
||||
}
|
||||
|
||||
vidBlitCfg();
|
||||
}
|
||||
|
||||
void vidDrawNotice(const char *txt)
|
||||
{
|
||||
if(framebuff) {
|
||||
drawTextNotice(txt);
|
||||
vidBlit(1);
|
||||
}
|
||||
}
|
9
platform/uiq3/engine/vid.h
Normal file
9
platform/uiq3/engine/vid.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <e32base.h>
|
||||
|
||||
// let's do it in more c-like way
|
||||
int vidInit(void *vidmem, int reinit);
|
||||
void vidFree();
|
||||
void vidDrawFrame(char *noticeStr, char *fpsStr, int num);
|
||||
void vidKeyConfigFrame(const TUint whichAction);
|
||||
void vidDrawFCconfigDone();
|
||||
void vidDrawNotice(const char *txt); // safe to call anytime, draws text for 1 frame
|
3
platform/uiq3/makezip.cmd
Normal file
3
platform/uiq3/makezip.cmd
Normal file
|
@ -0,0 +1,3 @@
|
|||
@cd _out
|
||||
@"C:\Program Files\arch\WinRAR\WinRAR.exe" a PicoDrive.zip PicoDrive.SIS config.txt ..\..\readme.txt
|
||||
@cd..
|
25
platform/uiq3/port_config.h
Normal file
25
platform/uiq3/port_config.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
// port specific settings
|
||||
|
||||
#ifndef PORT_CONFIG_H
|
||||
#define PORT_CONFIG_H
|
||||
|
||||
#define CPU_CALL
|
||||
|
||||
// draw2.c
|
||||
#define START_ROW 0 // which row of tiles to start rendering at?
|
||||
#define END_ROW 28 // ..end
|
||||
|
||||
// pico.c
|
||||
#define CAN_HANDLE_240_LINES 0 // fow now
|
||||
|
||||
//#define dprintf(f,...) printf(f"\n",##__VA_ARGS__)
|
||||
#ifdef __DEBUG_PRINT
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
void dprintf(char *format, ...);
|
||||
#else
|
||||
#define dprintf(x...)
|
||||
#endif
|
||||
|
||||
#endif //PORT_CONFIG_H
|
8
platform/uiq3/port_config.s
Normal file
8
platform/uiq3/port_config.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
@ .equiv START_ROW, 1
|
||||
@ .equiv END_ROW, 27
|
||||
@ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.
|
||||
.equiv START_ROW, 0
|
||||
.equiv END_ROW, 28
|
||||
|
||||
@ this should be set to one only for GP2X port
|
||||
.equiv EXTERNAL_YM2612, 0
|
1
platform/uiq3/qconn.cmd
Normal file
1
platform/uiq3/qconn.cmd
Normal file
|
@ -0,0 +1 @@
|
|||
@..\..\..\qconsole-1.60\qtty-1.60\release\qtty --qc-addr M600i --qc-channel 5 --user qconsole --pass server
|
1
platform/uiq3/qlog.cmd
Normal file
1
platform/uiq3/qlog.cmd
Normal file
|
@ -0,0 +1 @@
|
|||
@..\..\..\qconsole-1.60\qtty-1.60\release\qtty --qc-addr M600i --qc-channel 5 --user qconsole --pass server --cmds "cat c:\logs\pico.log" exit
|
1
platform/uiq3/qup.cmd
Normal file
1
platform/uiq3/qup.cmd
Normal file
|
@ -0,0 +1 @@
|
|||
@..\..\..\qconsole-1.60\qtty-1.60\release\qtty --qc-addr M600i --qc-channel 5 --user qconsole --pass server --cmds "put c:\Shared\PicoDrive.SIS _out\PicoDrive.SIS" "rundoc c:\Shared\PicoDrive.SIS" exit
|
BIN
platform/uiq3/rsc/Pico18x18.bmp
Normal file
BIN
platform/uiq3/rsc/Pico18x18.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
platform/uiq3/rsc/Pico18x18m.bmp
Normal file
BIN
platform/uiq3/rsc/Pico18x18m.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 334 B |
BIN
platform/uiq3/rsc/Pico40x40.bmp
Normal file
BIN
platform/uiq3/rsc/Pico40x40.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
platform/uiq3/rsc/Pico40x40m.bmp
Normal file
BIN
platform/uiq3/rsc/Pico40x40m.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
platform/uiq3/rsc/Pico64x64.bmp
Normal file
BIN
platform/uiq3/rsc/Pico64x64.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
platform/uiq3/rsc/Pico64x64m.bmp
Normal file
BIN
platform/uiq3/rsc/Pico64x64m.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
601
platform/uiq3/rsc/PicoDrive.rss
Normal file
601
platform/uiq3/rsc/PicoDrive.rss
Normal file
|
@ -0,0 +1,601 @@
|
|||
NAME PCDR
|
||||
|
||||
#include <eikon.rh>
|
||||
#include <eikon.rsg>
|
||||
#include <qikon.rh>
|
||||
#include <QikCommand.rh>
|
||||
#include "picodrive.hrh"
|
||||
|
||||
|
||||
RESOURCE RSS_SIGNATURE { }
|
||||
|
||||
// Defines the name of the default file the application framework creates.
|
||||
// This resource must always be the second resource in the resource file.
|
||||
RESOURCE TBUF { buf = "PicoDrive"; }
|
||||
|
||||
RESOURCE EIK_APP_INFO { }
|
||||
|
||||
|
||||
// A view shall use the QIK_VIEW_CONFIGURATIONS resource struct to define which
|
||||
// UI configurations it supports. Can also use QIK_VIEW_CONFIGURATIONS to setup
|
||||
// the view to switch layout and command list automatically when changes of UI
|
||||
// configuration occur. This is done with the view and command_list members of
|
||||
// the QIK_VIEW_CONFIGURATIONS.
|
||||
// The application supports the reference UI Configurations that are supported
|
||||
// in the UIQ 3 SDK. Use the UiqEnv tool, to change the UI Configuration in the
|
||||
// emulator in order to develop and test the application with varying phone styles.
|
||||
RESOURCE QIK_VIEW_CONFIGURATIONS r_app_ui_configurations
|
||||
{
|
||||
configurations =
|
||||
{
|
||||
QIK_VIEW_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = KQikPenStyleTouchPortrait;
|
||||
command_list = r_app_commands;
|
||||
view = r_app_layout;
|
||||
},
|
||||
QIK_VIEW_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = KQikPenStyleTouchLandscape;
|
||||
command_list = r_app_commands;
|
||||
view = r_app_layout;
|
||||
},
|
||||
QIK_VIEW_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = KQikSoftkeyStyleTouchPortrait;
|
||||
command_list = r_app_commands;
|
||||
view = r_app_layout;
|
||||
},
|
||||
QIK_VIEW_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = KQikSoftkeyStylePortrait;
|
||||
command_list = r_app_commands;
|
||||
view = r_app_layout;
|
||||
},
|
||||
QIK_VIEW_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = KQikSoftkeyStyleSmallPortrait;
|
||||
command_list = r_app_commands;
|
||||
view = r_app_layout;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Commands are defined with the QIK_COMMAND_LIST struct,
|
||||
// commands can also be created in code by instantiating CQikCommand.
|
||||
// The control command id for debug command is a reserved id from uikon.hrh.
|
||||
// The id for each command is defined in the .hrh file.
|
||||
RESOURCE QIK_COMMAND_LIST r_app_commands
|
||||
{
|
||||
items =
|
||||
{
|
||||
// QIK_COMMAND { id=EEikCmdPicoMain; text="Main"; type=EQikCommandTypeDone; namedGroupLinkId=EEikCmdPicoMain; },
|
||||
// QIK_COMMAND { id=EEikCmdPicoDebugInfo; text="Debug info"; type=EQikCommandTypeScreen; stateFlags=EQikCmdFlagDebugOnly; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip; text="Frameskip"; type=EQikCommandTypeScreen; namedGroupLinkId=EEikCmdPicoFrameskip; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskipAuto; text="Auto"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip; stateFlags=EQikCmdFlagRadioStart; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip0; text="0"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip0; stateFlags=EQikCmdFlagRadioMiddle; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip1; text="1"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip0; stateFlags=EQikCmdFlagRadioMiddle; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip2; text="2"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip0; stateFlags=EQikCmdFlagRadioMiddle; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip4; text="4"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip0; stateFlags=EQikCmdFlagRadioMiddle; },
|
||||
QIK_COMMAND { id=EEikCmdPicoFrameskip8; text="8"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoFrameskip;
|
||||
groupId=EEikCmdPicoFrameskip0; stateFlags=EQikCmdFlagRadioEnd; },
|
||||
QIK_COMMAND { id=EEikCmdPicoConfig; text="Configure"; type=EQikCommandTypeScreen; namedGroupLinkId=EEikCmdPicoConfig; },
|
||||
QIK_COMMAND { id=EEikCmdPicoKeys; text="Keys"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoConfig; },
|
||||
QIK_COMMAND { id=EEikCmdPicoSettings; text="Settings"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoConfig; },
|
||||
QIK_COMMAND { id=EEikCmdHelpAbout; text="About"; type=EQikCommandTypeScreen; namedGroupId=EEikCmdPicoConfig; },
|
||||
|
||||
QIK_COMMAND { id=EEikCmdPicoLoadROM; text="Load new ROM"; type=EQikCommandTypeScreen; groupId=EEikCmdPicoResume; },
|
||||
QIK_COMMAND { id=EEikCmdPicoReset; text="Reset game"; type=EQikCommandTypeScreen; groupId=EEikCmdPicoResume; },
|
||||
QIK_COMMAND { id=EEikCmdPicoLoadState; text="Load state"; type=EQikCommandTypeScreen; groupId=EEikCmdPicoResume; },
|
||||
QIK_COMMAND { id=EEikCmdPicoSaveState; text="Save state"; type=EQikCommandTypeScreen; groupId=EEikCmdPicoResume; },
|
||||
QIK_COMMAND { id=EEikCmdPicoResume; text="Resume game"; type=EQikCommandTypeScreen; groupId=EEikCmdPicoResume; cpfFlags=EQikCpfFlagIsDefault; },
|
||||
|
||||
QIK_COMMAND { id=EEikCmdExit; text="Exit"; type=EQikCommandTypeScreen; groupId=EEikCmdExit; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Defines the view by linking to the pages.
|
||||
RESOURCE QIK_VIEW r_app_layout
|
||||
{
|
||||
pages = {};
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* config dialog
|
||||
*
|
||||
**************************************/
|
||||
|
||||
RESOURCE DIALOG r_pico_config
|
||||
{
|
||||
title = "Settings";
|
||||
buttons = R_EIK_BUTTONS_CANCEL_OK;
|
||||
flags = EEikDialogFlagWait;
|
||||
pages = r_pico_config_pages;
|
||||
}
|
||||
|
||||
RESOURCE ARRAY r_pico_config_pages
|
||||
{
|
||||
items = {
|
||||
PAGE
|
||||
{
|
||||
id = ECtlOptPageMain;
|
||||
text = "Main";
|
||||
lines = r_pico_config_page_main;
|
||||
},
|
||||
PAGE
|
||||
{
|
||||
id = ECtlOptPageSound;
|
||||
text = "Sound";
|
||||
lines = r_pico_config_page_sound;
|
||||
},
|
||||
PAGE
|
||||
{
|
||||
id = ECtlOptPageMisc;
|
||||
text = "Misc";
|
||||
lines = r_pico_config_page_misc;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_page_main
|
||||
{
|
||||
items = {
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptRotationLabel;
|
||||
type = EEikCtLabel;
|
||||
prompt = "Screen Rotation";
|
||||
control = LABEL { horiz_align = EEikLabelAlignHLeft; };
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptRotation;
|
||||
type = EEikCtHorOptionButList;
|
||||
control = HOROPBUT
|
||||
{
|
||||
array_id = r_pico_config_rotation_buttons;
|
||||
};
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptScreenModeLabel;
|
||||
type = EEikCtLabel;
|
||||
prompt = "Screen Mode";
|
||||
control = LABEL { horiz_align = EEikLabelAlignHLeft; };
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptScreenMode;
|
||||
type = EEikCtHorOptionButList;
|
||||
control = HOROPBUT
|
||||
{
|
||||
array_id = r_pico_config_screenmode_buttons;
|
||||
};
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptUseAltRend;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Fast renderer (inaccurate)";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptUseAccTiming;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Accurate timing (slower)";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptUseAccSprites;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Accurate sprites (slower)";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptShowFPS;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Show FPS";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_page_sound
|
||||
{
|
||||
items = {
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptEnableSound;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Enable sound";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptChipSelLabel;
|
||||
type = EEikCtLabel;
|
||||
prompt = "Emulate these sound chips:";
|
||||
control = LABEL { horiz_align = EEikLabelAlignHLeft; };
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptEmulateZ80;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Z80";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptEmulateYM2612;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "YM2612";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptEmulateSN76496;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "SN76496 (PSG)";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptSndQLabel;
|
||||
type = EEikCtLabel;
|
||||
prompt = "Quality (lowest is fastest)";
|
||||
control = LABEL { horiz_align = EEikLabelAlignHLeft; };
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptSndQuality;
|
||||
type = EEikCtChoiceList;
|
||||
prompt = "";
|
||||
control = CHOICELIST { array_id = r_pico_config_snd_quality; };
|
||||
itemflags = EEikDlgItemNonFocusing;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_page_misc
|
||||
{
|
||||
items = {
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOpt6ButtonPad;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "6 button pad";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptGzipStates;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "gzip save states";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptUseSRAM;
|
||||
type = EEikCtCheckBox;
|
||||
prompt = "Use SRAM saves (.srm)";
|
||||
},
|
||||
DLG_LINE
|
||||
{
|
||||
id = ECtlOptRegion;
|
||||
type = EEikCtChoiceList;
|
||||
prompt = "Region:";
|
||||
control = CHOICELIST { array_id = r_pico_config_region; };
|
||||
itemflags = EEikDlgItemNonFocusing;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_rotation_buttons
|
||||
{
|
||||
items = {
|
||||
OPBUT { id = ECtlOptRotation0; text = "0º"; },
|
||||
OPBUT { id = ECtlOptRotation90; text = "90º"; },
|
||||
OPBUT { id = ECtlOptRotation180; text = "180º"; },
|
||||
OPBUT { id = ECtlOptRotation270; text = "270º"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_screenmode_buttons
|
||||
{
|
||||
items = {
|
||||
OPBUT { id = ECtlOptScreenModeCenter; text = "Center"; },
|
||||
OPBUT { id = ECtlOptScreenModeFit; text = "Fit"; },
|
||||
OPBUT { id = ECtlOptScreenModeFit2; text = "Fit2"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_snd_quality
|
||||
{
|
||||
items = {
|
||||
LBUF { txt = "8000Hz mono"; },
|
||||
LBUF { txt = "11025Hz mono"; },
|
||||
LBUF { txt = "16000Hz mono"; },
|
||||
LBUF { txt = "22050Hz mono"; },
|
||||
LBUF { txt = "44100Hz mono"; },
|
||||
LBUF { txt = "8000Hz stereo"; },
|
||||
LBUF { txt = "11025Hz stereo"; },
|
||||
LBUF { txt = "16000Hz stereo"; },
|
||||
LBUF { txt = "22050Hz stereo"; },
|
||||
LBUF { txt = "44100Hz stereo"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_config_region
|
||||
{
|
||||
items = {
|
||||
LBUF { txt = "Auto"; },
|
||||
LBUF { txt = "Europe"; },
|
||||
LBUF { txt = "USA"; },
|
||||
LBUF { txt = "Japan PAL"; },
|
||||
LBUF { txt = "Japan NTSC"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* about dialog
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// A simple dialog shall use the QIK_DIALOG resource struct to
|
||||
// define which UI configurations it supports.
|
||||
RESOURCE QIK_DIALOG r_pico_about
|
||||
{
|
||||
title = "About";
|
||||
configurations =
|
||||
{
|
||||
QIK_DIALOG_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = 0;
|
||||
container = r_pico_about_container;
|
||||
command_list = r_pico_about_commands;
|
||||
}
|
||||
};
|
||||
controls = r_pico_about_controls;
|
||||
}
|
||||
|
||||
RESOURCE QIK_COMMAND_LIST r_pico_about_commands
|
||||
{
|
||||
items=
|
||||
{
|
||||
QIK_COMMAND
|
||||
{
|
||||
id = EEikCmdPicoAboutDoneCmd;
|
||||
type = EQikCommandTypeDone;
|
||||
text = "Done";
|
||||
},
|
||||
QIK_COMMAND
|
||||
{
|
||||
id = EEikCmdPicoAboutCreditsCmd;
|
||||
type = EQikCommandTypeItem;
|
||||
text = "Credits";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// A collection of controls that can be used throughout the various
|
||||
// view/container/building block structs by using the unique handle in
|
||||
// QIK_CONTROL. So you can specify how the control should be created here and
|
||||
// just reference to it from other places.
|
||||
RESOURCE QIK_CONTROL_COLLECTION r_pico_about_controls
|
||||
{
|
||||
items =
|
||||
{
|
||||
QIK_CONTROL
|
||||
{
|
||||
unique_handle = ECtlPicoAboutText;
|
||||
type = EEikCtRichTextEditor;
|
||||
control = r_pico_about_rtxted;
|
||||
itemflags = EQikCtrlFlagIsEditInPlace;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// the controls themselves
|
||||
RESOURCE RTXTED r_pico_about_rtxted
|
||||
{
|
||||
flags = EEikEdwinDisplayOnly|EEikEdwinReadOnly|EEikEdwinNoHorizScrolling;
|
||||
numlines = 13;
|
||||
displayMode = 1; // EDisplayModeView;
|
||||
}
|
||||
|
||||
// Defines the content of the simple dialog and how they are laid out.
|
||||
// Default layout manager is used for laying out the controls, which is a row
|
||||
// layout.
|
||||
RESOURCE QIK_CONTAINER_SETTINGS r_pico_about_container
|
||||
{
|
||||
controls =
|
||||
{
|
||||
QIK_CONTAINER_ITEM_CI_LI
|
||||
{
|
||||
type = EQikCtOnelineBuildingBlock;
|
||||
control = r_pico_about_bb1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Building block that contains the label.
|
||||
RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_pico_about_bb1
|
||||
{
|
||||
content =
|
||||
{
|
||||
QIK_SLOT_CONTENT
|
||||
{
|
||||
slot_id = EQikItemSlot1;
|
||||
unique_handle = ECtlPicoAboutText;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RESOURCE TBUF r_pico_text_about
|
||||
{
|
||||
buf=
|
||||
"<f=Polo><s=26><a=center><fg=RgbDarkBlue>PicoDrive"\
|
||||
"<p><f=Polo><s=10><a=center>for UIQ3"\
|
||||
"<p><s=6> <p><f=Corinna><s=12>Version %S, by notaz."\
|
||||
"<p><s=5> <p><s=10>Port based on UIQ2 version, which is based on PicoDrive 0.030 for Pocket PC by Dave"\
|
||||
"<p><s=5> <p><f=Corinna><s=11><u>Email</u>: notasas@gmail.com"\
|
||||
"<p><f=Corinna><s=10><u>Web</u>: http://notaz.atspace.com"\
|
||||
"<p><f=Corinna><s=10><u>Dave's Web</u>: http://www.finalburn.com";
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* credits dialog
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// A simple dialog shall use the QIK_DIALOG resource struct to
|
||||
// define which UI configurations it supports.
|
||||
RESOURCE QIK_DIALOG r_pico_credits
|
||||
{
|
||||
title = "Credits and thanks";
|
||||
configurations =
|
||||
{
|
||||
QIK_DIALOG_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = 0;
|
||||
container = r_pico_credits_container;
|
||||
command_list = r_pico_credits_commands;
|
||||
}
|
||||
};
|
||||
controls = r_pico_credits_controls;
|
||||
}
|
||||
|
||||
RESOURCE QIK_COMMAND_LIST r_pico_credits_commands
|
||||
{
|
||||
items=
|
||||
{
|
||||
QIK_COMMAND
|
||||
{
|
||||
id = EEikCmdPicoAboutDoneCmd;
|
||||
type = EQikCommandTypeDone;
|
||||
text = "Done";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// A collection of controls that can be used throughout the various
|
||||
// view/container/building block structs by using the unique handle in
|
||||
// QIK_CONTROL. So you can specify how the control should be created here and
|
||||
// just reference to it from other places.
|
||||
RESOURCE QIK_CONTROL_COLLECTION r_pico_credits_controls
|
||||
{
|
||||
items =
|
||||
{
|
||||
QIK_CONTROL
|
||||
{
|
||||
unique_handle = ECtlPicoCreditsText;
|
||||
type = EEikCtEdwin;
|
||||
control = r_pico_credits_edwin;
|
||||
itemflags = EQikCtrlFlagIsEditInPlace;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// the controls themselves
|
||||
RESOURCE EDWIN r_pico_credits_edwin
|
||||
{
|
||||
flags = EEikEdwinDisplayOnly|EEikEdwinReadOnly|EEikEdwinNoHorizScrolling|EEikEdwinDisableAutoCurEnd;
|
||||
lines = 11;
|
||||
}
|
||||
|
||||
// Defines the content of the simple dialog and how they are laid out.
|
||||
// Default layout manager is used for laying out the controls, which is a row
|
||||
// layout.
|
||||
RESOURCE QIK_CONTAINER_SETTINGS r_pico_credits_container
|
||||
{
|
||||
controls =
|
||||
{
|
||||
QIK_CONTAINER_ITEM_CI_LI
|
||||
{
|
||||
type = EQikCtOnelineBuildingBlock;
|
||||
control = r_pico_credits_bb1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Building block that contains the label.
|
||||
RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_pico_credits_bb1
|
||||
{
|
||||
content =
|
||||
{
|
||||
QIK_SLOT_CONTENT
|
||||
{
|
||||
slot_id = EQikItemSlot1;
|
||||
unique_handle = ECtlPicoCreditsText;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
RESOURCE ARRAY r_pico_tbuf_credits
|
||||
{
|
||||
items=
|
||||
{
|
||||
LBUF{txt="This emulator uses code from these people / projects:";},
|
||||
LBUF{txt="";},
|
||||
LBUF{txt="Dave";},
|
||||
LBUF{txt="- Cyclone 68000 core, Pico emulation library";},
|
||||
LBUF{txt="Homepage: http://www.finalburn.com/";},
|
||||
LBUF{txt="";},
|
||||
LBUF{txt="Reesy & FluBBa";},
|
||||
LBUF{txt="- DrZ80, the Z80 emulator written in ARM assembly.";},
|
||||
LBUF{txt="Homepage: http://reesy.gp32x.de/";},
|
||||
LBUF{txt="";},
|
||||
LBUF{txt="Tatsuyuki Satoh, Jarek Burczynski, MultiArcadeMachineEmulator (MAME) development";},
|
||||
LBUF{txt="- software implementation of Yamaha FM sound generator and";},
|
||||
LBUF{txt="Texas Instruments SN76489 / SN76496 programmable tone / noise generator";},
|
||||
LBUF{txt="Homepage: http://www.mame.net/";},
|
||||
LBUF{txt="";},
|
||||
LBUF{txt="Additional thanks:";},
|
||||
LBUF{txt="- Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful info about genesis hardware.";},
|
||||
LBUF{txt="- Stéphane Dallongeville for creating Gens and making it open-source.";},
|
||||
LBUF{txt="- Steve Snake for all that he has done for Genesis emulation scene.";},
|
||||
LBUF{txt="- Bart Trzynadlowski for his SSFII and 68000 docs.";},
|
||||
LBUF{txt="- Maze for his research (http://haze.mameworld.info).";},
|
||||
LBUF{txt="- Mark and Jean-loup for zlib library.";},
|
||||
LBUF{txt="- Peter van Sebille for his various open-source Symbian projects to learn from.";},
|
||||
LBUF{txt="- Steve Fischer for his open-source Motorola projects.";},
|
||||
LBUF{txt="- AnotherGuest for all his Symbian stuff and support.";},
|
||||
LBUF{txt="- Inder for the icons.";},
|
||||
LBUF{txt="- Anyone else I forgot. You know who you are.";}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* debug dialog
|
||||
*
|
||||
**************************************/
|
||||
|
||||
RESOURCE QIK_DIALOG r_pico_debug
|
||||
{
|
||||
title = "debug";
|
||||
configurations =
|
||||
{
|
||||
QIK_DIALOG_CONFIGURATION
|
||||
{
|
||||
ui_config_mode = 0;
|
||||
container = r_pico_credits_container; // stuff from credits should fit
|
||||
command_list = r_pico_credits_commands;
|
||||
}
|
||||
};
|
||||
controls = r_pico_credits_controls;
|
||||
}
|
||||
|
20
platform/uiq3/rsc/PicoDrive_loc.rss
Normal file
20
platform/uiq3/rsc/PicoDrive_loc.rss
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <AppInfo.rh>
|
||||
|
||||
// This file localise the applications icons and caption
|
||||
RESOURCE LOCALISABLE_APP_INFO
|
||||
{
|
||||
caption_and_icon =
|
||||
{
|
||||
CAPTION_AND_ICON_INFO
|
||||
{
|
||||
caption = "PicoDrive";
|
||||
// Icons are used to represent applications in the
|
||||
// application launcher and application title bar.
|
||||
// The number_of_icons value identifies how many icons
|
||||
// that exist in the icon_file.
|
||||
number_of_icons = 3;
|
||||
// Using the application icons.
|
||||
icon_file = "\\Resource\\Apps\\PicoDrive.mbm";
|
||||
}
|
||||
};
|
||||
}
|
17
platform/uiq3/rsc/PicoDrive_reg.rss
Normal file
17
platform/uiq3/rsc/PicoDrive_reg.rss
Normal file
|
@ -0,0 +1,17 @@
|
|||
// All registration files need to #include appinfo.rh.
|
||||
#include <AppInfo.rh>
|
||||
|
||||
// All registration files must define UID2, which is always
|
||||
// KUidAppRegistrationResourceFile, and UID3, which is the application's UID.
|
||||
UID2 KUidAppRegistrationResourceFile
|
||||
UID3 0xA00010F3 // application UID
|
||||
|
||||
// Registration file need to containo an APP_REGISTRATION_INFO resource that
|
||||
// minimally needs to provide the name of the application binary (using the
|
||||
// app_file statement).
|
||||
RESOURCE APP_REGISTRATION_INFO
|
||||
{
|
||||
app_file = "PicoDrive"; // filename of application binary (minus extension)
|
||||
// Specify the location of the localisable icon/caption definition file
|
||||
localisable_resource_file = "\\Resource\\Apps\\PicoDrive_loc";
|
||||
}
|
10
platform/uiq3/version.h
Normal file
10
platform/uiq3/version.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
// version number
|
||||
|
||||
#ifndef __VERSION_H
|
||||
#define __VERSION_H
|
||||
|
||||
#define KPicoMajorVersionNumber 0
|
||||
#define KPicoMinorVersionNumber 96
|
||||
#define KPicoBuildNumber 0
|
||||
|
||||
#endif /* __VERSION_H */
|
Loading…
Add table
Add a link
Reference in a new issue