1 #include "libretro.h"
2 #include "libretro-hatari.h"
3 #include "graph.h"
4 #include "vkbd.h"
5 #include "joy.h"
6 #include "screen.h"
7 #include "video.h"	/* FIXME: video.h is dependent on HBL_PALETTE_LINES from screen.h */
8 #include "ikbd.h"
9 
10 //CORE VAR
11 extern const char *retro_save_directory;
12 extern const char *retro_system_directory;
13 extern const char *retro_content_directory;
14 char RETRO_DIR[512];
15 char RETRO_TOS[512];
16 extern bool hatari_nomouse;
17 extern bool hatari_nokeys;
18 
19 /* HATARI PROTOTYPES */
20 #include "configuration.h"
21 #include "file.h"
22 extern bool Dialog_DoProperty(void);
23 extern void Screen_SetFullUpdate(void);
24 extern void Main_HandleMouseMotion(void);
25 extern void Main_UnInit(void);
26 extern int  hmain(int argc, char *argv[]);
27 extern int Reset_Cold(void);
28 
29 #ifdef __PS3__
30 #ifndef __PSL1GHT__
31 #include <sys/sys_time.h>
32 #include <sys/timer.h>
33 #define usleep  sys_timer_usleep
34 #endif
35 #endif
36 
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <time.h>
40 
41 /* VIDEO */
42 extern SDL_Surface *sdlscrn;
43 unsigned short int bmp[1024*1024];
44 unsigned char savbkg[1024*1024* 2];
45 
46 //SOUND
47 short signed int SNDBUF[1024*2];
48 int snd_sampler = 44100 / 50;
49 
50 //PATH
51 char RPATH[512];
52 
53 //EMU FLAGS
54 int NPAGE=-1, KCOL=1, BKGCOLOR=0, MAXPAS=6;
55 int SHIFTON=-1,MOUSEMODE=-1,SHOWKEY=-1,PAS=2,STATUTON=-1;
56 int SND=1; //SOUND ON/OFF
57 int pauseg=0; //enter_gui
58 int slowdown=0;
59 int exitgui=0; // exit gui (not serialized)
60 
61 //JOY
62 int al[2];//left analog1
63 unsigned char MXjoy0; // joy 1
64 unsigned char MXjoy1; // joy 2
65 int mbt[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
66 
67 //MOUSE
68 int touch=-1; // gui mouse btn
69 int fmousex,fmousey; // emu mouse
70 extern int gmx,gmy; //gui mouse
71 int point_x_last = -1;
72 int point_y_last = -1;
73 int mbL=0,mbR=0;
74 int mmbL=0, mmbR=0;
75 
76 //KEYBOARD
77 char Key_Sate[512];
78 char Key_Sate2[512];
79 int oldi=-1;
80 int vkx=0,vky=0;
81 int vkflag[5]={0,0,0,0,0};
82 
83 //STATS GUI
84 extern int LEDA,LEDB,LEDC;
85 int BOXDEC= 32+2;
86 int STAT_BASEY;
87 
88 // savestate serialization
89 
90 static bool serialize_forward;
91 static char* serialize_data;
92 
93 #define SERIALIZE_STEP \
94 	if (serialize_forward) memcpy(serialize_data, x, sizeof(*x)); \
95 	else                   memcpy(x, serialize_data, sizeof(*x)); \
96 	serialize_data += sizeof(*x);
97 
serialize_char(char * x)98 void serialize_char(char *x) { SERIALIZE_STEP }
serialize_int(int * x)99 void serialize_int(int *x) { SERIALIZE_STEP }
100 
hatari_mapper_serialize_size(void)101 int hatari_mapper_serialize_size(void)
102 {
103 	return 1023; // +1 byte for version makes an even 1kb header
104 }
105 
hatari_mapper_serialize_bidi(char * data,char version)106 static bool hatari_mapper_serialize_bidi(char* data, char version)
107 {
108    int i;
109    int NUMjoy  = 0;
110    int firstps = 0;
111 	/* ignoring version, there is only one version so far
112 	 * (Might be okay to append to this list without increasing version
113 	 * if 0 is an acceptable fallback for the new value,
114 	 * but do not reorder without increasing version number.)
115     */
116 	serialize_data = data;
117 	serialize_int(&NPAGE);
118 	serialize_int(&KCOL);
119 	serialize_int(&BKGCOLOR);
120 	serialize_int(&MAXPAS);
121 	serialize_int(&SHIFTON);
122 	serialize_int(&MOUSEMODE);
123 	serialize_int(&SHOWKEY);
124 	serialize_int(&PAS);
125 	serialize_int(&STATUTON);
126 	serialize_int(&SND);
127 	serialize_int(&pauseg);
128 	serialize_int(&slowdown);
129 	serialize_int(&fmousex);
130 	serialize_int(&fmousey);
131 	serialize_int(&gmx);
132 	serialize_int(&gmy);
133 	serialize_int(&NUMjoy); // this variable was removed
134 	serialize_int(&firstps); // this variable was removed
135 	serialize_int(&mbL);
136 	serialize_int(&mbR);
137 	serialize_int(&mmbL);
138 	serialize_int(&mmbR);
139 	serialize_int(&oldi);
140 	serialize_int(&vkx);
141 	serialize_int(&vky);
142 	for (i=0; i<5;  ++i)
143       serialize_int(&(vkflag[i]));
144 	for (i=0; i<16; ++i)
145       serialize_int(&(mbt[i]));
146 
147 	if ((int)(data - serialize_data) > hatari_mapper_serialize_size())
148 	{
149 		fprintf(stderr, "hatari_mapper_serialize_size()=%d insufficient! (Needs: %d)\n", hatari_mapper_serialize_size(), (int)(data - serialize_data));
150 		return false;
151 	}
152 	return true;
153 }
154 
hatari_mapper_serialize(char * data,char version)155 bool hatari_mapper_serialize(char* data, char version)
156 {
157 	serialize_forward = true;
158 	return hatari_mapper_serialize_bidi(data, version);
159 }
160 
hatari_mapper_unserialize(const char * data,char version)161 bool hatari_mapper_unserialize(const char* data, char version)
162 {
163 	serialize_forward = false;
164 	int pauseg_old    = pauseg;
165 	bool result       = hatari_mapper_serialize_bidi((char*)data, version);
166 	exitgui            = 0;
167 	if (pauseg_old && !pauseg)
168 	{
169       /* want to exit GUI, turn pauseg back on
170        * and tell it to exit on its own */
171 		pauseg = pauseg_old;
172 		exitgui = 1;
173 	}
174 	return result;
175 }
176 
177 /* input state */
178 static retro_input_state_t input_state_cb;
179 static retro_input_poll_t input_poll_cb;
180 
retro_set_input_state(retro_input_state_t cb)181 void retro_set_input_state(retro_input_state_t cb)
182 {
183    input_state_cb = cb;
184 }
185 
retro_set_input_poll(retro_input_poll_t cb)186 void retro_set_input_poll(retro_input_poll_t cb)
187 {
188    input_poll_cb = cb;
189 }
190 
191 #ifdef __PS3__
192 #ifndef __PSL1GHT__
193 #define sysGetCurrentTime sys_time_get_current_time
194 #endif
195 #endif
196 
197 /* in milliseconds */
GetTicks(void)198 long GetTicks(void)
199 {
200 #ifdef _ANDROID_
201    struct timespec now;
202    clock_gettime(CLOCK_MONOTONIC, &now);
203    return (now.tv_sec*1000000 + now.tv_nsec/1000)/1000;
204 #else
205 #ifdef __PS3__
206    unsigned long        ticks_micro;
207    uint64_t secs;
208    uint64_t nsecs;
209 
210    sysGetCurrentTime(&secs, &nsecs);
211    ticks_micro =  secs * 1000000UL + (nsecs / 1000);
212 
213    return ticks_micro/1000;
214 #else
215    struct timeval tv;
216    gettimeofday (&tv, NULL);
217    return (tv.tv_sec*1000000 + tv.tv_usec)/1000;
218 #endif
219 #endif
220 
221 }
222 
223 //NO SURE FIND BETTER WAY TO COME BACK IN MAIN THREAD IN HATARI GUI
gui_poll_events(void)224 bool gui_poll_events(void)
225 {
226    slowdown=0;
227    co_switch(mainThread);
228    return (exitgui != 0);
229 }
230 
231 //save bkg for screenshot
save_bkg(void)232 void save_bkg(void)
233 {
234    int i, j, k;
235    unsigned char *ptr;
236 
237    k = 0;
238    ptr = (unsigned char*)sdlscrn->pixels;
239 
240    for(j=0;j<retroh;j++)
241    {
242       for(i=0;i<retrow*2;i++)
243       {
244          savbkg[k]=*ptr;
245          ptr++;
246          k++;
247       }
248    }
249 }
250 
retro_fillrect(SDL_Surface * surf,SDL_Rect * rect,unsigned int col)251 void retro_fillrect(SDL_Surface * surf,SDL_Rect *rect,unsigned int col)
252 {
253    DrawFBoxBmp(bmp,rect->x,rect->y,rect->w ,rect->h,col);
254 }
255 
GuiGetMouseState(int * x,int * y)256 int  GuiGetMouseState( int * x,int * y)
257 {
258    *x=gmx;
259    *y=gmy;
260    return 0;
261 }
262 
texture_uninit(void)263 void texture_uninit(void)
264 {
265    if(sdlscrn)
266    {
267       if(sdlscrn->format)
268          free(sdlscrn->format);
269 
270       free(sdlscrn);
271    }
272 }
273 
prepare_texture(int w,int h,int b)274 SDL_Surface *prepare_texture(int w,int h,int b)
275 {
276    SDL_Surface *bitmp;
277 
278    if(sdlscrn)
279       texture_uninit();
280 
281    bitmp = (SDL_Surface *) calloc(1, sizeof(*bitmp));
282    if (bitmp == NULL)
283    {
284       printf("tex surface failed");
285       return NULL;
286    }
287 
288    bitmp->format = calloc(1,sizeof(*bitmp->format));
289    if (bitmp->format == NULL)
290    {
291       printf("tex format failed");
292       return NULL;
293    }
294 
295    bitmp->format->BitsPerPixel = 16;
296    bitmp->format->BytesPerPixel = 2;
297    bitmp->format->Rloss=3;
298    bitmp->format->Gloss=3;
299    bitmp->format->Bloss=3;
300    bitmp->format->Aloss=0;
301    bitmp->format->Rshift=11;
302    bitmp->format->Gshift=6;
303    bitmp->format->Bshift=0;
304    bitmp->format->Ashift=0;
305    bitmp->format->Rmask=0x0000F800;
306    bitmp->format->Gmask=0x000007E0;
307    bitmp->format->Bmask=0x0000001F;
308    bitmp->format->Amask=0x00000000;
309    bitmp->format->colorkey=0;
310    bitmp->format->alpha=0;
311    bitmp->format->palette = NULL;
312 
313    bitmp->flags=0;
314    bitmp->w=w;
315    bitmp->h=h;
316    bitmp->pitch=retrow*2;
317    bitmp->pixels=(unsigned char *)&bmp[0];
318    bitmp->clip_rect.x=0;
319    bitmp->clip_rect.y=0;
320    bitmp->clip_rect.w=w;
321    bitmp->clip_rect.h=h;
322 
323    return bitmp;
324 }
325 
texture_init(void)326 void texture_init(void)
327 {
328    memset(bmp, 0, sizeof(bmp));
329 
330    gmx=(retrow/2)-1;
331    gmy=(retroh/2)-1;
332 }
333 
enter_gui(void)334 void enter_gui(void)
335 {
336    save_bkg();
337    exitgui=0;
338    pauseg=1; // should already be set
339    Dialog_DoProperty();
340    pauseg=0;
341 }
342 
Print_Statut(void)343 void Print_Statut(void)
344 {
345    STAT_BASEY=CROP_HEIGHT+24;
346    int NUMjoy = (ConfigureParams.Joysticks.Joy[0].nJoystickMode == JOYSTICK_REALSTICK) ? 2 : 1;
347 
348    DrawFBoxBmp(bmp,0,STAT_BASEY,CROP_WIDTH,STAT_YSZ,RGB565(0,0,0));
349 
350    Draw_text(bmp,STAT_DECX    ,STAT_BASEY,0xffff,0x8080,1,2,40,(MOUSEMODE<0)?" Joy ":"Mouse");
351    if (MOUSEMODE>=0)
352    Draw_text(bmp,STAT_DECX+40 ,STAT_BASEY,0xffff,0x8080,1,2,40,"Speed:%d",PAS);
353    Draw_text(bmp,STAT_DECX+100,STAT_BASEY,0xffff,0x8080,1,2,40,(SHIFTON>0)?"SHIFT":"     ");
354    Draw_text(bmp,STAT_DECX+150,STAT_BASEY,0xffff,0x8080,1,2,40,"Joysticks:%s",(NUMjoy > 1) ? " 2 " : " 1 ");
355 
356    if(LEDA)
357    {
358       DrawFBoxBmp(bmp,CROP_WIDTH-6*BOXDEC-6-16,STAT_BASEY,16,16,RGB565(0,7,0));//led A drive
359       Draw_text(bmp,CROP_WIDTH-6*BOXDEC-6-16,STAT_BASEY,0xffff,0x0,1,2,40," A");
360    }
361 
362    if(LEDB)
363    {
364       DrawFBoxBmp(bmp,CROP_WIDTH-7*BOXDEC-6-16,STAT_BASEY,16,16,RGB565(0,7,0));//led B drive
365       Draw_text(bmp,CROP_WIDTH-7*BOXDEC-6-16,STAT_BASEY,0xffff,0x0,1,2,40," B");
366    }
367 
368    if(LEDC)
369    {
370       DrawFBoxBmp(bmp,CROP_WIDTH-8*BOXDEC-6-16,STAT_BASEY,16,16,RGB565(0,7,0));//led C drive
371       Draw_text(bmp,CROP_WIDTH-8*BOXDEC-6-16,STAT_BASEY,0xffff,0x0,1,2,40," C");
372       LEDC=0;
373    }
374 
375 }
376 
retro_key_down(unsigned char retrok)377 void retro_key_down(unsigned char retrok)
378 {
379    IKBD_PressSTKey(retrok,1);
380 }
381 
retro_key_up(unsigned char retrok)382 void retro_key_up(unsigned char retrok)
383 {
384    IKBD_PressSTKey(retrok,0);
385 }
386 
Process_key(void)387 void Process_key(void)
388 {
389    int i;
390    for(i=0;i<320;i++)
391    {
392       Key_Sate[i]= (input_state_cb(0, RETRO_DEVICE_KEYBOARD, 0,i) && !hatari_nokeys) ? 0x80: 0;
393 
394       if (i == RETROK_SPACE) // can map R3 to space bar
395       {
396          char joyspace = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3) ? 0x80 : 0;
397          Key_Sate[i] |= joyspace;
398       }
399 
400       if(SDLKeyToSTScanCode[i]==0x2a )
401       {  //SHIFT CASE
402 
403          if( Key_Sate[i] && Key_Sate2[i]==0 )
404          {
405             if(SHIFTON == 1)
406                retro_key_up(   SDLKeyToSTScanCode[i] );
407             else if(SHIFTON == -1)
408                retro_key_down( SDLKeyToSTScanCode[i] );
409             SHIFTON=-SHIFTON;
410             Key_Sate2[i]=1;
411          }
412          else if ( !Key_Sate[i] && Key_Sate2[i]==1 )Key_Sate2[i]=0;
413       }
414       else
415       {
416          if(Key_Sate[i] && SDLKeyToSTScanCode[i]!=-1  && Key_Sate2[i]==0)
417          {
418             retro_key_down( SDLKeyToSTScanCode[i] );
419             Key_Sate2[i]=1;
420          }
421          else if ( !Key_Sate[i] && SDLKeyToSTScanCode[i]!=-1 && Key_Sate2[i]==1 )
422          {
423             retro_key_up(   SDLKeyToSTScanCode[i] );
424             Key_Sate2[i]=0;
425          }
426       }
427    }
428 }
429 
430 const int DEADZONE = 0x8000 / 12;
Deadzone(int * a)431 void Deadzone(int* a)
432 {
433    if (al[0] <= -DEADZONE) al[0] += DEADZONE;
434    if (al[1] <= -DEADZONE) al[1] += DEADZONE;
435    if (al[0] >=  DEADZONE) al[0] -= DEADZONE;
436    if (al[1] >=  DEADZONE) al[1] -= DEADZONE;
437 }
438 
439 /*
440    L   show/hide Status
441    R   swap kbd pages
442    L2  MOUSE SPEED DOWN (gui/emu)
443    R2  MOUSE SPEED UP(gui/emu)
444    SEL toggle mouse/joy mode
445    STR Hatari Gui / Exit Gui
446    B   fire/mouse-left/valid key in vkbd
447    A   mouse-right
448    Y   switch Shift ON/OFF
449    X   show/hide vkbd
450    R3  keyboard space
451    */
452 
update_input(void)453 void update_input(void)
454 {
455    int i;
456 
457    int mouse_l;
458    int mouse_r;
459    int16_t mouse_x;
460    int16_t mouse_y;
461 
462    MXjoy0=0;
463    MXjoy1=0;
464 
465    if(oldi!=-1)
466    {
467       IKBD_PressSTKey(oldi,0);
468       oldi=-1;
469    }
470 
471    input_poll_cb();
472 
473    Process_key();
474 
475    i=RETRO_DEVICE_ID_JOYPAD_START;// Hatari GUI
476    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
477       mbt[i]=1;
478    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
479    {
480       mbt[i]=0;
481       pauseg=1;
482    }
483 
484    i=RETRO_DEVICE_ID_JOYPAD_X;//show vkey toggle
485    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
486       mbt[i]=1;
487    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
488    {
489       mbt[i]=0;
490       SHOWKEY=-SHOWKEY;
491       Screen_SetFullUpdate();
492    }
493 
494    i=RETRO_DEVICE_ID_JOYPAD_SELECT;//mouse/joy toggle
495    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
496       mbt[i]=1;
497    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
498    {
499       mbt[i]=0;
500       MOUSEMODE=-MOUSEMODE;
501    }
502 
503    i=RETRO_DEVICE_ID_JOYPAD_L2;//mouse gui speed down
504    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
505       mbt[i]=1;
506    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
507    {
508       mbt[i]=0;
509       PAS--;if(PAS<1)PAS=MAXPAS;
510    }
511 
512    i=RETRO_DEVICE_ID_JOYPAD_R2;//mouse gui speed up
513    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
514       mbt[i]=1;
515    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
516    {
517       mbt[i]=0;
518       PAS++;if(PAS>MAXPAS)PAS=1;
519    }
520 
521    i=RETRO_DEVICE_ID_JOYPAD_Y;//switch shift On/Off
522    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
523       mbt[i]=1;
524    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
525    {
526       mbt[i]=0;
527       SHIFTON=-SHIFTON;
528       Screen_SetFullUpdate();
529    }
530 
531    i=RETRO_DEVICE_ID_JOYPAD_L;//show/hide status (either joystick)
532    if ( (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) || input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) && mbt[i]==0 )
533       mbt[i]=1;
534    else if ( mbt[i]==1 && ! (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) || input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) )
535    {
536       mbt[i]=0;
537       STATUTON=-STATUTON;
538       Screen_SetFullUpdate();
539    }
540 
541    i=RETRO_DEVICE_ID_JOYPAD_R;//swap kbd pages
542    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
543       mbt[i]=1;
544    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
545    {
546       mbt[i]=0;
547       if(SHOWKEY==1)
548       {
549          NPAGE=-NPAGE;
550          Screen_SetFullUpdate();
551       }
552    }
553 
554    // joystick 2
555 
556    if (ConfigureParams.Joysticks.Joy[0].nJoystickMode == JOYSTICK_REALSTICK) // 2 joysticks
557    {
558       al[0] =(input_state_cb(1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X));
559       al[1] =(input_state_cb(1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y));
560 
561       /* Directions */
562       if (al[1] <= JOYRANGE_UP_VALUE)
563          MXjoy1 |= ATARIJOY_BITMASK_UP;
564       else if (al[1] >= JOYRANGE_DOWN_VALUE)
565          MXjoy1 |= ATARIJOY_BITMASK_DOWN;
566 
567       if (al[0] <= JOYRANGE_LEFT_VALUE)
568          MXjoy1 |= ATARIJOY_BITMASK_LEFT;
569       else if (al[0] >= JOYRANGE_RIGHT_VALUE)
570          MXjoy1 |= ATARIJOY_BITMASK_RIGHT;
571 
572       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP   ) ) MXjoy1 |= ATARIJOY_BITMASK_UP;
573       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN ) ) MXjoy1 |= ATARIJOY_BITMASK_DOWN;
574       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT ) ) MXjoy1 |= ATARIJOY_BITMASK_LEFT;
575       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT) ) MXjoy1 |= ATARIJOY_BITMASK_RIGHT;
576       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)     ) MXjoy1 |= ATARIJOY_BITMASK_FIRE;
577 
578       // Joy autofire
579       if( input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A) )
580       {
581          MXjoy1 |= ATARIJOY_BITMASK_FIRE;
582          if ((nVBLs&0x7)<4)
583             MXjoy1 &= ~ATARIJOY_BITMASK_FIRE;
584       }
585    }
586 
587    // virtual keyboard (prevents other joystick 1 input and mouse)
588 
589    if(SHOWKEY==1)
590    {
591       // analog stick can work the keyboard
592       al[0] =(input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X));
593       al[1] =(input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y));
594       bool al_up = al[1] <= JOYRANGE_UP_VALUE;
595       bool al_dn = al[1] >= JOYRANGE_DOWN_VALUE;
596       bool al_lf = al[0] <= JOYRANGE_LEFT_VALUE;
597       bool al_rt = al[0] >= JOYRANGE_RIGHT_VALUE;
598 
599       if ( (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP) || al_up) && vkflag[0]==0 )
600          vkflag[0]=1;
601       else if (vkflag[0]==1 && ! (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP) || al_up) )
602       {
603          vkflag[0]=0;
604          vky -= 1;
605       }
606 
607       if ( (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN) || al_dn) && vkflag[1]==0 )
608          vkflag[1]=1;
609       else if (vkflag[1]==1 && ! (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN) || al_dn) )
610       {
611          vkflag[1]=0;
612          vky += 1;
613       }
614 
615       if ( (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT) || al_lf) && vkflag[2]==0 )
616          vkflag[2]=1;
617       else if (vkflag[2]==1 && ! (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT) || al_lf) )
618       {
619          vkflag[2]=0;
620          vkx -= 1;
621       }
622 
623       if ( (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT) || al_rt) && vkflag[3]==0 )
624          vkflag[3]=1;
625       else if (vkflag[3]==1 && ! (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT) || al_rt) )
626       {
627          vkflag[3]=0;
628          vkx += 1;
629       }
630 
631       if(vkx<0)vkx=9;
632       if(vkx>9)vkx=0;
633       if(vky<0)vky=4;
634       if(vky>4)vky=0;
635 
636       virtual_kdb(bmp,vkx,vky);
637 
638       i=RETRO_DEVICE_ID_JOYPAD_B;
639       if(input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)  && vkflag[4]==0)
640          vkflag[4]=1;
641       else if( !input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)  && vkflag[4]==1)
642       {
643          vkflag[4]=0;
644          i=check_vkey2(vkx,vky);
645 
646          if(i==-2)
647          {
648             NPAGE=-NPAGE;oldi=-1;
649             //Clear interface zone
650             Screen_SetFullUpdate();
651          }
652          else if(i==-1)
653             oldi=-1;
654          else if(i==-3)
655          {
656             //KDB bgcolor
657             Screen_SetFullUpdate();
658             KCOL=-KCOL;
659             oldi=-1;
660          }
661          else if(i==-4)
662          {
663             //VKbd show/hide
664             oldi=-1;
665             Screen_SetFullUpdate();
666             SHOWKEY=-SHOWKEY;
667          }
668          else if(i==-5)
669          {
670             //Toggle stats
671             STATUTON=-STATUTON;
672             Screen_SetFullUpdate();
673          }
674          else
675          {
676             if(i==0x2a)
677             {
678 
679                IKBD_PressSTKey(i,(SHIFTON == 1)?0:1);
680 
681                SHIFTON=-SHIFTON;
682 
683                Screen_SetFullUpdate();
684 
685                oldi=-1;
686             }
687             else
688             {
689                oldi=i;
690                IKBD_PressSTKey(i,1);
691             }
692          }
693       }
694 
695       if(STATUTON==1)
696          Print_Statut();
697 
698       return;
699    }
700 
701    // joystick 1 / mouse
702 
703    if(MOUSEMODE < 0)
704    {
705       //Joy mode (joystick controls joystick, mouse controls mouse)
706 
707       //emulate Joy0 with joy analog left
708       al[0] =(input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X));
709       al[1] =(input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y));
710 
711       /* Directions */
712       if (al[1] <= JOYRANGE_UP_VALUE)
713          MXjoy0 |= ATARIJOY_BITMASK_UP;
714       else if (al[1] >= JOYRANGE_DOWN_VALUE)
715          MXjoy0 |= ATARIJOY_BITMASK_DOWN;
716 
717       if (al[0] <= JOYRANGE_LEFT_VALUE)
718          MXjoy0 |= ATARIJOY_BITMASK_LEFT;
719       else if (al[0] >= JOYRANGE_RIGHT_VALUE)
720          MXjoy0 |= ATARIJOY_BITMASK_RIGHT;
721 
722       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP   ) ) MXjoy0 |= ATARIJOY_BITMASK_UP;
723       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN ) ) MXjoy0 |= ATARIJOY_BITMASK_DOWN;
724       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT ) ) MXjoy0 |= ATARIJOY_BITMASK_LEFT;
725       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT) ) MXjoy0 |= ATARIJOY_BITMASK_RIGHT;
726       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)     ) MXjoy0 |= ATARIJOY_BITMASK_FIRE;
727 
728       // Joy autofire
729       if( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A) )
730       {
731          MXjoy0 |= ATARIJOY_BITMASK_FIRE;
732          if ((nVBLs&0x7)<4)
733             MXjoy0 &= ~ATARIJOY_BITMASK_FIRE;
734       }
735 
736       if (hatari_nomouse)
737       {
738          mouse_l = 0;
739          mouse_r = 0;
740       }
741       else
742       {
743          mouse_x = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
744          mouse_y = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
745          mouse_l = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
746          mouse_r = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT);
747          fmousex=mouse_x;
748          fmousey=mouse_y;
749       }
750 
751    }
752    else // MOUSEMODE >= 0
753    {
754       //Mouse mode (joystick controls mouse)
755       fmousex=fmousey=0;
756 
757       //emulate mouse with joy analog left
758       al[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X));
759       al[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y));
760       Deadzone(al);
761       al[0] = (al[0] * PAS) / MAXPAS;
762       al[1] = (al[1] * PAS) / MAXPAS;
763       fmousex += al[0]/1024;
764       fmousey += al[1]/1024;
765 
766       //emulate mouse with dpad
767       if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
768          fmousex += PAS*3;
769       if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT))
770          fmousex -= PAS*3;
771       if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN))
772          fmousey += PAS*3;
773       if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP))
774          fmousey -= PAS*3;
775 
776       mouse_l=input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
777       mouse_r=input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
778    }
779 
780    if(mbL==0 && mouse_l)
781    {
782       mbL=1;
783       Keyboard.bLButtonDown |= BUTTON_MOUSE;
784    }
785    else if(mbL==1 && !mouse_l)
786    {
787       Keyboard.bLButtonDown &= ~BUTTON_MOUSE;
788       mbL=0;
789    }
790 
791    if(mbR==0 && mouse_r)
792    {
793       mbR=1;
794       Keyboard.bRButtonDown |= BUTTON_MOUSE;
795    }
796    else if(mbR==1 && !mouse_r)
797    {
798       Keyboard.bRButtonDown &= ~BUTTON_MOUSE;
799       mbR=0;
800    }
801 
802    Main_HandleMouseMotion();
803 
804    if(STATUTON==1)
805       Print_Statut();
806 }
807 
input_gui(void)808 void input_gui(void)
809 {
810 
811    int i;
812    int mouse_l;
813    int mouse_r;
814    int16_t mouse_x = 0;
815    int16_t mouse_y = 0;
816 
817    input_poll_cb();
818 
819    if(slowdown>0)
820       return;
821 
822    /* ability to adjust mouse speed in hatari GUI */
823 
824    i=RETRO_DEVICE_ID_JOYPAD_L2;
825    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
826       mbt[i]=1;
827    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
828    {
829       mbt[i]=0;
830       PAS--;if(PAS<0)PAS=MAXPAS;
831    }
832 
833    i=RETRO_DEVICE_ID_JOYPAD_R2;
834    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
835       mbt[i]=1;
836    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
837    {
838       mbt[i]=0;
839       PAS++;if(PAS>MAXPAS)PAS=1;
840    }
841 
842    // START to exit GUI
843 
844    i=RETRO_DEVICE_ID_JOYPAD_START;
845    if ( input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) && mbt[i]==0 )
846       mbt[i]=1;
847    else if ( mbt[i]==1 && ! input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) )
848    {
849       mbt[i]=0;
850       exitgui=1;
851    }
852 
853    //emulate mouse with joy analog left
854    al[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X));
855    al[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y));
856    Deadzone(al);
857    al[0] = (al[0] * PAS) / MAXPAS;
858    al[1] = (al[1] * PAS) / MAXPAS;
859    mouse_x += al[0]/1024;
860    mouse_y += al[1]/1024;
861 
862    if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
863       mouse_x += PAS*3;
864    if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT))
865       mouse_x -= PAS*3;
866    if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN))
867       mouse_y += PAS*3;
868    if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP))
869       mouse_y -= PAS*3;
870    mouse_l=input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
871    mouse_r=input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
872 
873    // joystick mouse control is relative
874    gmx+=mouse_x;
875    gmy+=mouse_y;
876 
877    // pointer mouse control is absolute, and overrides joystick when you move it
878    int point_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
879    int point_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
880    int point_b = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
881    if (point_x != point_x_last || point_y != point_y_last)
882    {
883       const int PMIN = -0x7FFF;
884       const int PMAX = 0x7FFF;
885       point_x_last   = point_x;
886       point_y_last   = point_y;
887       gmx            = ((point_x - PMIN) * retrow) / (PMAX - PMIN);
888       gmy            = ((point_y - PMIN) * retroh) / (PMAX - PMIN);
889    }
890 
891    slowdown=1;
892 
893    if(mmbL==0 && (mouse_l || point_b))
894    {
895       mmbL=1;
896       touch=1;
897    }
898    else if(mmbL==1 && (!mouse_l && !point_b))
899    {
900       mmbL=0;
901       touch=-1;
902    }
903 
904    // POINTER doesn't have a right button, but Hatari GUI doesn't need it
905    if(mmbR==0 && mouse_r)
906       mmbR=1;
907    else if(mmbR==1 && !mouse_r)
908       mmbR=0;
909 
910    if (gmx<0)
911       gmx=0;
912    if (gmx>retrow-1)
913       gmx=retrow-1;
914    if (gmy<0)
915       gmy=0;
916    if (gmy>retroh-1)
917       gmy=retroh-1;
918 }
919