+++ /dev/null
-// SimpleServer.cpp\r
-\r
-#include <e32svr.h>\r
-#include <e32math.h>\r
-#include <e32uid.h>\r
-\r
-#include <string.h>\r
-\r
-#include "debug.h"\r
-\r
-#include "version.h"\r
-#include "ClientServer.h"\r
-#include "SimpleServer.h"\r
-#include "pico\picoInt.h"\r
-\r
-extern TInt machineUid;\r
-extern int gamestate, gamestate_prev;\r
-extern TPicoConfig currentConfig;\r
-extern TPicoKeyConfigEntry keyConfigMotA[];\r
-extern const char *actionNames[];\r
-const char *RomFileName = 0;\r
-int pico_was_reset = 0;\r
-\r
-\r
-// utility\r
-unsigned int bigend(unsigned int l)\r
-{\r
- return (l>>24)|((l>>8)&0xff00)|((l<<8)&0xff0000)|(l<<24);\r
-}\r
-\r
-\r
-//**********************************\r
-//CPicoServServer\r
-//**********************************\r
-\r
-\r
-CPicoServServer::CPicoServServer(TInt aPriority)\r
- : CServer(aPriority)\r
-{\r
-}\r
-\r
-\r
-// Create and start a new count server.\r
-void CPicoServServer::New()\r
-{\r
- CPicoServServer *pS=new CPicoServServer(EPriority);\r
- __ASSERT_ALWAYS(pS!=NULL,PanicServer(ESvrCreateServer));\r
- pS->StartL(KServerName);\r
-}\r
-\r
-\r
-// Create a new server session.\r
-CSharableSession *CPicoServServer::NewSessionL(const TVersion &aVersion) const\r
-{\r
- // check we're the right version\r
- TVersion v(KPicoMajorVersionNumber,KPicoMinorVersionNumber,0);\r
- if (!User::QueryVersionSupported(v,aVersion))\r
- User::Leave(KErrNotSupported);\r
- // make new session\r
- RThread aClient = Message().Client();\r
- return CPicoServSession::NewL(aClient, (CPicoServServer*)this);\r
-}\r
-\r
-\r
-//**********************************\r
-//CPicoServSession\r
-//**********************************\r
-\r
-\r
-// constructor - must pass client to CSession\r
-CPicoServSession::CPicoServSession(RThread &aClient, CPicoServServer *aServer)\r
-: CSession(aClient), rom_data(0)\r
-{\r
-// iPicoSvr=aServer;\r
-}\r
-\r
-CPicoServSession* CPicoServSession::NewL(RThread &aClient, CPicoServServer * aServer)\r
-{\r
- return new(ELeave) CPicoServSession(aClient,aServer);\r
-}\r
-\r
-\r
-void CPicoServSession::ServiceL(const RMessage& aMessage)\r
-{\r
- TRAPD(err,DispatchMessageL(aMessage));\r
- aMessage.Complete(err);\r
-}\r
-\r
-\r
-\r
-// service a client request; test the opcode and then do appropriate servicing\r
-void CPicoServSession::DispatchMessageL(const RMessage &aMessage)\r
-{\r
- switch (aMessage.Function()) {\r
- case PicoMsgLoadState: \r
- if(!rom_data) User::Leave(-1); // no ROM\r
- User::LeaveIfError(saveLoadGame(1));\r
- gamestate = PGS_Running;\r
- return;\r
-\r
- case PicoMsgSaveState:\r
- if(!rom_data) User::Leave(-1);\r
- User::LeaveIfError(saveLoadGame(0));\r
- gamestate = PGS_Running;\r
- return;\r
-\r
- case PicoMsgLoadROM:\r
- loadROM();\r
- return;\r
- \r
- case PicoMsgResume:\r
- if(rom_data) gamestate = PGS_Running;\r
- return;\r
-\r
- case PicoMsgReset: \r
- if(rom_data) {\r
- PicoReset();\r
- pico_was_reset = 1;\r
- gamestate = PGS_Running;\r
- }\r
- return;\r
-\r
- case PicoMsgKeys:\r
- gamestate = PGS_KeyConfig;\r
- return;\r
-\r
- case PicoMsgPause:\r
- gamestate = PGS_Paused;\r
- return;\r
-\r
- case PicoMsgQuit:\r
- DEBUGPRINT(_L("got quit msg."));\r
- gamestate = PGS_Quit;\r
- return;\r
-\r
- // config change\r
- case PicoMsgConfigChange: // launcher -> emu\r
- changeConfig();\r
- return;\r
-\r
- case PicoMsgRetrieveConfig: // emu -> launcher\r
- sendConfig();\r
- return;\r
-\r
- case PicoMsgRetrieveDebugStr: // emu -> launcher\r
- sendDebug();\r
- return;\r
-\r
- // requests we don't understand at all are a different thing,\r
- // so panic the client here, this function also completes the message\r
- default:\r
- PanicClient(EBadRequest);\r
- return;\r
- }\r
-}\r
-\r
-\r
-void CPicoServSession::loadROM()\r
-{\r
- TInt res;\r
-\r
- const TAny* pD=Message().Ptr0();\r
-\r
- // TInt desLen=Message().Client().GetDesLength(pD);\r
-\r
- if(rom_data) {\r
- // save SRAM for previous ROM\r
- if(currentConfig.iFlags & 1)\r
- saveLoadGame(0, 1);\r
- }\r
-\r
- RomFileName = 0;\r
- if(rom_data) {\r
- free(rom_data);\r
- rom_data = 0;\r
- }\r
-\r
- // read the contents of the client pointer into a TPtr.\r
- static TBuf8<KMaxFileName> writeBuf;\r
- TRAP(res,Message().ReadL(pD,writeBuf));\r
- if (res!=KErrNone) {\r
- PanicClient(EBadDescriptor);\r
- return;\r
- }\r
-\r
- // detect wrong extensions (.srm and .mds)\r
- TBuf8<5> ext;\r
- ext.Copy(writeBuf.Right(4));\r
- ext.LowerCase();\r
- if(!strcmp((char *)ext.PtrZ(), ".srm") || !strcmp((char *)ext.PtrZ(), "s.gz") || // .mds.gz\r
- !strcmp((char *)ext.PtrZ(), ".mds")) {\r
- User::Leave(3);\r
- return;\r
- }\r
-\r
- FILE *rom = fopen((char *) writeBuf.PtrZ(), "rb");\r
- if(!rom) {\r
- DEBUGPRINT(_L("failed to open rom."));\r
- User::Leave(1);\r
- return;\r
- }\r
-\r
-\r
- unsigned int rom_size = 0;\r
- // zipfile support\r
- if(!strcmp((char *)ext.PtrZ(), ".zip")) {\r
- fclose(rom);\r
- res = CartLoadZip((const char *) writeBuf.PtrZ(), &rom_data, &rom_size);\r
- if(res) {\r
- User::Leave(res);\r
- return;\r
- }\r
- } else {\r
- if( (res = PicoCartLoad(rom, &rom_data, &rom_size)) ) {\r
- DEBUGPRINT(_L("PicoCartLoad() failed."));\r
- fclose(rom);\r
- User::Leave(2);\r
- return;\r
- }\r
- fclose(rom);\r
- }\r
-\r
- // detect wrong files (Pico crashes on very small files), also see if ROM EP is good\r
- if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 ||\r
- ((*(TUint16 *)(rom_data+4)<<16)|(*(TUint16 *)(rom_data+6))) >= (int)rom_size) {\r
- free(rom_data);\r
- rom_data = 0;\r
- User::Leave(3); // not a ROM\r
- }\r
-\r
- DEBUGPRINT(_L("PicoCartInsert(0x%08X, %d);"), rom_data, rom_size);\r
- if(PicoCartInsert(rom_data, rom_size)) {\r
- User::Leave(2);\r
- return;\r
- }\r
-\r
- pico_was_reset = 1;\r
-\r
- // global ROM file name for later use\r
- RomFileName = (const char *) writeBuf.PtrZ();\r
-\r
- // load SRAM for this ROM\r
- if(currentConfig.iFlags & 1)\r
- saveLoadGame(1, 1);\r
-\r
- // debug\r
- #ifdef __DEBUG_PRINT\r
- TInt cells = User::CountAllocCells();\r
- TInt mem;\r
- User::AllocSize(mem);\r
- DEBUGPRINT(_L("comm: cels=%d, size=%d KB"), cells, mem/1024);\r
- gamestate = PGS_DebugHeap;\r
- gamestate_prev = PGS_Running;\r
- #else\r
- gamestate = PGS_Running;\r
- #endif\r
-}\r
-\r
-\r
-void CPicoServSession::changeConfig()\r
-{\r
- DEBUGPRINT(_L("got new config."));\r
-\r
- // receve it\r
- const TAny* pD=Message().Ptr0();\r
- TPtr8 descr((TUint8*) ¤tConfig, sizeof(currentConfig));\r
- TRAPD(res,Message().ReadL(pD, descr));\r
- if (res!=KErrNone) {\r
- PanicClient(EBadDescriptor);\r
- return;\r
- }\r
-\r
- // Motorola: enable experimental volume control\r
- if((machineUid&0xfffffff0) == 0x101f6b20) { // Motorolas\r
- if(currentConfig.iFlags & 0x40) {\r
- currentConfig.iKeyBinds[11] = 0x00100000; // vol up\r
- currentConfig.iKeyBinds[12] = 0x00200000; // vol down\r
- keyConfigMotA[11].flags |= 0x40; // add "not configurable" flag\r
- keyConfigMotA[12].flags |= 0x40;\r
- } else {\r
- currentConfig.iKeyBinds[11] &= ~0x00100000; // remove vol actions\r
- currentConfig.iKeyBinds[12] &= ~0x00200000;\r
- keyConfigMotA[11].flags &= ~0x40; // remove "not configurable" flag\r
- keyConfigMotA[12].flags &= ~0x40;\r
- }\r
- }\r
-\r
- // set region, PicoOpt and rate\r
- PicoRegionOverride = currentConfig.PicoRegion;\r
- PicoOpt = currentConfig.iPicoOpt;\r
- switch((currentConfig.iFlags>>3)&3) {\r
- case 1: PsndRate=11025; break;\r
- case 2: PsndRate=16000; break;\r
- case 3: PsndRate=22050; break;\r
- default: PsndRate= 8000; break;\r
- }\r
-\r
- // 6 button pad, enable XYZM config if needed\r
- if(PicoOpt & 0x20) {\r
- actionNames[8] = "Z";\r
- actionNames[9] = "Y";\r
- actionNames[10] = "X";\r
- actionNames[11] = "MODE";\r
- } else {\r
- actionNames[8] = actionNames[9] = actionNames[10] = actionNames[11] = 0;\r
- }\r
-\r
- // if we are in center 90||270 modes, we can bind renderer switcher\r
- if(currentConfig.iScreenMode == TPicoConfig::PMCenter &&\r
- (currentConfig.iScreenRotation == TPicoConfig::PRot90 || currentConfig.iScreenRotation == TPicoConfig::PRot270))\r
- actionNames[25] = "RENDERER";\r
- else actionNames[25] = 0;\r
-}\r
-\r
-\r
-void CPicoServSession::sendConfig()\r
-{\r
- // send current config to client\r
- currentConfig.iPicoOpt = PicoOpt;\r
- TPtrC8 descr((TUint8*) ¤tConfig, sizeof(currentConfig));\r
- Write(Message().Ptr0(), descr);\r
-}\r
-\r
-#ifdef __DEBUG_PRINT\r
-extern "C" char *debugString();\r
-#endif\r
-\r
-void CPicoServSession::sendDebug()\r
-{\r
-#ifdef __DEBUG_PRINT\r
- char *str = debugString();\r
- // send current config to client\r
- currentConfig.iPicoOpt = PicoOpt;\r
- TPtrC8 descr((TUint8*) str, 1024);\r
- Write(Message().Ptr0(), descr);\r
-#endif\r
-}\r
-\r
-// panic the client\r
-void CPicoServSession::PanicClient(TInt aPanic) const\r
-{\r
- Panic(_L("PicoN client"), aPanic);\r
- // client screwed up - there is nothing for us to do now\r
- RProcess me;\r
- me.Terminate(1);\r
-}\r
-\r
-\r
-// write to the client thread; if unsuccessful, panic the client\r
-void CPicoServSession::Write(const TAny* aPtr,const TDesC8& aDes,TInt anOffset)\r
-{\r
- TRAPD(ret,WriteL(aPtr,aDes,anOffset);)\r
- if (ret!=KErrNone)\r
- PanicClient(EBadDescriptor);\r
-}\r
-\r
-\r
-\r
-//**********************************\r
-//Global functions\r
-//**********************************\r
-\r
-\r
-// The server thread.\r
-TInt CPicoServServer::ThreadFunction(TAny* anArg)\r
-{\r
- // install our exception hanler first\r
- RThread().SetExceptionHandler(&ExceptionHandler, -1);\r
-\r
- // convert argument into semaphore reference\r
-// RSemaphore& semaphore=*(RSemaphore *)anArg;\r
-\r
- // start scheduler and server\r
- CActiveScheduler *pA=new CActiveScheduler;\r
- __ASSERT_ALWAYS(pA!=NULL,PanicServer(EMainSchedulerError));\r
- CActiveScheduler::Install(pA);\r
- //CTrapCleanup::New(); // docs say this is created automatically, but I somehow got E32USER-CBase 69 panic\r
- CPicoServServer::New();\r
- // signal that we've started\r
-// semaphore.Signal();\r
- // start fielding requests from clients\r
- CActiveScheduler::Start();\r
- // finished\r
- return(KErrNone);\r
-}\r
-\r
-\r
-// Panic the server\r
-//GLDEF_C \r
-void PanicServer(TPicoServPanic aPanic)\r
-{\r
- User::Panic(_L("PicoN server"),aPanic);\r
-}\r
-\r
-\r
-// Create the server thread\r
-// This function is exported from the DLL and called from the client \r
-//EXPORT_C\r
-TInt StartThread()\r
-{\r
- TInt res=KErrNone;\r
- // create server - if one of this name does not already exist\r
- TFindServer findPicoServer(KServerName);\r
- TFullName name;\r
- if(findPicoServer.Next(name) == KErrNone) return -1; // we already exist\r
-\r
- RThread thread;\r
-// RSemaphore semaphore;\r
-// semaphore.CreateLocal(0); // create a semaphore so we know when thread finished\r
- res=thread.Create(KServerName, // create new server thread\r
- CPicoServServer::ThreadFunction, // thread's main function\r
- KDefaultStackSize,\r
- KMinHeapSize,\r
- KPicoMaxHeapSize,\r
-// &semaphore // passed as TAny* argument to thread function\r
- 0\r
- );\r
-\r
- if(res==KErrNone) { // thread created ok - now start it going\r
- thread.SetPriority(EPriorityNormal);\r
- thread.Resume(); // start it going\r
-// semaphore.Wait(); // wait until it's initialized\r
- thread.Close(); // we're no longer interested in the other thread\r
- }\r
-\r
-// semaphore.Close();\r
-\r
- return res;\r
-}\r
-\r