4 // Graphical User Interface support
20 using namespace std; // For STL stuff
22 // Private function prototypes
24 void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap);
25 void DrawStringTrans(int16 * screen, uint32 x, uint32 y, uint16 color, uint8 opacity, const char * text, ...);
26 void DrawStringOpaque(int16 * screen, uint32 x, uint32 y, uint16 color1, uint16 color2, const char * text, ...);
32 // Local global variables
39 0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // +
40 0x0300,0x03E0,0x0000,0x0000,0x0000,0x0000, // @+
41 0x0300,0x03E0,0x03E0,0x0000,0x0000,0x0000, // @++
42 0x0300,0x0300,0x03E0,0x03E0,0x0000,0x0000, // @@++
43 0x0300,0x0300,0x03E0,0x03E0,0x03E0,0x0000, // @@+++
44 0x0300,0x0300,0x0300,0x03E0,0x03E0,0x03E0, // @@@+++
45 0x0300,0x0300,0x0300,0x0000,0x0000,0x0000, // @@@
46 0x0300,0x0000,0x0000,0x0000,0x0000,0x0000 // @
48 0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000, // +
49 0xE318,0xFFFF,0x0000,0x0000,0x0000,0x0000, // @+
50 0xE318,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // @++
51 0xE318,0xE318,0xFFFF,0xFFFF,0x0000,0x0000, // @@++
52 0xE318,0xE318,0xFFFF,0xFFFF,0xFFFF,0x0000, // @@+++
53 0xE318,0xE318,0xE318,0xFFFF,0xFFFF,0xFFFF, // @@@+++
54 0xE318,0xE318,0xE318,0x0000,0x0000,0x0000, // @@@
55 0xE318,0x0000,0x0000,0x0000,0x0000,0x0000 // @
58 // 1 111 00 11 100 1 1100 -> F39C
59 // 1 100 00 10 000 1 0000 -> C210
60 // 1 110 00 11 000 1 1000 -> E318
61 // 0 000 00 11 111 0 0000 -> 03E0
62 // 0 000 00 11 000 0 0000 -> 0300
64 #define NUM_MENU_ITEMS 3
65 char * menu[NUM_MENU_ITEMS] = { "File", "Settings", "Options" };
67 char * menu1[4] = { "Load...", "Reset", "Run", "Quit" };
68 char * menu2[3] = { "Video...", "Audio...", "Misc..." };
69 char * menu3[1] = { "About..." };
71 char ** subMenu[NUM_MENU_ITEMS] = { menu1, menu2, menu3 };
72 uint8 subMenuNumItems[NUM_MENU_ITEMS] = { 4, 3, 1 };
74 void (* menu1Action[4])(void) = { LoadROM, NULL, RunEmu, Quit };
75 void (* menu2Action[3])(void) = { NULL, NULL, NULL };
76 void (* menu3Action[1])(void) = { About };
77 void (** subMenuAction[NUM_MENU_ITEMS])(void) = { menu1Action, menu2Action, menu3Action };
86 virtual void HandleKey(SDLKey key) = 0;
87 virtual void HandleMouseMove(uint32 x, uint32 y) = 0;
88 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0;
89 virtual void Draw(uint32, uint32) = 0;
90 //Needed? virtual ~Element() = 0;
91 //We're not allocating anything in the base class, so the answer would be NO.
92 bool Inside(uint32 x, uint32 y);
94 static void SetScreenAndPitch(int16 * s, uint32 p) { screenBuffer = s, pitch = p; }
99 static int16 * screenBuffer;
103 int16 * Element::screenBuffer = NULL;
104 uint32 Element::pitch = 0;
106 bool Element::Inside(uint32 x, uint32 y)
108 return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
109 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
112 class Button: public Element
115 Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): clicked(false),
116 inside(false), fgColor(0xFFFF), bgColor(0x03E0)
117 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
118 virtual void HandleKey(SDLKey key) {}
119 virtual void HandleMouseMove(uint32 x, uint32 y);
120 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
121 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
124 bool clicked, inside;
125 uint16 fgColor, bgColor;
128 void Button::HandleMouseMove(uint32 x, uint32 y)
130 inside = Inside(x, y);
133 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
135 if (inside && mouseDown)
141 void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
143 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
145 for(uint32 y=0; y<extents.h; y++)
147 for(uint32 x=0; x<extents.w; x++)
149 // Doesn't clip in y axis! !!! FIX !!!
150 if (extents.x + x < pitch)
151 screenBuffer[addr + x + (y * pitch)]
152 = (clicked ? fgColor : (inside ? 0x43F0 : bgColor));
157 class Window: public Element
160 Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): /*clicked(false),
161 inside(false),*/ fgColor(0x4FF0), bgColor(0xFE10)
162 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
163 virtual void HandleKey(SDLKey key) {}
164 virtual void HandleMouseMove(uint32 x, uint32 y);
165 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
166 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
167 void AddElement(Element * e);
170 // bool clicked, inside;
171 uint16 fgColor, bgColor;
172 vector<Element *> list;
175 void Window::HandleMouseMove(uint32 x, uint32 y)
177 // Handle the items this window contains...
178 for(uint32 i=0; i<list.size(); i++)
179 // Make coords relative to upper right corner of this window...
180 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
183 void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
185 // Handle the items this window contains...
186 for(uint32 i=0; i<list.size(); i++)
187 // Make coords relative to upper right corner of this window...
188 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
191 void Window::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
193 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
195 for(uint32 y=0; y<extents.h; y++)
197 for(uint32 x=0; x<extents.w; x++)
199 // Doesn't clip in y axis! !!! FIX !!!
200 if (extents.x + x < pitch)
201 screenBuffer[addr + x + (y * pitch)] = bgColor;
205 // Handle the items this window contains...
206 for(uint32 i=0; i<list.size(); i++)
207 list[i]->Draw(extents.x, extents.y);
210 void Window::AddElement(Element * e)
218 void (* action)(void);
221 NameAction(string n, void (* a)(void) = NULL, bool w = false): name(n), action(a),
228 MenuItems(): charLength(0) {}
231 vector<NameAction> item;
236 class Menu: public Element
239 Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 8,
240 uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F,
241 uint16 bgch = 0x1CFF): clicked(false), inside(0), fgColor(fgc), bgColor(bgc),
242 fgColorHL(fgch), bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1)
243 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
244 virtual void HandleKey(SDLKey key);
245 virtual void HandleMouseMove(uint32 x, uint32 y);
246 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
247 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
248 void Add(MenuItems mi);
253 uint16 fgColor, bgColor, fgColorHL, bgColorHL;
254 int menuChosen, menuItemChosen;
257 vector<MenuItems> itemList;
260 void Menu::HandleKey(SDLKey Key)
264 void Menu::HandleMouseMove(uint32 x, uint32 y)
270 // Find out *where* we are inside the menu bar
271 uint32 xpos = extents.x;
273 for(uint32 i=0; i<itemList.size(); i++)
275 uint32 width = (itemList[i].title.length() + 2) * 8;
277 if (x >= xpos && x < xpos + width)
288 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
290 if (inside && mouseDown)
291 clicked = true, menuChosen = inside - 1;
293 if (!inside && mouseDown)
294 clicked = false, menuChosen = -1;
297 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
299 uint32 xpos = extents.x + offsetX;
301 for(uint32 i=0; i<itemList.size(); i++)
303 uint16 color1 = fgColor, color2 = bgColor;
304 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
305 color1 = fgColorHL, color2 = bgColorHL;
307 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
308 " %s ", itemList[i].title.c_str());
309 xpos += (itemList[i].title.length() + 2) * 8;
315 // menuItemChosen = -1;
316 uint32 ypos = extents.y + 9;
318 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
320 uint16 color1 = fgColor, color2 = bgColor;
323 // if (((uint32)mouseX >= menuXPos && (uint32)mouseX < menuXPos + (length + 2) * 8)
324 // && mouseY >= (extents.y + 9 + i * 8) && mouseY < (extents.y + 9 + (i + 1) * 8))
325 // color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
327 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
328 color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
329 itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
335 void Menu::Add(MenuItems mi)
337 for(uint32 i=0; i<mi.item.size(); i++)
338 if (mi.item[i].name.length() > mi.charLength)
339 mi.charLength = mi.item[i].name.length();
341 // Set extents here as well...
342 mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + 9;
343 mi.extents.w = (mi.charLength + 2) * 8, mi.extents.h = mi.item.size() * 8;
345 itemList.push_back(mi);
346 extents.w += (mi.title.length() + 2) * 8;
349 class RootWindow: public Window
352 RootWindow(Menu * m, Window * w = NULL): menu(m), window(w) {}
353 //Do we even need to care about this crap?
354 // { extents.x = extents.y = 0, extents.w = 320, extents.h = 240; }
355 virtual void HandleKey(SDLKey key) {}
356 virtual void HandleMouseMove(uint32 x, uint32 y) {}
357 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
358 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) {}
363 int16 * rootImage[1280 * 240 * 2];
369 // GUI stuff--it's not crunchy, it's GUI! ;-)
374 SDL_ShowCursor(SDL_DISABLE);
375 SDL_GetMouseState(&mouseX, &mouseY);
383 // Draw text at the given x/y coordinates. Can invert text as well.
385 void DrawString(int16 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
391 vsprintf(string, text, arg);
394 uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
395 uint32 length = strlen(string), address = x + (y * pitch);
397 for(uint32 i=0; i<length; i++)
399 uint32 fontAddr = (uint32)string[i] * 64;
401 for(uint32 yy=0; yy<8; yy++)
403 for(uint32 xx=0; xx<8; xx++)
405 if ((font1[fontAddr] && !invert) || (!font1[fontAddr] && invert))
406 *(screen + address + xx + (yy * pitch)) = 0xFE00;
416 // Draw text at the given x/y coordinates, using FG/BG colors.
418 void DrawStringOpaque(int16 * screen, uint32 x, uint32 y, uint16 color1, uint16 color2, const char * text, ...)
424 vsprintf(string, text, arg);
427 uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
428 uint32 length = strlen(string), address = x + (y * pitch);
430 for(uint32 i=0; i<length; i++)
432 uint32 fontAddr = (uint32)string[i] * 64;
434 for(uint32 yy=0; yy<8; yy++)
436 for(uint32 xx=0; xx<8; xx++)
438 *(screen + address + xx + (yy * pitch)) = (font1[fontAddr] ? color1 : color2);
448 // Draw text at the given x/y coordinates. Can invert text as well.
450 void DrawStringTrans(int16 * screen, uint32 x, uint32 y, uint16 color, uint8 trans, const char * text, ...)
456 vsprintf(string, text, arg);
459 uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
460 uint32 length = strlen(string), address = x + (y * pitch);
462 for(uint32 i=0; i<length; i++)
464 uint32 fontAddr = (uint32)string[i] * 64;
466 for(uint32 yy=0; yy<8; yy++)
468 for(uint32 xx=0; xx<8; xx++)
472 uint16 existingColor = *(screen + address + xx + (yy * pitch));
474 uint8 eRed = (existingColor >> 10) & 0x1F,
475 eGreen = (existingColor >> 5) & 0x1F,
476 eBlue = existingColor & 0x1F,
477 //This could be done ahead of time, instead of on each pixel...
478 nRed = (color >> 10) & 0x1F,
479 nGreen = (color >> 5) & 0x1F,
480 nBlue = color & 0x1F;
482 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
483 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
484 //because dividing by 32 is faster than dividing by 31!
485 uint8 invTrans = 32 - trans;
486 uint16 bRed = (eRed * trans + nRed * invTrans) / 32;
487 uint16 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
488 uint16 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
490 uint16 blendedColor = (bRed << 10) | (bGreen << 5) | bBlue;
492 *(screen + address + xx + (yy * pitch)) = blendedColor;
506 enum { GUI_TOP_MENU, GUI_MENU_CLICKED, GUI_WINDOW };
509 extern int16 * backbuffer;
512 int32 menuChosen = -1;
514 int32 menuItemChosen = -1;
515 uint32 GUIState = GUI_TOP_MENU;
517 Element::SetScreenAndPitch(backbuffer, GetSDLScreenPitch() / 2);
519 Button closeButton(45, 90, 16, 16);
520 Window someWindow(15, 16, 60, 60);
521 Button button1(50, 1, 9, 9), button2(10, 10, 8, 8), button3(25, 48, 15, 8);
522 someWindow.AddElement(&button1);
523 someWindow.AddElement(&button2);
524 someWindow.AddElement(&button3);
527 Menu mainMenu(0, 160);
529 mi.item.push_back(NameAction("Load...", LoadROM));
530 mi.item.push_back(NameAction("Reset"));
531 mi.item.push_back(NameAction("Run", RunEmu));
532 mi.item.push_back(NameAction(""));
533 mi.item.push_back(NameAction("Quit", Quit));
535 mi.title = "Settings";
538 mi.title = "Options";
541 bool showMouse = true;
543 //This is crappy!!! !!! FIX !!!
548 while (SDL_PollEvent(&event))
550 if (event.type == SDL_ACTIVEEVENT)
552 if (event.active.state == SDL_APPMOUSEFOCUS)
553 showMouse = (event.active.gain ? true : false);
555 if (event.type == SDL_KEYDOWN)
557 // if (event.key.keysym.sym == SDLK_ESCAPE)
561 else if (event.type == SDL_MOUSEMOTION)
563 mouseX = event.motion.x, mouseY = event.motion.y;
566 mouseX /= 2, mouseY /= 2;
568 closeButton.HandleMouseMove(mouseX, mouseY);
569 someWindow.HandleMouseMove(mouseX, mouseY);
570 mainMenu.HandleMouseMove(mouseX, mouseY);
572 else if (event.type == SDL_MOUSEBUTTONDOWN)
574 uint32 mx = event.button.x, my = event.button.y;
578 // Handle that click!
579 if (GUIState == GUI_TOP_MENU)
581 if (menuChosen != -1)
582 GUIState = GUI_MENU_CLICKED;
584 else if (GUIState == GUI_MENU_CLICKED)
586 if (menuItemChosen != -1)
588 // GUIState = GUI_WINDOW;
589 if (subMenuAction[menuChosen][menuItemChosen] != NULL)
590 subMenuAction[menuChosen][menuItemChosen]();
593 GUIState = GUI_TOP_MENU;
596 closeButton.HandleMouseButton(mx, my, true);
597 someWindow.HandleMouseButton(mx, my, true);
598 mainMenu.HandleMouseButton(mx, my, true);
600 else if (event.type == SDL_MOUSEBUTTONUP)
602 uint32 mx = event.button.x, my = event.button.y;
607 closeButton.HandleMouseButton(mx, my, false);
608 someWindow.HandleMouseButton(mx, my, false);
609 mainMenu.HandleMouseButton(mx, my, false);
614 // The way we do things here is kinda stupid (redrawing the screen every frame), but
615 // it's simple. Perhaps there may be a reason down the road to be more selective with
616 // our clearing, but for now, this will suffice.
617 memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
623 // We always draw the top level menu...
624 if (GUIState == GUI_TOP_MENU)
628 for(uint32 i=0; i<NUM_MENU_ITEMS; i++)
630 uint16 colorFG = 0x1CFF, colorBG = 0x000F;
631 uint32 length = strlen(menu[i]) + 2;
633 if (((uint32)mouseX >= xpos && (uint32)mouseX < xpos + length * 8)
635 colorFG = 0x421F, colorBG = 0x1CFF, menuChosen = i, menuXPos = xpos;
637 if (GUIState != GUI_TOP_MENU && i == (uint32)menuChosen)
638 colorFG = 0x421F, colorBG = 0x1CFF;
639 // BG: 0 00011 00011 11111 -> 0000 1100 0111 1111
640 // FG: 0 10000 10000 11111 -> 0100 0010 0001 1111
641 DrawStringOpaque(backbuffer, xpos, 0, colorFG, colorBG, " %s ", menu[i]);
645 // We don't always draw the submenus...
646 if (GUIState == GUI_MENU_CLICKED)
650 for(int i=0; i<subMenuNumItems[menuChosen]; i++)
651 if (strlen(subMenu[menuChosen][i]) > length)
652 length = strlen(subMenu[menuChosen][i]);
655 for(int i=0; i<subMenuNumItems[menuChosen]; i++)
657 uint16 colorFG = 0x1CFF, colorBG = 0x000F;
659 if (((uint32)mouseX >= menuXPos && (uint32)mouseX < menuXPos + (length + 2) * 8)
660 && mouseY >= (9 + i * 8) && mouseY < (9 + (i + 1) * 8))
661 colorFG = 0x421F, colorBG = 0x1CFF, menuItemChosen = i;
663 DrawStringOpaque(backbuffer, menuXPos, ypos, colorFG, colorBG, " %-*.*s ", length, length, subMenu[menuChosen][i]);
667 // Windows? Isn't that an illegal monopoly or something? ;-)
668 else if (GUIState == GUI_WINDOW)
673 DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic);
683 // GUI "action" functions
691 //This is crappy... !!! FIX !!!
692 extern int16 * backbuffer;
693 extern bool finished;
695 uint32 nFrame = 0, nFrameskip = 0;
696 uint32 totalFrames = 0;
698 bool showMessage = true;
699 uint32 showMsgFrames = 60;
700 uint8 transparency = 0;
704 // Set up new backbuffer with new pixels and data
705 JaguarExecute(backbuffer, true);
707 //WriteLog("Frame #%u...\n", totalFrames);
708 //extern bool doDSPDis;
709 //if (totalFrames == 373)
712 // Some QnD GUI stuff here...
715 extern uint32 gpu_pc, dsp_pc;
716 DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
717 DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
722 DrawStringTrans(backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
724 if (showMsgFrames == 0)
728 if (transparency == 33)
736 if (nFrame == nFrameskip)
750 WriteLog("GUI: Quitting due to user request.\n");
757 extern int16 * backbuffer;
759 uint16 * bgSave = (uint16 *)malloc(tom_getVideoModeWidth() * 240 * 2);
760 memcpy(bgSave, backbuffer, tom_getVideoModeWidth() * 240 * 2);
765 while (SDL_PollEvent(&event))
767 if (event.type == SDL_KEYDOWN)
769 if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_RETURN)
772 else if (event.type == SDL_MOUSEMOTION)
774 mouseX = event.motion.x, mouseY = event.motion.y;
776 mouseX /= 2, mouseY /= 2;
778 else if (event.type == SDL_MOUSEBUTTONDOWN)
780 uint32 mx = event.button.x, my = event.button.y;
788 memcpy(backbuffer, bgSave, tom_getVideoModeWidth() * 240 * 2);
790 DrawStringOpaque(backbuffer, 64, 64, 0x1CFF, 0x000F, " ");
791 DrawStringOpaque(backbuffer, 64, 72, 0x1CFF, 0x000F, " Virtual Jaguar by JLH & crew ");
792 DrawStringOpaque(backbuffer, 64, 80, 0x1CFF, 0x000F, " ");
794 DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic);
805 // Uses zero as transparent color
807 void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap)
809 uint16 width = bitmap[0], height = bitmap[1];
812 uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
813 uint32 address = x + (y * pitch);
815 for(int yy=0; yy<height; yy++)
817 for(int xx=0; xx<width; xx++)
819 if (*bitmap && x + xx < pitch) // NOTE: Still doesn't clip the Y val...
820 *(screen + address + xx + (yy * pitch)) = *bitmap;
827 // Very very crude GUI file selector
829 bool UserSelectFile(char * path, char * filename)
834 extern int16 * backbuffer;
835 vector<string> fileList;
837 // Read in the candidate files from the directory pointed to by "path"
839 DIR * dp = opendir(path);
842 while ((de = readdir(dp)) != NULL)
844 char * ext = strrchr(de->d_name, '.');
847 if (stricmp(ext, ".zip") == 0 || stricmp(ext, ".jag") == 0)
848 fileList.push_back(string(de->d_name));
853 // Main GUI selection loop
855 uint32 cursor = 0, startFile = 0;
857 if (fileList.size() > 1) // Only go GUI if more than one possibility!
859 sort(fileList.begin(), fileList.end());
862 uint32 limit = (fileList.size() > 30 ? 30 : fileList.size());
865 // Ensure that the GUI is drawn before any user input...
866 event.type = SDL_USEREVENT;
867 SDL_PushEvent(&event);
871 while (SDL_PollEvent(&event))
873 if (event.type == SDL_KEYDOWN)
875 SDLKey key = event.key.keysym.sym;
877 if (key == SDLK_DOWN)
879 if (cursor != limit - 1) // Cursor is within its window
881 else // Otherwise, scroll the window...
883 if (cursor + startFile != fileList.size() - 1)
897 if (key == SDLK_PAGEDOWN)
899 if (cursor != limit - 1)
904 if (startFile > fileList.size() - limit)
905 startFile = fileList.size() - limit;
908 if (key == SDLK_PAGEUP)
914 if (startFile < limit)
920 if (key == SDLK_RETURN)
922 if (key == SDLK_ESCAPE)
924 WriteLog("GUI: Aborting VJ by user request.\n");
925 return false; // Bail out!
927 if (key >= SDLK_a && key <= SDLK_z)
929 // Advance cursor to filename with first letter pressed...
930 uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
932 for(uint32 i=0; i<fileList.size(); i++)
934 if ((fileList[i][0] & 0xDF) == which)
936 cursor = i - startFile;
937 if (i > startFile + limit - 1)
938 startFile = i - limit + 1,
948 else if (event.type == SDL_MOUSEMOTION)
950 mouseX = event.motion.x, mouseY = event.motion.y;
952 mouseX /= 2, mouseY /= 2;
954 else if (event.type == SDL_MOUSEBUTTONDOWN)
956 uint32 mx = event.button.x, my = event.button.y;
963 // memset(backbuffer, 0x11, tom_getVideoModeWidth() * tom_getVideoModeHeight() * 2);
964 memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
966 for(uint32 i=0; i<limit; i++)
968 // Clip our strings to guarantee that they fit on the screen...
969 // (and strip off the extension too)
970 string s(fileList[startFile + i], 0, fileList[startFile + i].length() - 4);
973 DrawString(backbuffer, 0, i*8, (cursor == i ? true : false), " %s ", s.c_str());
976 DrawTransparentBitmap(backbuffer, mouseX, mouseY, mousePic);
983 strcpy(filename, path);
985 if (strlen(path) > 0)
986 if (path[strlen(path) - 1] != '/')
987 strcat(filename, "/");
989 strcat(filename, fileList[startFile + cursor].c_str());