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;
89 for(uint32 i=0; i<length; i++)
92 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * font.width * font.height;
94 for(uint32 yy=0; yy<font.height; yy++)
96 for(uint32 xx=0; xx<font.width; xx++)
98 esColor[3] = (font.data[fontAddr++] * trans) / 255;
99 ((uint32 *)chr->pixels)[xx + (yy * (chr->pitch / 4))] = color;
103 SDL_BlitSurface(chr, NULL, screen, &rect);
104 rect.x += font.width;
107 SDL_FreeSurface(chr);
111 // Draw text at given x/y coords using foreground/background color combination
113 void DrawStringOpaque(SDL_Surface * screen, uint32 x, uint32 y, uint32 fg, uint32 bg, const char * text, ...)
119 vsprintf(string, text, arg);
122 uint8 * esColor = (uint8 *)&fg; // Do things endian safe...!
123 uint32 length = strlen(string);
127 destRect.x = x, destRect.y = y;
128 destRect.w = length * font.width, destRect.h = font.height;
130 SDL_FillRect(screen, &destRect, bg);
132 // Make a "stamp" surface (with built in alpha!) for constructing our font chars...
133 SDL_Surface * chr = SDL_CreateRGBSurface(SDL_SWSURFACE, font.width, font.height, 32,
134 MASK_R, MASK_G, MASK_B, MASK_A);
136 rect.x = x, rect.y = y;
138 for(uint32 i=0; i<length; i++)
141 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * font.width * font.height;
143 for(uint32 yy=0; yy<font.height; yy++)
145 for(uint32 xx=0; xx<font.width; xx++)
147 esColor[3] = font.data[fontAddr++];
148 ((uint32 *)chr->pixels)[xx + (yy * (chr->pitch / 4))] = fg;
152 SDL_BlitSurface(chr, NULL, screen, &rect);
153 rect.x += font.width;
156 SDL_FreeSurface(chr);
159 bool RectanglesIntersect(SDL_Rect r1, SDL_Rect r2)
161 // The strategy here is to see if any of the sides of the smaller rect
162 // fall within the larger.
165 +-----------------+ r1
176 //This approach fails if r2 is inside of r1. !!! FIX !!! [DONE]
177 if (RectangleFirstInsideSecond(r2, r1))
180 if ((r1.x > r2.x && r1.x < (r2.x + r2.w))
181 || ((r1.x + r1.w) > r2.x && (r1.x + r1.w) < (r2.x + r2.w))
182 || (r1.y > r2.y && r1.y < (r2.y + r2.h))
183 || ((r1.y + r1.h) > r2.y && (r1.y + r1.h) < (r2.y + r2.h)))
189 bool RectangleFirstInsideSecond(SDL_Rect r1, SDL_Rect r2)
191 if ((r1.x > r2.x && (r1.x + r1.w) > r2.x)
192 && (r1.x < (r2.x + r2.w) && (r1.x + r1.w) < (r2.x + r2.w))
193 && (r1.y > r2.y && (r1.y + r1.h) > r2.y)
194 && (r1.y < (r2.y + r2.h) && (r1.y + r1.h) < (r2.y + r2.h)))
202 // Various GUI bitmaps
205 // These representations *should* be endian safe.
208 15 / 256, 15 % 256, // width (HI byte, LO byte)
209 15 / 256, 15 % 256, // height (HI byte, LO byte)
211 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,
212 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,
213 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,
214 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,
215 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,
216 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,
217 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,
218 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,
219 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,
220 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,
221 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,
222 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,
223 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,
224 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,
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
228 uint8 closeBoxHover[] = {
229 15 / 256, 15 % 256, // width (HI byte, LO byte)
230 15 / 256, 15 % 256, // height (HI byte, LO byte)
232 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,
233 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,
234 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,
235 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,
236 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,
237 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,
238 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,
239 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,
240 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,
241 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,
242 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,
243 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,
244 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,
245 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,
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
249 uint8 closeBoxDown[] = {
250 15 / 256, 15 % 256, // width (HI byte, LO byte)
251 15 / 256, 15 % 256, // height (HI byte, LO byte)
253 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,
254 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,
255 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,
256 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,
257 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,
258 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,
259 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,
260 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,
261 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,
262 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,
263 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,
264 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,
265 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,
266 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,
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
270 #include "fd-img-128x128.c"
275 #include <sys/types.h> // For MacOS <dirent.h> dependency
281 #include <ctype.h> // For toupper()
282 #include "settings.h"
287 #include "font14pt.h" // Also 15, 16, 17, 18
288 #include "guielements.h"
292 #include "sdlemu_opengl.h"
295 using namespace std; // For STL stuff
297 // Private function prototypes
299 class Window; // Forward declaration...
301 //void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha = NULL);
302 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap);
303 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
304 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
305 //Should call this FillScreenRectangle with a number representing the RGBA value to fill. !!! FIX !!!
306 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h);
307 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color);
308 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 opacity, const char * text, ...);
309 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...);
310 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
311 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...);
312 Window * LoadROM(void);
313 Window * ResetJaguar(void);
314 Window * ResetJaguarCD(void);
315 Window * RunEmu(void);
317 Window * About(void);
318 Window * MiscOptions(void);
320 int gzfilelength(gzFile gd);
322 // External variables
324 extern uint8 * jaguar_mainRam;
325 extern uint8 * jaguar_mainRom;
326 extern uint8 * jaguar_bootRom;
327 extern uint8 * jaguar_CDBootROM;
328 extern bool BIOSLoaded;
329 extern bool CDBIOSLoaded;
331 // Local global variables
333 bool exitGUI = false; // GUI (emulator) done variable
334 int mouseX = 0, mouseY = 0;
335 uint32 background[1280 * 256]; // GUI background buffer
337 char separator[] = "--------------------------------------------------------";
340 // Case insensitive string compare function
341 // Taken straight out of Thinking In C++ by Bruce Eckel. Thanks Bruce!
344 int stringCmpi(const string &s1, const string &s2)
346 // Select the first element of each string:
347 string::const_iterator p1 = s1.begin(), p2 = s2.begin();
349 while (p1 != s1.end() && p2 != s2.end()) // Don�t run past the end
351 if (toupper(*p1) != toupper(*p2)) // Compare upper-cased chars
352 return (toupper(*p1) < toupper(*p2) ? -1 : 1);// Report which was lexically greater
358 // If they match up to the detected eos, say which was longer. Return 0 if the same.
359 return s2.size() - s1.size();
366 enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN };
371 Element(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0)
372 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
373 virtual void HandleKey(SDLKey key) = 0; // These are "pure" virtual functions...
374 virtual void HandleMouseMove(uint32 x, uint32 y) = 0;
375 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0;
376 virtual void Draw(uint32, uint32) = 0;
377 virtual void Notify(Element *) = 0;
378 //Needed? virtual ~Element() = 0;
379 //We're not allocating anything in the base class, so the answer would be NO.
380 bool Inside(uint32 x, uint32 y);
382 // static void SetScreenAndPitch(int16 * s, uint32 p) { screenBuffer = s, pitch = p; }
383 static void SetScreenAndPitch(uint32 * s, uint32 p) { screenBuffer = s, pitch = p; }
388 // Class variables...
389 // static int16 * screenBuffer;
390 static uint32 * screenBuffer;
394 // Initialize class variables (Element)
395 //int16 * Element::screenBuffer = NULL;
396 uint32 * Element::screenBuffer = NULL;
397 uint32 Element::pitch = 0;
399 bool Element::Inside(uint32 x, uint32 y)
401 return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
402 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
410 class Button: public Element
413 Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
414 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
415 bgColor(0xFF00FF00), pic(NULL), elementToTell(NULL) {}
416 Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
417 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
418 bgColor(0xFF00FF00), pic(p), elementToTell(NULL) {}
419 // Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
420 Button(uint32 x, uint32 y, uint32 * p, uint32 * pH = NULL, uint32 * pD = NULL): Element(x, y, 0, 0),
421 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
422 bgColor(0xFF00FF00), pic(p), picHover(pH), picDown(pD), elementToTell(NULL)
423 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
424 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
425 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
426 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL) {}
427 Button(uint32 x, uint32 y, string s): Element(x, y, 0, FONT_HEIGHT),
428 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
429 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL)
430 { extents.w = s.length() * FONT_WIDTH; }
431 virtual void HandleKey(SDLKey key) {}
432 virtual void HandleMouseMove(uint32 x, uint32 y);
433 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
434 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
435 virtual void Notify(Element *) {}
436 bool ButtonClicked(void) { return activated; }
437 void SetNotificationElement(Element * e) { elementToTell = e; }
440 bool activated, clicked, inside;
441 uint32 fgColor, bgColor;
442 uint32 * pic, * picHover, * picDown;
444 Element * elementToTell;
447 void Button::HandleMouseMove(uint32 x, uint32 y)
449 inside = Inside(x, y);
452 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
459 if (clicked && !mouseDown)
461 clicked = false, activated = true;
463 // Send a message that we're activated (if there's someone to tell, that is)
465 elementToTell->Notify(this);
469 clicked = activated = false;
472 void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
474 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
476 if (text.length() > 0) // Simple text button
479 for(uint32 y=0; y<extents.h; y++)
481 for(uint32 x=0; x<extents.w; x++)
483 // Doesn't clip in y axis! !!! FIX !!!
484 if (extents.x + x < pitch)
485 screenBuffer[addr + x + (y * pitch)]
486 // = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
487 //43F0 -> 010000 11111 10000 -> 0100 0001 1111 1111 1000 0100 -> 41 FF 84
488 = (clicked && inside ? fgColor : (inside ? 0xFF84FF41 : bgColor));
492 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
494 else // Graphical button
496 uint32 * picToShow = pic;
498 if (picHover != NULL && inside && !clicked)
499 picToShow = picHover;
501 if (picDown != NULL && inside && clicked)
504 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, picToShow);
513 class PushButton: public Element
516 // Save state externally?
517 //We pass in a state variable if we want to track it externally, otherwise we use our own
518 //internal state var. Still need to do some kind of callback for pushbuttons that do things
519 //like change from fullscreen to windowed... !!! FIX !!!
522 // PushButton(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
523 // activated(false), clicked(false), inside(false), fgColor(0xFFFF),
524 // bgColor(0x03E0), pic(NULL), elementToTell(NULL) {}
525 // PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 8, 8), state(st),
526 // inside(false), text(s) { if (st == NULL) state = &internalState; }
527 PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 16, 16), state(st),
528 inside(false), text(s) { if (st == NULL) state = &internalState; }
529 /* Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
530 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
531 bgColor(0x03E0), pic(p), elementToTell(NULL) {}
532 Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
533 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
534 bgColor(0x03E0), pic(p), elementToTell(NULL)
535 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
536 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
537 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
538 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) {}
539 PushButton(uint32 x, uint32 y, string s): Element(x, y, 0, 8),
540 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
541 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL)
542 { extents.w = s.length() * 8; }*/
543 virtual void HandleKey(SDLKey key) {}
544 virtual void HandleMouseMove(uint32 x, uint32 y);
545 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
546 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
547 virtual void Notify(Element *) {}
548 // bool ButtonClicked(void) { return activated; }
549 // void SetNotificationElement(Element * e) { elementToTell = e; }
554 // bool activated, clicked, inside;
555 // uint16 fgColor, bgColor;
558 // Element * elementToTell;
562 void PushButton::HandleMouseMove(uint32 x, uint32 y)
564 inside = Inside(x, y);
567 void PushButton::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
569 if (inside && mouseDown)
574 if (clicked && !mouseDown)
576 clicked = false, activated = true;
578 // Send a message that we're activated (if there's someone to tell, that is)
580 elementToTell->Notify(this);
585 // clicked = activated = false;
588 void PushButton::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
590 /* uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
592 for(uint32 y=0; y<extents.h; y++)
594 for(uint32 x=0; x<extents.w; x++)
596 // Doesn't clip in y axis! !!! FIX !!!
597 if (extents.x + x < pitch)
598 screenBuffer[addr + x + (y * pitch)]
599 = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
604 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbDown);
606 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbUp);
608 if (text.length() > 0)
609 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text.c_str());
617 class SlideSwitch: public Element
620 // Save state externally?
621 //Seems to be handled the same as PushButton, but without sanity checks. !!! FIX !!!
624 SlideSwitch(uint32 x, uint32 y, bool * st, string s1, string s2): Element(x, y, 16, 32), state(st),
625 inside(false), text1(s1), text2(s2) {}
626 virtual void HandleKey(SDLKey key) {}
627 virtual void HandleMouseMove(uint32 x, uint32 y);
628 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
629 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
630 virtual void Notify(Element *) {}
631 // bool ButtonClicked(void) { return activated; }
632 // void SetNotificationElement(Element * e) { elementToTell = e; }
637 // bool activated, clicked, inside;
638 // uint16 fgColor, bgColor;
641 // Element * elementToTell;
644 void SlideSwitch::HandleMouseMove(uint32 x, uint32 y)
646 inside = Inside(x, y);
649 void SlideSwitch::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
651 if (inside && mouseDown)
656 if (clicked && !mouseDown)
658 clicked = false, activated = true;
660 // Send a message that we're activated (if there's someone to tell, that is)
662 elementToTell->Notify(this);
667 // clicked = activated = false;
670 void SlideSwitch::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
672 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, (*state ? slideSwitchDown : slideSwitchUp));
674 if (text1.length() > 0)
675 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text1.c_str());
677 if (text2.length() > 0)
678 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY + 16, false, "%s", text2.c_str());
686 class Window: public Element
689 /* Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
690 fgColor(0x4FF0), bgColor(0xFE10)
691 { close = new Button(w - 8, 1, closeBox); list.push_back(close); }*/
692 Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0,
693 void (* f)(Element *) = NULL): Element(x, y, w, h),
694 // /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0x1E10),
695 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
696 //1E10 -> 000111 10000 10000 -> 0001 1111 1000 0100 1000 0100 -> 1F 84 84
697 /*clicked(false), inside(false),*/ fgColor(0xFF84FF4D), bgColor(0xFF84841F),
699 { close = new Button(w - (CLOSEBOX_WIDTH + 1), 1, closeBox, closeBoxHover, closeBoxDown);
700 list.push_back(close);
701 close->SetNotificationElement(this); }
703 virtual void HandleKey(SDLKey key);
704 virtual void HandleMouseMove(uint32 x, uint32 y);
705 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
706 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
707 virtual void Notify(Element * e);
708 void AddElement(Element * e);
709 // bool WindowActive(void) { return true; }//return !close->ButtonClicked(); }
712 // bool clicked, inside;
713 uint32 fgColor, bgColor;
714 void (* handler)(Element *);
716 //We have to use a list of Element *pointers* because we can't make a list that will hold
717 //all the different object types in the same list...
718 vector<Element *> list;
723 for(uint32 i=0; i<list.size(); i++)
728 void Window::HandleKey(SDLKey key)
730 if (key == SDLK_ESCAPE)
733 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
734 SDL_PushEvent(&event);
737 // Handle the items this window contains...
738 for(uint32 i=0; i<list.size(); i++)
739 // Make coords relative to upper right corner of this window...
740 list[i]->HandleKey(key);
743 void Window::HandleMouseMove(uint32 x, uint32 y)
745 // Handle the items this window contains...
746 for(uint32 i=0; i<list.size(); i++)
747 // Make coords relative to upper right corner of this window...
748 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
751 void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
753 // Handle the items this window contains...
754 for(uint32 i=0; i<list.size(); i++)
755 // Make coords relative to upper right corner of this window...
756 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
759 void Window::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
761 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
763 for(uint32 y=0; y<extents.h; y++)
765 for(uint32 x=0; x<extents.w; x++)
767 // Doesn't clip in y axis! !!! FIX !!!
768 if (extents.x + x < pitch)
769 screenBuffer[addr + x + (y * pitch)] = bgColor;
773 // Handle the items this window contains...
774 for(uint32 i=0; i<list.size(); i++)
775 list[i]->Draw(extents.x, extents.y);
778 void Window::AddElement(Element * e)
783 void Window::Notify(Element * e)
788 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
789 SDL_PushEvent(&event);
798 class Text: public Element
801 // Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
802 // fgColor(0x4FF0), bgColor(0xFE10) {}
803 // Text(uint32 x, uint32 y, string s, uint16 fg = 0x4FF0, uint16 bg = 0xFE10): Element(x, y, 0, 0),
804 // fgColor(fg), bgColor(bg), text(s) {}
805 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
806 //FE10 -> 111111 10000 10000 -> 1111 1111 1000 0100 1000 0100 -> FF 84 84
807 Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
808 fgColor(0xFF8484FF), bgColor(0xFF84FF4D) {}
809 Text(uint32 x, uint32 y, string s, uint32 fg = 0xFF8484FF, uint32 bg = 0xFF84FF4D):
810 Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s) {}
811 virtual void HandleKey(SDLKey key) {}
812 virtual void HandleMouseMove(uint32 x, uint32 y) {}
813 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
814 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
815 virtual void Notify(Element *) {}
818 uint32 fgColor, bgColor;
822 void Text::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
824 if (text.length() > 0)
825 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
826 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
831 // Static image class
834 class Image: public Element
837 Image(uint32 x, uint32 y, const void * img): Element(x, y, 0, 0), image(img) {}
838 virtual void HandleKey(SDLKey key) {}
839 virtual void HandleMouseMove(uint32 x, uint32 y) {}
840 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
841 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
842 virtual void Notify(Element *) {}
845 uint32 fgColor, bgColor;
849 void Image::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
852 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, image);
860 class TextEdit: public Element
863 TextEdit(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
864 fgColor(0xFF8484FF), bgColor(0xFF84FF4D), text(""), caretPos(0),
866 TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
867 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
868 caretPos(0), maxScreenSize(mss) {}
869 virtual void HandleKey(SDLKey key);
870 virtual void HandleMouseMove(uint32 x, uint32 y) {}
871 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
872 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
873 virtual void Notify(Element *) {}
876 uint32 fgColor, bgColor;
879 uint32 maxScreenSize;
882 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
883 void TextEdit::HandleKey(SDLKey key)
885 if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9) || key == SDLK_PERIOD
886 || key == SDLK_SLASH)
888 //Need to handle shift key as well...
889 text[caretPos++] = key;
892 else if (key == SDLK_BACKSPACE)
896 else if (key == SDLK_DELETE)
902 void TextEdit::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
904 if (text.length() > 0)
906 FillScreenRectangle(screenBuffer, extents.x + offsetX, extents.y + offsetY, FONT_WIDTH * maxScreenSize, FONT_HEIGHT, bgColor);
907 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
908 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
911 // Draw the caret (underscore? or vertical line?)
919 class ListBox: public Element
920 //class ListBox: public Window
923 // ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
924 ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);//: Window(x, y, w, h),
925 // windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8),
926 // elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
927 // downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) {}
928 virtual void HandleKey(SDLKey key);
929 virtual void HandleMouseMove(uint32 x, uint32 y);
930 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
931 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
932 virtual void Notify(Element * e);
933 void SetNotificationElement(Element * e) { elementToTell = e; }
934 void AddItem(string s);
935 string GetSelectedItem(void);
939 uint32 windowPtr, cursor, limit;
940 uint32 charWidth, charHeight; // Box width/height in characters
941 Element * elementToTell;
942 Button upArrow, downArrow, upArrow2;
946 uint32 yRelativePoint;
949 ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h),
950 thumbClicked(false), windowPtr(0), cursor(0), limit(0), charWidth((w / FONT_WIDTH) - 1),
951 charHeight(h / FONT_HEIGHT), elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
952 downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox)
954 upArrow.SetNotificationElement(this);
955 downArrow.SetNotificationElement(this);
956 upArrow2.SetNotificationElement(this);
957 extents.w -= 8; // Make room for scrollbar...
960 void ListBox::HandleKey(SDLKey key)
962 if (key == SDLK_DOWN)
964 if (cursor != limit - 1) // Cursor is within its window
966 else // Otherwise, scroll the window...
968 if (cursor + windowPtr != item.size() - 1)
972 else if (key == SDLK_UP)
982 else if (key == SDLK_PAGEDOWN)
984 if (cursor != limit - 1)
989 if (windowPtr > item.size() - limit)
990 windowPtr = item.size() - limit;
993 else if (key == SDLK_PAGEUP)
999 if (windowPtr < limit)
1005 else if (key >= SDLK_a && key <= SDLK_z)
1007 // Advance cursor to filename with first letter pressed...
1008 uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
1010 for(uint32 i=0; i<item.size(); i++)
1012 if ((item[i][0] & 0xDF) == which)
1014 cursor = i - windowPtr;
1015 if (i > windowPtr + limit - 1)
1016 windowPtr = i - limit + 1, cursor = limit - 1;
1018 windowPtr = i, cursor = 0;
1025 void ListBox::HandleMouseMove(uint32 x, uint32 y)
1027 upArrow.HandleMouseMove(x - extents.x, y - extents.y);
1028 downArrow.HandleMouseMove(x - extents.x, y - extents.y);
1029 upArrow2.HandleMouseMove(x - extents.x, y - extents.y);
1033 uint32 sbHeight = extents.h - 24,
1034 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight);
1036 //yRelativePoint is the spot on the thumb where we clicked...
1037 int32 newThumbStart = y - yRelativePoint;
1039 if (newThumbStart < 0)
1042 if ((uint32)newThumbStart > sbHeight - thumb)
1043 newThumbStart = sbHeight - thumb;
1045 windowPtr = (uint32)(((float)newThumbStart / (float)sbHeight) * (float)item.size());
1046 //Check for cursor bounds as well... Or do we need to???
1047 //Actually, we don't...!
1051 void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1053 if (Inside(x, y) && mouseDown)
1055 // Why do we have to do this??? (- extents.y?)
1056 // I guess it's because only the Window class has offsetting implemented... !!! FIX !!!
1057 // cursor = (y - extents.y) / 8;
1058 cursor = (y - extents.y) / FONT_HEIGHT;
1061 // Check for a hit on the scrollbar...
1062 if (x > (uint32)(extents.x + extents.w) && x <= (uint32)(extents.x + extents.w + 8)
1063 && y > (uint32)(extents.y + 8) && y <= (uint32)(extents.y + extents.h - 16))
1067 // This shiaut should be calculated in AddItem(), not here... (or in Draw() for that matter)
1068 uint32 sbHeight = extents.h - 24,
1069 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1070 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1072 // Did we hit the thumb?
1073 if (y >= (extents.y + 8 + thumbStart) && y < (extents.y + 8 + thumbStart + thumb))
1074 thumbClicked = true, yRelativePoint = y - thumbStart;
1076 //Seems that this is useless--never reached except in rare cases and that the code outside is
1079 // thumbClicked = false;
1083 thumbClicked = false;
1085 upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1086 downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1087 upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1090 void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1092 for(uint32 i=0; i<limit; i++)
1094 // Strip off the extension
1095 // (extension stripping should be an option, not default!)
1096 string s(item[windowPtr + i], 0, item[windowPtr + i].length() - 4);
1097 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*8,
1098 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*FONT_HEIGHT,
1099 (cursor == i ? true : false), "%-*.*s", charWidth, charWidth, s.c_str());
1102 upArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1103 downArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1104 upArrow2.Draw(extents.x + offsetX, extents.y + offsetY);
1106 uint32 sbHeight = extents.h - 24,
1107 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1108 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1110 for(uint32 y=extents.y+offsetY+8; y<extents.y+offsetY+extents.h-16; y++)
1112 // for(uint32 x=extents.x+offsetX+extents.w-8; x<extents.x+offsetX+extents.w; x++)
1113 for(uint32 x=extents.x+offsetX+extents.w; x<extents.x+offsetX+extents.w+8; x++)
1115 if (y >= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8))
1116 // screenBuffer[x + (y * pitch)] = (thumbClicked ? 0x458E : 0xFFFF);
1117 //458E -> 01 0001 0 1100 0 1110 -> 0100 0101 0110 0011 0111 0011 -> 45 63 73
1118 screenBuffer[x + (y * pitch)] = (thumbClicked ? 0xFF736345 : 0xFFFFFFFF);
1120 // screenBuffer[x + (y * pitch)] = 0x0200;
1121 //0200 -> 000000 10000 00000 -> 00 1000 0100 00
1122 screenBuffer[x + (y * pitch)] = 0xFF008400;
1127 void ListBox::Notify(Element * e)
1129 if (e == &upArrow || e == &upArrow2)
1135 if (cursor < limit - 1)
1139 else if (e == &downArrow)
1141 if (windowPtr < item.size() - limit)
1151 void ListBox::AddItem(string s)
1153 // Do a simple insertion sort
1154 bool inserted = false;
1156 for(vector<string>::iterator i=item.begin(); i<item.end(); i++)
1158 if (stringCmpi(s, *i) == -1)
1169 limit = (item.size() > charHeight ? charHeight : item.size());
1172 string ListBox::GetSelectedItem(void)
1174 return item[windowPtr + cursor];
1182 class FileList: public Window
1185 FileList(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);
1186 virtual ~FileList() {}
1187 virtual void HandleKey(SDLKey key);
1188 virtual void HandleMouseMove(uint32 x, uint32 y) { Window::HandleMouseMove(x, y); }
1189 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) { Window::HandleMouseButton(x, y, mouseDown); }
1190 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) { Window::Draw(offsetX, offsetY); }
1191 virtual void Notify(Element * e);
1198 //Need 4 buttons, one scrollbar...
1199 FileList::FileList(uint32 x, uint32 y, uint32 w, uint32 h): Window(x, y, w, h)
1201 files = new ListBox(8, 8, w - 16, h - 32);
1203 load = new Button(8, h - 16, " Load ");
1205 load->SetNotificationElement(this);
1207 //!!! FIX !!! Directory might not exist--this shouldn't cause VJ to crash!
1208 DIR * dp = opendir(vjs.ROMPath);
1213 while ((de = readdir(dp)) != NULL)
1215 char * ext = strrchr(de->d_name, '.');
1218 if (strcasecmp(ext, ".zip") == 0 || strcasecmp(ext, ".j64") == 0
1219 || strcasecmp(ext, ".abs") == 0 || strcasecmp(ext, ".jag") == 0
1220 || strcasecmp(ext, ".rom") == 0)
1221 files->AddItem(string(de->d_name));
1228 //Give a diagnostic message here so that the (l)user can figure out what went wrong. !!! FIX !!!
1232 void FileList::HandleKey(SDLKey key)
1234 if (key == SDLK_RETURN)
1237 Window::HandleKey(key);
1240 void FileList::Notify(Element * e)
1244 char filename[MAX_PATH];
1245 strcpy(filename, vjs.ROMPath);
1247 if (strlen(filename) > 0)
1248 if (filename[strlen(filename) - 1] != '/')
1249 strcat(filename, "/");
1251 strcat(filename, files->GetSelectedItem().c_str());
1253 // uint32 romSize = JaguarLoadROM(jaguar_mainRom, filename);
1254 // JaguarLoadCart(jaguar_mainRom, filename);
1255 if (JaguarLoadFile(filename))
1258 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1259 SDL_PushEvent(&event);
1261 event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1262 event.user.data1 = (void *)ResetJaguar;
1263 SDL_PushEvent(&event);
1268 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1269 SDL_PushEvent(&event);
1271 // Handle the error, but don't run...
1272 // Tell the user that we couldn't run their file for some reason... !!! FIX !!!
1273 //how to kludge: Make a function like ResetJaguar which creates the dialog window
1282 // Menu class & supporting structs/classes
1288 Window * (* action)(void);
1291 NameAction(string n, Window * (* a)(void) = NULL, SDLKey k = SDLK_UNKNOWN): name(n),
1292 action(a), hotKey(k) {}
1298 MenuItems(): charLength(0) {}
1299 bool Inside(uint32 x, uint32 y)
1300 { return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
1301 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false); }
1304 vector<NameAction> item;
1309 class Menu: public Element
1312 // 1CFF -> 0 001 11 00 111 1 1111
1313 // 421F -> 0 100 00 10 000 1 1111
1314 Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = FONT_HEIGHT,
1315 /* uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F,
1316 uint16 bgch = 0x1CFF): Element(x, y, w, h), activated(false), clicked(false),*/
1317 /* uint32 fgc = 0xFF3F3F00, uint32 bgc = 0x7F000000, uint32 fgch = 0xFF878700,
1318 uint32 bgch = 0xFF3F3F00): Element(x, y, w, h), activated(false), clicked(false),*/
1319 /* uint32 fgc = 0xFFFF3F3F, uint32 bgc = 0xFF7F0000, uint32 fgch = 0xFFFF8787,
1320 uint32 bgch = 0xFFFF3F3F): Element(x, y, w, h), activated(false), clicked(false),*/
1321 uint32 fgc = 0xFF7F0000, uint32 bgc = 0xFFFF3F3F, uint32 fgch = 0xFFFF3F3F,
1322 uint32 bgch = 0xFFFF8787): Element(x, y, w, h), activated(false), clicked(false),
1323 inside(0), insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch),
1324 bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1) {}
1325 virtual void HandleKey(SDLKey key);
1326 virtual void HandleMouseMove(uint32 x, uint32 y);
1327 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
1328 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
1329 virtual void Notify(Element *) {}
1330 void Add(MenuItems mi);
1333 bool activated, clicked;
1334 uint32 inside, insidePopup;
1335 // uint16 fgColor, bgColor, fgColorHL, bgColorHL;
1336 uint32 fgColor, bgColor, fgColorHL, bgColorHL;
1337 int menuChosen, menuItemChosen;
1340 vector<MenuItems> itemList;
1343 void Menu::HandleKey(SDLKey key)
1345 for(uint32 i=0; i<itemList.size(); i++)
1347 for(uint32 j=0; j<itemList[i].item.size(); j++)
1349 if (itemList[i].item[j].hotKey == key)
1352 event.type = SDL_USEREVENT;
1353 event.user.code = MENU_ITEM_CHOSEN;
1354 event.user.data1 = (void *)itemList[i].item[j].action;
1355 SDL_PushEvent(&event);
1357 clicked = false, menuChosen = menuItemChosen = -1;
1364 void Menu::HandleMouseMove(uint32 x, uint32 y)
1366 inside = insidePopup = 0;
1370 // Find out *where* we are inside the menu bar
1371 uint32 xpos = extents.x;
1373 for(uint32 i=0; i<itemList.size(); i++)
1375 uint32 width = (itemList[i].title.length() + 2) * FONT_WIDTH;
1377 if (x >= xpos && x < xpos + width)
1388 if (!Inside(x, y) && !clicked)
1393 if (itemList[menuChosen].Inside(x, y) && clicked)
1395 insidePopup = ((y - itemList[menuChosen].extents.y) / FONT_HEIGHT) + 1;
1396 menuItemChosen = insidePopup - 1;
1400 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1409 menuChosen = -1; // clicked is already false...!
1412 else // clicked == true
1414 if (insidePopup && !mouseDown) // I.e., mouse-button-up
1417 if (itemList[menuChosen].item[menuItemChosen].action != NULL)
1419 // itemList[menuChosen].item[menuItemChosen].action();
1421 event.type = SDL_USEREVENT;
1422 event.user.code = MENU_ITEM_CHOSEN;
1423 event.user.data1 = (void *)itemList[menuChosen].item[menuItemChosen].action;
1424 SDL_PushEvent(&event);
1426 clicked = false, menuChosen = menuItemChosen = -1;
1429 while (SDL_PollEvent(&event)); // Flush the event queue...
1430 event.type = SDL_MOUSEMOTION;
1432 SDL_GetMouseState(&mx, &my);
1433 event.motion.x = mx, event.motion.y = my;
1434 SDL_PushEvent(&event); // & update mouse position...!
1438 if (!inside && !insidePopup && mouseDown)
1439 clicked = false, menuChosen = menuItemChosen = -1;
1443 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1445 uint32 xpos = extents.x + offsetX;
1447 for(uint32 i=0; i<itemList.size(); i++)
1449 // uint16 color1 = fgColor, color2 = bgColor;
1450 uint32 color1 = fgColor, color2 = bgColor;
1451 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
1452 color1 = fgColorHL, color2 = bgColorHL;
1454 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
1455 " %s ", itemList[i].title.c_str());
1456 xpos += (itemList[i].title.length() + 2) * FONT_WIDTH;
1459 // Draw sub menu (but only if active)
1462 uint32 ypos = extents.y + FONT_HEIGHT + 1;
1464 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
1466 // uint16 color1 = fgColor, color2 = bgColor;
1467 uint32 color1 = fgColor, color2 = bgColor;
1469 if (insidePopup == i + 1)
1470 color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
1472 if (itemList[menuChosen].item[i].name.length() > 0)
1473 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1474 color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
1475 itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
1477 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1478 fgColor, bgColor, "%.*s", itemList[menuChosen].charLength + 2, separator);
1480 ypos += FONT_HEIGHT;
1485 void Menu::Add(MenuItems mi)
1487 for(uint32 i=0; i<mi.item.size(); i++)
1488 if (mi.item[i].name.length() > mi.charLength)
1489 mi.charLength = mi.item[i].name.length();
1491 // Set extents here as well...
1492 mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + FONT_HEIGHT + 1;
1493 mi.extents.w = (mi.charLength + 2) * FONT_WIDTH, mi.extents.h = mi.item.size() * FONT_HEIGHT;
1495 itemList.push_back(mi);
1496 extents.w += (mi.title.length() + 2) * FONT_WIDTH;
1500 //Do we even *need* this?
1501 //Doesn't seem like it...
1502 /*class RootWindow: public Window
1505 RootWindow(Menu * m, Window * w = NULL): menu(m), window(w) {}
1506 //Do we even need to care about this crap?
1507 // { extents.x = extents.y = 0, extents.w = 320, extents.h = 240; }
1508 virtual void HandleKey(SDLKey key) {}
1509 virtual void HandleMouseMove(uint32 x, uint32 y) {}
1510 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
1511 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) {}
1512 virtual void Notify(Element *) {}
1517 int16 * rootImage[1280 * 240 * 2];
1522 // Draw text at the given x/y coordinates. Can invert text as well.
1524 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
1529 va_start(arg, text);
1530 vsprintf(string, text, arg);
1533 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1534 uint32 length = strlen(string), address = x + (y * pitch);
1536 uint32 color1 = 0x0080FF;
1537 uint8 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1538 uint8 xorMask = (invert ? 0xFF : 0x00);
1540 for(uint32 i=0; i<length; i++)
1542 uint8 c = string[i];
1543 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * FONT_WIDTH * FONT_HEIGHT;
1545 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1547 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1549 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1551 uint8 eBlue = (existingColor >> 16) & 0xFF,
1552 eGreen = (existingColor >> 8) & 0xFF,
1553 eRed = existingColor & 0xFF;
1555 uint8 trans = font2[fontAddr] ^ xorMask;
1556 uint8 invTrans = trans ^ 0xFF;
1558 uint32 bRed = (eRed * invTrans + nRed * trans) / 255,
1559 bGreen = (eGreen * invTrans + nGreen * trans) / 255,
1560 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1562 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1567 address += FONT_WIDTH;
1572 // Draw text at the given x/y coordinates, using FG/BG colors.
1574 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...)
1579 va_start(arg, text);
1580 vsprintf(string, text, arg);
1583 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1584 uint32 length = strlen(string), address = x + (y * pitch);
1586 uint8 eBlue = (color2 >> 16) & 0xFF, eGreen = (color2 >> 8) & 0xFF, eRed = color2 & 0xFF,
1587 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1589 for(uint32 i=0; i<length; i++)
1591 uint8 c = string[i];
1592 c = (c < 32 ? 0 : c - 32);
1593 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1595 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1597 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1599 uint8 trans = font2[fontAddr++];
1600 uint8 invTrans = trans ^ 0xFF;
1602 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1603 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1604 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1606 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1610 address += FONT_WIDTH;
1615 // Draw text at the given x/y coordinates with transparency (0 is fully opaque, 32 is fully transparent).
1617 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 trans, const char * text, ...)
1622 va_start(arg, text);
1623 vsprintf(string, text, arg);
1626 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1627 uint32 length = strlen(string), address = x + (y * pitch);
1629 for(uint32 i=0; i<length; i++)
1631 uint32 fontAddr = (uint32)string[i] * 64;
1633 for(uint32 yy=0; yy<8; yy++)
1635 for(uint32 xx=0; xx<8; xx++)
1637 if (font1[fontAddr])
1639 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1641 uint8 eBlue = (existingColor >> 16) & 0xFF,
1642 eGreen = (existingColor >> 8) & 0xFF,
1643 eRed = existingColor & 0xFF,
1644 //This could be done ahead of time, instead of on each pixel...
1645 nBlue = (color >> 16) & 0xFF,
1646 nGreen = (color >> 8) & 0xFF,
1647 nRed = color & 0xFF;
1649 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
1650 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
1651 //because dividing by 32 is faster than dividing by 31...!
1652 uint8 invTrans = 32 - trans;
1654 uint32 bRed = (eRed * trans + nRed * invTrans) / 32;
1655 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
1656 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
1658 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1670 // Draw text at the given x/y coordinates, using FG color and overlay alpha blending.
1672 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...)
1677 va_start(arg, text);
1678 vsprintf(string, text, arg);
1681 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1682 uint32 length = strlen(string), address = x + (y * pitch);
1684 color &= 0x00FFFFFF; // Just in case alpha was passed in...
1686 for(uint32 i=0; i<length; i++)
1688 uint8 c = string[i];
1689 c = (c < 32 ? 0 : c - 32);
1690 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1692 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1694 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1696 uint8 fontTrans = font2[fontAddr++];
1697 uint32 newTrans = (fontTrans * transparency / 255) << 24;
1698 uint32 pixel = newTrans | color;
1700 *(screen + address + xx + (yy * pitch)) = pixel;
1704 address += FONT_WIDTH;
1710 // Uses zero as transparent color
1711 // Can also use an optional alpha channel
1712 // Alpha channel is now mandatory! ;-)
1714 //void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap, uint8 * alpha/*=NULL*/)
1715 /*void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha)
1717 uint32 width = bitmap[0], height = bitmap[1];
1720 // uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
1721 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1722 uint32 address = x + (y * pitch);
1724 for(uint32 yy=0; yy<height; yy++)
1726 for(uint32 xx=0; xx<width; xx++)
1730 if (*bitmap && x + xx < pitch) // NOTE: Still doesn't clip the Y val...
1731 *(screen + address + xx + (yy * pitch)) = *bitmap;
1735 uint8 trans = *alpha;
1736 uint32 color = *bitmap;
1737 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1739 uint8 eRed = existingColor & 0xFF,
1740 eGreen = (existingColor >> 8) & 0xFF,
1741 eBlue = (existingColor >> 16) & 0xFF,
1743 nRed = color & 0xFF,
1744 nGreen = (color >> 8) & 0xFF,
1745 nBlue = (color >> 16) & 0xFF;
1747 uint8 invTrans = 255 - trans;
1748 uint32 bRed = (eRed * trans + nRed * invTrans) / 255;
1749 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 255;
1750 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 255;
1752 uint32 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1754 *(screen + address + xx + (yy * pitch)) = blendedColor;
1763 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap)
1765 uint32 width = bitmap[0], height = bitmap[1];
1768 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1769 uint32 address = x + (y * pitch);
1771 for(uint32 yy=0; yy<height; yy++)
1773 for(uint32 xx=0; xx<width; xx++)
1775 uint32 color = *bitmap;
1776 uint32 blendedColor = color;
1777 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1779 if (existingColor >> 24 != 0x00) // Pixel needs blending
1781 uint8 trans = color >> 24;
1782 uint8 invTrans = trans ^ 0xFF;//255 - trans;
1784 uint8 eRed = existingColor & 0xFF,
1785 eGreen = (existingColor >> 8) & 0xFF,
1786 eBlue = (existingColor >> 16) & 0xFF,
1788 nRed = color & 0xFF,
1789 nGreen = (color >> 8) & 0xFF,
1790 nBlue = (color >> 16) & 0xFF;
1792 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1793 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1794 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1796 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1799 *(screen + address + xx + (yy * pitch)) = blendedColor;
1805 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1807 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1808 uint32 address = x + (y * pitch);
1811 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1813 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1815 uint32 color = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1816 uint32 blendedColor = color;
1817 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1819 if (existingColor >> 24 != 0x00) // Pixel needs blending
1821 uint8 trans = color >> 24;
1822 uint8 invTrans = trans ^ 0xFF;
1824 uint8 eRed = existingColor & 0xFF,
1825 eGreen = (existingColor >> 8) & 0xFF,
1826 eBlue = (existingColor >> 16) & 0xFF,
1828 nRed = color & 0xFF,
1829 nGreen = (color >> 8) & 0xFF,
1830 nBlue = (color >> 16) & 0xFF;
1832 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1833 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1834 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1836 // Instead of $FF, should use the alpha from the destination pixel as the final alpha value...
1837 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1840 *(screen + address + xx + (yy * pitch)) = blendedColor;
1847 // Draw a bitmap without using blending
1849 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1851 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1852 uint32 address = x + (y * pitch);
1855 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1857 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1859 *(screen + address + xx + (yy * pitch)) = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1866 // Fill a portion of the screen with the passed in color
1868 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color)
1869 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h)
1871 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1872 uint32 address = x + (y * pitch);
1874 for(uint32 yy=0; yy<h; yy++)
1875 for(uint32 xx=0; xx<w; xx++)
1876 *(screen + address + xx + (yy * pitch)) = color;
1881 // GUI stuff--it's not crunchy, it's GUI! ;-)
1886 SDL_ShowCursor(SDL_DISABLE);
1887 SDL_GetMouseState(&mouseX, &mouseY);
1897 //bool GUIMain(void)
1898 bool GUIMain(char * filename)
1900 WriteLog("GUI: Inside GUIMain...\n");
1902 uint32 pointerBGSave[6 * 8 + 2];
1903 pointerBGSave[0] = 6;
1904 pointerBGSave[1] = 8;
1906 // Need to set things up so that it loads and runs a file if given on the command line. !!! FIX !!! [DONE]
1907 extern uint32 * backbuffer;
1908 // bool done = false;
1910 Window * mainWindow = NULL;
1912 // Set up the GUI classes...
1913 // Element::SetScreenAndPitch(backbuffer, GetSDLScreenWidthInPixels());
1914 Element::SetScreenAndPitch((uint32 *)sdlemuGetOverlayPixels(), sdlemuGetOverlayWidthInPixels());
1915 sdlemuEnableOverlay();
1919 mi.title = "Jaguar";
1920 mi.item.push_back(NameAction("Load...", LoadROM, SDLK_l));
1921 mi.item.push_back(NameAction("Reset", ResetJaguar, SDLK_r));
1923 mi.item.push_back(NameAction("Reset CD", ResetJaguarCD, SDLK_c));
1924 mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE));
1925 mi.item.push_back(NameAction(""));
1926 mi.item.push_back(NameAction("Quit", Quit, SDLK_q));
1928 mi.title = "Settings";
1930 mi.item.push_back(NameAction("Video..."));
1931 mi.item.push_back(NameAction("Audio..."));
1932 mi.item.push_back(NameAction("Misc...", MiscOptions, SDLK_m));
1936 mi.item.push_back(NameAction("About...", About));
1939 bool showMouse = true;
1941 // Grab the BG where the mouse will be painted (prime the backstore)
1945 Bitmap ptr = { 6, 8, 4,
1946 ""//"000011112222333344445555"
1947 //"000011112222333344445555"
1948 //"000011112222333344445555"
1949 //"000011112222333344445555"
1950 //"000011112222333344445555"
1951 //"000011112222333344445555"
1952 //"000011112222333344445555"
1953 //"000011112222333344445555"
1955 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
1958 for(uint32 y=0; y<pointerBGSave[1]; y++)
1959 for(uint32 x=0; x<pointerBGSave[0]; x++)
1960 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
1962 uint32 oldMouseX = mouseX, oldMouseY = mouseY;
1964 //This is crappy!!! !!! FIX !!!
1965 //Is this even needed any more? Hmm. Maybe. Dunno.
1966 WriteLog("GUI: Resetting Jaguar...\n");
1969 WriteLog("GUI: Clearing BG save...\n");
1970 // Set up our background save...
1971 // memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2);
1972 //1111 -> 000100 01000 10001 -> 0001 0000 0100 0010 1000 1100 -> 10 42 8C
1973 for(uint32 i=0; i<tom_getVideoModeWidth()*240; i++)
1974 // background[i] = 0xFF8C4210;
1975 backbuffer[i] = 0xFF8C4210;
1977 /* uint32 * overlayPix = (uint32 *)sdlemuGetOverlayPixels();
1978 for(uint32 i=0; i<sdlemuGetOverlayWidthInPixels()*480; i++)
1979 overlayPix[i] = 0x00000000;*/
1981 // Handle loading file passed in on the command line...! [DONE]
1985 if (JaguarLoadFile(filename))
1987 // event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1988 // event.user.data1 = (void *)ResetJaguar;
1989 // SDL_PushEvent(&event);
1990 // Make it so that if passed in on the command line, we quit right
1991 // away when pressing ESC
1992 WriteLog("GUI: Bypassing GUI since ROM passed in on command line...\n");
1998 // Create error dialog...
2000 sprintf(errText, "The file %40s could not be loaded.", filename);
2002 mainWindow = new Window(8, 16, 304, 160);
2003 mainWindow->AddElement(new Text(8, 8, "Error!"));
2004 mainWindow->AddElement(new Text(8, 24, errText));
2008 WriteLog("GUI: Entering main loop...\n");
2011 if (SDL_PollEvent(&event))
2013 if (event.type == SDL_USEREVENT)
2015 if (event.user.code == WINDOW_CLOSE)
2020 else if (event.user.code == MENU_ITEM_CHOSEN)
2022 // Confused? Let me enlighten... What we're doing here is casting
2023 // data1 as a pointer to a function which returns a Window pointer and
2024 // which takes no parameters (the "(Window *(*)(void))" part), then
2025 // derefencing it (the "*" in front of that) in order to call the
2026 // function that it points to. Clear as mud? Yeah, I hate function
2027 // pointers too, but what else are you gonna do?
2028 mainWindow = (*(Window *(*)(void))event.user.data1)();
2030 while (SDL_PollEvent(&event)); // Flush the event queue...
2031 event.type = SDL_MOUSEMOTION;
2033 SDL_GetMouseState(&mx, &my);
2034 event.motion.x = mx, event.motion.y = my;
2035 SDL_PushEvent(&event); // & update mouse position...!
2037 oldMouseX = mouseX, oldMouseY = mouseY;
2038 mouseX = mx, mouseY = my; // This prevents "mouse flash"...
2041 else if (event.type == SDL_ACTIVEEVENT)
2043 if (event.active.state == SDL_APPMOUSEFOCUS)
2044 showMouse = (event.active.gain ? true : false);
2046 else if (event.type == SDL_KEYDOWN)
2049 mainWindow->HandleKey(event.key.keysym.sym);
2051 mainMenu.HandleKey(event.key.keysym.sym);
2053 else if (event.type == SDL_MOUSEMOTION)
2055 oldMouseX = mouseX, oldMouseY = mouseY;
2056 mouseX = event.motion.x, mouseY = event.motion.y;
2059 mainWindow->HandleMouseMove(mouseX, mouseY);
2061 mainMenu.HandleMouseMove(mouseX, mouseY);
2063 else if (event.type == SDL_MOUSEBUTTONDOWN)
2065 uint32 mx = event.button.x, my = event.button.y;
2068 mainWindow->HandleMouseButton(mx, my, true);
2070 mainMenu.HandleMouseButton(mx, my, true);
2072 else if (event.type == SDL_MOUSEBUTTONUP)
2074 uint32 mx = event.button.x, my = event.button.y;
2077 mainWindow->HandleMouseButton(mx, my, false);
2079 mainMenu.HandleMouseButton(mx, my, false);
2082 //PROBLEM: In order to use the dirty rectangle approach here, we need some way of
2083 // handling it in mainMenu.Draw() and mainWindow->Draw(). !!! FIX !!!
2084 //POSSIBLE SOLUTION:
2085 // When mouse is moving and not on menu or window, can do straight dirty rect.
2086 // When mouse is on menu, need to update screen. Same for buttons on windows...
2087 // What the menu & windows should do is only redraw on a state change. IOW, they
2088 // should call their own/child window's Draw() function instead of doing it top
2090 //#define NEW_BACKSTORE_METHOD
2093 // The way we do things here is kinda stupid (redrawing the screen every frame), but
2094 // it's simple. Perhaps there may be a reason down the road to be more selective with
2095 // our clearing, but for now, this will suffice.
2096 // memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
2097 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 2);
2098 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 4);
2099 #ifndef NEW_BACKSTORE_METHOD
2100 memset(sdlemuGetOverlayPixels(), 0, sdlemuGetOverlayWidthInPixels() * 480 * 4);
2103 //Could do multiple windows here by using a vector + priority info...
2104 //Though the way ZSNES does it seems to be by a bool (i.e., they're always active, just not shown)
2109 /*uint32 pBGS[6 * 8 + 3] = { 6, 8, 4,
2119 //This isn't working... Why????
2120 //It's because DrawTransparentBitmap does alpha blending if it detects zero in the alpha channel.
2121 //So why do it that way? Hm.
2122 overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2124 #ifdef NEW_BACKSTORE_METHOD
2125 // DrawTransparentBitmapDeprecated(overlayPixels, oldMouseX, oldMouseY, pointerBGSave);
2126 // DrawTransparentBitmap(overlayPixels, oldMouseX, oldMouseY, pBGS);
2127 for(uint32 y=0; y<pointerBGSave[1]; y++)
2128 for(uint32 x=0; x<pointerBGSave[0]; x++)
2129 overlayPixels[((oldMouseY + y) * sdlemuGetOverlayWidthInPixels()) + (oldMouseX + x)] = 0x00000000;
2133 for(uint32 y=0; y<pointerBGSave[1]; y++)
2134 for(uint32 x=0; x<pointerBGSave[0]; x++)
2135 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
2139 // DrawTransparentBitmapDeprecated(backbuffer, mouseX, mouseY, mousePic);
2140 DrawTransparentBitmapDeprecated(overlayPixels, mouseX, mouseY, mousePic);
2150 // GUI "action" functions
2153 Window * LoadROM(void)
2155 FileList * fileList = new FileList(20, 20, 600, 440);
2157 return (Window *)fileList;
2160 Window * ResetJaguar(void)
2167 Window * ResetJaguarCD(void)
2169 memcpy(jaguar_mainRom, jaguar_CDBootROM, 0x40000);
2170 jaguarRunAddress = 0x802000;
2171 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, 0x40000);
2173 //This is a quick kludge to get the CDBIOS to boot properly...
2174 //Wild speculation: It could be that this memory location is wired into the CD unit
2175 //somehow, which lets it know whether or not a cart is present in the unit...
2176 jaguar_mainRom[0x0040B] = 0x03;
2184 bool debounceRunKey = true;
2185 Window * RunEmu(void)
2187 extern uint32 * backbuffer;
2188 //Temporary, to test the new timer based code...
2189 sdlemuDisableOverlay();
2191 sdlemuEnableOverlay();
2192 // Save the background for the GUI...
2193 // In this case, we squash the color to monochrome, then force it to blue + green...
2194 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2196 uint32 pixel = backbuffer[i];
2197 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2198 pixel = ((r + g + b) / 3) & 0x00FF;
2199 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2203 //This is crappy... !!! FIX !!!
2204 extern bool finished, showGUI;
2206 // uint32 nFrame = 0, nFrameskip = 0;
2207 uint32 totalFrames = 0;
2209 bool showMessage = true;
2210 uint32 showMsgFrames = 120;
2211 uint8 transparency = 0;
2212 // Pass a message to the "joystick" code to debounce the ESC key...
2213 debounceRunKey = true;
2215 uint32 cartType = 4;
2216 if (jaguarRomSize == 0x200000)
2218 else if (jaguarRomSize == 0x400000)
2220 else if (jaguar_mainRom_crc32 == 0x687068D5)
2222 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2225 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2226 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2230 // Set up new backbuffer with new pixels and data
2231 JaguarExecute(backbuffer, true);
2232 // JaguarExecuteNew();
2234 //WriteLog("Frame #%u...\n", totalFrames);
2235 //extern bool doDSPDis;
2236 //if (totalFrames == 373)
2239 //This sucks... !!! FIX !!!
2241 //This is done here so that the crud below doesn't get on our GUI background...
2245 // Some QnD GUI stuff here...
2248 extern uint32 gpu_pc, dsp_pc;
2249 DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
2250 DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
2251 DrawString(backbuffer, 8, 32, false, "%u FPS", framesPerSecond);
2256 // FF0F -> 1111 11 11 000 0 1111 -> 3F 18 0F
2257 // 3FE3 -> 0011 11 11 111 0 0011 -> 0F 3F 03
2258 /* DrawStringTrans((uint32 *)backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
2259 DrawStringTrans((uint32 *)backbuffer, 8, 26*8, 0x3FE3, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2260 DrawStringTrans((uint32 *)backbuffer, 8, 27*8, 0x3FE3, transparency, "CRC: %08X", jaguar_mainRom_crc32);//*/
2261 //first has wrong color. !!! FIX !!!
2262 DrawStringTrans(backbuffer, 8, 24*8, 0xFF7F63FF, transparency, "Running...");
2263 DrawStringTrans(backbuffer, 8, 26*8, 0xFF1FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2264 DrawStringTrans(backbuffer, 8, 27*8, 0xFF1FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2266 if (showMsgFrames == 0)
2270 if (transparency == 33)
2272 showMessage = false;
2273 /*extern bool doGPUDis;
2274 doGPUDis = true;//*/
2285 if (SDL_GetTicks() - elapsedTicks > 250)
2286 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2289 // Reset the pitch, since it may have been changed in-game...
2290 Element::SetScreenAndPitch((uint32 *)backbuffer, GetSDLScreenWidthInPixels());
2292 // Save the background for the GUI...
2293 // memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2);
2294 // In this case, we squash the color to monochrome, then force it to blue + green...
2295 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2297 uint32 pixel = backbuffer[i];
2298 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2299 pixel = ((r + g + b) / 3) & 0x00FF;
2300 background[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2308 bool debounceRunKey = true;
2309 Window * RunEmu(void)
2311 extern uint32 * backbuffer;
2312 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2313 memset(overlayPixels, 0x00, 640 * 480 * 4); // Clear out overlay...
2315 //This is crappy... !!! FIX !!!
2316 extern bool finished, showGUI;
2318 sdlemuDisableOverlay();
2320 // uint32 nFrame = 0, nFrameskip = 0;
2321 uint32 totalFrames = 0;
2323 bool showMessage = true;
2324 uint32 showMsgFrames = 120;
2325 uint8 transparency = 0xFF;
2326 // Pass a message to the "joystick" code to debounce the ESC key...
2327 debounceRunKey = true;
2329 uint32 cartType = 4;
2330 if (jaguarRomSize == 0x200000)
2332 else if (jaguarRomSize == 0x400000)
2334 else if (jaguar_mainRom_crc32 == 0x687068D5)
2336 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2339 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2340 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2344 // Set up new backbuffer with new pixels and data
2347 //WriteLog("Frame #%u...\n", totalFrames);
2348 //extern bool doDSPDis;
2349 //if (totalFrames == 373)
2352 //Problem: Need to do this *only* when the state changes from visible to not...
2353 //Also, need to clear out the GUI when not on (when showMessage is active...)
2354 if (showGUI || showMessage)
2355 sdlemuEnableOverlay();
2357 sdlemuDisableOverlay();
2359 //Add in a new function for clearing patches of screen (ClearOverlayRect)
2361 // Some QnD GUI stuff here...
2364 FillScreenRectangle(overlayPixels, 8, 1*FONT_HEIGHT, 128, 4*FONT_HEIGHT, 0x00000000);
2365 extern uint32 gpu_pc, dsp_pc;
2366 DrawString(overlayPixels, 8, 1*FONT_HEIGHT, false, "GPU PC: %08X", gpu_pc);
2367 DrawString(overlayPixels, 8, 2*FONT_HEIGHT, false, "DSP PC: %08X", dsp_pc);
2368 DrawString(overlayPixels, 8, 4*FONT_HEIGHT, false, "%u FPS", framesPerSecond);
2373 DrawString2(overlayPixels, 8, 24*FONT_HEIGHT, 0x007F63FF, transparency, "Running...");
2374 DrawString2(overlayPixels, 8, 26*FONT_HEIGHT, 0x001FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2375 DrawString2(overlayPixels, 8, 27*FONT_HEIGHT, 0x001FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2377 if (showMsgFrames == 0)
2381 if (transparency == 0)
2383 showMessage = false;
2384 /*extern bool doGPUDis;
2385 doGPUDis = true;//*/
2395 if (SDL_GetTicks() - elapsedTicks > 250)
2396 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2399 // Save the background for the GUI...
2400 // In this case, we squash the color to monochrome, then force it to blue + green...
2401 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2403 uint32 pixel = backbuffer[i];
2404 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2405 pixel = ((r + g + b) / 3) & 0x00FF;
2406 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2409 sdlemuEnableOverlay();
2419 WriteLog("GUI: Quitting due to user request.\n");
2425 Window * About(void)
2428 // sprintf(buf, "Virtual Jaguar CVS %s", __DATE__);
2429 sprintf(buf, "CVS %s", __DATE__);
2430 //fprintf(fp, "VirtualJaguar v1.0.8 (Last full build was on %s %s)\n", __DATE__, __TIME__);
2431 //VirtualJaguar v1.0.8 (Last full build was on Dec 30 2004 20:01:31)
2432 //Hardwired, bleh... !!! FIX !!!
2433 uint32 width = 55 * FONT_WIDTH, height = 18 * FONT_HEIGHT;
2434 uint32 xpos = (640 - width) / 2, ypos = (480 - height) / 2;
2435 // Window * window = new Window(8, 16, 50 * FONT_WIDTH, 21 * FONT_HEIGHT);
2436 Window * window = new Window(xpos, ypos, width, height);
2437 // window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.8"));
2438 // window->AddElement(new Text(8, 8, "Virtual Jaguar CVS 20050110", 0xFF3030FF, 0xFF000000));
2439 // window->AddElement(new Text(208, 8+0*FONT_HEIGHT, buf, 0xFF3030FF, 0xFF000000));
2440 window->AddElement(new Text(248, 8+4*FONT_HEIGHT+5, buf, 0xFF3030FF, 0xFF000000));
2441 window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "Coders:"));
2442 window->AddElement(new Text(16, 8+1*FONT_HEIGHT, "James L. Hammons (shamus)"));
2443 window->AddElement(new Text(16, 8+2*FONT_HEIGHT, "Niels Wagenaar (nwagenaar)"));
2444 window->AddElement(new Text(16, 8+3*FONT_HEIGHT, "Carwin Jones (Caz)"));
2445 window->AddElement(new Text(16, 8+4*FONT_HEIGHT, "Adam Green"));
2446 window->AddElement(new Text(8, 8+6*FONT_HEIGHT, "Testers:"));
2447 window->AddElement(new Text(16, 8+7*FONT_HEIGHT, "Guruma"));
2448 window->AddElement(new Text(8, 8+9*FONT_HEIGHT, "Thanks go out to:"));
2449 window->AddElement(new Text(16, 8+10*FONT_HEIGHT, "Aaron Giles for the original CoJag"));
2450 window->AddElement(new Text(16, 8+11*FONT_HEIGHT, "David Raingeard for the original VJ"));
2451 window->AddElement(new Text(16, 8+12*FONT_HEIGHT, "Karl Stenerud for his Musashi 68K emu"));
2452 window->AddElement(new Text(16, 8+13*FONT_HEIGHT, "Sam Lantinga for his amazing SDL libs"));
2453 window->AddElement(new Text(16, 8+14*FONT_HEIGHT, "Ryan C. Gordon for VJ's web presence"));
2454 window->AddElement(new Text(16, 8+15*FONT_HEIGHT, "Curt Vendel for various Jaguar goodies"));
2455 window->AddElement(new Text(16, 8+16*FONT_HEIGHT, "The guys over at Atari Age ;-)"));
2456 // window->AddElement(new Image(8, 8, &vj_title_small));
2457 window->AddElement(new Image(width - (vj_title_small.width + 8), 8, &vj_title_small));
2462 Window * MiscOptions(void)
2464 Window * window = new Window(8, 16, 304, 192);
2465 window->AddElement(new PushButton(8, 8, &vjs.useJaguarBIOS, "BIOS"));
2466 window->AddElement(new SlideSwitch(8, 32, &vjs.hardwareTypeNTSC, "PAL", "NTSC"));
2467 window->AddElement(new PushButton(8, 64, &vjs.DSPEnabled, "DSP"));
2468 window->AddElement(new SlideSwitch(24, 88, &vjs.usePipelinedDSP, "Original", "Pipelined"));
2469 window->AddElement(new SlideSwitch(8, 120, (bool *)&vjs.glFilter, "Sharp", "Blurry"));
2470 window->AddElement(new SlideSwitch(8, 152, (bool *)&vjs.renderType, "Normal render", "TV style"));
2472 window->AddElement(new TextEdit(88, 8, vjs.ROMPath, 20, 0xFF8484FF, 0xFF000000));
2474 /*TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
2475 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
2476 caretPos(0), maxScreenSize(mss) {}*/
2485 // * Window/fullscreen
2486 // * Key definitions
2493 // Generic ROM loading
2495 uint32 JaguarLoadROM(uint8 * rom, char * path)
2497 // We really should have some kind of sanity checking for the ROM size here to prevent
2498 // a buffer overflow... !!! FIX !!!
2501 WriteLog("JaguarLoadROM: Attempting to load file '%s'...", path);
2502 char * ext = strrchr(path, '.');
2504 WriteLog("FAILED!\n");
2506 WriteLog("Succeeded in finding extension (%s)!\n", ext);
2510 WriteLog("VJ: Loading \"%s\"...", path);
2512 if (strcasecmp(ext, ".zip") == 0)
2514 // Handle ZIP file loading here...
2515 WriteLog("(ZIPped)...");
2517 if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1)
2519 WriteLog("Failed!\n");
2525 /* FILE * fp = fopen(path, "rb");
2529 WriteLog("Failed!\n");
2533 fseek(fp, 0, SEEK_END);
2534 romSize = ftell(fp);
2535 fseek(fp, 0, SEEK_SET);
2536 fread(rom, 1, romSize, fp);
2539 // Handle gzipped files transparently [Adam Green]...
2541 gzFile fp = gzopen(path, "rb");
2545 WriteLog("Failed!\n");
2549 romSize = gzfilelength(fp);
2550 gzseek(fp, 0, SEEK_SET);
2551 gzread(fp, rom, romSize);
2555 WriteLog("OK (%i bytes)\n", romSize);
2562 // Jaguar file loading
2564 bool JaguarLoadFile(char * path)
2566 // jaguarRomSize = JaguarLoadROM(mem, path);
2567 jaguarRomSize = JaguarLoadROM(jaguar_mainRom, path);
2569 /*//This is not *nix friendly for some reason...
2570 // if (!UserSelectFile(path, newPath))
2571 if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath))
2573 WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path);
2578 if (jaguarRomSize == 0)
2580 // WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath);
2581 WriteLog("GUI: Could not load ROM from file \"%s\"...\nAborting load!\n", path);
2582 // Need to do something else here, like throw up an error dialog instead of aborting. !!! FIX !!!
2585 return false; // This is a start...
2588 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, jaguarRomSize);
2589 WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32);
2592 jaguarRunAddress = 0x802000;
2594 char * ext = strrchr(path, '.'); // Get the file's extension for non-cartridge checking
2596 //NOTE: Should fix JaguarLoadROM() to replace .zip with what's *in* the zip (.abs, .j64, etc.)
2597 if (strcasecmp(ext, ".rom") == 0)
2599 // File extension ".ROM": Alpine image that loads/runs at $802000
2600 WriteLog("GUI: Setting up homebrew (ROM)... Run address: 00802000, length: %08X\n", jaguarRomSize);
2602 for(int i=jaguarRomSize-1; i>=0; i--)
2603 jaguar_mainRom[0x2000 + i] = jaguar_mainRom[i];
2605 memset(jaguar_mainRom, 0xFF, 0x2000);
2606 /* memcpy(jaguar_mainRam, jaguar_mainRom, jaguarRomSize);
2607 memset(jaguar_mainRom, 0xFF, 0x600000);
2608 memcpy(jaguar_mainRom + 0x2000, jaguar_mainRam, jaguarRomSize);
2609 memset(jaguar_mainRam, 0x00, 0x400000);*/
2612 Stubulator ROM vectors...
2613 handler 001 at $00E00008
2614 handler 002 at $00E008DE
2615 handler 003 at $00E008E2
2616 handler 004 at $00E008E6
2617 handler 005 at $00E008EA
2618 handler 006 at $00E008EE
2619 handler 007 at $00E008F2
2620 handler 008 at $00E0054A
2621 handler 009 at $00E008FA
2622 handler 010 at $00000000
2623 handler 011 at $00000000
2624 handler 012 at $00E008FE
2625 handler 013 at $00E00902
2626 handler 014 at $00E00906
2627 handler 015 at $00E0090A
2628 handler 016 at $00E0090E
2629 handler 017 at $00E00912
2630 handler 018 at $00E00916
2631 handler 019 at $00E0091A
2632 handler 020 at $00E0091E
2633 handler 021 at $00E00922
2634 handler 022 at $00E00926
2635 handler 023 at $00E0092A
2636 handler 024 at $00E0092E
2637 handler 025 at $00E0107A
2638 handler 026 at $00E0107A
2639 handler 027 at $00E0107A
2640 handler 028 at $00E008DA
2641 handler 029 at $00E0107A
2642 handler 030 at $00E0107A
2643 handler 031 at $00E0107A
2644 handler 032 at $00000000
2646 Let's try setting up the illegal instruction vector for a stubulated jaguar...
2648 /* SET32(jaguar_mainRam, 0x08, 0x00E008DE);
2649 SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
2650 SET32(jaguar_mainRam, 0x10, 0x00E008E6); // <-- Should be here (it is)...
2651 SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
2653 // Try setting the vector to say, $1000 and putting an instruction there that loops forever:
2654 // This kludge works! Yeah!
2655 SET32(jaguar_mainRam, 0x10, 0x00001000);
2656 SET16(jaguar_mainRam, 0x1000, 0x60FE); // Here: bra Here
2658 else if (strcasecmp(ext, ".abs") == 0)
2660 // File extension ".ABS": Atari linker output file with header (w/o is useless to us here)
2663 ABS Format sleuthing (LBUGDEMO.ABS):
2665 000000 60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
2666 000010 12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
2669 DRI-format file detected...
2670 Text segment size = 0x0000050c bytes
2671 Data segment size = 0x000462c0 bytes
2672 BSS Segment size = 0x00000428 bytes
2673 Symbol Table size = 0x000012a6 bytes
2674 Absolute Address for text segment = 0x00802000
2675 Absolute Address for data segment = 0x0080250c
2676 Absolute Address for BSS segment = 0x00004000
2679 000000 01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
2680 000010 00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
2681 000020 00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
2683 000030 2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
2684 000040 00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
2685 000050 00 00 00 00 00 00 00 20
2686 000058 2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
2687 000068 00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
2688 000078 00 00 00 00 00 00 00 40
2689 000080 2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
2690 000090 00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
2691 0000a0 00 00 00 00 00 00 00 80
2693 Header size is $A8 bytes...
2695 BSD/COFF format file detected...
2696 3 sections specified
2697 Symbol Table offset = 230160 ($00038310)
2698 Symbol Table contains 1339 symbol entries ($0000053B)
2699 The additional header size is 28 bytes ($001C)
2700 Magic Number for RUN_HDR = 0x00000107
2701 Text Segment Size = 7632 ($00001DD0)
2702 Data Segment Size = 222360 ($00036498)
2703 BSS Segment Size = 428928 ($00068B80)
2704 Starting Address for executable = 0x00802000
2705 Start of Text Segment = 0x00802000
2706 Start of Data Segment = 0x00803dd0
2708 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1B)
2710 uint32 loadAddress = GET32(jaguar_mainRom, 0x16), //runAddress = GET32(jaguar_mainRom, 0x2A),
2711 codeSize = GET32(jaguar_mainRom, 0x02) + GET32(jaguar_mainRom, 0x06);
2712 WriteLog("GUI: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize);
2714 if (loadAddress < 0x800000)
2715 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x24, codeSize);
2718 for(int i=codeSize-1; i>=0; i--)
2719 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0x24];
2720 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0x24, codeSize);
2721 memset(jaguar_mainRom, 0xFF, 0x600000);
2722 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2723 memset(jaguar_mainRam, 0x00, 0x400000);*/
2726 jaguarRunAddress = loadAddress;
2728 else if (jaguar_mainRom[0] == 0x01 && jaguar_mainRom[1] == 0x50)
2730 uint32 loadAddress = GET32(jaguar_mainRom, 0x28), runAddress = GET32(jaguar_mainRom, 0x24),
2731 codeSize = GET32(jaguar_mainRom, 0x18) + GET32(jaguar_mainRom, 0x1C);
2732 WriteLog("GUI: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize);
2734 if (loadAddress < 0x800000)
2735 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0xA8, codeSize);
2738 for(int i=codeSize-1; i>=0; i--)
2739 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0xA8];
2740 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0xA8, codeSize);
2741 memset(jaguar_mainRom, 0xFF, 0x600000);
2742 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2743 memset(jaguar_mainRam, 0x00, 0x400000);*/
2746 jaguarRunAddress = runAddress;
2750 WriteLog("GUI: Couldn't find correct ABS format: %02X %02X\n", jaguar_mainRom[0], jaguar_mainRom[1]);
2754 else if (strcasecmp(ext, ".jag") == 0)
2756 // File extension ".JAG": Atari server file with header
2757 //NOTE: The bytes 'JAGR' should also be at position $1C...
2758 // Also, there's *always* a $601A header at position $00...
2759 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
2761 uint32 loadAddress = GET32(jaguar_mainRom, 0x22), runAddress = GET32(jaguar_mainRom, 0x2A);
2762 //This is not always right! Especially when converted via bin2jag1!!!
2763 //We should have access to the length of the furshlumiger file that was loaded anyway!
2765 // uint32 progLength = GET32(jaguar_mainRom, 0x02);
2768 // WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
2769 // memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, progLength);
2770 WriteLog("GUI: Setting up homebrew (JAG)... Run address: %08X, length: %08X\n", runAddress, jaguarRomSize - 0x2E);
2771 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, jaguarRomSize - 0x2E);
2772 // SET32(jaguar_mainRam, 4, runAddress);
2773 jaguarRunAddress = runAddress;
2778 // .J64 (Jaguar cartridge ROM image) is implied by the FileList object...
2784 // Get the length of a (possibly) gzipped file
2786 int gzfilelength(gzFile gd)
2788 int size = 0, length = 0;
2789 unsigned char buffer[0x10000];
2795 // Read in chunks until EOF
2796 size = gzread(gd, buffer, 0x10000);