1 /** AlmostTI: portable TI calcs emulator *********************/
2 /**                                                         **/
3 /**                         Unix.c                          **/
4 /**                                                         **/
5 /** This file contains Unix-dependent subroutines and       **/
6 /** drivers. It includes screen drivers via Display.h.      **/
7 /**                                                         **/
8 /** Copyright (C) Marat Fayzullin 2009                      **/
9 /**     You are not allowed to distribute this software     **/
10 /**     commercially. Please, notify me, if you make any    **/
11 /**     changes to this file.                               **/
12 /*************************************************************/
13 #include "TI85.h"
14 #include "Console.h"
15 #include "EMULib.h"
16 #include "Sound.h"
17 
18 #include <string.h>
19 #include <stdio.h>
20 
21 #define WIDTH       480                   /* Buffer width    */
22 #define HEIGHT      800                   /* Buffer height   */
23 #define XOFFSET     (WIDTH-128*3)/2       /* Display offset  */
24 #define YOFFSET     54                    /* Display offset  */
25 #define PORTRAIT
26 
27 /* Combination of EFF_* bits */
28 int UseEffects  = EFF_SCALE|EFF_SAVECPU|EFF_MITSHM|EFF_VARBPP|EFF_SYNC;
29 
30 int InMenu;                /* 1: In MenuTI85(), ignore keys  */
31 int UseStatic   = 1;       /* 1: Use static palette          */
32 int UseZoom     = 1;       /* Zoom factor (1=no zoom)        */
33 int UseSound    = 22050;   /* Audio sampling frequency (Hz)  */
34 int SyncFreq    = 60;      /* Sync frequency (0=sync off)    */
35 int FastForward;           /* Fast-forwarded UPeriod backup  */
36 int SndSwitch;             /* Mask of enabled sound channels */
37 int SndVolume;             /* Master volume for audio        */
38 byte KeyReady;             /* 1: Key has been pressed        */
39 Image OutImage;            /* Unix display image buffer      */
40 Image ScrImage;            /* TI85 display image buffer      */
41 unsigned int XPal[2];      /* Referenced from Common.h       */
42 unsigned int Black,White;
43 
44 const char *Title = "AlmostTI-Unix 1.3"; /* Program version  */
45 
46 void HandleKeys(unsigned int Key);
47 void HandleMouse(int X, int Y, int State);
48 
49 /** TouchMap[] ***********************************************/
50 /** This map translates on-screen rectangles into keys.     **/
51 /*************************************************************/
52 struct
53 {
54   byte KeyCode;
55   int X,Y,W,H;
56 } TouchMap[] =
57 {
58   { KBD_RIGHT,  407,380,28,43 },
59   { KBD_LEFT,   289,380,28,43 },
60   { KBD_UP,     333,352,58,25 },
61   { KBD_DOWN,   333,427,58,25 },
62 
63   { KBD_F5,     371,291,65,25 },
64   { KBD_F4,     290,291,65,25 },
65   { KBD_F3,     208,291,65,25 },
66   { KBD_F2,     126,291,65,25 },
67   { KBD_F1,     44,291,65,25 },
68 
69   { KBD_CLEAR,  373,467,67,30 },
70   { KBD_POWER,  373,511,67,30 },
71   { KBD_DIV,    373,555,67,30 },
72   { KBD_MUL,    373,599,67,30 },
73   { KBD_MINUS,  373,643,67,30 },
74   { KBD_PLUS,   373,687,67,30 },
75   { KBD_ENTER,  373,731,67,38 },
76 
77   { KBD_CUSTOM, 290,467,67,30 },
78   { KBD_TAN,    290,511,67,30 },
79   { KBD_RPARENT,290,555,67,30 },
80   { KBD_9,      290,599,67,30 },
81   { KBD_6,      290,643,67,30 },
82   { KBD_3,      290,687,67,30 },
83   { KBD_SIGN,   290,731,67,30 },
84 
85   { KBD_MORE,   207,379,67,30 },
86   { KBD_DEL,    207,423,67,30 },
87   { KBD_PRGM,   207,467,67,30 },
88   { KBD_COS,    207,511,67,30 },
89   { KBD_LPARENT,207,555,67,30 },
90   { KBD_8,      207,599,67,30 },
91   { KBD_5,      207,643,67,30 },
92   { KBD_2,      207,687,67,30 },
93   { KBD_DOT,    207,731,67,30 },
94 
95   { KBD_EXIT,   124,379,67,30 },
96   { KBD_XVAR,   124,423,67,30 },
97   { KBD_STAT,   124,467,67,30 },
98   { KBD_SIN,    124,511,67,30 },
99   { KBD_EE,     124,555,67,30 },
100   { KBD_7,      124,599,67,30 },
101   { KBD_4,      124,643,67,30 },
102   { KBD_1,      124,687,67,30 },
103   { KBD_0,      124,731,67,30 },
104 
105   { KBD_2ND,    41,379,67,30 },
106   { KBD_ALPHA,  41,423,67,30 },
107   { KBD_GRAPH,  41,467,67,30 },
108   { KBD_LOG,    41,511,67,30 },
109   { KBD_LN,     41,555,67,30 },
110   { KBD_SQR,    41,599,67,30 },
111   { KBD_COMMA,  41,643,67,30 },
112   { KBD_STO,    41,687,67,30 },
113   { KBD_ON,     41,731,67,30 },
114 
115   { 0,0,0,0,0 }
116 };
117 
118 /** InitMachine() ********************************************/
119 /** Allocate resources needed by machine-dependent code.    **/
120 /*************************************************************/
InitMachine(void)121 int InitMachine(void)
122 {
123   int J;
124 
125   /* Initialize variables */
126   UseZoom       = UseZoom<1? 1:UseZoom>5? 5:UseZoom;
127   InMenu        = 0;
128   FastForward   = 0;
129   OutImage.Data = 0;
130   KeyReady      = 0;
131 
132   /* Initialize system resources */
133   InitUnix(Title,UseZoom*WIDTH,UseZoom*HEIGHT);
134 
135   /* Set visual effects */
136   X11SetEffects(UseEffects);
137 
138   /* Create main image buffer */
139   if(!NewImage(&OutImage,WIDTH,HEIGHT)) { TrashUnix();return(0); }
140   ClearImage(&OutImage,X11GetColor(0,0,0));
141   CropImage(&ScrImage,&OutImage,XOFFSET,YOFFSET,3*128,3*64);
142 
143   /* Initialize video to main image */
144   SetVideo(&OutImage,0,0,WIDTH,HEIGHT);
145 
146   /* Set colors */
147   XPal[0] = White = X11GetColor(255,255,255);
148   XPal[1] = Black = X11GetColor(0,0,0);
149 
150   /* Attach keyboard handler */
151   SetKeyHandler(HandleKeys);
152 
153   /* Attach mouse handler */
154   SetMouseHandler(HandleMouse);
155 
156   /* Initialize sound */
157   InitSound(UseSound,150);
158   SndSwitch=(1<<4)-1;
159   SndVolume=255/4;
160   SetChannels(SndVolume,SndSwitch);
161 
162   /* Initialize sync timer if needed */
163   if((SyncFreq>0)&&!SetSyncTimer(SyncFreq*UPeriod/100)) SyncFreq=0;
164 
165   /* Done */
166   return(1);
167 }
168 
169 /** TrashMachine() *******************************************/
170 /** Deallocate all resources taken by InitMachine().        **/
171 /*************************************************************/
TrashMachine(void)172 void TrashMachine(void)
173 {
174   FreeImage(&OutImage);
175   TrashAudio();
176   TrashUnix();
177 }
178 
179 /** SetColor() ***********************************************/
180 /** Allocate new color.                                     **/
181 /*************************************************************/
SetColor(byte N,byte R,byte G,byte B)182 void SetColor(byte N,byte R,byte G,byte B)
183 {
184   /* Set requested color */
185   XPal[N&1]=X11GetColor(R,G,B);
186 }
187 
188 /** PutImage() ***********************************************/
189 /** Put an image on the screen.                             **/
190 /*************************************************************/
PutImage(void)191 void PutImage(void)
192 {
193   /* Show rendered screen buffer */
194   ShowVideo();
195 }
196 
197 /** Keypad() *************************************************/
198 /** Poll the keyboard.                                      **/
199 /*************************************************************/
Keypad(void)200 byte Keypad(void)
201 {
202   X11ProcessEvents();
203   return(IS_KBD(KBD_ON));
204 }
205 
206 /** ShowBackdrop() *******************************************/
207 /** Show backdrop image with calculator faceplate.          **/
208 /*************************************************************/
209 #include "lodepng.h"
210 
ShowBackdrop(const char * FileName)211 int ShowBackdrop(const char *FileName)
212 {
213   /* Not loading backdrop image for now */
214   unsigned char* buffer;
215   unsigned char* image;
216   size_t buffersize, imagesize, i;
217   LodePNG_Decoder decoder;
218 
219   // Load the image file with given filename.
220   LodePNG_loadFile(&buffer, &buffersize, FileName);
221 
222   // Decode the png.
223   LodePNG_Decoder_init(&decoder);
224   LodePNG_decode(&decoder, &image, &imagesize, buffer, buffersize);
225 
226   // If there's an error, display it and quit
227   if (decoder.error) {
228       printf("error: %d\n", decoder.error);
229       return(0);
230   }
231 #ifndef PORTRAIT
232   if (decoder.infoPng.width != WIDTH) {
233 #else
234   if (decoder.infoPng.height != WIDTH) {
235 #endif
236       printf("error: skin width != %d\n", WIDTH);
237       return(0);
238   }
239 #ifndef PORTRAIT
240   if (decoder.infoPng.height != HEIGHT) {
241 #else
242   if (decoder.infoPng.width != HEIGHT) {
243 #endif
244       printf("error: skin height != %d\n", HEIGHT);
245       return(0);
246   }
247 
248   // Draw the image on the canvas
249   uint j;
250   pixel *P = (pixel *)OutImage.Data;
251   unsigned char *Q = image;
252 
253 #ifndef PORTRAIT
254   for (j = HEIGHT * WIDTH; j; j--) {
255       *P++ = X11GetColor(*Q++,*Q++,*Q++);
256       Q++;
257   }
258 #else
259   uint k;
260   for (k = 0; k < HEIGHT; k++) {
261     for (j = WIDTH; j > 0; j--) {
262       Q = image + (j * HEIGHT + k) * 4;
263      *P++ = X11GetColor(*Q++,*Q++,*Q++);
264     }
265   }
266 #endif
267 
268   // Cleanup decoder
269   free(image);
270   free(buffer);
271   LodePNG_Decoder_cleanup(&decoder);
272   return(1);
273 }
274 
275 /** HandleKeys() *********************************************/
276 /** Key handler.                                            **/
277 /*************************************************************/
278 void HandleKeys(unsigned int Key)
279 {
280   if(InMenu||CPU.Trace) return;
281 
282   if(Key&CON_RELEASE)
283     switch(Key&CON_KEYCODE)
284     {
285       case XK_F9:
286       case XK_Page_Up:
287         if(FastForward)
288         {
289           X11SetEffects(UseEffects);
290           UPeriod=FastForward;
291           FastForward=0;
292         }
293         break;
294 
295       case 'q':
296       case 'Q':          KBD_RES(KBD_ON);KeyReady=1;break;
297       case XK_F1:        KBD_RES(KBD_F1);KeyReady=1;break;
298       case XK_F2:        KBD_RES(KBD_F2);KeyReady=1;break;
299       case XK_F3:        KBD_RES(KBD_F3);KeyReady=1;break;
300       case XK_F4:        KBD_RES(KBD_F4);KeyReady=1;break;
301       case XK_F5:        KBD_RES(KBD_F5);KeyReady=1;break;
302       case XK_KP_Enter:
303       case XK_Return:    KBD_RES(KBD_ENTER);KeyReady=1;break;
304       case XK_Shift_L:
305       case XK_Shift_R:   KBD_RES(KBD_2ND);KeyReady=1;break;
306       case XK_Escape:    KBD_RES(KBD_EXIT);KeyReady=1;break;
307       case XK_Left:      KBD_RES(KBD_LEFT);KeyReady=1;break;
308       case XK_Right:     KBD_RES(KBD_RIGHT);KeyReady=1;break;
309       case XK_Up:        KBD_RES(KBD_UP);KeyReady=1;break;
310       case XK_Down:      KBD_RES(KBD_DOWN);KeyReady=1;break;
311       case XK_greater:   KBD_RES(KBD_STO);KeyReady=1;break;
312       case XK_Delete:    KBD_RES(KBD_DEL);KeyReady=1;break;
313       case XK_BackSpace: KBD_RES(KBD_CLEAR);KeyReady=1;break;
314       case XK_Alt_L:
315       case XK_Alt_R:     KBD_RES(KBD_ALPHA);KeyReady=1;break;
316       case XK_KP_Home:   KBD_RES(KBD_7);KeyReady=1;break;
317       case XK_KP_Up:     KBD_RES(KBD_8);KeyReady=1;break;
318       case XK_KP_Page_Up: KBD_RES(KBD_9);KeyReady=1;break;
319       case XK_KP_Left:   KBD_RES(KBD_4);KeyReady=1;break;
320       case XK_KP_Begin:  KBD_RES(KBD_5);KeyReady=1;break;
321       case XK_KP_Right:  KBD_RES(KBD_6);KeyReady=1;break;
322       case XK_KP_End:    KBD_RES(KBD_1);KeyReady=1;break;
323       case XK_KP_Down:   KBD_RES(KBD_2);KeyReady=1;break;
324       case XK_KP_Page_Down: KBD_RES(KBD_3);KeyReady=1;break;
325       case XK_KP_Insert: KBD_RES(KBD_0);KeyReady=1;break;
326       case XK_KP_Delete: KBD_RES(KBD_DOT);KeyReady=1;break;
327       case XK_KP_Divide: KBD_RES(KBD_DIV);KeyReady=1;break;
328       case XK_KP_Multiply: KBD_RES(KBD_MUL);KeyReady=1;break;
329       case XK_KP_Subtract: KBD_RES(KBD_MINUS);KeyReady=1;break;
330       case XK_KP_Add:    KBD_RES(KBD_PLUS);KeyReady=1;break;
331       default:
332         Key&=CON_KEYCODE;
333         if((Key>=' ')&&(Key<0x80)) { KBD_RES(Key);KeyReady=1; }
334         break;
335     }
336   else
337     switch(Key&CON_KEYCODE)
338     {
339 #ifdef DEBUG
340       case XK_Tab:      CPU.Trace=1;break;
341 #endif
342       case XK_F6:        LoadSTA("DEFAULT.STA");break;
343       case XK_F7:        SaveSTA("DEFAULT.STA");break;
344       case XK_F8:
345         UseEffects^=Key&CON_ALT? EFF_SOFTEN:EFF_TVLINES;
346         X11SetEffects(UseEffects);
347         break;
348       case XK_F9:
349       case XK_Page_Up:
350         if(!FastForward)
351         {
352           X11SetEffects(UseEffects&~EFF_SYNC);
353           FastForward=UPeriod;
354           UPeriod=10;
355         }
356         break;
357 
358       case 'q':
359       case 'Q':          KBD_SET(KBD_ON);KeyReady=1;break;
360       case XK_F11:       ResetTI85(Mode);break;
361       case XK_F12:       ExitNow=1;break;
362 
363       case XK_F1:        KBD_SET(KBD_F1);KeyReady=1;break;
364       case XK_F2:        KBD_SET(KBD_F2);KeyReady=1;break;
365       case XK_F3:        KBD_SET(KBD_F3);KeyReady=1;break;
366       case XK_F4:        KBD_SET(KBD_F4);KeyReady=1;break;
367       case XK_F5:        KBD_SET(KBD_F5);KeyReady=1;break;
368       case XK_KP_Enter:
369       case XK_Return:    KBD_SET(KBD_ENTER);KeyReady=1;break;
370       case XK_Shift_L:
371       case XK_Shift_R:   KBD_SET(KBD_2ND);KeyReady=1;break;
372       case XK_Escape:    KBD_SET(KBD_EXIT);KeyReady=1;break;
373       case XK_Left:      KBD_SET(KBD_LEFT);KeyReady=1;break;
374       case XK_Right:     KBD_SET(KBD_RIGHT);KeyReady=1;break;
375       case XK_Up:        KBD_SET(KBD_UP);KeyReady=1;break;
376       case XK_Down:      KBD_SET(KBD_DOWN);KeyReady=1;break;
377       case XK_greater:   KBD_SET(KBD_STO);KeyReady=1;break;
378       case XK_Delete:    KBD_SET(KBD_DEL);KeyReady=1;break;
379       case XK_BackSpace: KBD_SET(KBD_CLEAR);KeyReady=1;break;
380       case XK_Alt_L:
381       case XK_Alt_R:     KBD_SET(KBD_ALPHA);KeyReady=1;break;
382       case XK_KP_Home:   KBD_SET(KBD_7);KeyReady=1;break;
383       case XK_KP_Up:     KBD_SET(KBD_8);KeyReady=1;break;
384       case XK_KP_Page_Up: KBD_SET(KBD_9);KeyReady=1;break;
385       case XK_KP_Left:   KBD_SET(KBD_4);KeyReady=1;break;
386       case XK_KP_Begin:  KBD_SET(KBD_5);KeyReady=1;break;
387       case XK_KP_Right:  KBD_SET(KBD_6);KeyReady=1;break;
388       case XK_KP_End:    KBD_SET(KBD_1);KeyReady=1;break;
389       case XK_KP_Down:   KBD_SET(KBD_2);KeyReady=1;break;
390       case XK_KP_Page_Down: KBD_SET(KBD_3);KeyReady=1;break;
391       case XK_KP_Insert: KBD_SET(KBD_0);KeyReady=1;break;
392       case XK_KP_Delete: KBD_SET(KBD_DOT);KeyReady=1;break;
393       case XK_KP_Divide: KBD_SET(KBD_DIV);KeyReady=1;break;
394       case XK_KP_Multiply: KBD_SET(KBD_MUL);KeyReady=1;break;
395       case XK_KP_Subtract: KBD_SET(KBD_MINUS);KeyReady=1;break;
396       case XK_KP_Add:    KBD_SET(KBD_PLUS);KeyReady=1;break;
397       default:
398         Key&=CON_KEYCODE;
399         if((Key>=' ')&&(Key<0x80)) { KBD_SET(Key);KeyReady=1; }
400         break;
401     }
402 }
403 
404 /** HandleMouse() *********************************************/
405 /** Mouse click/unclick handler.                             **/
406 /*************************************************************/
407 void HandleMouse(int X, int Y, int State)
408 {
409     int J;
410     int Flags = State ? 0:CON_RELEASE;
411     for(J=0;TouchMap[J].W;++J)
412       if((X>=TouchMap[J].X)&&(Y>=TouchMap[J].Y))
413         if((X<TouchMap[J].X+TouchMap[J].W)&&(Y<TouchMap[J].Y+TouchMap[J].H))
414         {
415           if (State)
416             KBD_SET(TouchMap[J].KeyCode);
417           else
418             KBD_RES(TouchMap[J].KeyCode);
419           break;
420         }
421 }
422 
423 /** Common.h *************************************************/
424 /** Common display drivers.                                 **/
425 /*************************************************************/
426 #include "Common.h"
427 
428 
429