]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/gui.cpp
2cdd58d65486854729b912c1b3395b86f4d9e0de
[virtualjaguar] / src / gui / gui.cpp
1 //
2 // GUI.CPP
3 //
4 // Graphical User Interface support
5 // by James L. Hammons
6 //
7
8 #include "gui.h"
9
10 #include <SDL.h>
11 #include "crc32.h"
12 #include "file.h"
13 #include "jaguar.h"
14 #include "log.h"
15 #include "sdlemu_opengl.h"
16 #include "settings.h"
17 #include "tom.h"
18 #include "video.h"
19
20 // Once these are split off, these may not be needed anymore...
21 #include "button.h"
22 #include "element.h"
23 #include "filelist.h"
24 #include "guimisc.h"
25 #include "image.h"
26 #include "listbox.h"
27 #include "menu.h"
28 #include "pushbutton.h"
29 #include "slideswitch.h"
30 #include "text.h"
31 #include "textedit.h"
32 #include "window.h"
33
34 // Private function prototypes
35
36 Window * LoadROM(void);
37 Window * ResetJaguar(void);
38 Window * ResetJaguarCD(void);
39 Window * RunEmu(void);
40 Window * Quit(void);
41 Window * About(void);
42 Window * MiscOptions(void);
43
44 // Local global variables
45
46 bool showGUI = false;
47 bool exitGUI = false;                                                           // GUI (emulator) done variable
48 int mouseX = 0, mouseY = 0;
49 uint32 background[1280 * 256];                                          // GUI background buffer
50 bool showMessage = false;
51 //uint32 showMessageTimeout;
52 //char messageBuffer[200];
53 bool finished = false;
54
55 //
56 // GUI stuff--it's not crunchy, it's GUI! ;-)
57 //
58
59 void GUIInit(void)
60 {
61         SDL_ShowCursor(SDL_DISABLE);
62         SDL_GetMouseState(&mouseX, &mouseY);
63 }
64
65 void GUIDone(void)
66 {
67 }
68
69 //
70 // GUI main loop
71 //
72 //bool GUIMain(void)
73 bool GUIMain(char * filename)
74 {
75 WriteLog("GUI: Inside GUIMain...\n");
76
77         uint32 pointerBGSave[6 * 8 + 2];
78         pointerBGSave[0] = 6;
79         pointerBGSave[1] = 8;
80
81 // Need to set things up so that it loads and runs a file if given on the command line. !!! FIX !!! [DONE]
82 //      extern uint32 * backbuffer;
83 //      bool done = false;
84         SDL_Event event;
85         Window * mainWindow = NULL;
86
87         // Set up the GUI classes...
88 //      Element::SetScreenAndPitch(backbuffer, GetSDLScreenWidthInPixels());
89         Element::SetScreenAndPitch((uint32 *)sdlemuGetOverlayPixels(), sdlemuGetOverlayWidthInPixels());
90         sdlemuEnableOverlay();
91
92         Menu mainMenu;
93         MenuItems mi;
94         mi.title = "Jaguar";
95         mi.item.push_back(NameAction("Load...", LoadROM, SDLK_l));
96         mi.item.push_back(NameAction("Reset", ResetJaguar, SDLK_r));
97         if (CDBIOSLoaded)
98                 mi.item.push_back(NameAction("Reset CD", ResetJaguarCD, SDLK_c));
99         mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE));
100         mi.item.push_back(NameAction(""));
101         mi.item.push_back(NameAction("Quit", Quit, SDLK_q));
102         mainMenu.Add(mi);
103         mi.title = "Settings";
104         mi.item.clear();
105         mi.item.push_back(NameAction("Video..."));
106         mi.item.push_back(NameAction("Audio..."));
107         mi.item.push_back(NameAction("Misc...", MiscOptions, SDLK_m));
108         mainMenu.Add(mi);
109         mi.title = "Info";
110         mi.item.clear();
111         mi.item.push_back(NameAction("About...", About));
112         mainMenu.Add(mi);
113
114         bool showMouse = true;
115
116         // Grab the BG where the mouse will be painted (prime the backstore)
117
118 /*
119 DISNOWOK
120 Bitmap ptr = { 6, 8, 4,
121 ""//"000011112222333344445555"
122 //"000011112222333344445555"
123 //"000011112222333344445555"
124 //"000011112222333344445555"
125 //"000011112222333344445555"
126 //"000011112222333344445555"
127 //"000011112222333344445555"
128 //"000011112222333344445555"
129 };//*/
130         uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
131         uint32 count = 2;
132
133         for(uint32 y=0; y<pointerBGSave[1]; y++)
134                 for(uint32 x=0; x<pointerBGSave[0]; x++)
135                         pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
136
137         uint32 oldMouseX = mouseX, oldMouseY = mouseY;
138
139 //This is crappy!!! !!! FIX !!!
140 //Is this even needed any more? Hmm. Maybe. Dunno.
141 WriteLog("GUI: Resetting Jaguar...\n");
142         JaguarReset();
143
144 WriteLog("GUI: Clearing BG save...\n");
145         // Set up our background save...
146 //      memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2);
147 //1111 -> 000100 01000 10001 -> 0001 0000 0100 0010 1000 1100 -> 10 42 8C
148         for(uint32 i=0; i<TOMGetVideoModeWidth()*240; i++)
149 //              background[i] = 0xFF8C4210;
150                 backbuffer[i] = 0xFF8C4210;
151
152 /*      uint32 * overlayPix = (uint32 *)sdlemuGetOverlayPixels();
153         for(uint32 i=0; i<sdlemuGetOverlayWidthInPixels()*480; i++)
154                 overlayPix[i] = 0x00000000;*/
155
156         // Handle loading file passed in on the command line...! [DONE]
157
158         if (filename)
159         {
160                 if (JaguarLoadFile(filename))
161                 {
162 //                      event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
163 //                      event.user.data1 = (void *)ResetJaguar;
164 //              SDL_PushEvent(&event);
165                         // Make it so that if passed in on the command line, we quit right
166                         // away when pressing ESC
167 WriteLog("GUI: Bypassing GUI since ROM passed in on command line...\n");
168                         ResetJaguar();
169                         return true;
170                 }
171                 else
172                 {
173                         // Create error dialog...
174                         char errText[1024];
175                         sprintf(errText, "The file %40s could not be loaded.", filename);
176
177                         mainWindow = new Window(8, 16, 304, 160);
178                         mainWindow->AddElement(new Text(8, 8, "Error!"));
179                         mainWindow->AddElement(new Text(8, 24, errText));
180                 }
181         }
182
183 WriteLog("GUI: Entering main loop...\n");
184         while (!exitGUI)
185         {
186                 if (SDL_PollEvent(&event))
187                 {
188                         if (event.type == SDL_USEREVENT)
189                         {
190                                 if (event.user.code == WINDOW_CLOSE)
191                                 {
192                                         delete mainWindow;
193                                         mainWindow = NULL;
194                                 }
195                                 else if (event.user.code == MENU_ITEM_CHOSEN)
196                                 {
197                                         // Confused? Let me enlighten... What we're doing here is casting
198                                         // data1 as a pointer to a function which returns a Window pointer and
199                                         // which takes no parameters (the "(Window *(*)(void))" part), then
200                                         // derefencing it (the "*" in front of that) in order to call the
201                                         // function that it points to. Clear as mud? Yeah, I hate function
202                                         // pointers too, but what else are you gonna do?
203                                         mainWindow = (*(Window *(*)(void))event.user.data1)();
204
205                                         while (SDL_PollEvent(&event));  // Flush the event queue...
206                                         event.type = SDL_MOUSEMOTION;
207                                         int mx, my;
208                                         SDL_GetMouseState(&mx, &my);
209                                         event.motion.x = mx, event.motion.y = my;
210                                     SDL_PushEvent(&event);                      // & update mouse position...!
211
212                                         oldMouseX = mouseX, oldMouseY = mouseY;
213                                         mouseX = mx, mouseY = my;               // This prevents "mouse flash"...
214                                 }
215                         }
216                         else if (event.type == SDL_ACTIVEEVENT)
217                         {
218                                 if (event.active.state == SDL_APPMOUSEFOCUS)
219                                         showMouse = (event.active.gain ? true : false);
220                         }
221                         else if (event.type == SDL_KEYDOWN)
222                         {
223 // Ugly kludge for windowed<-->fullscreen switching...
224 uint8 * keystate = SDL_GetKeyState(NULL);
225
226 if ((keystate[SDLK_LALT] || keystate[SDLK_RALT]) & keystate[SDLK_RETURN])
227         ToggleFullscreen();
228
229                                 if (mainWindow)
230                                         mainWindow->HandleKey(event.key.keysym.sym);
231                                 else
232                                         mainMenu.HandleKey(event.key.keysym.sym);
233                         }
234                         else if (event.type == SDL_MOUSEMOTION)
235                         {
236                                 oldMouseX = mouseX, oldMouseY = mouseY;
237                                 mouseX = event.motion.x, mouseY = event.motion.y;
238
239                                 if (mainWindow)
240                                         mainWindow->HandleMouseMove(mouseX, mouseY);
241                                 else
242                                         mainMenu.HandleMouseMove(mouseX, mouseY);
243                         }
244                         else if (event.type == SDL_MOUSEBUTTONDOWN)
245                         {
246                                 uint32 mx = event.button.x, my = event.button.y;
247
248                                 if (mainWindow)
249                                         mainWindow->HandleMouseButton(mx, my, true);
250                                 else
251                                         mainMenu.HandleMouseButton(mx, my, true);
252                         }
253                         else if (event.type == SDL_MOUSEBUTTONUP)
254                         {
255                                 uint32 mx = event.button.x, my = event.button.y;
256
257                                 if (mainWindow)
258                                         mainWindow->HandleMouseButton(mx, my, false);
259                                 else
260                                         mainMenu.HandleMouseButton(mx, my, false);
261                         }
262
263 //PROBLEM: In order to use the dirty rectangle approach here, we need some way of
264 //         handling it in mainMenu.Draw() and mainWindow->Draw(). !!! FIX !!!
265 //POSSIBLE SOLUTION:
266 // When mouse is moving and not on menu or window, can do straight dirty rect.
267 // When mouse is on menu, need to update screen. Same for buttons on windows...
268 // What the menu & windows should do is only redraw on a state change. IOW, they
269 // should call their own/child window's Draw() function instead of doing it top
270 // level.
271 //#define NEW_BACKSTORE_METHOD
272
273                         // Draw the GUI...
274 // The way we do things here is kinda stupid (redrawing the screen every frame), but
275 // it's simple. Perhaps there may be a reason down the road to be more selective with
276 // our clearing, but for now, this will suffice.
277 //                      memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
278 //                      memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 2);
279 //                      memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 4);
280 #ifndef NEW_BACKSTORE_METHOD
281                         memset(sdlemuGetOverlayPixels(), 0, sdlemuGetOverlayWidthInPixels() * 480 * 4);
282
283                         mainMenu.Draw();
284 //Could do multiple windows here by using a vector + priority info...
285 //Though the way ZSNES does it seems to be by a bool (i.e., they're always active, just not shown)
286                         if (mainWindow)
287                                 mainWindow->Draw();
288 #endif
289
290 /*uint32 pBGS[6 * 8 + 3] = { 6, 8, 4,
291         0, 0, 0, 0, 0, 0,
292         0, 0, 0, 0, 0, 0,
293         0, 0, 0, 0, 0, 0,
294         0, 0, 0, 0, 0, 0,
295         0, 0, 0, 0, 0, 0,
296         0, 0, 0, 0, 0, 0,
297         0, 0, 0, 0, 0, 0,
298         0, 0, 0, 0, 0, 0
299 };*/
300 //This isn't working... Why????
301 //It's because DrawTransparentBitmap does alpha blending if it detects zero in the alpha channel.
302 //So why do it that way? Hm.
303                         overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
304
305 #ifdef NEW_BACKSTORE_METHOD
306 //                      DrawTransparentBitmapDeprecated(overlayPixels, oldMouseX, oldMouseY, pointerBGSave);
307 //                      DrawTransparentBitmap(overlayPixels, oldMouseX, oldMouseY, pBGS);
308                         for(uint32 y=0; y<pointerBGSave[1]; y++)
309                                 for(uint32 x=0; x<pointerBGSave[0]; x++)
310                                         overlayPixels[((oldMouseY + y) * sdlemuGetOverlayWidthInPixels()) + (oldMouseX + x)] = 0x00000000;
311
312                         count = 2;
313
314                         for(uint32 y=0; y<pointerBGSave[1]; y++)
315                                 for(uint32 x=0; x<pointerBGSave[0]; x++)
316                                         pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
317 #endif
318
319                         if (showMouse)
320 //                              DrawTransparentBitmapDeprecated(backbuffer, mouseX, mouseY, mousePic);
321                                 DrawTransparentBitmapDeprecated(overlayPixels, mouseX, mouseY, mousePic);
322
323                         RenderBackbuffer();
324                 }
325         }
326
327         return true;
328 }
329
330 //
331 // GUI "action" functions
332 //
333
334 Window * LoadROM(void)
335 {
336         FileList * fileList = new FileList(20, 20, 600, 440);
337
338         return (Window *)fileList;
339 }
340
341 Window * ResetJaguar(void)
342 {
343         JaguarReset();
344
345         return RunEmu();
346 }
347
348 Window * ResetJaguarCD(void)
349 {
350         memcpy(jaguarMainROM, jaguarCDBootROM, 0x40000);
351         jaguarRunAddress = 0x802000;
352         jaguarMainROMCRC32 = crc32_calcCheckSum(jaguarMainROM, 0x40000);
353         JaguarReset();
354 //This is a quick kludge to get the CDBIOS to boot properly...
355 //Wild speculation: It could be that this memory location is wired into the CD unit
356 //somehow, which lets it know whether or not a cart is present in the unit...
357         jaguarMainROM[0x0040B] = 0x03;
358
359         return RunEmu();
360 }
361
362
363 #if 0
364
365 bool debounceRunKey = true;
366 Window * RunEmu(void)
367 {
368         extern uint32 * backbuffer;
369 //Temporary, to test the new timer based code...
370 sdlemuDisableOverlay();
371 JaguarExecuteNew();
372 sdlemuEnableOverlay();
373         // Save the background for the GUI...
374         // In this case, we squash the color to monochrome, then force it to blue + green...
375         for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
376         {
377                 uint32 pixel = backbuffer[i];
378                 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
379                 pixel = ((r + g + b) / 3) & 0x00FF;
380                 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
381         }
382 return NULL;//*/
383
384 //This is crappy... !!! FIX !!!
385         extern bool finished, showGUI;
386
387 //      uint32 nFrame = 0, nFrameskip = 0;
388         uint32 totalFrames = 0;
389         finished = false;
390         bool showMessage = true;
391         uint32 showMsgFrames = 120;
392         uint8 transparency = 0;
393         // Pass a message to the "joystick" code to debounce the ESC key...
394         debounceRunKey = true;
395
396         uint32 cartType = 4;
397         if (jaguarRomSize == 0x200000)
398                 cartType = 0;
399         else if (jaguarRomSize == 0x400000)
400                 cartType = 1;
401         else if (jaguar_mainRom_crc32 == 0x687068D5)
402                 cartType = 2;
403         else if (jaguar_mainRom_crc32 == 0x55A0669C)
404                 cartType = 3;
405
406         char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
407         uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
408
409         while (true)
410         {
411                 // Set up new backbuffer with new pixels and data
412                 JaguarExecute(backbuffer, true);
413 //              JaguarExecuteNew();
414                 totalFrames++;
415 //WriteLog("Frame #%u...\n", totalFrames);
416 //extern bool doDSPDis;
417 //if (totalFrames == 373)
418 //      doDSPDis = true;
419
420 //This sucks... !!! FIX !!!
421                 joystick_exec();
422 //This is done here so that the crud below doesn't get on our GUI background...
423                 if (finished)
424                         break;
425
426                 // Some QnD GUI stuff here...
427                 if (showGUI)
428                 {
429                         extern uint32 gpu_pc, dsp_pc;
430                         DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
431                         DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
432                         DrawString(backbuffer, 8, 32, false, "%u FPS", framesPerSecond);
433                 }
434
435                 if (showMessage)
436                 {
437 // FF0F -> 1111 11 11  000 0 1111 -> 3F 18 0F
438 // 3FE3 -> 0011 11 11  111 0 0011 -> 0F 3F 03
439 /*                      DrawStringTrans((uint32 *)backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
440                         DrawStringTrans((uint32 *)backbuffer, 8, 26*8, 0x3FE3, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
441                         DrawStringTrans((uint32 *)backbuffer, 8, 27*8, 0x3FE3, transparency, "CRC: %08X", jaguar_mainRom_crc32);//*/
442 //first has wrong color. !!! FIX !!!
443                         DrawStringTrans(backbuffer, 8, 24*8, 0xFF7F63FF, transparency, "Running...");
444                         DrawStringTrans(backbuffer, 8, 26*8, 0xFF1FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
445                         DrawStringTrans(backbuffer, 8, 27*8, 0xFF1FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
446
447                         if (showMsgFrames == 0)
448                         {
449                                 transparency++;
450
451                                 if (transparency == 33)
452 {
453                                         showMessage = false;
454 /*extern bool doGPUDis;
455 doGPUDis = true;//*/
456 }
457
458                         }
459                         else
460                                 showMsgFrames--;
461                 }
462
463                 RenderBackbuffer();
464                 frameCount++;
465
466                 if (SDL_GetTicks() - elapsedTicks > 250)
467                         elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
468         }
469
470         // Reset the pitch, since it may have been changed in-game...
471         Element::SetScreenAndPitch((uint32 *)backbuffer, GetSDLScreenWidthInPixels());
472
473         // Save the background for the GUI...
474 //      memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2);
475         // In this case, we squash the color to monochrome, then force it to blue + green...
476         for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
477         {
478                 uint32 pixel = backbuffer[i];
479                 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
480                 pixel = ((r + g + b) / 3) & 0x00FF;
481                 background[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
482         }
483
484         return NULL;
485 }
486
487 #else
488
489 bool debounceRunKey = true;
490 Window * RunEmu(void)
491 {
492 //      extern uint32 * backbuffer;
493         uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
494         memset(overlayPixels, 0x00, 640 * 480 * 4);                     // Clear out overlay...
495
496 //This is crappy... !!! FIX !!!
497 //      extern bool finished, showGUI;
498
499         sdlemuDisableOverlay();
500
501 //      uint32 nFrame = 0, nFrameskip = 0;
502         uint32 totalFrames = 0;
503         finished = false;
504         bool showMessage = true;
505         uint32 showMsgFrames = 120;
506         uint8 transparency = 0xFF;
507         // Pass a message to the "joystick" code to debounce the ESC key...
508         debounceRunKey = true;
509
510         uint32 cartType = 4;
511         if (jaguarROMSize == 0x200000)
512                 cartType = 0;
513         else if (jaguarROMSize == 0x400000)
514                 cartType = 1;
515         else if (jaguarMainROMCRC32 == 0x687068D5)
516                 cartType = 2;
517         else if (jaguarMainROMCRC32 == 0x55A0669C)
518                 cartType = 3;
519
520         const char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
521         uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
522
523         while (!finished)
524         {
525                 // Set up new backbuffer with new pixels and data
526                 JaguarExecuteNew();
527                 totalFrames++;
528 //WriteLog("Frame #%u...\n", totalFrames);
529 //extern bool doDSPDis;
530 //if (totalFrames == 373)
531 //      doDSPDis = true;
532
533 //Problem: Need to do this *only* when the state changes from visible to not...
534 //Also, need to clear out the GUI when not on (when showMessage is active...)
535 if (showGUI || showMessage)
536         sdlemuEnableOverlay();
537 else
538         sdlemuDisableOverlay();
539
540 //Add in a new function for clearing patches of screen (ClearOverlayRect)
541
542 // Also: Take frame rate into account when calculating fade time...
543
544                 // Some QnD GUI stuff here...
545                 if (showGUI)
546                 {
547                         FillScreenRectangle(overlayPixels, 8, 1*FONT_HEIGHT, 128, 4*FONT_HEIGHT, 0x00000000);
548                         extern uint32 gpu_pc, dsp_pc;
549                         DrawString(overlayPixels, 8, 1*FONT_HEIGHT, false, "GPU PC: %08X", gpu_pc);
550                         DrawString(overlayPixels, 8, 2*FONT_HEIGHT, false, "DSP PC: %08X", dsp_pc);
551                         DrawString(overlayPixels, 8, 4*FONT_HEIGHT, false, "%u FPS", framesPerSecond);
552                 }
553
554                 if (showMessage)
555                 {
556                         DrawString2(overlayPixels, 8, 24*FONT_HEIGHT, 0x007F63FF, transparency, "Running...");
557                         DrawString2(overlayPixels, 8, 26*FONT_HEIGHT, 0x001FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
558                         DrawString2(overlayPixels, 8, 27*FONT_HEIGHT, 0x001FFF3F, transparency, "CRC: %08X", jaguarMainROMCRC32);
559
560                         if (showMsgFrames == 0)
561                         {
562                                 transparency--;
563
564                                 if (transparency == 0)
565 {
566                                         showMessage = false;
567 /*extern bool doGPUDis;
568 doGPUDis = true;//*/
569 }
570
571                         }
572                         else
573                                 showMsgFrames--;
574                 }
575
576                 frameCount++;
577
578                 if (SDL_GetTicks() - elapsedTicks > 250)
579                         elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
580         }
581
582         // Save the background for the GUI...
583         // In this case, we squash the color to monochrome, then force it to blue + green...
584         for(uint32 i=0; i<TOMGetVideoModeWidth() * 256; i++)
585         {
586                 uint32 pixel = backbuffer[i];
587                 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
588                 pixel = ((r + g + b) / 3) & 0x00FF;
589                 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
590         }
591
592         sdlemuEnableOverlay();
593
594         return NULL;
595 }
596
597 #endif
598
599
600 Window * Quit(void)
601 {
602         WriteLog("GUI: Quitting due to user request.\n");
603         exitGUI = true;
604
605         return NULL;
606 }
607
608 Window * About(void)
609 {
610         char buf[512];
611         sprintf(buf, "SVN %s", __DATE__);
612 //fprintf(fp, "VirtualJaguar v1.0.8 (Last full build was on %s %s)\n", __DATE__, __TIME__);
613 //VirtualJaguar v1.0.8 (Last full build was on Dec 30 2004 20:01:31)
614 //Hardwired, bleh... !!! FIX !!!
615 uint32 width = 55 * FONT_WIDTH, height = 18 * FONT_HEIGHT;
616 uint32 xpos = (640 - width) / 2, ypos = (480 - height) / 2;
617 //      Window * window = new Window(8, 16, 50 * FONT_WIDTH, 21 * FONT_HEIGHT);
618         Window * window = new Window(xpos, ypos, width, height);
619 //      window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.8"));
620 //      window->AddElement(new Text(8, 8, "Virtual Jaguar CVS 20050110", 0xFF3030FF, 0xFF000000));
621 //      window->AddElement(new Text(208, 8+0*FONT_HEIGHT, buf, 0xFF3030FF, 0xFF000000));
622         window->AddElement(new Text(248, 8+4*FONT_HEIGHT+5, buf, 0xFF3030FF, 0xFF000000));
623         window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "Coders:"));
624         window->AddElement(new Text(16, 8+1*FONT_HEIGHT, "James L. Hammons (shamus)"));
625         window->AddElement(new Text(16, 8+2*FONT_HEIGHT, "Niels Wagenaar (nwagenaar)"));
626         window->AddElement(new Text(16, 8+3*FONT_HEIGHT, "Carwin Jones (Caz)"));
627         window->AddElement(new Text(16, 8+4*FONT_HEIGHT, "Adam Green"));
628         window->AddElement(new Text(8, 8+6*FONT_HEIGHT, "Testers:"));
629         window->AddElement(new Text(16, 8+7*FONT_HEIGHT, "Guruma"));
630         window->AddElement(new Text(8, 8+9*FONT_HEIGHT, "Thanks go out to:"));
631         window->AddElement(new Text(16, 8+10*FONT_HEIGHT, "Aaron Giles for the original CoJag"));
632         window->AddElement(new Text(16, 8+11*FONT_HEIGHT, "David Raingeard for the original VJ"));
633         window->AddElement(new Text(16, 8+12*FONT_HEIGHT, "Karl Stenerud for his Musashi 68K emu"));
634         window->AddElement(new Text(16, 8+13*FONT_HEIGHT, "Sam Lantinga for his amazing SDL libs"));
635         window->AddElement(new Text(16, 8+14*FONT_HEIGHT, "Ryan C. Gordon for VJ's web presence"));
636         window->AddElement(new Text(16, 8+15*FONT_HEIGHT, "Curt Vendel for various Jaguar goodies"));
637         window->AddElement(new Text(16, 8+16*FONT_HEIGHT, "The guys over at Atari Age ;-)"));
638 //      window->AddElement(new Image(8, 8, &vj_title_small));
639 //      window->AddElement(new Image(width - (vj_title_small.width + 8), 8, &vj_title_small));
640         window->AddElement(new Image(width - (((Bitmap *)vj_title_small)->width + 8), 8, &vj_title_small));
641
642         return window;
643 }
644
645 Window * MiscOptions(void)
646 {
647         Window * window = new Window(8, 16, 304, 192);
648         window->AddElement(new PushButton(8, 8, &vjs.useJaguarBIOS, "BIOS"));
649         window->AddElement(new SlideSwitch(8, 32, &vjs.hardwareTypeNTSC, "PAL", "NTSC"));
650         window->AddElement(new PushButton(8, 64, &vjs.DSPEnabled, "DSP"));
651         window->AddElement(new SlideSwitch(24, 88, &vjs.usePipelinedDSP, "Original", "Pipelined"));
652         window->AddElement(new SlideSwitch(8, 120, (bool *)&vjs.glFilter, "Sharp", "Blurry"));
653         window->AddElement(new SlideSwitch(8, 152, (bool *)&vjs.renderType, "Normal render", "TV style"));
654
655         window->AddElement(new TextEdit(88, 8, vjs.ROMPath, 20, 0xFF8484FF, 0xFF000000));
656
657 /*TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
658         uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
659         caretPos(0), maxScreenSize(mss) {}*/
660 // Missing:
661 // * BIOS path
662 // * ROM path
663 // * EEPROM path
664 // * joystick
665 // * joystick port
666 // * OpenGL?
667 // * GL Filter type
668 // * Window/fullscreen
669 // * Key definitions
670
671         return window;
672 }
673
674 // Function prototype
675 Window * CrashGracefullyCallback(void);
676
677 //NOTE: Probably should set a flag as well telling it to do a full reset
678 //      of the Jaguar hardware if this happens...
679 void GUICrashGracefully(const char * reason)
680 {
681         finished = true;                                                        // We're finished for now!
682
683         // Since this is used in the menu code as well, we could create another
684         // internal function called "PushWindowOnQueue" or somesuch
685         SDL_Event event;
686         event.type = SDL_USEREVENT;
687         event.user.code = MENU_ITEM_CHOSEN;
688         event.user.data1 = (void *)CrashGracefullyCallback;
689         SDL_PushEvent(&event);
690 }
691
692 Window * CrashGracefullyCallback(void)
693 {
694         Window * window = new Window(8, 16, 304, 192);
695
696         window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "We CRASHED!!!"));
697
698         return window;
699 }