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