]> Shamusworld >> Repos - virtualjaguar/blob - src/gui.cpp
404af7e4f481fbf71ebdf01686c64bc9e3bb0830
[virtualjaguar] / src / gui.cpp
1 //
2 // GUI.CPP
3 //
4 // Graphical User Interface support
5 // by James L. Hammons
6 //
7
8 #include <dirent.h>
9 #include <SDL.h>
10 #include <string>
11 #include <vector>
12 #include <algorithm>
13 #include "types.h"
14 #include "settings.h"
15 #include "tom.h"
16 #include "video.h"
17 #include "font1.h"
18 #include "gui.h"
19
20 using namespace std;                                                            // For STL stuff
21
22 // Private function prototypes
23
24 // Local global variables
25
26 int mouseX, mouseY;
27
28 uint16 mousePic[] = {
29         6, 8,
30
31         0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,              // +
32         0x0300,0x03E0,0x0000,0x0000,0x0000,0x0000,              // @+
33         0x0300,0x03E0,0x03E0,0x0000,0x0000,0x0000,              // @++
34         0x0300,0x0300,0x03E0,0x03E0,0x0000,0x0000,              // @@++
35         0x0300,0x0300,0x03E0,0x03E0,0x03E0,0x0000,              // @@+++
36         0x0300,0x0300,0x0300,0x03E0,0x03E0,0x03E0,              // @@@+++
37         0x0300,0x0300,0x0300,0x0000,0x0000,0x0000,              // @@@
38         0x0300,0x0000,0x0000,0x0000,0x0000,0x0000               // @
39 /*
40         0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,              // +
41         0xE318,0xFFFF,0x0000,0x0000,0x0000,0x0000,              // @+
42         0xE318,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,              // @++
43         0xE318,0xE318,0xFFFF,0xFFFF,0x0000,0x0000,              // @@++
44         0xE318,0xE318,0xFFFF,0xFFFF,0xFFFF,0x0000,              // @@+++
45         0xE318,0xE318,0xE318,0xFFFF,0xFFFF,0xFFFF,              // @@@+++
46         0xE318,0xE318,0xE318,0x0000,0x0000,0x0000,              // @@@
47         0xE318,0x0000,0x0000,0x0000,0x0000,0x0000               // @
48 */
49 };
50 // 1 111 00 11 100 1 1100 -> F39C
51 // 1 100 00 10 000 1 0000 -> C210
52 // 1 110 00 11 000 1 1000 -> E318
53 // 0 000 00 11 111 0 0000 -> 03E0
54 // 0 000 00 11 000 0 0000 -> 0300
55
56 void InitGUI(void)
57 {
58         SDL_ShowCursor(SDL_DISABLE);
59         SDL_GetMouseState(&mouseX, &mouseY);
60 }
61
62 void GUIDone(void)
63 {
64 }
65
66 //
67 // Draw text at the given x/y coordinates. Can invert text as well.
68 //
69 void DrawString(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
70 {
71         char string[4096];
72         va_list arg;
73
74         va_start(arg, text);
75         vsprintf(string, text, arg);
76         va_end(arg);
77
78         uint32 pitch = GetSDLScreenPitch() / 2;                 // Returns pitch in bytes but we need words...
79         uint32 length = strlen(string), address = x + (y * pitch);
80
81         for(uint32 i=0; i<length; i++)
82         {
83                 uint32 fontAddr = (uint32)string[i] * 64;
84
85                 for(uint32 yy=0; yy<8; yy++)
86                 {
87                         for(uint32 xx=0; xx<8; xx++)
88                         {
89                                 if ((font1[fontAddr] && !invert) || (!font1[fontAddr] && invert))
90                                         *(screen + address + xx + (yy * pitch)) = 0xFE00;
91                                 fontAddr++;
92                         }
93                 }
94
95                 address += 8;
96         }
97 }
98
99 //
100 // Draw "picture"
101 // Uses zero as transparent color
102 //
103 void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap)
104 {
105         uint16 width = bitmap[0], height = bitmap[1];
106         bitmap += 2;
107
108         uint32 pitch = GetSDLScreenPitch() / 2;                 // Returns pitch in bytes but we need words...
109         uint32 address = x + (y * pitch);
110
111         for(int yy=0; yy<height; yy++)
112         {
113                 for(int xx=0; xx<width; xx++)
114                 {
115                                 if (*bitmap && x + xx < pitch)          // NOTE: Still doesn't clip the Y val...
116                                         *(screen + address + xx + (yy * pitch)) = *bitmap;
117                                 bitmap++;
118                 }
119         }
120 }
121
122 //
123 // Very very crude GUI file selector
124 //
125 bool UserSelectFile(char * path, char * filename)
126 {
127         extern int16 * backbuffer;
128         vector<string> fileList;
129
130         // Read in the candidate files from the directory pointed to by "path"
131
132         DIR * dp = opendir(path);
133         dirent * de;
134
135         while ((de = readdir(dp)) != NULL)
136         {
137                 char * ext = strrchr(de->d_name, '.');
138
139                 if (ext != NULL)
140                         if (stricmp(ext, ".zip") == 0 || stricmp(ext, ".jag") == 0)
141                                 fileList.push_back(string(de->d_name));
142         }
143
144         closedir(dp);
145
146         // Main GUI selection loop
147
148         uint32 cursor = 0, startFile = 0;
149
150         if (fileList.size() > 1)        // Only go GUI if more than one possibility!
151         {
152                 sort(fileList.begin(), fileList.end());
153
154                 bool done = false;
155                 uint32 limit = (fileList.size() > 30 ? 30 : fileList.size());
156                 SDL_Event event;
157
158                 // Ensure that the GUI is drawn before any user input...
159                 event.type = SDL_USEREVENT;
160                 SDL_PushEvent(&event);
161
162                 while (!done)
163                 {
164                         while (SDL_PollEvent(&event))
165                         {
166                                 if (event.type == SDL_KEYDOWN)
167                                 {
168                                         SDLKey key = event.key.keysym.sym;
169
170                                         if (key == SDLK_DOWN)
171                                         {
172                                                 if (cursor != limit - 1)        // Cursor is within its window
173                                                         cursor++;
174                                                 else                                            // Otherwise, scroll the window...
175                                                 {
176                                                         if (cursor + startFile != fileList.size() - 1)
177                                                                 startFile++;
178                                                 }
179                                         }
180                                         if (key == SDLK_UP)
181                                         {
182                                                 if (cursor != 0)
183                                                         cursor--;
184                                                 else
185                                                 {
186                                                         if (startFile != 0)
187                                                                 startFile--;
188                                                 }
189                                         }
190                                         if (key == SDLK_PAGEDOWN)
191                                         {
192                                                 if (cursor != limit - 1)
193                                                         cursor = limit - 1;
194                                                 else
195                                                 {
196                                                         startFile += limit;
197                                                         if (startFile > fileList.size() - limit)
198                                                                 startFile = fileList.size() - limit;
199                                                 }
200                                         }
201                                         if (key == SDLK_PAGEUP)
202                                         {
203                                                 if (cursor != 0)
204                                                         cursor = 0;
205                                                 else
206                                                 {
207                                                         if (startFile < limit)
208                                                                 startFile = 0;
209                                                         else
210                                                                 startFile -= limit;
211                                                 }
212                                         }
213                                         if (key == SDLK_RETURN)
214                                                 done = true;
215                                         if (key == SDLK_ESCAPE)
216                                         {
217                                                 WriteLog("GUI: Aborting VJ by user request.\n");
218                                                 return false;                                           // Bail out!
219                                         }
220                                         if (key >= SDLK_a && key <= SDLK_z)
221                                         {
222                                                 // Advance cursor to filename with first letter pressed...
223                                                 uint8 which = (key - SDLK_a) + 65;      // Convert key to A-Z char
224
225                                                 for(uint32 i=0; i<fileList.size(); i++)
226                                                 {
227                                                         if ((fileList[i][0] & 0xDF) == which)
228                                                         {
229                                                                 cursor = i - startFile;
230                                                                 if (i > startFile + limit - 1)
231                                                                         startFile = i - limit + 1,
232                                                                         cursor = limit - 1;
233                                                                 if (i < startFile)
234                                                                         startFile = i,
235                                                                         cursor = 0;
236                                                                 break;
237                                                         }
238                                                 }
239                                         }
240                                 }
241                                 else if (event.type == SDL_MOUSEMOTION)
242                                 {
243                                         mouseX = event.motion.x, mouseY = event.motion.y;
244                                         if (vjs.useOpenGL)
245                                                 mouseX /= 2, mouseY /= 2;
246                                 }
247                                 else if (event.type == SDL_MOUSEBUTTONDOWN)
248                                 {
249                                         uint32 mx = event.button.x, my = event.button.y;
250                                         if (vjs.useOpenGL)
251                                                 mx /= 2, my /= 2;
252                                         cursor = my / 8;
253                                 }
254
255                                 // Draw the GUI...
256 //                              memset(backbuffer, 0x11, tom_getVideoModeWidth() * tom_getVideoModeHeight() * 2);
257                                 memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
258
259                                 for(uint32 i=0; i<limit; i++)
260                                 {
261                                         // Clip our strings to guarantee that they fit on the screen...
262                                         // (and strip off the extension too)
263                                         string s(fileList[startFile + i], 0, fileList[startFile + i].length() - 4);
264                                         if (s.length() > 38)
265                                                 s[38] = 0;
266                                         DrawString(backbuffer, 0, i*8, (cursor == i ? true : false), " %s ", s.c_str());
267                                 }
268
269                                 DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic);
270
271                                 RenderBackbuffer();
272                         }
273                 }
274         }
275
276         strcpy(filename, path);
277
278         if (strlen(path) > 0)
279                 if (path[strlen(path) - 1] != '/')
280                         strcat(filename, "/");
281
282         strcat(filename, fileList[startFile + cursor].c_str());
283
284         return true;
285 }