4 // Graphical User Interface support
11 #include <ctype.h> // For toupper()
14 #include <sys/types.h> // For MacOS <dirent.h> dependency
21 #include "font14pt.h" // Also 15, 16, 17, 18
22 #include "guielements.h"
25 #include "sdlemu_opengl.h"
30 using namespace std; // For STL stuff
32 // Private function prototypes
34 class Window; // Forward declaration...
36 //void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha = NULL);
37 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap);
38 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
39 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
40 //Should call this FillScreenRectangle with a number representing the RGBA value to fill. !!! FIX !!!
41 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h);
42 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color);
43 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 opacity, const char * text, ...);
44 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...);
45 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
46 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...);
47 Window * LoadROM(void);
48 Window * ResetJaguar(void);
49 Window * ResetJaguarCD(void);
50 Window * RunEmu(void);
53 Window * MiscOptions(void);
55 // Local global variables
58 bool exitGUI = false; // GUI (emulator) done variable
59 int mouseX = 0, mouseY = 0;
60 uint32 background[1280 * 256]; // GUI background buffer
61 bool showMessage = false;
62 //uint32 showMessageTimeout;
63 //char messageBuffer[200];
64 bool finished = false;
66 const char separator[] = "--------------------------------------------------------";
69 // Case insensitive string compare function
70 // Taken straight out of Thinking In C++ by Bruce Eckel. Thanks Bruce!
73 int stringCmpi(const string &s1, const string &s2)
75 // Select the first element of each string:
76 string::const_iterator p1 = s1.begin(), p2 = s2.begin();
78 while (p1 != s1.end() && p2 != s2.end()) // Don�t run past the end
80 if (toupper(*p1) != toupper(*p2)) // Compare upper-cased chars
81 return (toupper(*p1) < toupper(*p2) ? -1 : 1);// Report which was lexically greater
87 // If they match up to the detected eos, say which was longer. Return 0 if the same.
88 return s2.size() - s1.size();
95 enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN };
100 Element(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0)
101 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
102 virtual void HandleKey(SDLKey key) = 0; // These are "pure" virtual functions...
103 virtual void HandleMouseMove(uint32 x, uint32 y) = 0;
104 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0;
105 virtual void Draw(uint32, uint32) = 0;
106 virtual void Notify(Element *) = 0;
107 //Needed? virtual ~Element() = 0;
108 //We're not allocating anything in the base class, so the answer would be NO.
109 bool Inside(uint32 x, uint32 y);
111 // static void SetScreenAndPitch(int16 * s, uint32 p) { screenBuffer = s, pitch = p; }
112 static void SetScreenAndPitch(uint32 * s, uint32 p) { screenBuffer = s, pitch = p; }
117 // Class variables...
118 // static int16 * screenBuffer;
119 static uint32 * screenBuffer;
123 // Initialize class variables (Element)
124 //int16 * Element::screenBuffer = NULL;
125 uint32 * Element::screenBuffer = NULL;
126 uint32 Element::pitch = 0;
128 bool Element::Inside(uint32 x, uint32 y)
130 return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
131 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
139 class Button: public Element
142 Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
143 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
144 bgColor(0xFF00FF00), pic(NULL), elementToTell(NULL) {}
145 Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
146 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
147 bgColor(0xFF00FF00), pic(p), elementToTell(NULL) {}
148 // Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
149 Button(uint32 x, uint32 y, uint32 * p, uint32 * pH = NULL, uint32 * pD = NULL): Element(x, y, 0, 0),
150 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
151 bgColor(0xFF00FF00), pic(p), picHover(pH), picDown(pD), elementToTell(NULL)
152 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
153 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
154 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
155 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL) {}
156 Button(uint32 x, uint32 y, string s): Element(x, y, 0, FONT_HEIGHT),
157 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
158 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL)
159 { extents.w = s.length() * FONT_WIDTH; }
160 virtual void HandleKey(SDLKey key) {}
161 virtual void HandleMouseMove(uint32 x, uint32 y);
162 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
163 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
164 virtual void Notify(Element *) {}
165 bool ButtonClicked(void) { return activated; }
166 void SetNotificationElement(Element * e) { elementToTell = e; }
169 bool activated, clicked, inside;
170 uint32 fgColor, bgColor;
171 uint32 * pic, * picHover, * picDown;
173 Element * elementToTell;
176 void Button::HandleMouseMove(uint32 x, uint32 y)
178 inside = Inside(x, y);
181 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
188 if (clicked && !mouseDown)
190 clicked = false, activated = true;
192 // Send a message that we're activated (if there's someone to tell, that is)
194 elementToTell->Notify(this);
198 clicked = activated = false;
201 void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
203 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
205 if (text.length() > 0) // Simple text button
208 for(uint32 y=0; y<extents.h; y++)
210 for(uint32 x=0; x<extents.w; x++)
212 // Doesn't clip in y axis! !!! FIX !!!
213 if (extents.x + x < pitch)
214 screenBuffer[addr + x + (y * pitch)]
215 // = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
216 //43F0 -> 010000 11111 10000 -> 0100 0001 1111 1111 1000 0100 -> 41 FF 84
217 = (clicked && inside ? fgColor : (inside ? 0xFF84FF41 : bgColor));
221 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
223 else // Graphical button
225 uint32 * picToShow = pic;
227 if (picHover != NULL && inside && !clicked)
228 picToShow = picHover;
230 if (picDown != NULL && inside && clicked)
233 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, picToShow);
242 class PushButton: public Element
245 // Save state externally?
246 //We pass in a state variable if we want to track it externally, otherwise we use our own
247 //internal state var. Still need to do some kind of callback for pushbuttons that do things
248 //like change from fullscreen to windowed... !!! FIX !!!
251 // PushButton(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
252 // activated(false), clicked(false), inside(false), fgColor(0xFFFF),
253 // bgColor(0x03E0), pic(NULL), elementToTell(NULL) {}
254 // PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 8, 8), state(st),
255 // inside(false), text(s) { if (st == NULL) state = &internalState; }
256 PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 16, 16), state(st),
257 inside(false), text(s) { if (st == NULL) state = &internalState; }
258 /* Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
259 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
260 bgColor(0x03E0), pic(p), elementToTell(NULL) {}
261 Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
262 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
263 bgColor(0x03E0), pic(p), elementToTell(NULL)
264 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
265 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
266 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
267 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) {}
268 PushButton(uint32 x, uint32 y, string s): Element(x, y, 0, 8),
269 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
270 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL)
271 { extents.w = s.length() * 8; }*/
272 virtual void HandleKey(SDLKey key) {}
273 virtual void HandleMouseMove(uint32 x, uint32 y);
274 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
275 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
276 virtual void Notify(Element *) {}
277 // bool ButtonClicked(void) { return activated; }
278 // void SetNotificationElement(Element * e) { elementToTell = e; }
283 // bool activated, clicked, inside;
284 // uint16 fgColor, bgColor;
287 // Element * elementToTell;
291 void PushButton::HandleMouseMove(uint32 x, uint32 y)
293 inside = Inside(x, y);
296 void PushButton::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
298 if (inside && mouseDown)
303 if (clicked && !mouseDown)
305 clicked = false, activated = true;
307 // Send a message that we're activated (if there's someone to tell, that is)
309 elementToTell->Notify(this);
314 // clicked = activated = false;
317 void PushButton::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
319 /* uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
321 for(uint32 y=0; y<extents.h; y++)
323 for(uint32 x=0; x<extents.w; x++)
325 // Doesn't clip in y axis! !!! FIX !!!
326 if (extents.x + x < pitch)
327 screenBuffer[addr + x + (y * pitch)]
328 = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
333 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbDown);
335 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbUp);
337 if (text.length() > 0)
338 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text.c_str());
346 class SlideSwitch: public Element
349 // Save state externally?
350 //Seems to be handled the same as PushButton, but without sanity checks. !!! FIX !!!
353 SlideSwitch(uint32 x, uint32 y, bool * st, string s1, string s2): Element(x, y, 16, 32), state(st),
354 inside(false), text1(s1), text2(s2) {}
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);
359 virtual void Notify(Element *) {}
360 // bool ButtonClicked(void) { return activated; }
361 // void SetNotificationElement(Element * e) { elementToTell = e; }
366 // bool activated, clicked, inside;
367 // uint16 fgColor, bgColor;
370 // Element * elementToTell;
373 void SlideSwitch::HandleMouseMove(uint32 x, uint32 y)
375 inside = Inside(x, y);
378 void SlideSwitch::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
380 if (inside && mouseDown)
385 if (clicked && !mouseDown)
387 clicked = false, activated = true;
389 // Send a message that we're activated (if there's someone to tell, that is)
391 elementToTell->Notify(this);
396 // clicked = activated = false;
399 void SlideSwitch::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
401 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, (*state ? slideSwitchDown : slideSwitchUp));
403 if (text1.length() > 0)
404 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text1.c_str());
406 if (text2.length() > 0)
407 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY + 16, false, "%s", text2.c_str());
415 class Window: public Element
418 /* Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
419 fgColor(0x4FF0), bgColor(0xFE10)
420 { close = new Button(w - 8, 1, closeBox); list.push_back(close); }*/
421 Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0,
422 void (* f)(Element *) = NULL): Element(x, y, w, h),
423 // /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0x1E10),
424 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
425 //1E10 -> 000111 10000 10000 -> 0001 1111 1000 0100 1000 0100 -> 1F 84 84
426 /*clicked(false), inside(false),*/ fgColor(0xFF84FF4D), bgColor(0xFF84841F),
428 { close = new Button(w - (CLOSEBOX_WIDTH + 1), 1, closeBox, closeBoxHover, closeBoxDown);
429 list.push_back(close);
430 close->SetNotificationElement(this); }
432 virtual void HandleKey(SDLKey key);
433 virtual void HandleMouseMove(uint32 x, uint32 y);
434 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
435 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
436 virtual void Notify(Element * e);
437 void AddElement(Element * e);
438 // bool WindowActive(void) { return true; }//return !close->ButtonClicked(); }
441 // bool clicked, inside;
442 uint32 fgColor, bgColor;
443 void (* handler)(Element *);
445 //We have to use a list of Element *pointers* because we can't make a list that will hold
446 //all the different object types in the same list...
447 vector<Element *> list;
452 for(uint32 i=0; i<list.size(); i++)
457 void Window::HandleKey(SDLKey key)
459 if (key == SDLK_ESCAPE)
462 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
463 SDL_PushEvent(&event);
466 // Handle the items this window contains...
467 for(uint32 i=0; i<list.size(); i++)
468 // Make coords relative to upper right corner of this window...
469 list[i]->HandleKey(key);
472 void Window::HandleMouseMove(uint32 x, uint32 y)
474 // Handle the items this window contains...
475 for(uint32 i=0; i<list.size(); i++)
476 // Make coords relative to upper right corner of this window...
477 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
480 void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
482 // Handle the items this window contains...
483 for(uint32 i=0; i<list.size(); i++)
484 // Make coords relative to upper right corner of this window...
485 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
488 void Window::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
490 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
492 for(uint32 y=0; y<extents.h; y++)
494 for(uint32 x=0; x<extents.w; x++)
496 // Doesn't clip in y axis! !!! FIX !!!
497 if (extents.x + x < pitch)
498 screenBuffer[addr + x + (y * pitch)] = bgColor;
502 // Handle the items this window contains...
503 for(uint32 i=0; i<list.size(); i++)
504 list[i]->Draw(extents.x, extents.y);
507 void Window::AddElement(Element * e)
512 void Window::Notify(Element * e)
517 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
518 SDL_PushEvent(&event);
527 class Text: public Element
530 // Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
531 // fgColor(0x4FF0), bgColor(0xFE10) {}
532 // Text(uint32 x, uint32 y, string s, uint16 fg = 0x4FF0, uint16 bg = 0xFE10): Element(x, y, 0, 0),
533 // fgColor(fg), bgColor(bg), text(s) {}
534 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
535 //FE10 -> 111111 10000 10000 -> 1111 1111 1000 0100 1000 0100 -> FF 84 84
536 Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
537 fgColor(0xFF8484FF), bgColor(0xFF84FF4D) {}
538 Text(uint32 x, uint32 y, string s, uint32 fg = 0xFF8484FF, uint32 bg = 0xFF84FF4D):
539 Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s) {}
540 virtual void HandleKey(SDLKey key) {}
541 virtual void HandleMouseMove(uint32 x, uint32 y) {}
542 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
543 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
544 virtual void Notify(Element *) {}
547 uint32 fgColor, bgColor;
551 void Text::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
553 if (text.length() > 0)
554 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
555 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
560 // Static image class
563 class Image: public Element
566 Image(uint32 x, uint32 y, const void * img): Element(x, y, 0, 0), image(img) {}
567 virtual void HandleKey(SDLKey key) {}
568 virtual void HandleMouseMove(uint32 x, uint32 y) {}
569 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
570 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
571 virtual void Notify(Element *) {}
574 uint32 fgColor, bgColor;
578 void Image::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
581 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, image);
589 class TextEdit: public Element
592 TextEdit(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
593 fgColor(0xFF8484FF), bgColor(0xFF84FF4D), text(""), caretPos(0),
595 TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
596 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
597 caretPos(0), maxScreenSize(mss) {}
598 virtual void HandleKey(SDLKey key);
599 virtual void HandleMouseMove(uint32 x, uint32 y) {}
600 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
601 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
602 virtual void Notify(Element *) {}
605 uint32 fgColor, bgColor;
608 uint32 maxScreenSize;
611 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
612 void TextEdit::HandleKey(SDLKey key)
614 if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9) || key == SDLK_PERIOD
615 || key == SDLK_SLASH)
617 //Need to handle shift key as well...
618 text[caretPos++] = key;
621 else if (key == SDLK_BACKSPACE)
625 else if (key == SDLK_DELETE)
631 void TextEdit::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
633 if (text.length() > 0)
635 FillScreenRectangle(screenBuffer, extents.x + offsetX, extents.y + offsetY, FONT_WIDTH * maxScreenSize, FONT_HEIGHT, bgColor);
636 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
637 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
640 // Draw the caret (underscore? or vertical line?)
648 class ListBox: public Element
649 //class ListBox: public Window
652 // ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
653 ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);//: Window(x, y, w, h),
654 // windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8),
655 // elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
656 // downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) {}
657 virtual void HandleKey(SDLKey key);
658 virtual void HandleMouseMove(uint32 x, uint32 y);
659 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
660 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
661 virtual void Notify(Element * e);
662 void SetNotificationElement(Element * e) { elementToTell = e; }
663 void AddItem(string s);
664 string GetSelectedItem(void);
668 uint32 windowPtr, cursor, limit;
669 uint32 charWidth, charHeight; // Box width/height in characters
670 Element * elementToTell;
671 Button upArrow, downArrow, upArrow2;
675 uint32 yRelativePoint;
678 ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h),
679 thumbClicked(false), windowPtr(0), cursor(0), limit(0), charWidth((w / FONT_WIDTH) - 1),
680 charHeight(h / FONT_HEIGHT), elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
681 downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox)
683 upArrow.SetNotificationElement(this);
684 downArrow.SetNotificationElement(this);
685 upArrow2.SetNotificationElement(this);
686 extents.w -= 8; // Make room for scrollbar...
689 void ListBox::HandleKey(SDLKey key)
691 if (key == SDLK_DOWN)
693 if (cursor != limit - 1) // Cursor is within its window
695 else // Otherwise, scroll the window...
697 if (cursor + windowPtr != item.size() - 1)
701 else if (key == SDLK_UP)
711 else if (key == SDLK_PAGEDOWN)
713 if (cursor != limit - 1)
718 if (windowPtr > item.size() - limit)
719 windowPtr = item.size() - limit;
722 else if (key == SDLK_PAGEUP)
728 if (windowPtr < limit)
734 else if (key >= SDLK_a && key <= SDLK_z)
736 // Advance cursor to filename with first letter pressed...
737 uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
739 for(uint32 i=0; i<item.size(); i++)
741 if ((item[i][0] & 0xDF) == which)
743 cursor = i - windowPtr;
744 if (i > windowPtr + limit - 1)
745 windowPtr = i - limit + 1, cursor = limit - 1;
747 windowPtr = i, cursor = 0;
754 void ListBox::HandleMouseMove(uint32 x, uint32 y)
756 upArrow.HandleMouseMove(x - extents.x, y - extents.y);
757 downArrow.HandleMouseMove(x - extents.x, y - extents.y);
758 upArrow2.HandleMouseMove(x - extents.x, y - extents.y);
762 uint32 sbHeight = extents.h - 24,
763 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight);
765 //yRelativePoint is the spot on the thumb where we clicked...
766 int32 newThumbStart = y - yRelativePoint;
768 if (newThumbStart < 0)
771 if ((uint32)newThumbStart > sbHeight - thumb)
772 newThumbStart = sbHeight - thumb;
774 windowPtr = (uint32)(((float)newThumbStart / (float)sbHeight) * (float)item.size());
775 //Check for cursor bounds as well... Or do we need to???
776 //Actually, we don't...!
780 void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
782 if (Inside(x, y) && mouseDown)
784 // Why do we have to do this??? (- extents.y?)
785 // I guess it's because only the Window class has offsetting implemented... !!! FIX !!!
786 // cursor = (y - extents.y) / 8;
787 cursor = (y - extents.y) / FONT_HEIGHT;
790 // Check for a hit on the scrollbar...
791 if (x > (uint32)(extents.x + extents.w) && x <= (uint32)(extents.x + extents.w + 8)
792 && y > (uint32)(extents.y + 8) && y <= (uint32)(extents.y + extents.h - 16))
796 // This shiaut should be calculated in AddItem(), not here... (or in Draw() for that matter)
797 uint32 sbHeight = extents.h - 24,
798 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
799 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
801 // Did we hit the thumb?
802 if (y >= (extents.y + 8 + thumbStart) && y < (extents.y + 8 + thumbStart + thumb))
803 thumbClicked = true, yRelativePoint = y - thumbStart;
805 //Seems that this is useless--never reached except in rare cases and that the code outside is
808 // thumbClicked = false;
812 thumbClicked = false;
814 upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
815 downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
816 upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
819 void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
821 for(uint32 i=0; i<limit; i++)
823 // Strip off the extension
824 // (extension stripping should be an option, not default!)
825 string s(item[windowPtr + i], 0, item[windowPtr + i].length() - 4);
826 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*8,
827 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*FONT_HEIGHT,
828 (cursor == i ? true : false), "%-*.*s", charWidth, charWidth, s.c_str());
831 upArrow.Draw(extents.x + offsetX, extents.y + offsetY);
832 downArrow.Draw(extents.x + offsetX, extents.y + offsetY);
833 upArrow2.Draw(extents.x + offsetX, extents.y + offsetY);
835 uint32 sbHeight = extents.h - 24,
836 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
837 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
839 for(uint32 y=extents.y+offsetY+8; y<extents.y+offsetY+extents.h-16; y++)
841 // for(uint32 x=extents.x+offsetX+extents.w-8; x<extents.x+offsetX+extents.w; x++)
842 for(uint32 x=extents.x+offsetX+extents.w; x<extents.x+offsetX+extents.w+8; x++)
844 if (y >= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8))
845 // screenBuffer[x + (y * pitch)] = (thumbClicked ? 0x458E : 0xFFFF);
846 //458E -> 01 0001 0 1100 0 1110 -> 0100 0101 0110 0011 0111 0011 -> 45 63 73
847 screenBuffer[x + (y * pitch)] = (thumbClicked ? 0xFF736345 : 0xFFFFFFFF);
849 // screenBuffer[x + (y * pitch)] = 0x0200;
850 //0200 -> 000000 10000 00000 -> 00 1000 0100 00
851 screenBuffer[x + (y * pitch)] = 0xFF008400;
856 void ListBox::Notify(Element * e)
858 if (e == &upArrow || e == &upArrow2)
864 if (cursor < limit - 1)
868 else if (e == &downArrow)
870 if (windowPtr < item.size() - limit)
880 void ListBox::AddItem(string s)
882 // Do a simple insertion sort
883 bool inserted = false;
885 for(vector<string>::iterator i=item.begin(); i<item.end(); i++)
887 if (stringCmpi(s, *i) == -1)
898 limit = (item.size() > charHeight ? charHeight : item.size());
901 string ListBox::GetSelectedItem(void)
903 return item[windowPtr + cursor];
911 class FileList: public Window
914 FileList(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);
915 virtual ~FileList() {}
916 virtual void HandleKey(SDLKey key);
917 virtual void HandleMouseMove(uint32 x, uint32 y) { Window::HandleMouseMove(x, y); }
918 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) { Window::HandleMouseButton(x, y, mouseDown); }
919 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) { Window::Draw(offsetX, offsetY); }
920 virtual void Notify(Element * e);
927 //Need 4 buttons, one scrollbar...
928 FileList::FileList(uint32 x, uint32 y, uint32 w, uint32 h): Window(x, y, w, h)
930 files = new ListBox(8, 8, w - 16, h - 32);
932 load = new Button(8, h - 16, " Load ");
934 load->SetNotificationElement(this);
936 #warning !!! FIX !!! Directory might not exist--this shouldn't cause VJ to crash!
937 DIR * dp = opendir(vjs.ROMPath);
942 while ((de = readdir(dp)) != NULL)
944 char * ext = strrchr(de->d_name, '.');
947 if (strcasecmp(ext, ".zip") == 0 || strcasecmp(ext, ".j64") == 0
948 || strcasecmp(ext, ".abs") == 0 || strcasecmp(ext, ".jag") == 0
949 || strcasecmp(ext, ".rom") == 0)
950 files->AddItem(string(de->d_name));
957 //Give a diagnostic message here so that the (l)user can figure out what went wrong. !!! FIX !!!
961 void FileList::HandleKey(SDLKey key)
963 if (key == SDLK_RETURN)
966 Window::HandleKey(key);
969 void FileList::Notify(Element * e)
973 char filename[MAX_PATH];
974 strcpy(filename, vjs.ROMPath);
976 if (strlen(filename) > 0)
977 if (filename[strlen(filename) - 1] != '/')
978 strcat(filename, "/");
980 strcat(filename, files->GetSelectedItem().c_str());
982 // uint32 romSize = JaguarLoadROM(jaguar_mainRom, filename);
983 // JaguarLoadCart(jaguar_mainRom, filename);
984 if (JaguarLoadFile(filename))
987 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
988 SDL_PushEvent(&event);
990 event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
991 event.user.data1 = (void *)ResetJaguar;
992 SDL_PushEvent(&event);
997 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
998 SDL_PushEvent(&event);
1000 // Handle the error, but don't run...
1001 // Tell the user that we couldn't run their file for some reason... !!! FIX !!!
1002 //how to kludge: Make a function like ResetJaguar which creates the dialog window
1011 // Menu class & supporting structs/classes
1017 Window * (* action)(void);
1020 NameAction(string n, Window * (* a)(void) = NULL, SDLKey k = SDLK_UNKNOWN): name(n),
1021 action(a), hotKey(k) {}
1027 MenuItems(): charLength(0) {}
1028 bool Inside(uint32 x, uint32 y)
1029 { return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
1030 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false); }
1033 vector<NameAction> item;
1038 class Menu: public Element
1041 // 1CFF -> 0 001 11 00 111 1 1111
1042 // 421F -> 0 100 00 10 000 1 1111
1043 Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = FONT_HEIGHT,
1044 /* uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F,
1045 uint16 bgch = 0x1CFF): Element(x, y, w, h), activated(false), clicked(false),*/
1046 /* uint32 fgc = 0xFF3F3F00, uint32 bgc = 0x7F000000, uint32 fgch = 0xFF878700,
1047 uint32 bgch = 0xFF3F3F00): Element(x, y, w, h), activated(false), clicked(false),*/
1048 /* uint32 fgc = 0xFFFF3F3F, uint32 bgc = 0xFF7F0000, uint32 fgch = 0xFFFF8787,
1049 uint32 bgch = 0xFFFF3F3F): Element(x, y, w, h), activated(false), clicked(false),*/
1050 uint32 fgc = 0xFF7F0000, uint32 bgc = 0xFFFF3F3F, uint32 fgch = 0xFFFF3F3F,
1051 uint32 bgch = 0xFFFF8787): Element(x, y, w, h), activated(false), clicked(false),
1052 inside(0), insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch),
1053 bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1) {}
1054 virtual void HandleKey(SDLKey key);
1055 virtual void HandleMouseMove(uint32 x, uint32 y);
1056 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
1057 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
1058 virtual void Notify(Element *) {}
1059 void Add(MenuItems mi);
1062 bool activated, clicked;
1063 uint32 inside, insidePopup;
1064 // uint16 fgColor, bgColor, fgColorHL, bgColorHL;
1065 uint32 fgColor, bgColor, fgColorHL, bgColorHL;
1066 int menuChosen, menuItemChosen;
1069 vector<MenuItems> itemList;
1072 void Menu::HandleKey(SDLKey key)
1074 for(uint32 i=0; i<itemList.size(); i++)
1076 for(uint32 j=0; j<itemList[i].item.size(); j++)
1078 if (itemList[i].item[j].hotKey == key)
1081 event.type = SDL_USEREVENT;
1082 event.user.code = MENU_ITEM_CHOSEN;
1083 event.user.data1 = (void *)itemList[i].item[j].action;
1084 SDL_PushEvent(&event);
1086 clicked = false, menuChosen = menuItemChosen = -1;
1093 void Menu::HandleMouseMove(uint32 x, uint32 y)
1095 inside = insidePopup = 0;
1099 // Find out *where* we are inside the menu bar
1100 uint32 xpos = extents.x;
1102 for(uint32 i=0; i<itemList.size(); i++)
1104 uint32 width = (itemList[i].title.length() + 2) * FONT_WIDTH;
1106 if (x >= xpos && x < xpos + width)
1117 if (!Inside(x, y) && !clicked)
1122 if (itemList[menuChosen].Inside(x, y) && clicked)
1124 insidePopup = ((y - itemList[menuChosen].extents.y) / FONT_HEIGHT) + 1;
1125 menuItemChosen = insidePopup - 1;
1129 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1138 menuChosen = -1; // clicked is already false...!
1141 else // clicked == true
1143 if (insidePopup && !mouseDown) // I.e., mouse-button-up
1146 if (itemList[menuChosen].item[menuItemChosen].action != NULL)
1148 // itemList[menuChosen].item[menuItemChosen].action();
1150 event.type = SDL_USEREVENT;
1151 event.user.code = MENU_ITEM_CHOSEN;
1152 event.user.data1 = (void *)itemList[menuChosen].item[menuItemChosen].action;
1153 SDL_PushEvent(&event);
1155 clicked = false, menuChosen = menuItemChosen = -1;
1158 while (SDL_PollEvent(&event)); // Flush the event queue...
1159 event.type = SDL_MOUSEMOTION;
1161 SDL_GetMouseState(&mx, &my);
1162 event.motion.x = mx, event.motion.y = my;
1163 SDL_PushEvent(&event); // & update mouse position...!
1167 if (!inside && !insidePopup && mouseDown)
1168 clicked = false, menuChosen = menuItemChosen = -1;
1172 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1174 uint32 xpos = extents.x + offsetX;
1176 for(uint32 i=0; i<itemList.size(); i++)
1178 // uint16 color1 = fgColor, color2 = bgColor;
1179 uint32 color1 = fgColor, color2 = bgColor;
1180 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
1181 color1 = fgColorHL, color2 = bgColorHL;
1183 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
1184 " %s ", itemList[i].title.c_str());
1185 xpos += (itemList[i].title.length() + 2) * FONT_WIDTH;
1188 // Draw sub menu (but only if active)
1191 uint32 ypos = extents.y + FONT_HEIGHT + 1;
1193 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
1195 // uint16 color1 = fgColor, color2 = bgColor;
1196 uint32 color1 = fgColor, color2 = bgColor;
1198 if (insidePopup == i + 1)
1199 color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
1201 if (itemList[menuChosen].item[i].name.length() > 0)
1202 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1203 color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
1204 itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
1206 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1207 fgColor, bgColor, "%.*s", itemList[menuChosen].charLength + 2, separator);
1209 ypos += FONT_HEIGHT;
1214 void Menu::Add(MenuItems mi)
1216 for(uint32 i=0; i<mi.item.size(); i++)
1217 if (mi.item[i].name.length() > mi.charLength)
1218 mi.charLength = mi.item[i].name.length();
1220 // Set extents here as well...
1221 mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + FONT_HEIGHT + 1;
1222 mi.extents.w = (mi.charLength + 2) * FONT_WIDTH, mi.extents.h = mi.item.size() * FONT_HEIGHT;
1224 itemList.push_back(mi);
1225 extents.w += (mi.title.length() + 2) * FONT_WIDTH;
1229 //Do we even *need* this?
1230 //Doesn't seem like it...
1231 /*class RootWindow: public Window
1234 RootWindow(Menu * m, Window * w = NULL): menu(m), window(w) {}
1235 //Do we even need to care about this crap?
1236 // { extents.x = extents.y = 0, extents.w = 320, extents.h = 240; }
1237 virtual void HandleKey(SDLKey key) {}
1238 virtual void HandleMouseMove(uint32 x, uint32 y) {}
1239 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
1240 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) {}
1241 virtual void Notify(Element *) {}
1246 int16 * rootImage[1280 * 240 * 2];
1251 // Draw text at the given x/y coordinates. Can invert text as well.
1253 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
1258 va_start(arg, text);
1259 vsprintf(string, text, arg);
1262 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1263 uint32 length = strlen(string), address = x + (y * pitch);
1265 uint32 color1 = 0x0080FF;
1266 uint8 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1267 uint8 xorMask = (invert ? 0xFF : 0x00);
1269 for(uint32 i=0; i<length; i++)
1271 uint8 c = string[i];
1272 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * FONT_WIDTH * FONT_HEIGHT;
1274 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1276 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1278 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1280 uint8 eBlue = (existingColor >> 16) & 0xFF,
1281 eGreen = (existingColor >> 8) & 0xFF,
1282 eRed = existingColor & 0xFF;
1284 uint8 trans = font2[fontAddr] ^ xorMask;
1285 uint8 invTrans = trans ^ 0xFF;
1287 uint32 bRed = (eRed * invTrans + nRed * trans) / 255,
1288 bGreen = (eGreen * invTrans + nGreen * trans) / 255,
1289 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1291 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1296 address += FONT_WIDTH;
1301 // Draw text at the given x/y coordinates, using FG/BG colors.
1303 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...)
1308 va_start(arg, text);
1309 vsprintf(string, text, arg);
1312 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1313 uint32 length = strlen(string), address = x + (y * pitch);
1315 uint8 eBlue = (color2 >> 16) & 0xFF, eGreen = (color2 >> 8) & 0xFF, eRed = color2 & 0xFF,
1316 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1318 for(uint32 i=0; i<length; i++)
1320 uint8 c = string[i];
1321 c = (c < 32 ? 0 : c - 32);
1322 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1324 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1326 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1328 uint8 trans = font2[fontAddr++];
1329 uint8 invTrans = trans ^ 0xFF;
1331 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1332 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1333 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1335 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1339 address += FONT_WIDTH;
1344 // Draw text at the given x/y coordinates with transparency (0 is fully opaque, 32 is fully transparent).
1346 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 trans, const char * text, ...)
1351 va_start(arg, text);
1352 vsprintf(string, text, arg);
1355 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1356 uint32 length = strlen(string), address = x + (y * pitch);
1358 for(uint32 i=0; i<length; i++)
1360 uint32 fontAddr = (uint32)string[i] * 64;
1362 for(uint32 yy=0; yy<8; yy++)
1364 for(uint32 xx=0; xx<8; xx++)
1366 if (font1[fontAddr])
1368 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1370 uint8 eBlue = (existingColor >> 16) & 0xFF,
1371 eGreen = (existingColor >> 8) & 0xFF,
1372 eRed = existingColor & 0xFF,
1373 //This could be done ahead of time, instead of on each pixel...
1374 nBlue = (color >> 16) & 0xFF,
1375 nGreen = (color >> 8) & 0xFF,
1376 nRed = color & 0xFF;
1378 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
1379 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
1380 //because dividing by 32 is faster than dividing by 31...!
1381 uint8 invTrans = 32 - trans;
1383 uint32 bRed = (eRed * trans + nRed * invTrans) / 32;
1384 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
1385 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
1387 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1399 // Draw text at the given x/y coordinates, using FG color and overlay alpha blending.
1401 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...)
1406 va_start(arg, text);
1407 vsprintf(string, text, arg);
1410 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1411 uint32 length = strlen(string), address = x + (y * pitch);
1413 color &= 0x00FFFFFF; // Just in case alpha was passed in...
1415 for(uint32 i=0; i<length; i++)
1417 uint8 c = string[i];
1418 c = (c < 32 ? 0 : c - 32);
1419 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1421 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1423 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1425 uint8 fontTrans = font2[fontAddr++];
1426 uint32 newTrans = (fontTrans * transparency / 255) << 24;
1427 uint32 pixel = newTrans | color;
1429 *(screen + address + xx + (yy * pitch)) = pixel;
1433 address += FONT_WIDTH;
1439 // Uses zero as transparent color
1440 // Can also use an optional alpha channel
1441 // Alpha channel is now mandatory! ;-)
1443 //void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap, uint8 * alpha/*=NULL*/)
1444 /*void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha)
1446 uint32 width = bitmap[0], height = bitmap[1];
1449 // uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
1450 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1451 uint32 address = x + (y * pitch);
1453 for(uint32 yy=0; yy<height; yy++)
1455 for(uint32 xx=0; xx<width; xx++)
1459 if (*bitmap && x + xx < pitch) // NOTE: Still doesn't clip the Y val...
1460 *(screen + address + xx + (yy * pitch)) = *bitmap;
1464 uint8 trans = *alpha;
1465 uint32 color = *bitmap;
1466 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1468 uint8 eRed = existingColor & 0xFF,
1469 eGreen = (existingColor >> 8) & 0xFF,
1470 eBlue = (existingColor >> 16) & 0xFF,
1472 nRed = color & 0xFF,
1473 nGreen = (color >> 8) & 0xFF,
1474 nBlue = (color >> 16) & 0xFF;
1476 uint8 invTrans = 255 - trans;
1477 uint32 bRed = (eRed * trans + nRed * invTrans) / 255;
1478 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 255;
1479 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 255;
1481 uint32 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1483 *(screen + address + xx + (yy * pitch)) = blendedColor;
1492 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap)
1494 uint32 width = bitmap[0], height = bitmap[1];
1497 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1498 uint32 address = x + (y * pitch);
1500 for(uint32 yy=0; yy<height; yy++)
1502 for(uint32 xx=0; xx<width; xx++)
1504 uint32 color = *bitmap;
1505 uint32 blendedColor = color;
1506 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1508 if (existingColor >> 24 != 0x00) // Pixel needs blending
1510 uint8 trans = color >> 24;
1511 uint8 invTrans = trans ^ 0xFF;//255 - trans;
1513 uint8 eRed = existingColor & 0xFF,
1514 eGreen = (existingColor >> 8) & 0xFF,
1515 eBlue = (existingColor >> 16) & 0xFF,
1517 nRed = color & 0xFF,
1518 nGreen = (color >> 8) & 0xFF,
1519 nBlue = (color >> 16) & 0xFF;
1521 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1522 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1523 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1525 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1528 *(screen + address + xx + (yy * pitch)) = blendedColor;
1534 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1536 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1537 uint32 address = x + (y * pitch);
1540 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1542 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1544 uint32 color = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1545 uint32 blendedColor = color;
1546 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1548 if (existingColor >> 24 != 0x00) // Pixel needs blending
1550 uint8 trans = color >> 24;
1551 uint8 invTrans = trans ^ 0xFF;
1553 uint8 eRed = existingColor & 0xFF,
1554 eGreen = (existingColor >> 8) & 0xFF,
1555 eBlue = (existingColor >> 16) & 0xFF,
1557 nRed = color & 0xFF,
1558 nGreen = (color >> 8) & 0xFF,
1559 nBlue = (color >> 16) & 0xFF;
1561 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1562 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1563 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1565 // Instead of $FF, should use the alpha from the destination pixel as the final alpha value...
1566 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1569 *(screen + address + xx + (yy * pitch)) = blendedColor;
1576 // Draw a bitmap without using blending
1578 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1580 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1581 uint32 address = x + (y * pitch);
1584 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1586 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1588 *(screen + address + xx + (yy * pitch)) = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1595 // Fill a portion of the screen with the passed in color
1597 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color)
1598 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h)
1600 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1601 uint32 address = x + (y * pitch);
1603 for(uint32 yy=0; yy<h; yy++)
1604 for(uint32 xx=0; xx<w; xx++)
1605 *(screen + address + xx + (yy * pitch)) = color;
1610 // GUI stuff--it's not crunchy, it's GUI! ;-)
1615 SDL_ShowCursor(SDL_DISABLE);
1616 SDL_GetMouseState(&mouseX, &mouseY);
1626 //bool GUIMain(void)
1627 bool GUIMain(char * filename)
1629 WriteLog("GUI: Inside GUIMain...\n");
1631 uint32 pointerBGSave[6 * 8 + 2];
1632 pointerBGSave[0] = 6;
1633 pointerBGSave[1] = 8;
1635 // Need to set things up so that it loads and runs a file if given on the command line. !!! FIX !!! [DONE]
1636 // extern uint32 * backbuffer;
1637 // bool done = false;
1639 Window * mainWindow = NULL;
1641 // Set up the GUI classes...
1642 // Element::SetScreenAndPitch(backbuffer, GetSDLScreenWidthInPixels());
1643 Element::SetScreenAndPitch((uint32 *)sdlemuGetOverlayPixels(), sdlemuGetOverlayWidthInPixels());
1644 sdlemuEnableOverlay();
1648 mi.title = "Jaguar";
1649 mi.item.push_back(NameAction("Load...", LoadROM, SDLK_l));
1650 mi.item.push_back(NameAction("Reset", ResetJaguar, SDLK_r));
1652 mi.item.push_back(NameAction("Reset CD", ResetJaguarCD, SDLK_c));
1653 mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE));
1654 mi.item.push_back(NameAction(""));
1655 mi.item.push_back(NameAction("Quit", Quit, SDLK_q));
1657 mi.title = "Settings";
1659 mi.item.push_back(NameAction("Video..."));
1660 mi.item.push_back(NameAction("Audio..."));
1661 mi.item.push_back(NameAction("Misc...", MiscOptions, SDLK_m));
1665 mi.item.push_back(NameAction("About...", About));
1668 bool showMouse = true;
1670 // Grab the BG where the mouse will be painted (prime the backstore)
1674 Bitmap ptr = { 6, 8, 4,
1675 ""//"000011112222333344445555"
1676 //"000011112222333344445555"
1677 //"000011112222333344445555"
1678 //"000011112222333344445555"
1679 //"000011112222333344445555"
1680 //"000011112222333344445555"
1681 //"000011112222333344445555"
1682 //"000011112222333344445555"
1684 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
1687 for(uint32 y=0; y<pointerBGSave[1]; y++)
1688 for(uint32 x=0; x<pointerBGSave[0]; x++)
1689 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
1691 uint32 oldMouseX = mouseX, oldMouseY = mouseY;
1693 //This is crappy!!! !!! FIX !!!
1694 //Is this even needed any more? Hmm. Maybe. Dunno.
1695 WriteLog("GUI: Resetting Jaguar...\n");
1698 WriteLog("GUI: Clearing BG save...\n");
1699 // Set up our background save...
1700 // memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2);
1701 //1111 -> 000100 01000 10001 -> 0001 0000 0100 0010 1000 1100 -> 10 42 8C
1702 for(uint32 i=0; i<TOMGetVideoModeWidth()*240; i++)
1703 // background[i] = 0xFF8C4210;
1704 backbuffer[i] = 0xFF8C4210;
1706 /* uint32 * overlayPix = (uint32 *)sdlemuGetOverlayPixels();
1707 for(uint32 i=0; i<sdlemuGetOverlayWidthInPixels()*480; i++)
1708 overlayPix[i] = 0x00000000;*/
1710 // Handle loading file passed in on the command line...! [DONE]
1714 if (JaguarLoadFile(filename))
1716 // event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1717 // event.user.data1 = (void *)ResetJaguar;
1718 // SDL_PushEvent(&event);
1719 // Make it so that if passed in on the command line, we quit right
1720 // away when pressing ESC
1721 WriteLog("GUI: Bypassing GUI since ROM passed in on command line...\n");
1727 // Create error dialog...
1729 sprintf(errText, "The file %40s could not be loaded.", filename);
1731 mainWindow = new Window(8, 16, 304, 160);
1732 mainWindow->AddElement(new Text(8, 8, "Error!"));
1733 mainWindow->AddElement(new Text(8, 24, errText));
1737 WriteLog("GUI: Entering main loop...\n");
1740 if (SDL_PollEvent(&event))
1742 if (event.type == SDL_USEREVENT)
1744 if (event.user.code == WINDOW_CLOSE)
1749 else if (event.user.code == MENU_ITEM_CHOSEN)
1751 // Confused? Let me enlighten... What we're doing here is casting
1752 // data1 as a pointer to a function which returns a Window pointer and
1753 // which takes no parameters (the "(Window *(*)(void))" part), then
1754 // derefencing it (the "*" in front of that) in order to call the
1755 // function that it points to. Clear as mud? Yeah, I hate function
1756 // pointers too, but what else are you gonna do?
1757 mainWindow = (*(Window *(*)(void))event.user.data1)();
1759 while (SDL_PollEvent(&event)); // Flush the event queue...
1760 event.type = SDL_MOUSEMOTION;
1762 SDL_GetMouseState(&mx, &my);
1763 event.motion.x = mx, event.motion.y = my;
1764 SDL_PushEvent(&event); // & update mouse position...!
1766 oldMouseX = mouseX, oldMouseY = mouseY;
1767 mouseX = mx, mouseY = my; // This prevents "mouse flash"...
1770 else if (event.type == SDL_ACTIVEEVENT)
1772 if (event.active.state == SDL_APPMOUSEFOCUS)
1773 showMouse = (event.active.gain ? true : false);
1775 else if (event.type == SDL_KEYDOWN)
1777 // Ugly kludge for windowed<-->fullscreen switching...
1778 uint8 * keystate = SDL_GetKeyState(NULL);
1780 if ((keystate[SDLK_LALT] || keystate[SDLK_RALT]) & keystate[SDLK_RETURN])
1784 mainWindow->HandleKey(event.key.keysym.sym);
1786 mainMenu.HandleKey(event.key.keysym.sym);
1788 else if (event.type == SDL_MOUSEMOTION)
1790 oldMouseX = mouseX, oldMouseY = mouseY;
1791 mouseX = event.motion.x, mouseY = event.motion.y;
1794 mainWindow->HandleMouseMove(mouseX, mouseY);
1796 mainMenu.HandleMouseMove(mouseX, mouseY);
1798 else if (event.type == SDL_MOUSEBUTTONDOWN)
1800 uint32 mx = event.button.x, my = event.button.y;
1803 mainWindow->HandleMouseButton(mx, my, true);
1805 mainMenu.HandleMouseButton(mx, my, true);
1807 else if (event.type == SDL_MOUSEBUTTONUP)
1809 uint32 mx = event.button.x, my = event.button.y;
1812 mainWindow->HandleMouseButton(mx, my, false);
1814 mainMenu.HandleMouseButton(mx, my, false);
1817 //PROBLEM: In order to use the dirty rectangle approach here, we need some way of
1818 // handling it in mainMenu.Draw() and mainWindow->Draw(). !!! FIX !!!
1819 //POSSIBLE SOLUTION:
1820 // When mouse is moving and not on menu or window, can do straight dirty rect.
1821 // When mouse is on menu, need to update screen. Same for buttons on windows...
1822 // What the menu & windows should do is only redraw on a state change. IOW, they
1823 // should call their own/child window's Draw() function instead of doing it top
1825 //#define NEW_BACKSTORE_METHOD
1828 // The way we do things here is kinda stupid (redrawing the screen every frame), but
1829 // it's simple. Perhaps there may be a reason down the road to be more selective with
1830 // our clearing, but for now, this will suffice.
1831 // memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
1832 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 2);
1833 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 4);
1834 #ifndef NEW_BACKSTORE_METHOD
1835 memset(sdlemuGetOverlayPixels(), 0, sdlemuGetOverlayWidthInPixels() * 480 * 4);
1838 //Could do multiple windows here by using a vector + priority info...
1839 //Though the way ZSNES does it seems to be by a bool (i.e., they're always active, just not shown)
1844 /*uint32 pBGS[6 * 8 + 3] = { 6, 8, 4,
1854 //This isn't working... Why????
1855 //It's because DrawTransparentBitmap does alpha blending if it detects zero in the alpha channel.
1856 //So why do it that way? Hm.
1857 overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
1859 #ifdef NEW_BACKSTORE_METHOD
1860 // DrawTransparentBitmapDeprecated(overlayPixels, oldMouseX, oldMouseY, pointerBGSave);
1861 // DrawTransparentBitmap(overlayPixels, oldMouseX, oldMouseY, pBGS);
1862 for(uint32 y=0; y<pointerBGSave[1]; y++)
1863 for(uint32 x=0; x<pointerBGSave[0]; x++)
1864 overlayPixels[((oldMouseY + y) * sdlemuGetOverlayWidthInPixels()) + (oldMouseX + x)] = 0x00000000;
1868 for(uint32 y=0; y<pointerBGSave[1]; y++)
1869 for(uint32 x=0; x<pointerBGSave[0]; x++)
1870 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
1874 // DrawTransparentBitmapDeprecated(backbuffer, mouseX, mouseY, mousePic);
1875 DrawTransparentBitmapDeprecated(overlayPixels, mouseX, mouseY, mousePic);
1885 // GUI "action" functions
1888 Window * LoadROM(void)
1890 FileList * fileList = new FileList(20, 20, 600, 440);
1892 return (Window *)fileList;
1895 Window * ResetJaguar(void)
1902 Window * ResetJaguarCD(void)
1904 memcpy(jaguarMainRom, jaguarCDBootROM, 0x40000);
1905 jaguarRunAddress = 0x802000;
1906 jaguarMainRomCRC32 = crc32_calcCheckSum(jaguarMainRom, 0x40000);
1908 //This is a quick kludge to get the CDBIOS to boot properly...
1909 //Wild speculation: It could be that this memory location is wired into the CD unit
1910 //somehow, which lets it know whether or not a cart is present in the unit...
1911 jaguarMainRom[0x0040B] = 0x03;
1919 bool debounceRunKey = true;
1920 Window * RunEmu(void)
1922 extern uint32 * backbuffer;
1923 //Temporary, to test the new timer based code...
1924 sdlemuDisableOverlay();
1926 sdlemuEnableOverlay();
1927 // Save the background for the GUI...
1928 // In this case, we squash the color to monochrome, then force it to blue + green...
1929 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
1931 uint32 pixel = backbuffer[i];
1932 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
1933 pixel = ((r + g + b) / 3) & 0x00FF;
1934 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
1938 //This is crappy... !!! FIX !!!
1939 extern bool finished, showGUI;
1941 // uint32 nFrame = 0, nFrameskip = 0;
1942 uint32 totalFrames = 0;
1944 bool showMessage = true;
1945 uint32 showMsgFrames = 120;
1946 uint8 transparency = 0;
1947 // Pass a message to the "joystick" code to debounce the ESC key...
1948 debounceRunKey = true;
1950 uint32 cartType = 4;
1951 if (jaguarRomSize == 0x200000)
1953 else if (jaguarRomSize == 0x400000)
1955 else if (jaguar_mainRom_crc32 == 0x687068D5)
1957 else if (jaguar_mainRom_crc32 == 0x55A0669C)
1960 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
1961 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
1965 // Set up new backbuffer with new pixels and data
1966 JaguarExecute(backbuffer, true);
1967 // JaguarExecuteNew();
1969 //WriteLog("Frame #%u...\n", totalFrames);
1970 //extern bool doDSPDis;
1971 //if (totalFrames == 373)
1974 //This sucks... !!! FIX !!!
1976 //This is done here so that the crud below doesn't get on our GUI background...
1980 // Some QnD GUI stuff here...
1983 extern uint32 gpu_pc, dsp_pc;
1984 DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
1985 DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
1986 DrawString(backbuffer, 8, 32, false, "%u FPS", framesPerSecond);
1991 // FF0F -> 1111 11 11 000 0 1111 -> 3F 18 0F
1992 // 3FE3 -> 0011 11 11 111 0 0011 -> 0F 3F 03
1993 /* DrawStringTrans((uint32 *)backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
1994 DrawStringTrans((uint32 *)backbuffer, 8, 26*8, 0x3FE3, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
1995 DrawStringTrans((uint32 *)backbuffer, 8, 27*8, 0x3FE3, transparency, "CRC: %08X", jaguar_mainRom_crc32);//*/
1996 //first has wrong color. !!! FIX !!!
1997 DrawStringTrans(backbuffer, 8, 24*8, 0xFF7F63FF, transparency, "Running...");
1998 DrawStringTrans(backbuffer, 8, 26*8, 0xFF1FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
1999 DrawStringTrans(backbuffer, 8, 27*8, 0xFF1FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2001 if (showMsgFrames == 0)
2005 if (transparency == 33)
2007 showMessage = false;
2008 /*extern bool doGPUDis;
2009 doGPUDis = true;//*/
2020 if (SDL_GetTicks() - elapsedTicks > 250)
2021 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2024 // Reset the pitch, since it may have been changed in-game...
2025 Element::SetScreenAndPitch((uint32 *)backbuffer, GetSDLScreenWidthInPixels());
2027 // Save the background for the GUI...
2028 // memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2);
2029 // In this case, we squash the color to monochrome, then force it to blue + green...
2030 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2032 uint32 pixel = backbuffer[i];
2033 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2034 pixel = ((r + g + b) / 3) & 0x00FF;
2035 background[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2043 bool debounceRunKey = true;
2044 Window * RunEmu(void)
2046 // extern uint32 * backbuffer;
2047 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2048 memset(overlayPixels, 0x00, 640 * 480 * 4); // Clear out overlay...
2050 //This is crappy... !!! FIX !!!
2051 // extern bool finished, showGUI;
2053 sdlemuDisableOverlay();
2055 // uint32 nFrame = 0, nFrameskip = 0;
2056 uint32 totalFrames = 0;
2058 bool showMessage = true;
2059 uint32 showMsgFrames = 120;
2060 uint8 transparency = 0xFF;
2061 // Pass a message to the "joystick" code to debounce the ESC key...
2062 debounceRunKey = true;
2064 uint32 cartType = 4;
2065 if (jaguarRomSize == 0x200000)
2067 else if (jaguarRomSize == 0x400000)
2069 else if (jaguarMainRomCRC32 == 0x687068D5)
2071 else if (jaguarMainRomCRC32 == 0x55A0669C)
2074 const char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2075 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2079 // Set up new backbuffer with new pixels and data
2082 //WriteLog("Frame #%u...\n", totalFrames);
2083 //extern bool doDSPDis;
2084 //if (totalFrames == 373)
2087 //Problem: Need to do this *only* when the state changes from visible to not...
2088 //Also, need to clear out the GUI when not on (when showMessage is active...)
2089 if (showGUI || showMessage)
2090 sdlemuEnableOverlay();
2092 sdlemuDisableOverlay();
2094 //Add in a new function for clearing patches of screen (ClearOverlayRect)
2096 // Also: Take frame rate into account when calculating fade time...
2098 // Some QnD GUI stuff here...
2101 FillScreenRectangle(overlayPixels, 8, 1*FONT_HEIGHT, 128, 4*FONT_HEIGHT, 0x00000000);
2102 extern uint32 gpu_pc, dsp_pc;
2103 DrawString(overlayPixels, 8, 1*FONT_HEIGHT, false, "GPU PC: %08X", gpu_pc);
2104 DrawString(overlayPixels, 8, 2*FONT_HEIGHT, false, "DSP PC: %08X", dsp_pc);
2105 DrawString(overlayPixels, 8, 4*FONT_HEIGHT, false, "%u FPS", framesPerSecond);
2110 DrawString2(overlayPixels, 8, 24*FONT_HEIGHT, 0x007F63FF, transparency, "Running...");
2111 DrawString2(overlayPixels, 8, 26*FONT_HEIGHT, 0x001FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2112 DrawString2(overlayPixels, 8, 27*FONT_HEIGHT, 0x001FFF3F, transparency, "CRC: %08X", jaguarMainRomCRC32);
2114 if (showMsgFrames == 0)
2118 if (transparency == 0)
2120 showMessage = false;
2121 /*extern bool doGPUDis;
2122 doGPUDis = true;//*/
2132 if (SDL_GetTicks() - elapsedTicks > 250)
2133 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2136 // Save the background for the GUI...
2137 // In this case, we squash the color to monochrome, then force it to blue + green...
2138 for(uint32 i=0; i<TOMGetVideoModeWidth() * 256; i++)
2140 uint32 pixel = backbuffer[i];
2141 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2142 pixel = ((r + g + b) / 3) & 0x00FF;
2143 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2146 sdlemuEnableOverlay();
2156 WriteLog("GUI: Quitting due to user request.\n");
2162 Window * About(void)
2165 sprintf(buf, "SVN %s", __DATE__);
2166 //fprintf(fp, "VirtualJaguar v1.0.8 (Last full build was on %s %s)\n", __DATE__, __TIME__);
2167 //VirtualJaguar v1.0.8 (Last full build was on Dec 30 2004 20:01:31)
2168 //Hardwired, bleh... !!! FIX !!!
2169 uint32 width = 55 * FONT_WIDTH, height = 18 * FONT_HEIGHT;
2170 uint32 xpos = (640 - width) / 2, ypos = (480 - height) / 2;
2171 // Window * window = new Window(8, 16, 50 * FONT_WIDTH, 21 * FONT_HEIGHT);
2172 Window * window = new Window(xpos, ypos, width, height);
2173 // window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.8"));
2174 // window->AddElement(new Text(8, 8, "Virtual Jaguar CVS 20050110", 0xFF3030FF, 0xFF000000));
2175 // window->AddElement(new Text(208, 8+0*FONT_HEIGHT, buf, 0xFF3030FF, 0xFF000000));
2176 window->AddElement(new Text(248, 8+4*FONT_HEIGHT+5, buf, 0xFF3030FF, 0xFF000000));
2177 window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "Coders:"));
2178 window->AddElement(new Text(16, 8+1*FONT_HEIGHT, "James L. Hammons (shamus)"));
2179 window->AddElement(new Text(16, 8+2*FONT_HEIGHT, "Niels Wagenaar (nwagenaar)"));
2180 window->AddElement(new Text(16, 8+3*FONT_HEIGHT, "Carwin Jones (Caz)"));
2181 window->AddElement(new Text(16, 8+4*FONT_HEIGHT, "Adam Green"));
2182 window->AddElement(new Text(8, 8+6*FONT_HEIGHT, "Testers:"));
2183 window->AddElement(new Text(16, 8+7*FONT_HEIGHT, "Guruma"));
2184 window->AddElement(new Text(8, 8+9*FONT_HEIGHT, "Thanks go out to:"));
2185 window->AddElement(new Text(16, 8+10*FONT_HEIGHT, "Aaron Giles for the original CoJag"));
2186 window->AddElement(new Text(16, 8+11*FONT_HEIGHT, "David Raingeard for the original VJ"));
2187 window->AddElement(new Text(16, 8+12*FONT_HEIGHT, "Karl Stenerud for his Musashi 68K emu"));
2188 window->AddElement(new Text(16, 8+13*FONT_HEIGHT, "Sam Lantinga for his amazing SDL libs"));
2189 window->AddElement(new Text(16, 8+14*FONT_HEIGHT, "Ryan C. Gordon for VJ's web presence"));
2190 window->AddElement(new Text(16, 8+15*FONT_HEIGHT, "Curt Vendel for various Jaguar goodies"));
2191 window->AddElement(new Text(16, 8+16*FONT_HEIGHT, "The guys over at Atari Age ;-)"));
2192 // window->AddElement(new Image(8, 8, &vj_title_small));
2193 window->AddElement(new Image(width - (vj_title_small.width + 8), 8, &vj_title_small));
2198 Window * MiscOptions(void)
2200 Window * window = new Window(8, 16, 304, 192);
2201 window->AddElement(new PushButton(8, 8, &vjs.useJaguarBIOS, "BIOS"));
2202 window->AddElement(new SlideSwitch(8, 32, &vjs.hardwareTypeNTSC, "PAL", "NTSC"));
2203 window->AddElement(new PushButton(8, 64, &vjs.DSPEnabled, "DSP"));
2204 window->AddElement(new SlideSwitch(24, 88, &vjs.usePipelinedDSP, "Original", "Pipelined"));
2205 window->AddElement(new SlideSwitch(8, 120, (bool *)&vjs.glFilter, "Sharp", "Blurry"));
2206 window->AddElement(new SlideSwitch(8, 152, (bool *)&vjs.renderType, "Normal render", "TV style"));
2208 window->AddElement(new TextEdit(88, 8, vjs.ROMPath, 20, 0xFF8484FF, 0xFF000000));
2210 /*TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
2211 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
2212 caretPos(0), maxScreenSize(mss) {}*/
2221 // * Window/fullscreen
2222 // * Key definitions
2227 // Function prototype
2228 Window * CrashGracefullyCallback(void);
2230 //NOTE: Probably should set a flag as well telling it to do a full reset
2231 // of the Jaguar hardware if this happens...
2232 void GUICrashGracefully(const char * reason)
2234 finished = true; // We're finished for now!
2236 // Since this is used in the menu code as well, we could create another
2237 // internal function called "PushWindowOnQueue" or somesuch
2239 event.type = SDL_USEREVENT;
2240 event.user.code = MENU_ITEM_CHOSEN;
2241 event.user.data1 = (void *)CrashGracefullyCallback;
2242 SDL_PushEvent(&event);
2245 Window * CrashGracefullyCallback(void)
2247 Window * window = new Window(8, 16, 304, 192);
2249 window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "We CRASHED!!!"));