11 #include "version.h"
\r
12 #include "ClientServer.h"
\r
13 #include "SimpleServer.h"
\r
14 #include "pico\picoInt.h"
\r
16 extern TInt machineUid;
\r
17 extern int gamestate, gamestate_prev;
\r
18 extern TPicoConfig currentConfig;
\r
19 extern TPicoKeyConfigEntry keyConfigMotA[];
\r
20 extern const char *actionNames[];
\r
21 const char *RomFileName = 0;
\r
22 int pico_was_reset = 0;
\r
26 unsigned int bigend(unsigned int l)
\r
28 return (l>>24)|((l>>8)&0xff00)|((l<<8)&0xff0000)|(l<<24);
\r
32 //**********************************
\r
34 //**********************************
\r
37 CPicoServServer::CPicoServServer(TInt aPriority)
\r
38 : CServer(aPriority)
\r
43 // Create and start a new count server.
\r
44 void CPicoServServer::New()
\r
46 CPicoServServer *pS=new CPicoServServer(EPriority);
\r
47 __ASSERT_ALWAYS(pS!=NULL,PanicServer(ESvrCreateServer));
\r
48 pS->StartL(KServerName);
\r
52 // Create a new server session.
\r
53 CSharableSession *CPicoServServer::NewSessionL(const TVersion &aVersion) const
\r
55 // check we're the right version
\r
56 TVersion v(KPicoMajorVersionNumber,KPicoMinorVersionNumber,0);
\r
57 if (!User::QueryVersionSupported(v,aVersion))
\r
58 User::Leave(KErrNotSupported);
\r
60 RThread aClient = Message().Client();
\r
61 return CPicoServSession::NewL(aClient, (CPicoServServer*)this);
\r
65 //**********************************
\r
67 //**********************************
\r
70 // constructor - must pass client to CSession
\r
71 CPicoServSession::CPicoServSession(RThread &aClient, CPicoServServer *aServer)
\r
72 : CSession(aClient), rom_data(0)
\r
74 // iPicoSvr=aServer;
\r
77 CPicoServSession* CPicoServSession::NewL(RThread &aClient, CPicoServServer * aServer)
\r
79 return new(ELeave) CPicoServSession(aClient,aServer);
\r
83 void CPicoServSession::ServiceL(const RMessage& aMessage)
\r
85 TRAPD(err,DispatchMessageL(aMessage));
\r
86 aMessage.Complete(err);
\r
91 // service a client request; test the opcode and then do appropriate servicing
\r
92 void CPicoServSession::DispatchMessageL(const RMessage &aMessage)
\r
94 switch (aMessage.Function()) {
\r
95 case PicoMsgLoadState:
\r
96 if(!rom_data) User::Leave(-1); // no ROM
\r
97 User::LeaveIfError(saveLoadGame(1));
\r
98 gamestate = PGS_Running;
\r
101 case PicoMsgSaveState:
\r
102 if(!rom_data) User::Leave(-1);
\r
103 User::LeaveIfError(saveLoadGame(0));
\r
104 gamestate = PGS_Running;
\r
107 case PicoMsgLoadROM:
\r
111 case PicoMsgResume:
\r
112 if(rom_data) gamestate = PGS_Running;
\r
115 case PicoMsgReset:
\r
118 pico_was_reset = 1;
\r
119 gamestate = PGS_Running;
\r
124 gamestate = PGS_KeyConfig;
\r
128 gamestate = PGS_Paused;
\r
132 DEBUGPRINT(_L("got quit msg."));
\r
133 gamestate = PGS_Quit;
\r
137 case PicoMsgConfigChange: // launcher -> emu
\r
141 case PicoMsgRetrieveConfig: // emu -> launcher
\r
145 case PicoMsgRetrieveDebugStr: // emu -> launcher
\r
149 // requests we don't understand at all are a different thing,
\r
150 // so panic the client here, this function also completes the message
\r
152 PanicClient(EBadRequest);
\r
158 void CPicoServSession::loadROM()
\r
162 const TAny* pD=Message().Ptr0();
\r
164 // TInt desLen=Message().Client().GetDesLength(pD);
\r
167 // save SRAM for previous ROM
\r
168 if(currentConfig.iFlags & 1)
\r
169 saveLoadGame(0, 1);
\r
178 // read the contents of the client pointer into a TPtr.
\r
179 static TBuf8<KMaxFileName> writeBuf;
\r
180 TRAP(res,Message().ReadL(pD,writeBuf));
\r
181 if (res!=KErrNone) {
\r
182 PanicClient(EBadDescriptor);
\r
186 // detect wrong extensions (.srm and .mds)
\r
188 ext.Copy(writeBuf.Right(4));
\r
190 if(!strcmp((char *)ext.PtrZ(), ".srm") || !strcmp((char *)ext.PtrZ(), "s.gz") || // .mds.gz
\r
191 !strcmp((char *)ext.PtrZ(), ".mds")) {
\r
196 FILE *rom = fopen((char *) writeBuf.PtrZ(), "rb");
\r
198 DEBUGPRINT(_L("failed to open rom."));
\r
204 unsigned int rom_size = 0;
\r
206 if(!strcmp((char *)ext.PtrZ(), ".zip")) {
\r
208 res = CartLoadZip((const char *) writeBuf.PtrZ(), &rom_data, &rom_size);
\r
214 if( (res = PicoCartLoad(rom, &rom_data, &rom_size)) ) {
\r
215 DEBUGPRINT(_L("PicoCartLoad() failed."));
\r
223 // detect wrong files (Pico crashes on very small files), also see if ROM EP is good
\r
224 if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 ||
\r
225 ((*(TUint16 *)(rom_data+4)<<16)|(*(TUint16 *)(rom_data+6))) >= (int)rom_size) {
\r
228 User::Leave(3); // not a ROM
\r
231 DEBUGPRINT(_L("PicoCartInsert(0x%08X, %d);"), rom_data, rom_size);
\r
232 if(PicoCartInsert(rom_data, rom_size)) {
\r
237 pico_was_reset = 1;
\r
239 // global ROM file name for later use
\r
240 RomFileName = (const char *) writeBuf.PtrZ();
\r
242 // load SRAM for this ROM
\r
243 if(currentConfig.iFlags & 1)
\r
244 saveLoadGame(1, 1);
\r
247 #ifdef __DEBUG_PRINT
\r
248 TInt cells = User::CountAllocCells();
\r
250 User::AllocSize(mem);
\r
251 DEBUGPRINT(_L("comm: cels=%d, size=%d KB"), cells, mem/1024);
\r
252 gamestate = PGS_DebugHeap;
\r
253 gamestate_prev = PGS_Running;
\r
255 gamestate = PGS_Running;
\r
260 void CPicoServSession::changeConfig()
\r
262 DEBUGPRINT(_L("got new config."));
\r
265 const TAny* pD=Message().Ptr0();
\r
266 TPtr8 descr((TUint8*) ¤tConfig, sizeof(currentConfig));
\r
267 TRAPD(res,Message().ReadL(pD, descr));
\r
268 if (res!=KErrNone) {
\r
269 PanicClient(EBadDescriptor);
\r
273 // Motorola: enable experimental volume control
\r
274 if((machineUid&0xfffffff0) == 0x101f6b20) { // Motorolas
\r
275 if(currentConfig.iFlags & 0x40) {
\r
276 currentConfig.iKeyBinds[11] = 0x00100000; // vol up
\r
277 currentConfig.iKeyBinds[12] = 0x00200000; // vol down
\r
278 keyConfigMotA[11].flags |= 0x40; // add "not configurable" flag
\r
279 keyConfigMotA[12].flags |= 0x40;
\r
281 currentConfig.iKeyBinds[11] &= ~0x00100000; // remove vol actions
\r
282 currentConfig.iKeyBinds[12] &= ~0x00200000;
\r
283 keyConfigMotA[11].flags &= ~0x40; // remove "not configurable" flag
\r
284 keyConfigMotA[12].flags &= ~0x40;
\r
288 // set region, PicoOpt and rate
\r
289 PicoRegionOverride = currentConfig.PicoRegion;
\r
290 PicoOpt = currentConfig.iPicoOpt;
\r
291 switch((currentConfig.iFlags>>3)&3) {
\r
292 case 1: PsndRate=11025; break;
\r
293 case 2: PsndRate=16000; break;
\r
294 case 3: PsndRate=22050; break;
\r
295 default: PsndRate= 8000; break;
\r
298 // 6 button pad, enable XYZM config if needed
\r
299 if(PicoOpt & 0x20) {
\r
300 actionNames[8] = "Z";
\r
301 actionNames[9] = "Y";
\r
302 actionNames[10] = "X";
\r
303 actionNames[11] = "MODE";
\r
305 actionNames[8] = actionNames[9] = actionNames[10] = actionNames[11] = 0;
\r
308 // if we are in center 90||270 modes, we can bind renderer switcher
\r
309 if(currentConfig.iScreenMode == TPicoConfig::PMCenter &&
\r
310 (currentConfig.iScreenRotation == TPicoConfig::PRot90 || currentConfig.iScreenRotation == TPicoConfig::PRot270))
\r
311 actionNames[25] = "RENDERER";
\r
312 else actionNames[25] = 0;
\r
316 void CPicoServSession::sendConfig()
\r
318 // send current config to client
\r
319 currentConfig.iPicoOpt = PicoOpt;
\r
320 TPtrC8 descr((TUint8*) ¤tConfig, sizeof(currentConfig));
\r
321 Write(Message().Ptr0(), descr);
\r
324 #ifdef __DEBUG_PRINT
\r
325 extern "C" char *debugString();
\r
328 void CPicoServSession::sendDebug()
\r
330 #ifdef __DEBUG_PRINT
\r
331 char *str = debugString();
\r
332 // send current config to client
\r
333 currentConfig.iPicoOpt = PicoOpt;
\r
334 TPtrC8 descr((TUint8*) str, 1024);
\r
335 Write(Message().Ptr0(), descr);
\r
339 // panic the client
\r
340 void CPicoServSession::PanicClient(TInt aPanic) const
\r
342 Panic(_L("PicoN client"), aPanic);
\r
343 // client screwed up - there is nothing for us to do now
\r
349 // write to the client thread; if unsuccessful, panic the client
\r
350 void CPicoServSession::Write(const TAny* aPtr,const TDesC8& aDes,TInt anOffset)
\r
352 TRAPD(ret,WriteL(aPtr,aDes,anOffset);)
\r
354 PanicClient(EBadDescriptor);
\r
359 //**********************************
\r
361 //**********************************
\r
364 // The server thread.
\r
365 TInt CPicoServServer::ThreadFunction(TAny* anArg)
\r
367 // install our exception hanler first
\r
368 RThread().SetExceptionHandler(&ExceptionHandler, -1);
\r
370 // convert argument into semaphore reference
\r
371 // RSemaphore& semaphore=*(RSemaphore *)anArg;
\r
373 // start scheduler and server
\r
374 CActiveScheduler *pA=new CActiveScheduler;
\r
375 __ASSERT_ALWAYS(pA!=NULL,PanicServer(EMainSchedulerError));
\r
376 CActiveScheduler::Install(pA);
\r
377 //CTrapCleanup::New(); // docs say this is created automatically, but I somehow got E32USER-CBase 69 panic
\r
378 CPicoServServer::New();
\r
379 // signal that we've started
\r
380 // semaphore.Signal();
\r
381 // start fielding requests from clients
\r
382 CActiveScheduler::Start();
\r
388 // Panic the server
\r
390 void PanicServer(TPicoServPanic aPanic)
\r
392 User::Panic(_L("PicoN server"),aPanic);
\r
396 // Create the server thread
\r
397 // This function is exported from the DLL and called from the client
\r
402 // create server - if one of this name does not already exist
\r
403 TFindServer findPicoServer(KServerName);
\r
405 if(findPicoServer.Next(name) == KErrNone) return -1; // we already exist
\r
408 // RSemaphore semaphore;
\r
409 // semaphore.CreateLocal(0); // create a semaphore so we know when thread finished
\r
410 res=thread.Create(KServerName, // create new server thread
\r
411 CPicoServServer::ThreadFunction, // thread's main function
\r
415 // &semaphore // passed as TAny* argument to thread function
\r
419 if(res==KErrNone) { // thread created ok - now start it going
\r
420 thread.SetPriority(EPriorityNormal);
\r
421 thread.Resume(); // start it going
\r
422 // semaphore.Wait(); // wait until it's initialized
\r
423 thread.Close(); // we're no longer interested in the other thread
\r
426 // semaphore.Close();
\r