1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #define FORBIDDEN_SYMBOL_ALLOW_ALL
24
25 #include <unistd.h>
26 #include <sys/time.h>
27 #include <list>
28
29 #include <retro_miscellaneous.h>
30 #include <retro_inline.h>
31
32 #include "graphics/surface.libretro.h"
33 #include "backends/base-backend.h"
34 #include "common/events.h"
35 #include "audio/mixer_intern.h"
36
37 #if defined(_WIN32)
38 #include "backends/fs/windows/windows-fs-factory.h"
39 #define FS_SYSTEM_FACTORY WindowsFilesystemFactory
40 #else
41 #include "backends/fs/libretro/libretro-fs-factory.h"
42 #define FS_SYSTEM_FACTORY LibRetroFilesystemFactory
43 #endif
44
45 #include "backends/timer/default/default-timer.h"
46 #include "graphics/colormasks.h"
47 #include "graphics/palette.h"
48 #include "backends/saves/default/default-saves.h"
49 #if defined(_WIN32)
50 #include <direct.h>
51 #ifdef _XBOX
52 #include <xtl.h>
53 #else
54 #include <windows.h>
55 #endif
56 #elif defined(__CELLOS_LV2__)
57 #include <sys/sys_time.h>
58 #elif (defined(GEKKO) && !defined(WIIU))
59 #include <ogc/lwp_watchdog.h>
60 #else
61 #include <time.h>
62 #endif
63
64 #include "libretro.h"
65
66 extern retro_log_printf_t log_cb;
67
68 struct RetroPalette
69 {
70 unsigned char _colors[256 * 3];
71
RetroPaletteRetroPalette72 RetroPalette()
73 {
74 memset(_colors, 0, sizeof(_colors));
75 }
76
setRetroPalette77 void set(const byte *colors, uint start, uint num)
78 {
79 memcpy(_colors + start * 3, colors, num * 3);
80 }
81
getRetroPalette82 void get(byte* colors, uint start, uint num) const
83 {
84 memcpy(colors, _colors + start * 3, num * 3);
85 }
86
getColorRetroPalette87 unsigned char *getColor(uint aIndex) const
88 {
89 return (unsigned char*)&_colors[aIndex * 3];
90 }
91 };
92
blit_uint8_uint16_fast(Graphics::Surface & aOut,const Graphics::Surface & aIn,const RetroPalette & aColors)93 static INLINE void blit_uint8_uint16_fast(Graphics::Surface& aOut, const Graphics::Surface& aIn, const RetroPalette& aColors)
94 {
95 for(int i = 0; i < aIn.h; i ++)
96 {
97 if(i >= aOut.h)
98 continue;
99
100 uint8_t * const in = (uint8_t*)aIn.pixels + (i * aIn.w);
101 uint16_t* const out = (uint16_t*)aOut.pixels + (i * aOut.w);
102
103 for(int j = 0; j < aIn.w; j ++)
104 {
105 if (j >= aOut.w)
106 continue;
107
108 uint8 r, g, b;
109
110 const uint8_t val = in[j];
111 if(val != 0xFFFFFFFF)
112 {
113 if(aIn.format.bytesPerPixel == 1)
114 {
115 unsigned char *col = aColors.getColor(val);
116 r = *col++;
117 g = *col++;
118 b = *col++;
119 }
120 else
121 aIn.format.colorToRGB(in[j], r, g, b);
122
123 out[j] = aOut.format.RGBToColor(r, g, b);
124 }
125 }
126 }
127 }
128
blit_uint32_uint16(Graphics::Surface & aOut,const Graphics::Surface & aIn,const RetroPalette & aColors)129 static INLINE void blit_uint32_uint16(Graphics::Surface& aOut, const Graphics::Surface& aIn, const RetroPalette& aColors)
130 {
131 for(int i = 0; i < aIn.h; i ++)
132 {
133 if(i >= aOut.h)
134 continue;
135
136 uint32_t* const in = (uint32_t*)aIn.pixels + (i * aIn.w);
137 uint16_t* const out = (uint16_t*)aOut.pixels + (i * aOut.w);
138
139 for(int j = 0; j < aIn.w; j ++)
140 {
141 if(j >= aOut.w)
142 continue;
143
144 uint8 r, g, b;
145
146 const uint32_t val = in[j];
147 if(val != 0xFFFFFFFF)
148 {
149 aIn.format.colorToRGB(in[j], r, g, b);
150 out[j] = aOut.format.RGBToColor(r, g, b);
151 }
152 }
153 }
154 }
155
blit_uint16_uint16(Graphics::Surface & aOut,const Graphics::Surface & aIn,const RetroPalette & aColors)156 static INLINE void blit_uint16_uint16(Graphics::Surface& aOut, const Graphics::Surface& aIn, const RetroPalette& aColors)
157 {
158 for(int i = 0; i < aIn.h; i ++)
159 {
160 if(i >= aOut.h)
161 continue;
162
163 uint16_t* const in = (uint16_t*)aIn.pixels + (i * aIn.w);
164 uint16_t* const out = (uint16_t*)aOut.pixels + (i * aOut.w);
165
166 for(int j = 0; j < aIn.w; j ++)
167 {
168 if(j >= aOut.w)
169 continue;
170
171 uint8 r, g, b;
172
173 const uint16_t val = in[j];
174 if(val != 0xFFFFFFFF)
175 {
176 aIn.format.colorToRGB(in[j], r, g, b);
177 out[j] = aOut.format.RGBToColor(r, g, b);
178 }
179 }
180 }
181 }
182
blit_uint8_uint16(Graphics::Surface & aOut,const Graphics::Surface & aIn,int aX,int aY,const RetroPalette & aColors,uint32 aKeyColor)183 static void blit_uint8_uint16(Graphics::Surface& aOut, const Graphics::Surface& aIn, int aX, int aY, const RetroPalette& aColors, uint32 aKeyColor)
184 {
185 for(int i = 0; i < aIn.h; i ++)
186 {
187 if((i + aY) < 0 || (i + aY) >= aOut.h)
188 continue;
189
190 uint8_t* const in = (uint8_t*)aIn.pixels + (i * aIn.w);
191 uint16_t* const out = (uint16_t*)aOut.pixels + ((i + aY) * aOut.w);
192
193 for(int j = 0; j < aIn.w; j ++)
194 {
195 if((j + aX) < 0 || (j + aX) >= aOut.w)
196 continue;
197
198 uint8 r, g, b;
199
200 const uint8_t val = in[j];
201 if(val != aKeyColor)
202 {
203 unsigned char *col = aColors.getColor(val);
204 r = *col++;
205 g = *col++;
206 b = *col++;
207 out[j + aX] = aOut.format.RGBToColor(r, g, b);
208 }
209 }
210 }
211 }
212
blit_uint16_uint16(Graphics::Surface & aOut,const Graphics::Surface & aIn,int aX,int aY,const RetroPalette & aColors,uint32 aKeyColor)213 static void blit_uint16_uint16(Graphics::Surface& aOut, const Graphics::Surface& aIn, int aX, int aY, const RetroPalette& aColors, uint32 aKeyColor)
214 {
215 for(int i = 0; i < aIn.h; i ++)
216 {
217 if((i + aY) < 0 || (i + aY) >= aOut.h)
218 continue;
219
220 uint16_t* const in = (uint16_t*)aIn.pixels + (i * aIn.w);
221 uint16_t* const out = (uint16_t*)aOut.pixels + ((i + aY) * aOut.w);
222
223 for(int j = 0; j < aIn.w; j ++)
224 {
225 if((j + aX) < 0 || (j + aX) >= aOut.w)
226 continue;
227
228 uint8 r, g, b;
229
230 const uint16_t val = in[j];
231 if(val != aKeyColor)
232 {
233 aIn.format.colorToRGB(in[j], r, g, b);
234 out[j + aX] = aOut.format.RGBToColor(r, g, b);
235 }
236 }
237 }
238 }
239
copyRectToSurface(uint8_t * pixels,int out_pitch,const uint8_t * src,int pitch,int x,int y,int w,int h,int out_bpp)240 static INLINE void copyRectToSurface(uint8_t *pixels, int out_pitch, const uint8_t *src, int pitch, int x, int y, int w, int h, int out_bpp)
241 {
242 uint8_t *dst = pixels + y * out_pitch + x * out_bpp;
243
244 do
245 {
246 memcpy(dst, src, w * out_bpp);
247 src += pitch;
248 dst += out_pitch;
249 }while(--h);
250 }
251
252 static Common::String s_systemDir;
253 static Common::String s_saveDir;
254
255 #ifdef FRONTEND_SUPPORTS_RGB565
256 #define SURF_BPP 2
257 #define SURF_RBITS 2
258 #define SURF_GBITS 5
259 #define SURF_BBITS 6
260 #define SURF_ABITS 5
261 #define SURF_ALOSS (8-SURF_ABITS)
262 #define SURF_RLOSS (8-SURF_RBITS)
263 #define SURF_GLOSS (8-SURF_GBITS)
264 #define SURF_BLOSS (8-SURF_BBITS)
265 #define SURF_RSHIFT 0
266 #define SURF_GSHIFT 11
267 #define SURF_BSHIFT 5
268 #define SURF_ASHIFT 0
269 #else
270 #define SURF_BPP 2
271 #define SURF_RBITS 5
272 #define SURF_GBITS 5
273 #define SURF_BBITS 5
274 #define SURF_ABITS 1
275 #define SURF_ALOSS (8-SURF_ABITS)
276 #define SURF_RLOSS (8-SURF_RBITS)
277 #define SURF_GLOSS (8-SURF_GBITS)
278 #define SURF_BLOSS (8-SURF_BBITS)
279 #define SURF_RSHIFT 10
280 #define SURF_GSHIFT 5
281 #define SURF_BSHIFT 0
282 #define SURF_ASHIFT 15
283 #endif
284
285 std::list<Common::Event> _events;
286
287 class OSystem_RETRO : public EventsBaseBackend, public PaletteManager {
288 public:
289 Graphics::Surface _screen;
290
291 Graphics::Surface _gameScreen;
292 RetroPalette _gamePalette;
293
294 Graphics::Surface _overlay;
295 bool _overlayVisible;
296
297 Graphics::Surface _mouseImage;
298 RetroPalette _mousePalette;
299 bool _mousePaletteEnabled;
300 bool _mouseVisible;
301 int _mouseX;
302 int _mouseY;
303 float _mouseXAcc;
304 float _mouseYAcc;
305 int _mouseHotspotX;
306 int _mouseHotspotY;
307 int _mouseKeyColor;
308 bool _mouseDontScale;
309 bool _mouseButtons[2];
310 bool _joypadmouseButtons[2];
311 bool _joypadkeyboardButtons[8];
312 unsigned _joypadnumpadLast;
313 bool _joypadnumpadActive;
314 bool _ptrmouseButton;
315
316 uint32 _startTime;
317 uint32 _threadExitTime;
318
319 bool _speed_hack_enabled;
320
321
322 Audio::MixerImpl* _mixer;
323
324
OSystem_RETRO(bool aEnableSpeedHack)325 OSystem_RETRO(bool aEnableSpeedHack) :
326 _mousePaletteEnabled(false), _mouseVisible(false),
327 _mouseX(0), _mouseY(0), _mouseXAcc(0.0), _mouseYAcc(0.0), _mouseHotspotX(0), _mouseHotspotY(0),
328 _mouseKeyColor(0), _mouseDontScale(false),
329 _joypadnumpadLast(8), _joypadnumpadActive(false),
330 _mixer(0), _startTime(0), _threadExitTime(10),
331 _speed_hack_enabled(aEnableSpeedHack)
332 {
333 _fsFactory = new FS_SYSTEM_FACTORY();
334 memset(_mouseButtons, 0, sizeof(_mouseButtons));
335 memset(_joypadmouseButtons, 0, sizeof(_joypadmouseButtons));
336 memset(_joypadkeyboardButtons, 0, sizeof(_joypadkeyboardButtons));
337
338 _startTime = getMillis();
339
340 if(s_systemDir.empty())
341 s_systemDir = ".";
342
343 if(s_saveDir.empty())
344 s_saveDir = ".";
345 }
346
~OSystem_RETRO()347 virtual ~OSystem_RETRO()
348 {
349 _gameScreen.free();
350 _overlay.free();
351 _mouseImage.free();
352 _screen.free();
353
354 delete _mixer;
355 }
356
initBackend()357 virtual void initBackend()
358 {
359 _savefileManager = new DefaultSaveFileManager(s_saveDir);
360 #ifdef FRONTEND_SUPPORTS_RGB565
361 _overlay.create(RES_W, RES_H, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
362 #else
363 _overlay.create(RES_W, RES_H, Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
364 #endif
365 _mixer = new Audio::MixerImpl(44100);
366 _timerManager = new DefaultTimerManager();
367
368 _mixer->setReady(true);
369
370 BaseBackend::initBackend();
371 }
372
hasFeature(Feature f)373 virtual bool hasFeature(Feature f)
374 {
375 return (f == OSystem::kFeatureCursorPalette);
376 }
377
setFeatureState(Feature f,bool enable)378 virtual void setFeatureState(Feature f, bool enable)
379 {
380 if (f == kFeatureCursorPalette)
381 _mousePaletteEnabled = enable;
382 }
383
getFeatureState(Feature f)384 virtual bool getFeatureState(Feature f)
385 {
386 return (f == kFeatureCursorPalette) ? _mousePaletteEnabled : false;
387 }
388
getSupportedGraphicsModes() const389 virtual const GraphicsMode *getSupportedGraphicsModes() const
390 {
391 static const OSystem::GraphicsMode s_noGraphicsModes[] = { {0, 0, 0} };
392 return s_noGraphicsModes;
393 }
394
getDefaultGraphicsMode() const395 virtual int getDefaultGraphicsMode() const
396 {
397 return 0;
398 }
399
setGraphicsMode(int mode)400 virtual bool setGraphicsMode(int mode)
401 {
402 return true;
403 }
404
getGraphicsMode() const405 virtual int getGraphicsMode() const
406 {
407 return 0;
408 }
409
initSize(uint width,uint height,const Graphics::PixelFormat * format)410 virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format)
411 {
412 _gameScreen.create(width, height, format ? *format : Graphics::PixelFormat::createFormatCLUT8());
413 }
414
getHeight()415 virtual int16 getHeight()
416 {
417 return _gameScreen.h;
418 }
419
getWidth()420 virtual int16 getWidth()
421 {
422 return _gameScreen.w;
423 }
424
getScreenFormat() const425 virtual Graphics::PixelFormat getScreenFormat() const
426 {
427 return _gameScreen.format;
428 }
429
getSupportedFormats() const430 virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const
431 {
432 Common::List<Graphics::PixelFormat> result;
433
434 /* RGBA8888 */
435 result.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
436
437 #ifdef FRONTEND_SUPPORTS_RGB565
438 /* RGB565 - overlay */
439 result.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
440 #endif
441 /* RGB555 - fmtowns */
442 result.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
443
444 /* Palette - most games */
445 result.push_back(Graphics::PixelFormat::createFormatCLUT8());
446 return result;
447 }
448
449
450
getPaletteManager()451 virtual PaletteManager *getPaletteManager() { return this; }
452 protected:
453 // PaletteManager API
setPalette(const byte * colors,uint start,uint num)454 virtual void setPalette(const byte *colors, uint start, uint num)
455 {
456 _gamePalette.set(colors, start, num);
457 }
458
grabPalette(byte * colors,uint start,uint num) const459 virtual void grabPalette(byte *colors, uint start, uint num) const
460 {
461 _gamePalette.get(colors, start, num);
462 }
463
464
465 public:
copyRectToScreen(const void * buf,int pitch,int x,int y,int w,int h)466 virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h)
467 {
468 const uint8_t *src = (const uint8_t*)buf;
469 uint8_t *pix = (uint8_t*)_gameScreen.pixels;
470 copyRectToSurface(pix, _gameScreen.pitch, src, pitch, x, y, w, h, _gameScreen.format.bytesPerPixel);
471 }
472
updateScreen()473 virtual void updateScreen()
474 {
475 const Graphics::Surface& srcSurface = (_overlayVisible) ? _overlay : _gameScreen;
476 if(srcSurface.w && srcSurface.h)
477 {
478 switch(srcSurface.format.bytesPerPixel)
479 {
480 case 1:
481 case 3:
482 blit_uint8_uint16_fast(_screen, srcSurface, _gamePalette);
483 break;
484 case 2:
485 blit_uint16_uint16(_screen, srcSurface, _gamePalette);
486 break;
487 case 4:
488 blit_uint32_uint16(_screen, srcSurface, _gamePalette);
489 break;
490 }
491 }
492
493 // Draw Mouse
494 if(_mouseVisible && _mouseImage.w && _mouseImage.h)
495 {
496 const int x = _mouseX - _mouseHotspotX;
497 const int y = _mouseY - _mouseHotspotY;
498
499 if(_mouseImage.format.bytesPerPixel == 1)
500 blit_uint8_uint16(_screen, _mouseImage, x, y, _mousePaletteEnabled ? _mousePalette : _gamePalette, _mouseKeyColor);
501 else
502 blit_uint16_uint16(_screen, _mouseImage, x, y, _mousePaletteEnabled ? _mousePalette : _gamePalette, _mouseKeyColor);
503 }
504 }
505
lockScreen()506 virtual Graphics::Surface *lockScreen()
507 {
508 return &_gameScreen;
509 }
510
unlockScreen()511 virtual void unlockScreen()
512 {
513 /* EMPTY */
514 }
515
setShakePos(int shakeXOffset,int shakeYOffset)516 virtual void setShakePos(int shakeXOffset, int shakeYOffset)
517 {
518 // TODO
519 }
520
showOverlay()521 virtual void showOverlay()
522 {
523 _overlayVisible = true;
524 }
525
hideOverlay()526 virtual void hideOverlay()
527 {
528 _overlayVisible = false;
529 }
530
clearOverlay()531 virtual void clearOverlay()
532 {
533 _overlay.fillRect(Common::Rect(_overlay.w, _overlay.h), 0);
534 }
535
grabOverlay(void * buf,int pitch)536 virtual void grabOverlay(void *buf, int pitch)
537 {
538 const unsigned char *src = (unsigned char*)_overlay.pixels;
539 unsigned char *dst = (byte *)buf;
540 unsigned i = RES_H;
541
542 do{
543 memcpy(dst, src, RES_W << 1);
544 dst += pitch;
545 src += RES_W << 1;
546 }while(--i);
547 }
548
copyRectToOverlay(const void * buf,int pitch,int x,int y,int w,int h)549 virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h)
550 {
551 const uint8_t *src = (const uint8_t*)buf;
552 uint8_t *pix = (uint8_t*)_overlay.pixels;
553 copyRectToSurface(pix, _overlay.pitch, src, pitch, x, y, w, h, _overlay.format.bytesPerPixel);
554 }
555
getOverlayHeight()556 virtual int16 getOverlayHeight()
557 {
558 return _overlay.h;
559 }
560
getOverlayWidth()561 virtual int16 getOverlayWidth()
562 {
563 return _overlay.w;
564 }
565
getOverlayFormat() const566 virtual Graphics::PixelFormat getOverlayFormat() const
567 {
568 return _overlay.format;
569 }
570
571
572
showMouse(bool visible)573 virtual bool showMouse(bool visible)
574 {
575 const bool wasVisible = _mouseVisible;
576 _mouseVisible = visible;
577 return wasVisible;
578 }
579
warpMouse(int x,int y)580 virtual void warpMouse(int x, int y)
581 {
582 _mouseX = x;
583 _mouseY = y;
584 }
585
setMouseCursor(const void * buf,uint w,uint h,int hotspotX,int hotspotY,uint32 keycolor=255,bool dontScale=false,const Graphics::PixelFormat * format=NULL)586 virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 255, bool dontScale = false, const Graphics::PixelFormat *format = NULL)
587 {
588 const Graphics::PixelFormat mformat = format ? *format : Graphics::PixelFormat::createFormatCLUT8();
589
590 if(_mouseImage.w != w || _mouseImage.h != h || _mouseImage.format != mformat)
591 {
592 _mouseImage.create(w, h, mformat);
593 }
594
595 memcpy(_mouseImage.pixels, buf, h * _mouseImage.pitch);
596
597 _mouseHotspotX = hotspotX;
598 _mouseHotspotY = hotspotY;
599 _mouseKeyColor = keycolor;
600 _mouseDontScale = dontScale;
601 }
602
setCursorPalette(const byte * colors,uint start,uint num)603 virtual void setCursorPalette(const byte *colors, uint start, uint num)
604 {
605 _mousePalette.set(colors, start, num);
606 _mousePaletteEnabled = true;
607 }
608
retroCheckThread(uint32 offset=0)609 void retroCheckThread(uint32 offset = 0)
610 {
611 if(_threadExitTime <= (getMillis() + offset))
612 {
613 extern void retro_leave_thread();
614 retro_leave_thread();
615
616 _threadExitTime = getMillis() + 10;
617 }
618 }
619
pollEvent(Common::Event & event)620 virtual bool pollEvent(Common::Event &event)
621 {
622 retroCheckThread();
623
624 ((DefaultTimerManager*)_timerManager)->handler();
625
626
627 if(!_events.empty())
628 {
629 event = _events.front();
630 _events.pop_front();
631 return true;
632 }
633
634 return false;
635 }
636
getMillis(bool skipRecord=false)637 virtual uint32 getMillis(bool skipRecord = false)
638 {
639 #if (defined(GEKKO) && !defined(WIIU))
640 return (ticks_to_microsecs(gettime()) / 1000.0) - _startTime;
641 #elif defined(WIIU)
642 return ((cpu_features_get_time_usec())/1000) - _startTime;
643 #elif defined(__CELLOS_LV2__)
644 return (sys_time_get_system_time() / 1000.0) - _startTime;
645 #else
646 struct timeval t;
647 gettimeofday(&t, 0);
648
649 return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - _startTime;
650 #endif
651 }
652
delayMillis(uint msecs)653 virtual void delayMillis(uint msecs)
654 {
655 // Implement 'non-blocking' sleep...
656 uint32 start_time = getMillis();
657 if (_speed_hack_enabled)
658 {
659 // Use janky inaccurate method...
660 uint32 elapsed_time = 0;
661 uint32 time_remaining = msecs;
662 while(time_remaining > 0)
663 {
664 // If delay would take us past the next
665 // thread exit time, exit the thread immediately
666 // (i.e. start burning delay time in the main RetroArch
667 // thread as soon as possible...)
668 retroCheckThread(time_remaining);
669 // Check how much delay time remains...
670 elapsed_time = getMillis() - start_time;
671 if (time_remaining > elapsed_time)
672 {
673 time_remaining = time_remaining - elapsed_time;
674 retro_sleep(1);
675 }
676 else
677 {
678 time_remaining = 0;
679 }
680 // Have to handle the timer manager here, since some engines
681 // (e.g. dreamweb) sit in a delayMillis() loop waiting for a
682 // timer callback...
683 ((DefaultTimerManager*)_timerManager)->handler();
684 }
685 }
686 else
687 {
688 // Use accurate method...
689 while(getMillis() < start_time + msecs)
690 {
691 retro_sleep(1);
692 retroCheckThread();
693 // Have to handle the timer manager here, since some engines
694 // (e.g. dreamweb) sit in a delayMillis() loop waiting for a
695 // timer callback...
696 ((DefaultTimerManager*)_timerManager)->handler();
697 }
698 }
699 }
700
createMutex(void)701 virtual MutexRef createMutex(void)
702 {
703 return MutexRef();
704 }
705
lockMutex(MutexRef mutex)706 virtual void lockMutex(MutexRef mutex)
707 {
708 /* EMPTY */
709 }
710
unlockMutex(MutexRef mutex)711 virtual void unlockMutex(MutexRef mutex)
712 {
713 /* EMPTY */
714 }
715
deleteMutex(MutexRef mutex)716 virtual void deleteMutex(MutexRef mutex)
717 {
718 /* EMPTY */
719 }
720
quit()721 virtual void quit()
722 {
723 // TODO:
724 }
725
addSysArchivesToSearchSet(Common::SearchSet & s,int priority=0)726 virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0)
727 {
728 // TODO: NOTHING?
729 }
730
getTimeAndDate(TimeDate & t) const731 virtual void getTimeAndDate(TimeDate &t) const
732 {
733 time_t curTime = time(NULL);
734
735 #define YEAR0 1900
736 #define EPOCH_YR 1970
737 #define SECS_DAY (24L * 60L * 60L)
738 #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
739 #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
740 const int _ytab[2][12] = {
741 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
742 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
743 };
744 int year = EPOCH_YR;
745 unsigned long dayclock = (unsigned long)curTime % SECS_DAY;
746 unsigned long dayno = (unsigned long)curTime / SECS_DAY;
747 t.tm_sec = dayclock % 60;
748 t.tm_min = (dayclock % 3600) / 60;
749 t.tm_hour = dayclock / 3600;
750 t.tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */
751 while (dayno >= YEARSIZE(year)) {
752 dayno -= YEARSIZE(year);
753 year++;
754 }
755 t.tm_year = year - YEAR0;
756 t.tm_mon = 0;
757 while (dayno >= _ytab[LEAPYEAR(year)][t.tm_mon]) {
758 dayno -= _ytab[LEAPYEAR(year)][t.tm_mon];
759 t.tm_mon++;
760 }
761 t.tm_mday = dayno + 1;
762 }
763
getMixer()764 virtual Audio::Mixer *getMixer()
765 {
766 return _mixer;
767 }
768
getDefaultConfigFileName()769 virtual Common::String getDefaultConfigFileName()
770 {
771 return s_systemDir + "/scummvm.ini";
772 }
773
logMessage(LogMessageType::Type type,const char * message)774 virtual void logMessage(LogMessageType::Type type, const char *message)
775 {
776 if (log_cb)
777 log_cb(RETRO_LOG_INFO, "%s\n", message);
778 }
779
780
781 //
782
getScreen()783 const Graphics::Surface& getScreen()
784 {
785 const Graphics::Surface& srcSurface = (_overlayVisible) ? _overlay : _gameScreen;
786
787 if(srcSurface.w != _screen.w || srcSurface.h != _screen.h)
788 {
789 #ifdef FRONTEND_SUPPORTS_RGB565
790 _screen.create(srcSurface.w, srcSurface.h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
791 #else
792 _screen.create(srcSurface.w, srcSurface.h, Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
793 #endif
794 }
795
796
797 return _screen;
798 }
799
800 #define ANALOG_RANGE 0x8000
801 #define BASE_CURSOR_SPEED 4
802 #define PI 3.141592653589793238
803
processMouse(retro_input_state_t aCallback,int device,float gampad_cursor_speed,bool analog_response_is_quadratic,int analog_deadzone,float mouse_speed)804 void processMouse(retro_input_state_t aCallback, int device, float gampad_cursor_speed, bool analog_response_is_quadratic, int analog_deadzone, float mouse_speed)
805 {
806 int16_t joy_x, joy_y, joy_rx, joy_ry, x, y;
807 float analog_amplitude_x, analog_amplitude_y;
808 int mouse_acc_int;
809 bool do_joystick, do_mouse, down;
810 float adjusted_cursor_speed = (float)BASE_CURSOR_SPEED * gampad_cursor_speed;
811 int dpad_cursor_offset;
812 double rs_radius, rs_angle;
813 unsigned numpad_index;
814
815 static const uint32_t retroButtons[2] = {RETRO_DEVICE_ID_MOUSE_LEFT, RETRO_DEVICE_ID_MOUSE_RIGHT};
816 static const Common::EventType eventID[2][2] =
817 {
818 {Common::EVENT_LBUTTONDOWN, Common::EVENT_LBUTTONUP},
819 {Common::EVENT_RBUTTONDOWN, Common::EVENT_RBUTTONUP}
820 };
821
822 static const unsigned gampad_key_map[8][3] = {
823 { RETRO_DEVICE_ID_JOYPAD_X, (unsigned)Common::KEYCODE_ESCAPE, (unsigned)Common::ASCII_ESCAPE }, // Esc
824 { RETRO_DEVICE_ID_JOYPAD_Y, (unsigned)Common::KEYCODE_PERIOD, 46 }, // .
825 { RETRO_DEVICE_ID_JOYPAD_L, (unsigned)Common::KEYCODE_RETURN, (unsigned)Common::ASCII_RETURN }, // Enter
826 { RETRO_DEVICE_ID_JOYPAD_R, (unsigned)Common::KEYCODE_KP5, 53 }, // Numpad 5
827 { RETRO_DEVICE_ID_JOYPAD_L2, (unsigned)Common::KEYCODE_BACKSPACE, (unsigned)Common::ASCII_BACKSPACE }, // Backspace
828 { RETRO_DEVICE_ID_JOYPAD_L3, (unsigned)Common::KEYCODE_F10, (unsigned)Common::ASCII_F10 }, // F10
829 { RETRO_DEVICE_ID_JOYPAD_R3, (unsigned)Common::KEYCODE_KP0, 48 }, // Numpad 0
830 { RETRO_DEVICE_ID_JOYPAD_SELECT, (unsigned)Common::KEYCODE_F1, (unsigned)Common::ASCII_F1 }, // F1
831 };
832
833 // Right stick circular wrap around: 1 -> 2 -> 3 -> 6 -> 9 -> 8 -> 7 -> 4
834 static const unsigned gampad_numpad_map[8][2] = {
835 { (unsigned)Common::KEYCODE_KP1, 49 },
836 { (unsigned)Common::KEYCODE_KP2, 50 },
837 { (unsigned)Common::KEYCODE_KP3, 51 },
838 { (unsigned)Common::KEYCODE_KP6, 54 },
839 { (unsigned)Common::KEYCODE_KP9, 57 },
840 { (unsigned)Common::KEYCODE_KP8, 56 },
841 { (unsigned)Common::KEYCODE_KP7, 55 },
842 { (unsigned)Common::KEYCODE_KP4, 52 },
843 };
844
845 // Reduce gamepad cursor speed, if required
846 if (device == RETRO_DEVICE_JOYPAD &&
847 aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2))
848 {
849 adjusted_cursor_speed = adjusted_cursor_speed * (1.0f / 3.0f);
850 }
851
852 down = false;
853 do_joystick = false;
854 x = aCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
855 y = aCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
856 joy_x = aCallback(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
857 joy_y = aCallback(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y);
858
859 // Left Analog X Axis
860 if (joy_x > analog_deadzone || joy_x < -analog_deadzone)
861 {
862 if (joy_x > analog_deadzone)
863 {
864 // Reset accumulator when changing direction
865 _mouseXAcc = (_mouseXAcc < 0.0) ? 0.0 : _mouseXAcc;
866 joy_x = joy_x - analog_deadzone;
867 }
868 if (joy_x < -analog_deadzone)
869 {
870 // Reset accumulator when changing direction
871 _mouseXAcc = (_mouseXAcc > 0.0) ? 0.0 : _mouseXAcc;
872 joy_x = joy_x + analog_deadzone;
873 }
874 // Update accumulator
875 analog_amplitude_x = (float)joy_x / (float)(ANALOG_RANGE - analog_deadzone);
876 if (analog_response_is_quadratic)
877 {
878 if (analog_amplitude_x < 0.0)
879 analog_amplitude_x = -(analog_amplitude_x * analog_amplitude_x);
880 else
881 analog_amplitude_x = analog_amplitude_x * analog_amplitude_x;
882 }
883 //printf("analog_amplitude_x: %f\n", analog_amplitude_x);
884 _mouseXAcc += analog_amplitude_x * adjusted_cursor_speed;
885 // Get integer part of accumulator
886 mouse_acc_int = (int)_mouseXAcc;
887 if (mouse_acc_int != 0)
888 {
889 // Set mouse position
890 _mouseX += mouse_acc_int;
891 _mouseX = (_mouseX < 0) ? 0 : _mouseX;
892 _mouseX = (_mouseX >= _screen.w) ? _screen.w : _mouseX;
893 do_joystick = true;
894 // Update accumulator
895 _mouseXAcc -= (float)mouse_acc_int;
896 }
897 }
898
899 // Left Analog Y Axis
900 if (joy_y > analog_deadzone || joy_y < -analog_deadzone)
901 {
902 if (joy_y > analog_deadzone)
903 {
904 // Reset accumulator when changing direction
905 _mouseYAcc = (_mouseYAcc < 0.0) ? 0.0 : _mouseYAcc;
906 joy_y = joy_y - analog_deadzone;
907 }
908 if (joy_y < -analog_deadzone)
909 {
910 // Reset accumulator when changing direction
911 _mouseYAcc = (_mouseYAcc > 0.0) ? 0.0 : _mouseYAcc;
912 joy_y = joy_y + analog_deadzone;
913 }
914 // Update accumulator
915 analog_amplitude_y = (float)joy_y / (float)(ANALOG_RANGE - analog_deadzone);
916 if (analog_response_is_quadratic)
917 {
918 if (analog_amplitude_y < 0.0)
919 analog_amplitude_y = -(analog_amplitude_y * analog_amplitude_y);
920 else
921 analog_amplitude_y = analog_amplitude_y * analog_amplitude_y;
922 }
923 //printf("analog_amplitude_y: %f\n", analog_amplitude_y);
924 _mouseYAcc += analog_amplitude_y * adjusted_cursor_speed;
925 // Get integer part of accumulator
926 mouse_acc_int = (int)_mouseYAcc;
927 if (mouse_acc_int != 0)
928 {
929 // Set mouse position
930 _mouseY += mouse_acc_int;
931 _mouseY = (_mouseY < 0) ? 0 : _mouseY;
932 _mouseY = (_mouseY >= _screen.h) ? _screen.h : _mouseY;
933 do_joystick = true;
934 // Update accumulator
935 _mouseYAcc -= (float)mouse_acc_int;
936 }
937 }
938
939 if (device == RETRO_DEVICE_JOYPAD) {
940 if (aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT))
941 {
942 dpad_cursor_offset = (int)(adjusted_cursor_speed * 0.5f);
943 dpad_cursor_offset = (dpad_cursor_offset < 1) ? 1 : dpad_cursor_offset;
944 _mouseX -= dpad_cursor_offset;
945 _mouseX = (_mouseX < 0) ? 0 : _mouseX;
946 _mouseX = (_mouseX >= _screen.w) ? _screen.w : _mouseX;
947 do_joystick = true;
948 }
949
950 if (aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
951 {
952 dpad_cursor_offset = (int)(adjusted_cursor_speed * 0.5f);
953 dpad_cursor_offset = (dpad_cursor_offset < 1) ? 1 : dpad_cursor_offset;
954 _mouseX += dpad_cursor_offset;
955 _mouseX = (_mouseX < 0) ? 0 : _mouseX;
956 _mouseX = (_mouseX >= _screen.w) ? _screen.w : _mouseX;
957 do_joystick = true;
958 }
959
960 if (aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP))
961 {
962 dpad_cursor_offset = (int)(adjusted_cursor_speed * 0.5f);
963 dpad_cursor_offset = (dpad_cursor_offset < 1) ? 1 : dpad_cursor_offset;
964 _mouseY -= dpad_cursor_offset;
965 _mouseY = (_mouseY < 0) ? 0 : _mouseY;
966 _mouseY = (_mouseY >= _screen.h) ? _screen.h : _mouseY;
967 do_joystick = true;
968 }
969
970 if (aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN))
971 {
972 dpad_cursor_offset = (int)(adjusted_cursor_speed * 0.5f);
973 dpad_cursor_offset = (dpad_cursor_offset < 1) ? 1 : dpad_cursor_offset;
974 _mouseY += dpad_cursor_offset;
975 _mouseY = (_mouseY < 0) ? 0 : _mouseY;
976 _mouseY = (_mouseY >= _screen.h) ? _screen.h : _mouseY;
977 do_joystick = true;
978 }
979
980 if (aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START))
981 {
982 Common::Event ev;
983 ev.type = Common::EVENT_MAINMENU;
984 _events.push_back(ev);
985 }
986 }
987
988 #if defined(WIIU) || defined(__SWITCH__)
989 int p_x = aCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
990 int p_y = aCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
991 int p_press = aCallback(0, RETRO_DEVICE_POINTER, 0,RETRO_DEVICE_ID_POINTER_PRESSED);
992 int px=(int)((p_x+0x7fff)*_screen.w /0xffff);
993 int py=(int)((p_y+0x7fff)*_screen.h/0xffff);
994 //printf("(%d,%d) p:%d\n",px,py,pp);
995
996 static int ptrhold=0;
997
998 if(p_press)ptrhold++;
999 else ptrhold=0;
1000
1001 if(ptrhold>0){
1002 _mouseX = px;
1003 _mouseY = py;
1004
1005 Common::Event ev;
1006 ev.type = Common::EVENT_MOUSEMOVE;
1007 ev.mouse.x = _mouseX;
1008 ev.mouse.y = _mouseY;
1009 _events.push_back(ev);
1010 }
1011
1012 if(ptrhold>10 && _ptrmouseButton==0){
1013 _ptrmouseButton=1;
1014 Common::Event ev;
1015 ev.type = eventID[0][_ptrmouseButton ? 0 : 1];
1016 ev.mouse.x = _mouseX;
1017 ev.mouse.y = _mouseY;
1018 _events.push_back(ev);
1019 }
1020 else if (ptrhold==0 && _ptrmouseButton==1){
1021 _ptrmouseButton=0;
1022 Common::Event ev;
1023 ev.type = eventID[0][_ptrmouseButton ? 0 : 1];
1024 ev.mouse.x = _mouseX;
1025 ev.mouse.y = _mouseY;
1026 _events.push_back(ev);
1027 }
1028
1029 #endif
1030
1031 if (do_joystick)
1032 {
1033 Common::Event ev;
1034 ev.type = Common::EVENT_MOUSEMOVE;
1035 ev.mouse.x = _mouseX;
1036 ev.mouse.y = _mouseY;
1037 _events.push_back(ev);
1038 }
1039
1040 // Gampad mouse buttons
1041 down = aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
1042 if(down != _joypadmouseButtons[0])
1043 {
1044 _joypadmouseButtons[0] = down;
1045
1046 Common::Event ev;
1047 ev.type = eventID[0][down ? 0 : 1];
1048 ev.mouse.x = _mouseX;
1049 ev.mouse.y = _mouseY;
1050 _events.push_back(ev);
1051 }
1052
1053 down = aCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
1054 if(down != _joypadmouseButtons[1])
1055 {
1056 _joypadmouseButtons[1] = down;
1057
1058 Common::Event ev;
1059 ev.type = eventID[1][down ? 0 : 1];
1060 ev.mouse.x = _mouseX;
1061 ev.mouse.y = _mouseY;
1062 _events.push_back(ev);
1063 }
1064
1065 // Gamepad keyboard buttons
1066 for(int i = 0; i < 8; i ++)
1067 {
1068 down = aCallback(0, RETRO_DEVICE_JOYPAD, 0, gampad_key_map[i][0]);
1069 if (down != _joypadkeyboardButtons[i])
1070 {
1071 _joypadkeyboardButtons[i] = down;
1072 bool state = down ? true : false;
1073 processKeyEvent(state, gampad_key_map[i][1], (uint32_t)gampad_key_map[i][2], 0);
1074 }
1075 }
1076
1077 // Gamepad right stick numpad emulation
1078 joy_rx = aCallback(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
1079 joy_ry = aCallback(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
1080
1081 if (joy_rx > analog_deadzone)
1082 joy_rx = joy_rx - analog_deadzone;
1083 else if (joy_rx < -analog_deadzone)
1084 joy_rx = joy_rx + analog_deadzone;
1085 else
1086 joy_rx = 0;
1087
1088 if (joy_ry > analog_deadzone)
1089 joy_ry = joy_ry - analog_deadzone;
1090 else if (joy_ry < -analog_deadzone)
1091 joy_ry = joy_ry + analog_deadzone;
1092 else
1093 joy_ry = 0;
1094
1095 // This is very ugly, but I don't have time to make it nicer...
1096 if (joy_rx != 0 || joy_ry != 0)
1097 {
1098 analog_amplitude_x = (float)joy_rx / (float)(ANALOG_RANGE - analog_deadzone);
1099 analog_amplitude_y = (float)joy_ry / (float)(ANALOG_RANGE - analog_deadzone);
1100
1101 // Convert to polar coordinates: part 1
1102 rs_radius = sqrt((double)(analog_amplitude_x * analog_amplitude_x) + (double)(analog_amplitude_y * analog_amplitude_y));
1103
1104 // Check if radius is above threshold
1105 if (rs_radius > 0.5)
1106 {
1107 // Convert to polar coordinates: part 2
1108 rs_angle = atan2((double)analog_amplitude_y, (double)analog_amplitude_x);
1109
1110 // Adjust rotation offset...
1111 rs_angle = (2.0 * PI) - (rs_angle + PI);
1112 rs_angle = fmod(rs_angle - (0.125 * PI), 2.0 * PI);
1113 if (rs_angle < 0)
1114 rs_angle += 2.0 * PI;
1115
1116 // Convert angle into numpad key index
1117 numpad_index = (unsigned)((rs_angle / (2.0 * PI)) * 8.0);
1118 // Unnecessary safety check...
1119 numpad_index = (numpad_index > 7) ? 7 : numpad_index;
1120 //printf("numpad_index: %u\n", numpad_index);
1121
1122 if (numpad_index != _joypadnumpadLast)
1123 {
1124 // Unset last key, if required
1125 if (_joypadnumpadActive)
1126 processKeyEvent(false, gampad_numpad_map[_joypadnumpadLast][0], (uint32_t)gampad_numpad_map[_joypadnumpadLast][1], 0);
1127
1128 // Set new key
1129 processKeyEvent(true, gampad_numpad_map[numpad_index][0], (uint32_t)gampad_numpad_map[numpad_index][1], 0);
1130
1131 _joypadnumpadLast = numpad_index;
1132 _joypadnumpadActive = true;
1133 }
1134 }
1135 else if (_joypadnumpadActive)
1136 {
1137 processKeyEvent(false, gampad_numpad_map[_joypadnumpadLast][0], (uint32_t)gampad_numpad_map[_joypadnumpadLast][1], 0);
1138 _joypadnumpadActive = false;
1139 _joypadnumpadLast = 8;
1140 }
1141 }
1142 else if (_joypadnumpadActive)
1143 {
1144 processKeyEvent(false, gampad_numpad_map[_joypadnumpadLast][0], (uint32_t)gampad_numpad_map[_joypadnumpadLast][1], 0);
1145 _joypadnumpadActive = false;
1146 _joypadnumpadLast = 8;
1147 }
1148
1149 // Process input from physical mouse
1150 do_mouse = false;
1151 // > X Axis
1152 if (x != 0)
1153 {
1154 if (x > 0) {
1155 // Reset accumulator when changing direction
1156 _mouseXAcc = (_mouseXAcc < 0.0) ? 0.0 : _mouseXAcc;
1157 }
1158 if (x < 0) {
1159 // Reset accumulator when changing direction
1160 _mouseXAcc = (_mouseXAcc > 0.0) ? 0.0 : _mouseXAcc;
1161 }
1162 // Update accumulator
1163 _mouseXAcc += (float)x * mouse_speed;
1164 // Get integer part of accumulator
1165 mouse_acc_int = (int)_mouseXAcc;
1166 if (mouse_acc_int != 0)
1167 {
1168 // Set mouse position
1169 _mouseX += mouse_acc_int;
1170 _mouseX = (_mouseX < 0) ? 0 : _mouseX;
1171 _mouseX = (_mouseX >= _screen.w) ? _screen.w : _mouseX;
1172 do_mouse = true;
1173 // Update accumulator
1174 _mouseXAcc -= (float)mouse_acc_int;
1175 }
1176 }
1177 // > Y Axis
1178 if (y != 0)
1179 {
1180 if (y > 0) {
1181 // Reset accumulator when changing direction
1182 _mouseYAcc = (_mouseYAcc < 0.0) ? 0.0 : _mouseYAcc;
1183 }
1184 if (y < 0) {
1185 // Reset accumulator when changing direction
1186 _mouseYAcc = (_mouseYAcc > 0.0) ? 0.0 : _mouseYAcc;
1187 }
1188 // Update accumulator
1189 _mouseYAcc += (float)y * mouse_speed;
1190 // Get integer part of accumulator
1191 mouse_acc_int = (int)_mouseYAcc;
1192 if (mouse_acc_int != 0)
1193 {
1194 // Set mouse position
1195 _mouseY += mouse_acc_int;
1196 _mouseY = (_mouseY < 0) ? 0 : _mouseY;
1197 _mouseY = (_mouseY >= _screen.h) ? _screen.h : _mouseY;
1198 do_mouse = true;
1199 // Update accumulator
1200 _mouseYAcc -= (float)mouse_acc_int;
1201 }
1202 }
1203
1204 if (do_mouse)
1205 {
1206 Common::Event ev;
1207 ev.type = Common::EVENT_MOUSEMOVE;
1208 ev.mouse.x = _mouseX;
1209 ev.mouse.y = _mouseY;
1210 _events.push_back(ev);
1211 }
1212
1213 for(int i = 0; i < 2; i ++)
1214 {
1215 Common::Event ev;
1216 bool down = aCallback(0, RETRO_DEVICE_MOUSE, 0, retroButtons[i]);
1217 if(down != _mouseButtons[i])
1218 {
1219 _mouseButtons[i] = down;
1220
1221 ev.type = eventID[i][down ? 0 : 1];
1222 ev.mouse.x = _mouseX;
1223 ev.mouse.y = _mouseY;
1224 _events.push_back(ev);
1225 }
1226
1227 }
1228 }
1229
processKeyEvent(bool down,unsigned keycode,uint32_t character,uint16_t key_modifiers)1230 void processKeyEvent(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers)
1231 {
1232 int _keyflags = 0;
1233 _keyflags |= (key_modifiers & RETROKMOD_CTRL) ? Common::KBD_CTRL : 0;
1234 _keyflags |= (key_modifiers & RETROKMOD_ALT) ? Common::KBD_ALT : 0;
1235 _keyflags |= (key_modifiers & RETROKMOD_SHIFT) ? Common::KBD_SHIFT : 0;
1236 _keyflags |= (key_modifiers & RETROKMOD_META) ? Common::KBD_META : 0;
1237 _keyflags |= (key_modifiers & RETROKMOD_CAPSLOCK) ? Common::KBD_CAPS : 0;
1238 _keyflags |= (key_modifiers & RETROKMOD_NUMLOCK) ? Common::KBD_NUM : 0;
1239 _keyflags |= (key_modifiers & RETROKMOD_SCROLLOCK) ? Common::KBD_SCRL : 0;
1240
1241 if (keycode == RETROK_SPACE)
1242 keycode &= ~(RETROK_SPACE);
1243
1244 Common::Event ev;
1245 ev.type = down ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP;
1246 ev.kbd.keycode = (Common::KeyCode)keycode;
1247 ev.kbd.flags = _keyflags;
1248 ev.kbd.ascii = character;
1249
1250 /* If shift was down then send upper case letter to engine */
1251 if(ev.kbd.ascii >= 97 && ev.kbd.ascii <= 122 && (_keyflags & Common::KBD_SHIFT))
1252 ev.kbd.ascii = ev.kbd.ascii & ~0x20;
1253
1254 _events.push_back(ev);
1255 }
1256
postQuit()1257 void postQuit()
1258 {
1259 Common::Event ev;
1260 ev.type = Common::EVENT_QUIT;
1261 ((OSystem_RETRO*)g_system)->getEventManager()->pushEvent(ev);
1262 }
1263 };
1264
retroBuildOS(bool aEnableSpeedHack)1265 OSystem* retroBuildOS(bool aEnableSpeedHack)
1266 {
1267 return new OSystem_RETRO(aEnableSpeedHack);
1268 }
1269
getScreen()1270 const Graphics::Surface& getScreen()
1271 {
1272 return ((OSystem_RETRO*)g_system)->getScreen();
1273 }
1274
retroProcessMouse(retro_input_state_t aCallback,int device,float gampad_cursor_speed,bool analog_response_is_quadratic,int analog_deadzone,float mouse_speed)1275 void retroProcessMouse(retro_input_state_t aCallback, int device, float gampad_cursor_speed, bool analog_response_is_quadratic, int analog_deadzone, float mouse_speed)
1276 {
1277 ((OSystem_RETRO*)g_system)->processMouse(aCallback, device, gampad_cursor_speed, analog_response_is_quadratic, analog_deadzone, mouse_speed);
1278 }
1279
retroPostQuit()1280 void retroPostQuit()
1281 {
1282 ((OSystem_RETRO*)g_system)->postQuit();
1283 }
1284
retroSetSystemDir(const char * aPath)1285 void retroSetSystemDir(const char* aPath)
1286 {
1287 s_systemDir = Common::String(aPath ? aPath : ".");
1288 }
1289
retroSetSaveDir(const char * aPath)1290 void retroSetSaveDir(const char* aPath)
1291 {
1292 s_saveDir = Common::String(aPath ? aPath : ".");
1293 }
1294
retroKeyEvent(bool down,unsigned keycode,uint32_t character,uint16_t key_modifiers)1295 void retroKeyEvent(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers)
1296 {
1297 ((OSystem_RETRO*)g_system)->processKeyEvent(down, keycode, character, key_modifiers);
1298 }
1299