4 // Graphical User Interface support functions
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 02/02/2006 Created this file
12 // JLH 03/13/2006 Abstracted out font to allow external fonts
18 //#include "charset.h" // For Apple II font (small)
23 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
24 #define MASK_R 0xFF000000
25 #define MASK_G 0x00FF0000
26 #define MASK_B 0x0000FF00
27 #define MASK_A 0x000000FF
29 #define MASK_R 0x000000FF
30 #define MASK_G 0x0000FF00
31 #define MASK_B 0x00FF0000
32 #define MASK_A 0xFF000000
36 // This will enable us to set up any font without having it embedded here...
38 static Font font((uint8 *)font2, FONT_WIDTH, FONT_HEIGHT);
39 static std::vector<Font> oldFontList;
42 void SetNewFont(Font newFont)
44 oldFontList.push_back(font);
45 font.data = newFont.data, font.width = newFont.width, font.height = newFont.height;
48 void RestoreOldFont(void)
50 if (oldFontList.size() == 0)
53 font = oldFontList.back();
54 oldFontList.pop_back();
57 uint32 GetFontWidth(void)
62 uint32 GetFontHeight(void)
68 // Draw text at the given x/y coordinates with transparency (255 is fully opaque, 0 is fully transparent).
70 void DrawStringTrans(SDL_Surface * screen, uint32 x, uint32 y, uint32 color, const char * text, ...)
76 vsprintf(string, text, arg);
79 uint8 * esColor = (uint8 *)&color; // Do things endian safe...!
80 uint8 trans = esColor[3];
81 uint32 length = strlen(string);
83 // Make a "stamp" surface (with built in alpha!) for constructing our font chars...
84 SDL_Surface * chr = SDL_CreateRGBSurface(SDL_SWSURFACE, font.width, font.height, 32,
85 MASK_R, MASK_G, MASK_B, MASK_A);
87 rect.x = x, rect.y = y;
91 SDL_GetRGBA(color, screen->format, &r1, &g1, &b1, &a1);
92 color = SDL_MapRGBA(chr->format, r1, g1, b1, a1);
95 for(uint32 i=0; i<length; i++)
98 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * font.width * font.height;
100 for(uint32 yy=0; yy<font.height; yy++)
102 for(uint32 xx=0; xx<font.width; xx++)
104 esColor[3] = (font.data[fontAddr++] * trans) / 255;
105 ((uint32 *)chr->pixels)[xx + (yy * (chr->pitch / 4))] = color;
109 SDL_BlitSurface(chr, NULL, screen, &rect);
110 rect.x += font.width;
113 SDL_FreeSurface(chr);
117 // Draw text at given x/y coords using foreground/background color combination
119 void DrawStringOpaque(SDL_Surface * screen, uint32 x, uint32 y, uint32 fg, uint32 bg, const char * text, ...)
125 vsprintf(string, text, arg);
128 uint8 * esColor = (uint8 *)&fg; // Do things endian safe...!
129 uint32 length = strlen(string);
133 destRect.x = x, destRect.y = y;
134 destRect.w = length * font.width, destRect.h = font.height;
136 SDL_FillRect(screen, &destRect, bg);
138 // Make a "stamp" surface (with built in alpha!) for constructing our font chars...
139 SDL_Surface * chr = SDL_CreateRGBSurface(SDL_SWSURFACE, font.width, font.height, 32,
140 MASK_R, MASK_G, MASK_B, MASK_A);
142 rect.x = x, rect.y = y;
144 //bleh (we have to map colors from the HW surface to the SW surface)
145 uint8 r1, g1, b1, a1;
146 SDL_GetRGBA(fg, screen->format, &r1, &g1, &b1, &a1);
147 fg = SDL_MapRGBA(chr->format, r1, g1, b1, a1);
148 SDL_GetRGBA(bg, screen->format, &r1, &g1, &b1, &a1);
149 bg = SDL_MapRGBA(chr->format, r1, g1, b1, a1);
152 for(uint32 i=0; i<length; i++)
155 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * font.width * font.height;
157 for(uint32 yy=0; yy<font.height; yy++)
159 for(uint32 xx=0; xx<font.width; xx++)
161 esColor[3] = font.data[fontAddr++];
162 ((uint32 *)chr->pixels)[xx + (yy * (chr->pitch / 4))] = fg;
166 SDL_BlitSurface(chr, NULL, screen, &rect);
167 rect.x += font.width;
170 SDL_FreeSurface(chr);
173 bool RectanglesIntersect(SDL_Rect r1, SDL_Rect r2)
175 // The strategy here is to see if any of the sides of the smaller rect
176 // fall within the larger.
179 +-----------------+ r1
190 //This approach fails if r2 is inside of r1. !!! FIX !!! [DONE]
191 if (RectangleFirstInsideSecond(r2, r1))
194 if ((r1.x > r2.x && r1.x < (r2.x + r2.w))
195 || ((r1.x + r1.w) > r2.x && (r1.x + r1.w) < (r2.x + r2.w))
196 || (r1.y > r2.y && r1.y < (r2.y + r2.h))
197 || ((r1.y + r1.h) > r2.y && (r1.y + r1.h) < (r2.y + r2.h)))
203 bool RectangleFirstInsideSecond(SDL_Rect r1, SDL_Rect r2)
205 if ((r1.x > r2.x && (r1.x + r1.w) > r2.x)
206 && (r1.x < (r2.x + r2.w) && (r1.x + r1.w) < (r2.x + r2.w))
207 && (r1.y > r2.y && (r1.y + r1.h) > r2.y)
208 && (r1.y < (r2.y + r2.h) && (r1.y + r1.h) < (r2.y + r2.h)))
216 // Various GUI bitmaps
219 // These representations *should* be endian safe.
222 15 / 256, 15 % 256, // width (HI byte, LO byte)
223 15 / 256, 15 % 256, // height (HI byte, LO byte)
225 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00,
226 0xED, 0x38, 0x38, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xED, 0x38, 0x38, 0xFF,
227 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
228 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
229 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
230 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
231 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
232 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
233 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
234 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
235 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
236 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
237 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
238 0xED, 0x38, 0x38, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xED, 0x38, 0x38, 0xFF,
239 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00
242 uint8 closeBoxHover[] = {
243 15 / 256, 15 % 256, // width (HI byte, LO byte)
244 15 / 256, 15 % 256, // height (HI byte, LO byte)
246 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00,
247 0xED, 0x38, 0x38, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xED, 0x38, 0x38, 0xFF,
248 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
249 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
250 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
251 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xBE, 0x63, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
252 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
253 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xBE, 0x63, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xBE, 0x63, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
254 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
255 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xBE, 0x63, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
256 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xFF, 0xB7, 0x52, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
257 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xFF, 0xAF, 0x40, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
258 0xED, 0x38, 0x38, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFF, 0xA2, 0x20, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
259 0xED, 0x38, 0x38, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xFB, 0x6B, 0x6B, 0xFF, 0xE7, 0x58, 0x58, 0xFF, 0xED, 0x38, 0x38, 0xFF,
260 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00
263 uint8 closeBoxDown[] = {
264 15 / 256, 15 % 256, // width (HI byte, LO byte)
265 15 / 256, 15 % 256, // height (HI byte, LO byte)
267 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00,
268 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x1D, 0x1D, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xE2, 0x1D, 0x1D, 0xFF, 0xED, 0x38, 0x38, 0xFF,
269 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
270 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
271 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
272 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xBD, 0x6E, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
273 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
274 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xBD, 0x6E, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xBD, 0x6E, 0x00, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
275 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
276 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xBD, 0x6E, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
277 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xCC, 0x77, 0x00, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
278 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xE2, 0x86, 0x07, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
279 0xED, 0x38, 0x38, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xF7, 0x9D, 0x1F, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xED, 0x38, 0x38, 0xFF,
280 0xED, 0x38, 0x38, 0xFF, 0xE2, 0x1D, 0x1D, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xC0, 0x2B, 0x2B, 0xFF, 0xE2, 0x1D, 0x1D, 0xFF, 0xED, 0x38, 0x38, 0xFF,
281 0x00, 0x00, 0x00, 0x00, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0xED, 0x38, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00
284 #include "fd-img-128x128.c"
289 #include <sys/types.h> // For MacOS <dirent.h> dependency
295 #include <ctype.h> // For toupper()
296 #include "settings.h"
301 #include "font14pt.h" // Also 15, 16, 17, 18
302 #include "guielements.h"
306 #include "sdlemu_opengl.h"
309 using namespace std; // For STL stuff
311 // Private function prototypes
313 class Window; // Forward declaration...
315 //void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha = NULL);
316 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap);
317 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
318 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
319 //Should call this FillScreenRectangle with a number representing the RGBA value to fill. !!! FIX !!!
320 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h);
321 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color);
322 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 opacity, const char * text, ...);
323 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...);
324 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
325 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...);
326 Window * LoadROM(void);
327 Window * ResetJaguar(void);
328 Window * ResetJaguarCD(void);
329 Window * RunEmu(void);
331 Window * About(void);
332 Window * MiscOptions(void);
334 int gzfilelength(gzFile gd);
336 // External variables
338 extern uint8 * jaguar_mainRam;
339 extern uint8 * jaguar_mainRom;
340 extern uint8 * jaguar_bootRom;
341 extern uint8 * jaguar_CDBootROM;
342 extern bool BIOSLoaded;
343 extern bool CDBIOSLoaded;
345 // Local global variables
347 bool exitGUI = false; // GUI (emulator) done variable
348 int mouseX = 0, mouseY = 0;
349 uint32 background[1280 * 256]; // GUI background buffer
351 char separator[] = "--------------------------------------------------------";
354 // Case insensitive string compare function
355 // Taken straight out of Thinking In C++ by Bruce Eckel. Thanks Bruce!
358 int stringCmpi(const string &s1, const string &s2)
360 // Select the first element of each string:
361 string::const_iterator p1 = s1.begin(), p2 = s2.begin();
363 while (p1 != s1.end() && p2 != s2.end()) // Don�t run past the end
365 if (toupper(*p1) != toupper(*p2)) // Compare upper-cased chars
366 return (toupper(*p1) < toupper(*p2) ? -1 : 1);// Report which was lexically greater
372 // If they match up to the detected eos, say which was longer. Return 0 if the same.
373 return s2.size() - s1.size();
380 enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN };
385 Element(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0)
386 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
387 virtual void HandleKey(SDLKey key) = 0; // These are "pure" virtual functions...
388 virtual void HandleMouseMove(uint32 x, uint32 y) = 0;
389 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0;
390 virtual void Draw(uint32, uint32) = 0;
391 virtual void Notify(Element *) = 0;
392 //Needed? virtual ~Element() = 0;
393 //We're not allocating anything in the base class, so the answer would be NO.
394 bool Inside(uint32 x, uint32 y);
396 // static void SetScreenAndPitch(int16 * s, uint32 p) { screenBuffer = s, pitch = p; }
397 static void SetScreenAndPitch(uint32 * s, uint32 p) { screenBuffer = s, pitch = p; }
402 // Class variables...
403 // static int16 * screenBuffer;
404 static uint32 * screenBuffer;
408 // Initialize class variables (Element)
409 //int16 * Element::screenBuffer = NULL;
410 uint32 * Element::screenBuffer = NULL;
411 uint32 Element::pitch = 0;
413 bool Element::Inside(uint32 x, uint32 y)
415 return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
416 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
424 class Button: public Element
427 Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
428 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
429 bgColor(0xFF00FF00), pic(NULL), elementToTell(NULL) {}
430 Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
431 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
432 bgColor(0xFF00FF00), pic(p), elementToTell(NULL) {}
433 // Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
434 Button(uint32 x, uint32 y, uint32 * p, uint32 * pH = NULL, uint32 * pD = NULL): Element(x, y, 0, 0),
435 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
436 bgColor(0xFF00FF00), pic(p), picHover(pH), picDown(pD), elementToTell(NULL)
437 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
438 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
439 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
440 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL) {}
441 Button(uint32 x, uint32 y, string s): Element(x, y, 0, FONT_HEIGHT),
442 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
443 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL)
444 { extents.w = s.length() * FONT_WIDTH; }
445 virtual void HandleKey(SDLKey key) {}
446 virtual void HandleMouseMove(uint32 x, uint32 y);
447 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
448 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
449 virtual void Notify(Element *) {}
450 bool ButtonClicked(void) { return activated; }
451 void SetNotificationElement(Element * e) { elementToTell = e; }
454 bool activated, clicked, inside;
455 uint32 fgColor, bgColor;
456 uint32 * pic, * picHover, * picDown;
458 Element * elementToTell;
461 void Button::HandleMouseMove(uint32 x, uint32 y)
463 inside = Inside(x, y);
466 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
473 if (clicked && !mouseDown)
475 clicked = false, activated = true;
477 // Send a message that we're activated (if there's someone to tell, that is)
479 elementToTell->Notify(this);
483 clicked = activated = false;
486 void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
488 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
490 if (text.length() > 0) // Simple text button
493 for(uint32 y=0; y<extents.h; y++)
495 for(uint32 x=0; x<extents.w; x++)
497 // Doesn't clip in y axis! !!! FIX !!!
498 if (extents.x + x < pitch)
499 screenBuffer[addr + x + (y * pitch)]
500 // = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
501 //43F0 -> 010000 11111 10000 -> 0100 0001 1111 1111 1000 0100 -> 41 FF 84
502 = (clicked && inside ? fgColor : (inside ? 0xFF84FF41 : bgColor));
506 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
508 else // Graphical button
510 uint32 * picToShow = pic;
512 if (picHover != NULL && inside && !clicked)
513 picToShow = picHover;
515 if (picDown != NULL && inside && clicked)
518 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, picToShow);
527 class PushButton: public Element
530 // Save state externally?
531 //We pass in a state variable if we want to track it externally, otherwise we use our own
532 //internal state var. Still need to do some kind of callback for pushbuttons that do things
533 //like change from fullscreen to windowed... !!! FIX !!!
536 // PushButton(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
537 // activated(false), clicked(false), inside(false), fgColor(0xFFFF),
538 // bgColor(0x03E0), pic(NULL), elementToTell(NULL) {}
539 // PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 8, 8), state(st),
540 // inside(false), text(s) { if (st == NULL) state = &internalState; }
541 PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 16, 16), state(st),
542 inside(false), text(s) { if (st == NULL) state = &internalState; }
543 /* Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
544 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
545 bgColor(0x03E0), pic(p), elementToTell(NULL) {}
546 Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
547 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
548 bgColor(0x03E0), pic(p), elementToTell(NULL)
549 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
550 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
551 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
552 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) {}
553 PushButton(uint32 x, uint32 y, string s): Element(x, y, 0, 8),
554 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
555 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL)
556 { extents.w = s.length() * 8; }*/
557 virtual void HandleKey(SDLKey key) {}
558 virtual void HandleMouseMove(uint32 x, uint32 y);
559 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
560 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
561 virtual void Notify(Element *) {}
562 // bool ButtonClicked(void) { return activated; }
563 // void SetNotificationElement(Element * e) { elementToTell = e; }
568 // bool activated, clicked, inside;
569 // uint16 fgColor, bgColor;
572 // Element * elementToTell;
576 void PushButton::HandleMouseMove(uint32 x, uint32 y)
578 inside = Inside(x, y);
581 void PushButton::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
583 if (inside && mouseDown)
588 if (clicked && !mouseDown)
590 clicked = false, activated = true;
592 // Send a message that we're activated (if there's someone to tell, that is)
594 elementToTell->Notify(this);
599 // clicked = activated = false;
602 void PushButton::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
604 /* uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
606 for(uint32 y=0; y<extents.h; y++)
608 for(uint32 x=0; x<extents.w; x++)
610 // Doesn't clip in y axis! !!! FIX !!!
611 if (extents.x + x < pitch)
612 screenBuffer[addr + x + (y * pitch)]
613 = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
618 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbDown);
620 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbUp);
622 if (text.length() > 0)
623 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text.c_str());
631 class SlideSwitch: public Element
634 // Save state externally?
635 //Seems to be handled the same as PushButton, but without sanity checks. !!! FIX !!!
638 SlideSwitch(uint32 x, uint32 y, bool * st, string s1, string s2): Element(x, y, 16, 32), state(st),
639 inside(false), text1(s1), text2(s2) {}
640 virtual void HandleKey(SDLKey key) {}
641 virtual void HandleMouseMove(uint32 x, uint32 y);
642 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
643 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
644 virtual void Notify(Element *) {}
645 // bool ButtonClicked(void) { return activated; }
646 // void SetNotificationElement(Element * e) { elementToTell = e; }
651 // bool activated, clicked, inside;
652 // uint16 fgColor, bgColor;
655 // Element * elementToTell;
658 void SlideSwitch::HandleMouseMove(uint32 x, uint32 y)
660 inside = Inside(x, y);
663 void SlideSwitch::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
665 if (inside && mouseDown)
670 if (clicked && !mouseDown)
672 clicked = false, activated = true;
674 // Send a message that we're activated (if there's someone to tell, that is)
676 elementToTell->Notify(this);
681 // clicked = activated = false;
684 void SlideSwitch::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
686 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, (*state ? slideSwitchDown : slideSwitchUp));
688 if (text1.length() > 0)
689 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text1.c_str());
691 if (text2.length() > 0)
692 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY + 16, false, "%s", text2.c_str());
700 class Window: public Element
703 /* Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
704 fgColor(0x4FF0), bgColor(0xFE10)
705 { close = new Button(w - 8, 1, closeBox); list.push_back(close); }*/
706 Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0,
707 void (* f)(Element *) = NULL): Element(x, y, w, h),
708 // /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0x1E10),
709 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
710 //1E10 -> 000111 10000 10000 -> 0001 1111 1000 0100 1000 0100 -> 1F 84 84
711 /*clicked(false), inside(false),*/ fgColor(0xFF84FF4D), bgColor(0xFF84841F),
713 { close = new Button(w - (CLOSEBOX_WIDTH + 1), 1, closeBox, closeBoxHover, closeBoxDown);
714 list.push_back(close);
715 close->SetNotificationElement(this); }
717 virtual void HandleKey(SDLKey key);
718 virtual void HandleMouseMove(uint32 x, uint32 y);
719 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
720 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
721 virtual void Notify(Element * e);
722 void AddElement(Element * e);
723 // bool WindowActive(void) { return true; }//return !close->ButtonClicked(); }
726 // bool clicked, inside;
727 uint32 fgColor, bgColor;
728 void (* handler)(Element *);
730 //We have to use a list of Element *pointers* because we can't make a list that will hold
731 //all the different object types in the same list...
732 vector<Element *> list;
737 for(uint32 i=0; i<list.size(); i++)
742 void Window::HandleKey(SDLKey key)
744 if (key == SDLK_ESCAPE)
747 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
748 SDL_PushEvent(&event);
751 // Handle the items this window contains...
752 for(uint32 i=0; i<list.size(); i++)
753 // Make coords relative to upper right corner of this window...
754 list[i]->HandleKey(key);
757 void Window::HandleMouseMove(uint32 x, uint32 y)
759 // Handle the items this window contains...
760 for(uint32 i=0; i<list.size(); i++)
761 // Make coords relative to upper right corner of this window...
762 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
765 void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
767 // Handle the items this window contains...
768 for(uint32 i=0; i<list.size(); i++)
769 // Make coords relative to upper right corner of this window...
770 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
773 void Window::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
775 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
777 for(uint32 y=0; y<extents.h; y++)
779 for(uint32 x=0; x<extents.w; x++)
781 // Doesn't clip in y axis! !!! FIX !!!
782 if (extents.x + x < pitch)
783 screenBuffer[addr + x + (y * pitch)] = bgColor;
787 // Handle the items this window contains...
788 for(uint32 i=0; i<list.size(); i++)
789 list[i]->Draw(extents.x, extents.y);
792 void Window::AddElement(Element * e)
797 void Window::Notify(Element * e)
802 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
803 SDL_PushEvent(&event);
812 class Text: public Element
815 // Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
816 // fgColor(0x4FF0), bgColor(0xFE10) {}
817 // Text(uint32 x, uint32 y, string s, uint16 fg = 0x4FF0, uint16 bg = 0xFE10): Element(x, y, 0, 0),
818 // fgColor(fg), bgColor(bg), text(s) {}
819 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
820 //FE10 -> 111111 10000 10000 -> 1111 1111 1000 0100 1000 0100 -> FF 84 84
821 Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
822 fgColor(0xFF8484FF), bgColor(0xFF84FF4D) {}
823 Text(uint32 x, uint32 y, string s, uint32 fg = 0xFF8484FF, uint32 bg = 0xFF84FF4D):
824 Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s) {}
825 virtual void HandleKey(SDLKey key) {}
826 virtual void HandleMouseMove(uint32 x, uint32 y) {}
827 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
828 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
829 virtual void Notify(Element *) {}
832 uint32 fgColor, bgColor;
836 void Text::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
838 if (text.length() > 0)
839 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
840 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
845 // Static image class
848 class Image: public Element
851 Image(uint32 x, uint32 y, const void * img): Element(x, y, 0, 0), image(img) {}
852 virtual void HandleKey(SDLKey key) {}
853 virtual void HandleMouseMove(uint32 x, uint32 y) {}
854 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
855 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
856 virtual void Notify(Element *) {}
859 uint32 fgColor, bgColor;
863 void Image::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
866 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, image);
874 class TextEdit: public Element
877 TextEdit(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
878 fgColor(0xFF8484FF), bgColor(0xFF84FF4D), text(""), caretPos(0),
880 TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
881 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
882 caretPos(0), maxScreenSize(mss) {}
883 virtual void HandleKey(SDLKey key);
884 virtual void HandleMouseMove(uint32 x, uint32 y) {}
885 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
886 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
887 virtual void Notify(Element *) {}
890 uint32 fgColor, bgColor;
893 uint32 maxScreenSize;
896 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
897 void TextEdit::HandleKey(SDLKey key)
899 if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9) || key == SDLK_PERIOD
900 || key == SDLK_SLASH)
902 //Need to handle shift key as well...
903 text[caretPos++] = key;
906 else if (key == SDLK_BACKSPACE)
910 else if (key == SDLK_DELETE)
916 void TextEdit::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
918 if (text.length() > 0)
920 FillScreenRectangle(screenBuffer, extents.x + offsetX, extents.y + offsetY, FONT_WIDTH * maxScreenSize, FONT_HEIGHT, bgColor);
921 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
922 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
925 // Draw the caret (underscore? or vertical line?)
933 class ListBox: public Element
934 //class ListBox: public Window
937 // ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
938 ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);//: Window(x, y, w, h),
939 // windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8),
940 // elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
941 // downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) {}
942 virtual void HandleKey(SDLKey key);
943 virtual void HandleMouseMove(uint32 x, uint32 y);
944 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
945 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
946 virtual void Notify(Element * e);
947 void SetNotificationElement(Element * e) { elementToTell = e; }
948 void AddItem(string s);
949 string GetSelectedItem(void);
953 uint32 windowPtr, cursor, limit;
954 uint32 charWidth, charHeight; // Box width/height in characters
955 Element * elementToTell;
956 Button upArrow, downArrow, upArrow2;
960 uint32 yRelativePoint;
963 ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h),
964 thumbClicked(false), windowPtr(0), cursor(0), limit(0), charWidth((w / FONT_WIDTH) - 1),
965 charHeight(h / FONT_HEIGHT), elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
966 downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox)
968 upArrow.SetNotificationElement(this);
969 downArrow.SetNotificationElement(this);
970 upArrow2.SetNotificationElement(this);
971 extents.w -= 8; // Make room for scrollbar...
974 void ListBox::HandleKey(SDLKey key)
976 if (key == SDLK_DOWN)
978 if (cursor != limit - 1) // Cursor is within its window
980 else // Otherwise, scroll the window...
982 if (cursor + windowPtr != item.size() - 1)
986 else if (key == SDLK_UP)
996 else if (key == SDLK_PAGEDOWN)
998 if (cursor != limit - 1)
1003 if (windowPtr > item.size() - limit)
1004 windowPtr = item.size() - limit;
1007 else if (key == SDLK_PAGEUP)
1013 if (windowPtr < limit)
1019 else if (key >= SDLK_a && key <= SDLK_z)
1021 // Advance cursor to filename with first letter pressed...
1022 uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
1024 for(uint32 i=0; i<item.size(); i++)
1026 if ((item[i][0] & 0xDF) == which)
1028 cursor = i - windowPtr;
1029 if (i > windowPtr + limit - 1)
1030 windowPtr = i - limit + 1, cursor = limit - 1;
1032 windowPtr = i, cursor = 0;
1039 void ListBox::HandleMouseMove(uint32 x, uint32 y)
1041 upArrow.HandleMouseMove(x - extents.x, y - extents.y);
1042 downArrow.HandleMouseMove(x - extents.x, y - extents.y);
1043 upArrow2.HandleMouseMove(x - extents.x, y - extents.y);
1047 uint32 sbHeight = extents.h - 24,
1048 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight);
1050 //yRelativePoint is the spot on the thumb where we clicked...
1051 int32 newThumbStart = y - yRelativePoint;
1053 if (newThumbStart < 0)
1056 if ((uint32)newThumbStart > sbHeight - thumb)
1057 newThumbStart = sbHeight - thumb;
1059 windowPtr = (uint32)(((float)newThumbStart / (float)sbHeight) * (float)item.size());
1060 //Check for cursor bounds as well... Or do we need to???
1061 //Actually, we don't...!
1065 void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1067 if (Inside(x, y) && mouseDown)
1069 // Why do we have to do this??? (- extents.y?)
1070 // I guess it's because only the Window class has offsetting implemented... !!! FIX !!!
1071 // cursor = (y - extents.y) / 8;
1072 cursor = (y - extents.y) / FONT_HEIGHT;
1075 // Check for a hit on the scrollbar...
1076 if (x > (uint32)(extents.x + extents.w) && x <= (uint32)(extents.x + extents.w + 8)
1077 && y > (uint32)(extents.y + 8) && y <= (uint32)(extents.y + extents.h - 16))
1081 // This shiaut should be calculated in AddItem(), not here... (or in Draw() for that matter)
1082 uint32 sbHeight = extents.h - 24,
1083 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1084 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1086 // Did we hit the thumb?
1087 if (y >= (extents.y + 8 + thumbStart) && y < (extents.y + 8 + thumbStart + thumb))
1088 thumbClicked = true, yRelativePoint = y - thumbStart;
1090 //Seems that this is useless--never reached except in rare cases and that the code outside is
1093 // thumbClicked = false;
1097 thumbClicked = false;
1099 upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1100 downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1101 upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1104 void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1106 for(uint32 i=0; i<limit; i++)
1108 // Strip off the extension
1109 // (extension stripping should be an option, not default!)
1110 string s(item[windowPtr + i], 0, item[windowPtr + i].length() - 4);
1111 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*8,
1112 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*FONT_HEIGHT,
1113 (cursor == i ? true : false), "%-*.*s", charWidth, charWidth, s.c_str());
1116 upArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1117 downArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1118 upArrow2.Draw(extents.x + offsetX, extents.y + offsetY);
1120 uint32 sbHeight = extents.h - 24,
1121 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1122 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1124 for(uint32 y=extents.y+offsetY+8; y<extents.y+offsetY+extents.h-16; y++)
1126 // for(uint32 x=extents.x+offsetX+extents.w-8; x<extents.x+offsetX+extents.w; x++)
1127 for(uint32 x=extents.x+offsetX+extents.w; x<extents.x+offsetX+extents.w+8; x++)
1129 if (y >= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8))
1130 // screenBuffer[x + (y * pitch)] = (thumbClicked ? 0x458E : 0xFFFF);
1131 //458E -> 01 0001 0 1100 0 1110 -> 0100 0101 0110 0011 0111 0011 -> 45 63 73
1132 screenBuffer[x + (y * pitch)] = (thumbClicked ? 0xFF736345 : 0xFFFFFFFF);
1134 // screenBuffer[x + (y * pitch)] = 0x0200;
1135 //0200 -> 000000 10000 00000 -> 00 1000 0100 00
1136 screenBuffer[x + (y * pitch)] = 0xFF008400;
1141 void ListBox::Notify(Element * e)
1143 if (e == &upArrow || e == &upArrow2)
1149 if (cursor < limit - 1)
1153 else if (e == &downArrow)
1155 if (windowPtr < item.size() - limit)
1165 void ListBox::AddItem(string s)
1167 // Do a simple insertion sort
1168 bool inserted = false;
1170 for(vector<string>::iterator i=item.begin(); i<item.end(); i++)
1172 if (stringCmpi(s, *i) == -1)
1183 limit = (item.size() > charHeight ? charHeight : item.size());
1186 string ListBox::GetSelectedItem(void)
1188 return item[windowPtr + cursor];
1196 class FileList: public Window
1199 FileList(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);
1200 virtual ~FileList() {}
1201 virtual void HandleKey(SDLKey key);
1202 virtual void HandleMouseMove(uint32 x, uint32 y) { Window::HandleMouseMove(x, y); }
1203 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) { Window::HandleMouseButton(x, y, mouseDown); }
1204 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) { Window::Draw(offsetX, offsetY); }
1205 virtual void Notify(Element * e);
1212 //Need 4 buttons, one scrollbar...
1213 FileList::FileList(uint32 x, uint32 y, uint32 w, uint32 h): Window(x, y, w, h)
1215 files = new ListBox(8, 8, w - 16, h - 32);
1217 load = new Button(8, h - 16, " Load ");
1219 load->SetNotificationElement(this);
1221 //!!! FIX !!! Directory might not exist--this shouldn't cause VJ to crash!
1222 DIR * dp = opendir(vjs.ROMPath);
1227 while ((de = readdir(dp)) != NULL)
1229 char * ext = strrchr(de->d_name, '.');
1232 if (strcasecmp(ext, ".zip") == 0 || strcasecmp(ext, ".j64") == 0
1233 || strcasecmp(ext, ".abs") == 0 || strcasecmp(ext, ".jag") == 0
1234 || strcasecmp(ext, ".rom") == 0)
1235 files->AddItem(string(de->d_name));
1242 //Give a diagnostic message here so that the (l)user can figure out what went wrong. !!! FIX !!!
1246 void FileList::HandleKey(SDLKey key)
1248 if (key == SDLK_RETURN)
1251 Window::HandleKey(key);
1254 void FileList::Notify(Element * e)
1258 char filename[MAX_PATH];
1259 strcpy(filename, vjs.ROMPath);
1261 if (strlen(filename) > 0)
1262 if (filename[strlen(filename) - 1] != '/')
1263 strcat(filename, "/");
1265 strcat(filename, files->GetSelectedItem().c_str());
1267 // uint32 romSize = JaguarLoadROM(jaguar_mainRom, filename);
1268 // JaguarLoadCart(jaguar_mainRom, filename);
1269 if (JaguarLoadFile(filename))
1272 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1273 SDL_PushEvent(&event);
1275 event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1276 event.user.data1 = (void *)ResetJaguar;
1277 SDL_PushEvent(&event);
1282 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1283 SDL_PushEvent(&event);
1285 // Handle the error, but don't run...
1286 // Tell the user that we couldn't run their file for some reason... !!! FIX !!!
1287 //how to kludge: Make a function like ResetJaguar which creates the dialog window
1296 // Menu class & supporting structs/classes
1302 Window * (* action)(void);
1305 NameAction(string n, Window * (* a)(void) = NULL, SDLKey k = SDLK_UNKNOWN): name(n),
1306 action(a), hotKey(k) {}
1312 MenuItems(): charLength(0) {}
1313 bool Inside(uint32 x, uint32 y)
1314 { return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
1315 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false); }
1318 vector<NameAction> item;
1323 class Menu: public Element
1326 // 1CFF -> 0 001 11 00 111 1 1111
1327 // 421F -> 0 100 00 10 000 1 1111
1328 Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = FONT_HEIGHT,
1329 /* uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F,
1330 uint16 bgch = 0x1CFF): Element(x, y, w, h), activated(false), clicked(false),*/
1331 /* uint32 fgc = 0xFF3F3F00, uint32 bgc = 0x7F000000, uint32 fgch = 0xFF878700,
1332 uint32 bgch = 0xFF3F3F00): Element(x, y, w, h), activated(false), clicked(false),*/
1333 /* uint32 fgc = 0xFFFF3F3F, uint32 bgc = 0xFF7F0000, uint32 fgch = 0xFFFF8787,
1334 uint32 bgch = 0xFFFF3F3F): Element(x, y, w, h), activated(false), clicked(false),*/
1335 uint32 fgc = 0xFF7F0000, uint32 bgc = 0xFFFF3F3F, uint32 fgch = 0xFFFF3F3F,
1336 uint32 bgch = 0xFFFF8787): Element(x, y, w, h), activated(false), clicked(false),
1337 inside(0), insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch),
1338 bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1) {}
1339 virtual void HandleKey(SDLKey key);
1340 virtual void HandleMouseMove(uint32 x, uint32 y);
1341 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
1342 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
1343 virtual void Notify(Element *) {}
1344 void Add(MenuItems mi);
1347 bool activated, clicked;
1348 uint32 inside, insidePopup;
1349 // uint16 fgColor, bgColor, fgColorHL, bgColorHL;
1350 uint32 fgColor, bgColor, fgColorHL, bgColorHL;
1351 int menuChosen, menuItemChosen;
1354 vector<MenuItems> itemList;
1357 void Menu::HandleKey(SDLKey key)
1359 for(uint32 i=0; i<itemList.size(); i++)
1361 for(uint32 j=0; j<itemList[i].item.size(); j++)
1363 if (itemList[i].item[j].hotKey == key)
1366 event.type = SDL_USEREVENT;
1367 event.user.code = MENU_ITEM_CHOSEN;
1368 event.user.data1 = (void *)itemList[i].item[j].action;
1369 SDL_PushEvent(&event);
1371 clicked = false, menuChosen = menuItemChosen = -1;
1378 void Menu::HandleMouseMove(uint32 x, uint32 y)
1380 inside = insidePopup = 0;
1384 // Find out *where* we are inside the menu bar
1385 uint32 xpos = extents.x;
1387 for(uint32 i=0; i<itemList.size(); i++)
1389 uint32 width = (itemList[i].title.length() + 2) * FONT_WIDTH;
1391 if (x >= xpos && x < xpos + width)
1402 if (!Inside(x, y) && !clicked)
1407 if (itemList[menuChosen].Inside(x, y) && clicked)
1409 insidePopup = ((y - itemList[menuChosen].extents.y) / FONT_HEIGHT) + 1;
1410 menuItemChosen = insidePopup - 1;
1414 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1423 menuChosen = -1; // clicked is already false...!
1426 else // clicked == true
1428 if (insidePopup && !mouseDown) // I.e., mouse-button-up
1431 if (itemList[menuChosen].item[menuItemChosen].action != NULL)
1433 // itemList[menuChosen].item[menuItemChosen].action();
1435 event.type = SDL_USEREVENT;
1436 event.user.code = MENU_ITEM_CHOSEN;
1437 event.user.data1 = (void *)itemList[menuChosen].item[menuItemChosen].action;
1438 SDL_PushEvent(&event);
1440 clicked = false, menuChosen = menuItemChosen = -1;
1443 while (SDL_PollEvent(&event)); // Flush the event queue...
1444 event.type = SDL_MOUSEMOTION;
1446 SDL_GetMouseState(&mx, &my);
1447 event.motion.x = mx, event.motion.y = my;
1448 SDL_PushEvent(&event); // & update mouse position...!
1452 if (!inside && !insidePopup && mouseDown)
1453 clicked = false, menuChosen = menuItemChosen = -1;
1457 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1459 uint32 xpos = extents.x + offsetX;
1461 for(uint32 i=0; i<itemList.size(); i++)
1463 // uint16 color1 = fgColor, color2 = bgColor;
1464 uint32 color1 = fgColor, color2 = bgColor;
1465 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
1466 color1 = fgColorHL, color2 = bgColorHL;
1468 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
1469 " %s ", itemList[i].title.c_str());
1470 xpos += (itemList[i].title.length() + 2) * FONT_WIDTH;
1473 // Draw sub menu (but only if active)
1476 uint32 ypos = extents.y + FONT_HEIGHT + 1;
1478 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
1480 // uint16 color1 = fgColor, color2 = bgColor;
1481 uint32 color1 = fgColor, color2 = bgColor;
1483 if (insidePopup == i + 1)
1484 color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
1486 if (itemList[menuChosen].item[i].name.length() > 0)
1487 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1488 color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
1489 itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
1491 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1492 fgColor, bgColor, "%.*s", itemList[menuChosen].charLength + 2, separator);
1494 ypos += FONT_HEIGHT;
1499 void Menu::Add(MenuItems mi)
1501 for(uint32 i=0; i<mi.item.size(); i++)
1502 if (mi.item[i].name.length() > mi.charLength)
1503 mi.charLength = mi.item[i].name.length();
1505 // Set extents here as well...
1506 mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + FONT_HEIGHT + 1;
1507 mi.extents.w = (mi.charLength + 2) * FONT_WIDTH, mi.extents.h = mi.item.size() * FONT_HEIGHT;
1509 itemList.push_back(mi);
1510 extents.w += (mi.title.length() + 2) * FONT_WIDTH;
1514 //Do we even *need* this?
1515 //Doesn't seem like it...
1516 /*class RootWindow: public Window
1519 RootWindow(Menu * m, Window * w = NULL): menu(m), window(w) {}
1520 //Do we even need to care about this crap?
1521 // { extents.x = extents.y = 0, extents.w = 320, extents.h = 240; }
1522 virtual void HandleKey(SDLKey key) {}
1523 virtual void HandleMouseMove(uint32 x, uint32 y) {}
1524 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
1525 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) {}
1526 virtual void Notify(Element *) {}
1531 int16 * rootImage[1280 * 240 * 2];
1536 // Draw text at the given x/y coordinates. Can invert text as well.
1538 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
1543 va_start(arg, text);
1544 vsprintf(string, text, arg);
1547 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1548 uint32 length = strlen(string), address = x + (y * pitch);
1550 uint32 color1 = 0x0080FF;
1551 uint8 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1552 uint8 xorMask = (invert ? 0xFF : 0x00);
1554 for(uint32 i=0; i<length; i++)
1556 uint8 c = string[i];
1557 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * FONT_WIDTH * FONT_HEIGHT;
1559 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1561 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1563 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1565 uint8 eBlue = (existingColor >> 16) & 0xFF,
1566 eGreen = (existingColor >> 8) & 0xFF,
1567 eRed = existingColor & 0xFF;
1569 uint8 trans = font2[fontAddr] ^ xorMask;
1570 uint8 invTrans = trans ^ 0xFF;
1572 uint32 bRed = (eRed * invTrans + nRed * trans) / 255,
1573 bGreen = (eGreen * invTrans + nGreen * trans) / 255,
1574 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1576 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1581 address += FONT_WIDTH;
1586 // Draw text at the given x/y coordinates, using FG/BG colors.
1588 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...)
1593 va_start(arg, text);
1594 vsprintf(string, text, arg);
1597 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1598 uint32 length = strlen(string), address = x + (y * pitch);
1600 uint8 eBlue = (color2 >> 16) & 0xFF, eGreen = (color2 >> 8) & 0xFF, eRed = color2 & 0xFF,
1601 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1603 for(uint32 i=0; i<length; i++)
1605 uint8 c = string[i];
1606 c = (c < 32 ? 0 : c - 32);
1607 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1609 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1611 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1613 uint8 trans = font2[fontAddr++];
1614 uint8 invTrans = trans ^ 0xFF;
1616 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1617 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1618 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1620 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1624 address += FONT_WIDTH;
1629 // Draw text at the given x/y coordinates with transparency (0 is fully opaque, 32 is fully transparent).
1631 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 trans, const char * text, ...)
1636 va_start(arg, text);
1637 vsprintf(string, text, arg);
1640 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1641 uint32 length = strlen(string), address = x + (y * pitch);
1643 for(uint32 i=0; i<length; i++)
1645 uint32 fontAddr = (uint32)string[i] * 64;
1647 for(uint32 yy=0; yy<8; yy++)
1649 for(uint32 xx=0; xx<8; xx++)
1651 if (font1[fontAddr])
1653 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1655 uint8 eBlue = (existingColor >> 16) & 0xFF,
1656 eGreen = (existingColor >> 8) & 0xFF,
1657 eRed = existingColor & 0xFF,
1658 //This could be done ahead of time, instead of on each pixel...
1659 nBlue = (color >> 16) & 0xFF,
1660 nGreen = (color >> 8) & 0xFF,
1661 nRed = color & 0xFF;
1663 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
1664 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
1665 //because dividing by 32 is faster than dividing by 31...!
1666 uint8 invTrans = 32 - trans;
1668 uint32 bRed = (eRed * trans + nRed * invTrans) / 32;
1669 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
1670 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
1672 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1684 // Draw text at the given x/y coordinates, using FG color and overlay alpha blending.
1686 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...)
1691 va_start(arg, text);
1692 vsprintf(string, text, arg);
1695 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1696 uint32 length = strlen(string), address = x + (y * pitch);
1698 color &= 0x00FFFFFF; // Just in case alpha was passed in...
1700 for(uint32 i=0; i<length; i++)
1702 uint8 c = string[i];
1703 c = (c < 32 ? 0 : c - 32);
1704 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1706 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1708 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1710 uint8 fontTrans = font2[fontAddr++];
1711 uint32 newTrans = (fontTrans * transparency / 255) << 24;
1712 uint32 pixel = newTrans | color;
1714 *(screen + address + xx + (yy * pitch)) = pixel;
1718 address += FONT_WIDTH;
1724 // Uses zero as transparent color
1725 // Can also use an optional alpha channel
1726 // Alpha channel is now mandatory! ;-)
1728 //void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap, uint8 * alpha/*=NULL*/)
1729 /*void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha)
1731 uint32 width = bitmap[0], height = bitmap[1];
1734 // uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
1735 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1736 uint32 address = x + (y * pitch);
1738 for(uint32 yy=0; yy<height; yy++)
1740 for(uint32 xx=0; xx<width; xx++)
1744 if (*bitmap && x + xx < pitch) // NOTE: Still doesn't clip the Y val...
1745 *(screen + address + xx + (yy * pitch)) = *bitmap;
1749 uint8 trans = *alpha;
1750 uint32 color = *bitmap;
1751 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1753 uint8 eRed = existingColor & 0xFF,
1754 eGreen = (existingColor >> 8) & 0xFF,
1755 eBlue = (existingColor >> 16) & 0xFF,
1757 nRed = color & 0xFF,
1758 nGreen = (color >> 8) & 0xFF,
1759 nBlue = (color >> 16) & 0xFF;
1761 uint8 invTrans = 255 - trans;
1762 uint32 bRed = (eRed * trans + nRed * invTrans) / 255;
1763 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 255;
1764 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 255;
1766 uint32 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1768 *(screen + address + xx + (yy * pitch)) = blendedColor;
1777 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap)
1779 uint32 width = bitmap[0], height = bitmap[1];
1782 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1783 uint32 address = x + (y * pitch);
1785 for(uint32 yy=0; yy<height; yy++)
1787 for(uint32 xx=0; xx<width; xx++)
1789 uint32 color = *bitmap;
1790 uint32 blendedColor = color;
1791 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1793 if (existingColor >> 24 != 0x00) // Pixel needs blending
1795 uint8 trans = color >> 24;
1796 uint8 invTrans = trans ^ 0xFF;//255 - trans;
1798 uint8 eRed = existingColor & 0xFF,
1799 eGreen = (existingColor >> 8) & 0xFF,
1800 eBlue = (existingColor >> 16) & 0xFF,
1802 nRed = color & 0xFF,
1803 nGreen = (color >> 8) & 0xFF,
1804 nBlue = (color >> 16) & 0xFF;
1806 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1807 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1808 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1810 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1813 *(screen + address + xx + (yy * pitch)) = blendedColor;
1819 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1821 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1822 uint32 address = x + (y * pitch);
1825 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1827 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1829 uint32 color = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1830 uint32 blendedColor = color;
1831 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1833 if (existingColor >> 24 != 0x00) // Pixel needs blending
1835 uint8 trans = color >> 24;
1836 uint8 invTrans = trans ^ 0xFF;
1838 uint8 eRed = existingColor & 0xFF,
1839 eGreen = (existingColor >> 8) & 0xFF,
1840 eBlue = (existingColor >> 16) & 0xFF,
1842 nRed = color & 0xFF,
1843 nGreen = (color >> 8) & 0xFF,
1844 nBlue = (color >> 16) & 0xFF;
1846 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1847 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1848 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1850 // Instead of $FF, should use the alpha from the destination pixel as the final alpha value...
1851 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1854 *(screen + address + xx + (yy * pitch)) = blendedColor;
1861 // Draw a bitmap without using blending
1863 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1865 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1866 uint32 address = x + (y * pitch);
1869 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1871 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1873 *(screen + address + xx + (yy * pitch)) = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1880 // Fill a portion of the screen with the passed in color
1882 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color)
1883 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h)
1885 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1886 uint32 address = x + (y * pitch);
1888 for(uint32 yy=0; yy<h; yy++)
1889 for(uint32 xx=0; xx<w; xx++)
1890 *(screen + address + xx + (yy * pitch)) = color;
1895 // GUI stuff--it's not crunchy, it's GUI! ;-)
1900 SDL_ShowCursor(SDL_DISABLE);
1901 SDL_GetMouseState(&mouseX, &mouseY);
1911 //bool GUIMain(void)
1912 bool GUIMain(char * filename)
1914 WriteLog("GUI: Inside GUIMain...\n");
1916 uint32 pointerBGSave[6 * 8 + 2];
1917 pointerBGSave[0] = 6;
1918 pointerBGSave[1] = 8;
1920 // Need to set things up so that it loads and runs a file if given on the command line. !!! FIX !!! [DONE]
1921 extern uint32 * backbuffer;
1922 // bool done = false;
1924 Window * mainWindow = NULL;
1926 // Set up the GUI classes...
1927 // Element::SetScreenAndPitch(backbuffer, GetSDLScreenWidthInPixels());
1928 Element::SetScreenAndPitch((uint32 *)sdlemuGetOverlayPixels(), sdlemuGetOverlayWidthInPixels());
1929 sdlemuEnableOverlay();
1933 mi.title = "Jaguar";
1934 mi.item.push_back(NameAction("Load...", LoadROM, SDLK_l));
1935 mi.item.push_back(NameAction("Reset", ResetJaguar, SDLK_r));
1937 mi.item.push_back(NameAction("Reset CD", ResetJaguarCD, SDLK_c));
1938 mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE));
1939 mi.item.push_back(NameAction(""));
1940 mi.item.push_back(NameAction("Quit", Quit, SDLK_q));
1942 mi.title = "Settings";
1944 mi.item.push_back(NameAction("Video..."));
1945 mi.item.push_back(NameAction("Audio..."));
1946 mi.item.push_back(NameAction("Misc...", MiscOptions, SDLK_m));
1950 mi.item.push_back(NameAction("About...", About));
1953 bool showMouse = true;
1955 // Grab the BG where the mouse will be painted (prime the backstore)
1959 Bitmap ptr = { 6, 8, 4,
1960 ""//"000011112222333344445555"
1961 //"000011112222333344445555"
1962 //"000011112222333344445555"
1963 //"000011112222333344445555"
1964 //"000011112222333344445555"
1965 //"000011112222333344445555"
1966 //"000011112222333344445555"
1967 //"000011112222333344445555"
1969 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
1972 for(uint32 y=0; y<pointerBGSave[1]; y++)
1973 for(uint32 x=0; x<pointerBGSave[0]; x++)
1974 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
1976 uint32 oldMouseX = mouseX, oldMouseY = mouseY;
1978 //This is crappy!!! !!! FIX !!!
1979 //Is this even needed any more? Hmm. Maybe. Dunno.
1980 WriteLog("GUI: Resetting Jaguar...\n");
1983 WriteLog("GUI: Clearing BG save...\n");
1984 // Set up our background save...
1985 // memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2);
1986 //1111 -> 000100 01000 10001 -> 0001 0000 0100 0010 1000 1100 -> 10 42 8C
1987 for(uint32 i=0; i<tom_getVideoModeWidth()*240; i++)
1988 // background[i] = 0xFF8C4210;
1989 backbuffer[i] = 0xFF8C4210;
1991 /* uint32 * overlayPix = (uint32 *)sdlemuGetOverlayPixels();
1992 for(uint32 i=0; i<sdlemuGetOverlayWidthInPixels()*480; i++)
1993 overlayPix[i] = 0x00000000;*/
1995 // Handle loading file passed in on the command line...! [DONE]
1999 if (JaguarLoadFile(filename))
2001 // event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
2002 // event.user.data1 = (void *)ResetJaguar;
2003 // SDL_PushEvent(&event);
2004 // Make it so that if passed in on the command line, we quit right
2005 // away when pressing ESC
2006 WriteLog("GUI: Bypassing GUI since ROM passed in on command line...\n");
2012 // Create error dialog...
2014 sprintf(errText, "The file %40s could not be loaded.", filename);
2016 mainWindow = new Window(8, 16, 304, 160);
2017 mainWindow->AddElement(new Text(8, 8, "Error!"));
2018 mainWindow->AddElement(new Text(8, 24, errText));
2022 WriteLog("GUI: Entering main loop...\n");
2025 if (SDL_PollEvent(&event))
2027 if (event.type == SDL_USEREVENT)
2029 if (event.user.code == WINDOW_CLOSE)
2034 else if (event.user.code == MENU_ITEM_CHOSEN)
2036 // Confused? Let me enlighten... What we're doing here is casting
2037 // data1 as a pointer to a function which returns a Window pointer and
2038 // which takes no parameters (the "(Window *(*)(void))" part), then
2039 // derefencing it (the "*" in front of that) in order to call the
2040 // function that it points to. Clear as mud? Yeah, I hate function
2041 // pointers too, but what else are you gonna do?
2042 mainWindow = (*(Window *(*)(void))event.user.data1)();
2044 while (SDL_PollEvent(&event)); // Flush the event queue...
2045 event.type = SDL_MOUSEMOTION;
2047 SDL_GetMouseState(&mx, &my);
2048 event.motion.x = mx, event.motion.y = my;
2049 SDL_PushEvent(&event); // & update mouse position...!
2051 oldMouseX = mouseX, oldMouseY = mouseY;
2052 mouseX = mx, mouseY = my; // This prevents "mouse flash"...
2055 else if (event.type == SDL_ACTIVEEVENT)
2057 if (event.active.state == SDL_APPMOUSEFOCUS)
2058 showMouse = (event.active.gain ? true : false);
2060 else if (event.type == SDL_KEYDOWN)
2063 mainWindow->HandleKey(event.key.keysym.sym);
2065 mainMenu.HandleKey(event.key.keysym.sym);
2067 else if (event.type == SDL_MOUSEMOTION)
2069 oldMouseX = mouseX, oldMouseY = mouseY;
2070 mouseX = event.motion.x, mouseY = event.motion.y;
2073 mainWindow->HandleMouseMove(mouseX, mouseY);
2075 mainMenu.HandleMouseMove(mouseX, mouseY);
2077 else if (event.type == SDL_MOUSEBUTTONDOWN)
2079 uint32 mx = event.button.x, my = event.button.y;
2082 mainWindow->HandleMouseButton(mx, my, true);
2084 mainMenu.HandleMouseButton(mx, my, true);
2086 else if (event.type == SDL_MOUSEBUTTONUP)
2088 uint32 mx = event.button.x, my = event.button.y;
2091 mainWindow->HandleMouseButton(mx, my, false);
2093 mainMenu.HandleMouseButton(mx, my, false);
2096 //PROBLEM: In order to use the dirty rectangle approach here, we need some way of
2097 // handling it in mainMenu.Draw() and mainWindow->Draw(). !!! FIX !!!
2098 //POSSIBLE SOLUTION:
2099 // When mouse is moving and not on menu or window, can do straight dirty rect.
2100 // When mouse is on menu, need to update screen. Same for buttons on windows...
2101 // What the menu & windows should do is only redraw on a state change. IOW, they
2102 // should call their own/child window's Draw() function instead of doing it top
2104 //#define NEW_BACKSTORE_METHOD
2107 // The way we do things here is kinda stupid (redrawing the screen every frame), but
2108 // it's simple. Perhaps there may be a reason down the road to be more selective with
2109 // our clearing, but for now, this will suffice.
2110 // memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
2111 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 2);
2112 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 4);
2113 #ifndef NEW_BACKSTORE_METHOD
2114 memset(sdlemuGetOverlayPixels(), 0, sdlemuGetOverlayWidthInPixels() * 480 * 4);
2117 //Could do multiple windows here by using a vector + priority info...
2118 //Though the way ZSNES does it seems to be by a bool (i.e., they're always active, just not shown)
2123 /*uint32 pBGS[6 * 8 + 3] = { 6, 8, 4,
2133 //This isn't working... Why????
2134 //It's because DrawTransparentBitmap does alpha blending if it detects zero in the alpha channel.
2135 //So why do it that way? Hm.
2136 overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2138 #ifdef NEW_BACKSTORE_METHOD
2139 // DrawTransparentBitmapDeprecated(overlayPixels, oldMouseX, oldMouseY, pointerBGSave);
2140 // DrawTransparentBitmap(overlayPixels, oldMouseX, oldMouseY, pBGS);
2141 for(uint32 y=0; y<pointerBGSave[1]; y++)
2142 for(uint32 x=0; x<pointerBGSave[0]; x++)
2143 overlayPixels[((oldMouseY + y) * sdlemuGetOverlayWidthInPixels()) + (oldMouseX + x)] = 0x00000000;
2147 for(uint32 y=0; y<pointerBGSave[1]; y++)
2148 for(uint32 x=0; x<pointerBGSave[0]; x++)
2149 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
2153 // DrawTransparentBitmapDeprecated(backbuffer, mouseX, mouseY, mousePic);
2154 DrawTransparentBitmapDeprecated(overlayPixels, mouseX, mouseY, mousePic);
2164 // GUI "action" functions
2167 Window * LoadROM(void)
2169 FileList * fileList = new FileList(20, 20, 600, 440);
2171 return (Window *)fileList;
2174 Window * ResetJaguar(void)
2181 Window * ResetJaguarCD(void)
2183 memcpy(jaguar_mainRom, jaguar_CDBootROM, 0x40000);
2184 jaguarRunAddress = 0x802000;
2185 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, 0x40000);
2187 //This is a quick kludge to get the CDBIOS to boot properly...
2188 //Wild speculation: It could be that this memory location is wired into the CD unit
2189 //somehow, which lets it know whether or not a cart is present in the unit...
2190 jaguar_mainRom[0x0040B] = 0x03;
2198 bool debounceRunKey = true;
2199 Window * RunEmu(void)
2201 extern uint32 * backbuffer;
2202 //Temporary, to test the new timer based code...
2203 sdlemuDisableOverlay();
2205 sdlemuEnableOverlay();
2206 // Save the background for the GUI...
2207 // In this case, we squash the color to monochrome, then force it to blue + green...
2208 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2210 uint32 pixel = backbuffer[i];
2211 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2212 pixel = ((r + g + b) / 3) & 0x00FF;
2213 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2217 //This is crappy... !!! FIX !!!
2218 extern bool finished, showGUI;
2220 // uint32 nFrame = 0, nFrameskip = 0;
2221 uint32 totalFrames = 0;
2223 bool showMessage = true;
2224 uint32 showMsgFrames = 120;
2225 uint8 transparency = 0;
2226 // Pass a message to the "joystick" code to debounce the ESC key...
2227 debounceRunKey = true;
2229 uint32 cartType = 4;
2230 if (jaguarRomSize == 0x200000)
2232 else if (jaguarRomSize == 0x400000)
2234 else if (jaguar_mainRom_crc32 == 0x687068D5)
2236 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2239 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2240 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2244 // Set up new backbuffer with new pixels and data
2245 JaguarExecute(backbuffer, true);
2246 // JaguarExecuteNew();
2248 //WriteLog("Frame #%u...\n", totalFrames);
2249 //extern bool doDSPDis;
2250 //if (totalFrames == 373)
2253 //This sucks... !!! FIX !!!
2255 //This is done here so that the crud below doesn't get on our GUI background...
2259 // Some QnD GUI stuff here...
2262 extern uint32 gpu_pc, dsp_pc;
2263 DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
2264 DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
2265 DrawString(backbuffer, 8, 32, false, "%u FPS", framesPerSecond);
2270 // FF0F -> 1111 11 11 000 0 1111 -> 3F 18 0F
2271 // 3FE3 -> 0011 11 11 111 0 0011 -> 0F 3F 03
2272 /* DrawStringTrans((uint32 *)backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
2273 DrawStringTrans((uint32 *)backbuffer, 8, 26*8, 0x3FE3, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2274 DrawStringTrans((uint32 *)backbuffer, 8, 27*8, 0x3FE3, transparency, "CRC: %08X", jaguar_mainRom_crc32);//*/
2275 //first has wrong color. !!! FIX !!!
2276 DrawStringTrans(backbuffer, 8, 24*8, 0xFF7F63FF, transparency, "Running...");
2277 DrawStringTrans(backbuffer, 8, 26*8, 0xFF1FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2278 DrawStringTrans(backbuffer, 8, 27*8, 0xFF1FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2280 if (showMsgFrames == 0)
2284 if (transparency == 33)
2286 showMessage = false;
2287 /*extern bool doGPUDis;
2288 doGPUDis = true;//*/
2299 if (SDL_GetTicks() - elapsedTicks > 250)
2300 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2303 // Reset the pitch, since it may have been changed in-game...
2304 Element::SetScreenAndPitch((uint32 *)backbuffer, GetSDLScreenWidthInPixels());
2306 // Save the background for the GUI...
2307 // memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2);
2308 // In this case, we squash the color to monochrome, then force it to blue + green...
2309 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2311 uint32 pixel = backbuffer[i];
2312 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2313 pixel = ((r + g + b) / 3) & 0x00FF;
2314 background[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2322 bool debounceRunKey = true;
2323 Window * RunEmu(void)
2325 extern uint32 * backbuffer;
2326 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2327 memset(overlayPixels, 0x00, 640 * 480 * 4); // Clear out overlay...
2329 //This is crappy... !!! FIX !!!
2330 extern bool finished, showGUI;
2332 sdlemuDisableOverlay();
2334 // uint32 nFrame = 0, nFrameskip = 0;
2335 uint32 totalFrames = 0;
2337 bool showMessage = true;
2338 uint32 showMsgFrames = 120;
2339 uint8 transparency = 0xFF;
2340 // Pass a message to the "joystick" code to debounce the ESC key...
2341 debounceRunKey = true;
2343 uint32 cartType = 4;
2344 if (jaguarRomSize == 0x200000)
2346 else if (jaguarRomSize == 0x400000)
2348 else if (jaguar_mainRom_crc32 == 0x687068D5)
2350 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2353 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2354 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2358 // Set up new backbuffer with new pixels and data
2361 //WriteLog("Frame #%u...\n", totalFrames);
2362 //extern bool doDSPDis;
2363 //if (totalFrames == 373)
2366 //Problem: Need to do this *only* when the state changes from visible to not...
2367 //Also, need to clear out the GUI when not on (when showMessage is active...)
2368 if (showGUI || showMessage)
2369 sdlemuEnableOverlay();
2371 sdlemuDisableOverlay();
2373 //Add in a new function for clearing patches of screen (ClearOverlayRect)
2375 // Some QnD GUI stuff here...
2378 FillScreenRectangle(overlayPixels, 8, 1*FONT_HEIGHT, 128, 4*FONT_HEIGHT, 0x00000000);
2379 extern uint32 gpu_pc, dsp_pc;
2380 DrawString(overlayPixels, 8, 1*FONT_HEIGHT, false, "GPU PC: %08X", gpu_pc);
2381 DrawString(overlayPixels, 8, 2*FONT_HEIGHT, false, "DSP PC: %08X", dsp_pc);
2382 DrawString(overlayPixels, 8, 4*FONT_HEIGHT, false, "%u FPS", framesPerSecond);
2387 DrawString2(overlayPixels, 8, 24*FONT_HEIGHT, 0x007F63FF, transparency, "Running...");
2388 DrawString2(overlayPixels, 8, 26*FONT_HEIGHT, 0x001FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2389 DrawString2(overlayPixels, 8, 27*FONT_HEIGHT, 0x001FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2391 if (showMsgFrames == 0)
2395 if (transparency == 0)
2397 showMessage = false;
2398 /*extern bool doGPUDis;
2399 doGPUDis = true;//*/
2409 if (SDL_GetTicks() - elapsedTicks > 250)
2410 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2413 // Save the background for the GUI...
2414 // In this case, we squash the color to monochrome, then force it to blue + green...
2415 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2417 uint32 pixel = backbuffer[i];
2418 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2419 pixel = ((r + g + b) / 3) & 0x00FF;
2420 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2423 sdlemuEnableOverlay();
2433 WriteLog("GUI: Quitting due to user request.\n");
2439 Window * About(void)
2442 // sprintf(buf, "Virtual Jaguar CVS %s", __DATE__);
2443 sprintf(buf, "CVS %s", __DATE__);
2444 //fprintf(fp, "VirtualJaguar v1.0.8 (Last full build was on %s %s)\n", __DATE__, __TIME__);
2445 //VirtualJaguar v1.0.8 (Last full build was on Dec 30 2004 20:01:31)
2446 //Hardwired, bleh... !!! FIX !!!
2447 uint32 width = 55 * FONT_WIDTH, height = 18 * FONT_HEIGHT;
2448 uint32 xpos = (640 - width) / 2, ypos = (480 - height) / 2;
2449 // Window * window = new Window(8, 16, 50 * FONT_WIDTH, 21 * FONT_HEIGHT);
2450 Window * window = new Window(xpos, ypos, width, height);
2451 // window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.8"));
2452 // window->AddElement(new Text(8, 8, "Virtual Jaguar CVS 20050110", 0xFF3030FF, 0xFF000000));
2453 // window->AddElement(new Text(208, 8+0*FONT_HEIGHT, buf, 0xFF3030FF, 0xFF000000));
2454 window->AddElement(new Text(248, 8+4*FONT_HEIGHT+5, buf, 0xFF3030FF, 0xFF000000));
2455 window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "Coders:"));
2456 window->AddElement(new Text(16, 8+1*FONT_HEIGHT, "James L. Hammons (shamus)"));
2457 window->AddElement(new Text(16, 8+2*FONT_HEIGHT, "Niels Wagenaar (nwagenaar)"));
2458 window->AddElement(new Text(16, 8+3*FONT_HEIGHT, "Carwin Jones (Caz)"));
2459 window->AddElement(new Text(16, 8+4*FONT_HEIGHT, "Adam Green"));
2460 window->AddElement(new Text(8, 8+6*FONT_HEIGHT, "Testers:"));
2461 window->AddElement(new Text(16, 8+7*FONT_HEIGHT, "Guruma"));
2462 window->AddElement(new Text(8, 8+9*FONT_HEIGHT, "Thanks go out to:"));
2463 window->AddElement(new Text(16, 8+10*FONT_HEIGHT, "Aaron Giles for the original CoJag"));
2464 window->AddElement(new Text(16, 8+11*FONT_HEIGHT, "David Raingeard for the original VJ"));
2465 window->AddElement(new Text(16, 8+12*FONT_HEIGHT, "Karl Stenerud for his Musashi 68K emu"));
2466 window->AddElement(new Text(16, 8+13*FONT_HEIGHT, "Sam Lantinga for his amazing SDL libs"));
2467 window->AddElement(new Text(16, 8+14*FONT_HEIGHT, "Ryan C. Gordon for VJ's web presence"));
2468 window->AddElement(new Text(16, 8+15*FONT_HEIGHT, "Curt Vendel for various Jaguar goodies"));
2469 window->AddElement(new Text(16, 8+16*FONT_HEIGHT, "The guys over at Atari Age ;-)"));
2470 // window->AddElement(new Image(8, 8, &vj_title_small));
2471 window->AddElement(new Image(width - (vj_title_small.width + 8), 8, &vj_title_small));
2476 Window * MiscOptions(void)
2478 Window * window = new Window(8, 16, 304, 192);
2479 window->AddElement(new PushButton(8, 8, &vjs.useJaguarBIOS, "BIOS"));
2480 window->AddElement(new SlideSwitch(8, 32, &vjs.hardwareTypeNTSC, "PAL", "NTSC"));
2481 window->AddElement(new PushButton(8, 64, &vjs.DSPEnabled, "DSP"));
2482 window->AddElement(new SlideSwitch(24, 88, &vjs.usePipelinedDSP, "Original", "Pipelined"));
2483 window->AddElement(new SlideSwitch(8, 120, (bool *)&vjs.glFilter, "Sharp", "Blurry"));
2484 window->AddElement(new SlideSwitch(8, 152, (bool *)&vjs.renderType, "Normal render", "TV style"));
2486 window->AddElement(new TextEdit(88, 8, vjs.ROMPath, 20, 0xFF8484FF, 0xFF000000));
2488 /*TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
2489 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
2490 caretPos(0), maxScreenSize(mss) {}*/
2499 // * Window/fullscreen
2500 // * Key definitions
2507 // Generic ROM loading
2509 uint32 JaguarLoadROM(uint8 * rom, char * path)
2511 // We really should have some kind of sanity checking for the ROM size here to prevent
2512 // a buffer overflow... !!! FIX !!!
2515 WriteLog("JaguarLoadROM: Attempting to load file '%s'...", path);
2516 char * ext = strrchr(path, '.');
2518 WriteLog("FAILED!\n");
2520 WriteLog("Succeeded in finding extension (%s)!\n", ext);
2524 WriteLog("VJ: Loading \"%s\"...", path);
2526 if (strcasecmp(ext, ".zip") == 0)
2528 // Handle ZIP file loading here...
2529 WriteLog("(ZIPped)...");
2531 if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1)
2533 WriteLog("Failed!\n");
2539 /* FILE * fp = fopen(path, "rb");
2543 WriteLog("Failed!\n");
2547 fseek(fp, 0, SEEK_END);
2548 romSize = ftell(fp);
2549 fseek(fp, 0, SEEK_SET);
2550 fread(rom, 1, romSize, fp);
2553 // Handle gzipped files transparently [Adam Green]...
2555 gzFile fp = gzopen(path, "rb");
2559 WriteLog("Failed!\n");
2563 romSize = gzfilelength(fp);
2564 gzseek(fp, 0, SEEK_SET);
2565 gzread(fp, rom, romSize);
2569 WriteLog("OK (%i bytes)\n", romSize);
2576 // Jaguar file loading
2578 bool JaguarLoadFile(char * path)
2580 // jaguarRomSize = JaguarLoadROM(mem, path);
2581 jaguarRomSize = JaguarLoadROM(jaguar_mainRom, path);
2583 /*//This is not *nix friendly for some reason...
2584 // if (!UserSelectFile(path, newPath))
2585 if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath))
2587 WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path);
2592 if (jaguarRomSize == 0)
2594 // WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath);
2595 WriteLog("GUI: Could not load ROM from file \"%s\"...\nAborting load!\n", path);
2596 // Need to do something else here, like throw up an error dialog instead of aborting. !!! FIX !!!
2599 return false; // This is a start...
2602 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, jaguarRomSize);
2603 WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32);
2606 jaguarRunAddress = 0x802000;
2608 char * ext = strrchr(path, '.'); // Get the file's extension for non-cartridge checking
2610 //NOTE: Should fix JaguarLoadROM() to replace .zip with what's *in* the zip (.abs, .j64, etc.)
2611 if (strcasecmp(ext, ".rom") == 0)
2613 // File extension ".ROM": Alpine image that loads/runs at $802000
2614 WriteLog("GUI: Setting up homebrew (ROM)... Run address: 00802000, length: %08X\n", jaguarRomSize);
2616 for(int i=jaguarRomSize-1; i>=0; i--)
2617 jaguar_mainRom[0x2000 + i] = jaguar_mainRom[i];
2619 memset(jaguar_mainRom, 0xFF, 0x2000);
2620 /* memcpy(jaguar_mainRam, jaguar_mainRom, jaguarRomSize);
2621 memset(jaguar_mainRom, 0xFF, 0x600000);
2622 memcpy(jaguar_mainRom + 0x2000, jaguar_mainRam, jaguarRomSize);
2623 memset(jaguar_mainRam, 0x00, 0x400000);*/
2626 Stubulator ROM vectors...
2627 handler 001 at $00E00008
2628 handler 002 at $00E008DE
2629 handler 003 at $00E008E2
2630 handler 004 at $00E008E6
2631 handler 005 at $00E008EA
2632 handler 006 at $00E008EE
2633 handler 007 at $00E008F2
2634 handler 008 at $00E0054A
2635 handler 009 at $00E008FA
2636 handler 010 at $00000000
2637 handler 011 at $00000000
2638 handler 012 at $00E008FE
2639 handler 013 at $00E00902
2640 handler 014 at $00E00906
2641 handler 015 at $00E0090A
2642 handler 016 at $00E0090E
2643 handler 017 at $00E00912
2644 handler 018 at $00E00916
2645 handler 019 at $00E0091A
2646 handler 020 at $00E0091E
2647 handler 021 at $00E00922
2648 handler 022 at $00E00926
2649 handler 023 at $00E0092A
2650 handler 024 at $00E0092E
2651 handler 025 at $00E0107A
2652 handler 026 at $00E0107A
2653 handler 027 at $00E0107A
2654 handler 028 at $00E008DA
2655 handler 029 at $00E0107A
2656 handler 030 at $00E0107A
2657 handler 031 at $00E0107A
2658 handler 032 at $00000000
2660 Let's try setting up the illegal instruction vector for a stubulated jaguar...
2662 /* SET32(jaguar_mainRam, 0x08, 0x00E008DE);
2663 SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
2664 SET32(jaguar_mainRam, 0x10, 0x00E008E6); // <-- Should be here (it is)...
2665 SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
2667 // Try setting the vector to say, $1000 and putting an instruction there that loops forever:
2668 // This kludge works! Yeah!
2669 SET32(jaguar_mainRam, 0x10, 0x00001000);
2670 SET16(jaguar_mainRam, 0x1000, 0x60FE); // Here: bra Here
2672 else if (strcasecmp(ext, ".abs") == 0)
2674 // File extension ".ABS": Atari linker output file with header (w/o is useless to us here)
2677 ABS Format sleuthing (LBUGDEMO.ABS):
2679 000000 60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
2680 000010 12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
2683 DRI-format file detected...
2684 Text segment size = 0x0000050c bytes
2685 Data segment size = 0x000462c0 bytes
2686 BSS Segment size = 0x00000428 bytes
2687 Symbol Table size = 0x000012a6 bytes
2688 Absolute Address for text segment = 0x00802000
2689 Absolute Address for data segment = 0x0080250c
2690 Absolute Address for BSS segment = 0x00004000
2693 000000 01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
2694 000010 00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
2695 000020 00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
2697 000030 2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
2698 000040 00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
2699 000050 00 00 00 00 00 00 00 20
2700 000058 2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
2701 000068 00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
2702 000078 00 00 00 00 00 00 00 40
2703 000080 2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
2704 000090 00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
2705 0000a0 00 00 00 00 00 00 00 80
2707 Header size is $A8 bytes...
2709 BSD/COFF format file detected...
2710 3 sections specified
2711 Symbol Table offset = 230160 ($00038310)
2712 Symbol Table contains 1339 symbol entries ($0000053B)
2713 The additional header size is 28 bytes ($001C)
2714 Magic Number for RUN_HDR = 0x00000107
2715 Text Segment Size = 7632 ($00001DD0)
2716 Data Segment Size = 222360 ($00036498)
2717 BSS Segment Size = 428928 ($00068B80)
2718 Starting Address for executable = 0x00802000
2719 Start of Text Segment = 0x00802000
2720 Start of Data Segment = 0x00803dd0
2722 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1B)
2724 uint32 loadAddress = GET32(jaguar_mainRom, 0x16), //runAddress = GET32(jaguar_mainRom, 0x2A),
2725 codeSize = GET32(jaguar_mainRom, 0x02) + GET32(jaguar_mainRom, 0x06);
2726 WriteLog("GUI: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize);
2728 if (loadAddress < 0x800000)
2729 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x24, codeSize);
2732 for(int i=codeSize-1; i>=0; i--)
2733 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0x24];
2734 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0x24, codeSize);
2735 memset(jaguar_mainRom, 0xFF, 0x600000);
2736 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2737 memset(jaguar_mainRam, 0x00, 0x400000);*/
2740 jaguarRunAddress = loadAddress;
2742 else if (jaguar_mainRom[0] == 0x01 && jaguar_mainRom[1] == 0x50)
2744 uint32 loadAddress = GET32(jaguar_mainRom, 0x28), runAddress = GET32(jaguar_mainRom, 0x24),
2745 codeSize = GET32(jaguar_mainRom, 0x18) + GET32(jaguar_mainRom, 0x1C);
2746 WriteLog("GUI: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize);
2748 if (loadAddress < 0x800000)
2749 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0xA8, codeSize);
2752 for(int i=codeSize-1; i>=0; i--)
2753 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0xA8];
2754 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0xA8, codeSize);
2755 memset(jaguar_mainRom, 0xFF, 0x600000);
2756 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2757 memset(jaguar_mainRam, 0x00, 0x400000);*/
2760 jaguarRunAddress = runAddress;
2764 WriteLog("GUI: Couldn't find correct ABS format: %02X %02X\n", jaguar_mainRom[0], jaguar_mainRom[1]);
2768 else if (strcasecmp(ext, ".jag") == 0)
2770 // File extension ".JAG": Atari server file with header
2771 //NOTE: The bytes 'JAGR' should also be at position $1C...
2772 // Also, there's *always* a $601A header at position $00...
2773 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
2775 uint32 loadAddress = GET32(jaguar_mainRom, 0x22), runAddress = GET32(jaguar_mainRom, 0x2A);
2776 //This is not always right! Especially when converted via bin2jag1!!!
2777 //We should have access to the length of the furshlumiger file that was loaded anyway!
2779 // uint32 progLength = GET32(jaguar_mainRom, 0x02);
2782 // WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
2783 // memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, progLength);
2784 WriteLog("GUI: Setting up homebrew (JAG)... Run address: %08X, length: %08X\n", runAddress, jaguarRomSize - 0x2E);
2785 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, jaguarRomSize - 0x2E);
2786 // SET32(jaguar_mainRam, 4, runAddress);
2787 jaguarRunAddress = runAddress;
2792 // .J64 (Jaguar cartridge ROM image) is implied by the FileList object...
2798 // Get the length of a (possibly) gzipped file
2800 int gzfilelength(gzFile gd)
2802 int size = 0, length = 0;
2803 unsigned char buffer[0x10000];
2809 // Read in chunks until EOF
2810 size = gzread(gd, buffer, 0x10000);