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);
161 // Various GUI bitmaps
164 // These representations *should* be endian safe.
167 15 / 256, 15 % 256, // width (HI byte, LO byte)
168 15 / 256, 15 % 256, // height (HI byte, LO byte)
170 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,
171 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,
172 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,
173 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,
174 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,
175 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,
176 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,
177 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,
178 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,
179 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,
180 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,
181 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,
182 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,
183 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,
184 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
187 uint8 closeBoxHover[] = {
188 15 / 256, 15 % 256, // width (HI byte, LO byte)
189 15 / 256, 15 % 256, // height (HI byte, LO byte)
191 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,
192 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,
193 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,
194 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,
195 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,
196 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,
197 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,
198 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,
199 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,
200 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,
201 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,
202 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,
203 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,
204 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,
205 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
208 uint8 closeBoxDown[] = {
209 15 / 256, 15 % 256, // width (HI byte, LO byte)
210 15 / 256, 15 % 256, // height (HI byte, LO byte)
212 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,
213 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,
214 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,
215 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,
216 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,
217 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,
218 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,
219 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,
220 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,
221 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,
222 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,
223 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,
224 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,
225 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,
226 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
229 #include "fd-img-128x128.c"
234 #include <sys/types.h> // For MacOS <dirent.h> dependency
240 #include <ctype.h> // For toupper()
241 #include "settings.h"
246 #include "font14pt.h" // Also 15, 16, 17, 18
247 #include "guielements.h"
251 #include "sdlemu_opengl.h"
254 using namespace std; // For STL stuff
256 // Private function prototypes
258 class Window; // Forward declaration...
260 //void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha = NULL);
261 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap);
262 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
263 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap);
264 //Should call this FillScreenRectangle with a number representing the RGBA value to fill. !!! FIX !!!
265 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h);
266 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color);
267 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 opacity, const char * text, ...);
268 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...);
269 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...);
270 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...);
271 Window * LoadROM(void);
272 Window * ResetJaguar(void);
273 Window * ResetJaguarCD(void);
274 Window * RunEmu(void);
276 Window * About(void);
277 Window * MiscOptions(void);
279 int gzfilelength(gzFile gd);
281 // External variables
283 extern uint8 * jaguar_mainRam;
284 extern uint8 * jaguar_mainRom;
285 extern uint8 * jaguar_bootRom;
286 extern uint8 * jaguar_CDBootROM;
287 extern bool BIOSLoaded;
288 extern bool CDBIOSLoaded;
290 // Local global variables
292 bool exitGUI = false; // GUI (emulator) done variable
293 int mouseX = 0, mouseY = 0;
294 uint32 background[1280 * 256]; // GUI background buffer
296 char separator[] = "--------------------------------------------------------";
299 // Case insensitive string compare function
300 // Taken straight out of Thinking In C++ by Bruce Eckel. Thanks Bruce!
303 int stringCmpi(const string &s1, const string &s2)
305 // Select the first element of each string:
306 string::const_iterator p1 = s1.begin(), p2 = s2.begin();
308 while (p1 != s1.end() && p2 != s2.end()) // Don
\92t run past the end
310 if (toupper(*p1) != toupper(*p2)) // Compare upper-cased chars
311 return (toupper(*p1) < toupper(*p2) ? -1 : 1);// Report which was lexically greater
317 // If they match up to the detected eos, say which was longer. Return 0 if the same.
318 return s2.size() - s1.size();
325 enum { WINDOW_CLOSE, MENU_ITEM_CHOSEN };
330 Element(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0)
331 { extents.x = x, extents.y = y, extents.w = w, extents.h = h; }
332 virtual void HandleKey(SDLKey key) = 0; // These are "pure" virtual functions...
333 virtual void HandleMouseMove(uint32 x, uint32 y) = 0;
334 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) = 0;
335 virtual void Draw(uint32, uint32) = 0;
336 virtual void Notify(Element *) = 0;
337 //Needed? virtual ~Element() = 0;
338 //We're not allocating anything in the base class, so the answer would be NO.
339 bool Inside(uint32 x, uint32 y);
341 // static void SetScreenAndPitch(int16 * s, uint32 p) { screenBuffer = s, pitch = p; }
342 static void SetScreenAndPitch(uint32 * s, uint32 p) { screenBuffer = s, pitch = p; }
347 // Class variables...
348 // static int16 * screenBuffer;
349 static uint32 * screenBuffer;
353 // Initialize class variables (Element)
354 //int16 * Element::screenBuffer = NULL;
355 uint32 * Element::screenBuffer = NULL;
356 uint32 Element::pitch = 0;
358 bool Element::Inside(uint32 x, uint32 y)
360 return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
361 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false);
369 class Button: public Element
372 Button(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
373 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
374 bgColor(0xFF00FF00), pic(NULL), elementToTell(NULL) {}
375 Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
376 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
377 bgColor(0xFF00FF00), pic(p), elementToTell(NULL) {}
378 // Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
379 Button(uint32 x, uint32 y, uint32 * p, uint32 * pH = NULL, uint32 * pD = NULL): Element(x, y, 0, 0),
380 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
381 bgColor(0xFF00FF00), pic(p), picHover(pH), picDown(pD), elementToTell(NULL)
382 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
383 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
384 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
385 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL) {}
386 Button(uint32 x, uint32 y, string s): Element(x, y, 0, FONT_HEIGHT),
387 activated(false), clicked(false), inside(false), fgColor(0xFFFFFFFF),
388 bgColor(0xFF00FF00), pic(NULL), text(s), elementToTell(NULL)
389 { extents.w = s.length() * FONT_WIDTH; }
390 virtual void HandleKey(SDLKey key) {}
391 virtual void HandleMouseMove(uint32 x, uint32 y);
392 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
393 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
394 virtual void Notify(Element *) {}
395 bool ButtonClicked(void) { return activated; }
396 void SetNotificationElement(Element * e) { elementToTell = e; }
399 bool activated, clicked, inside;
400 uint32 fgColor, bgColor;
401 uint32 * pic, * picHover, * picDown;
403 Element * elementToTell;
406 void Button::HandleMouseMove(uint32 x, uint32 y)
408 inside = Inside(x, y);
411 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
418 if (clicked && !mouseDown)
420 clicked = false, activated = true;
422 // Send a message that we're activated (if there's someone to tell, that is)
424 elementToTell->Notify(this);
428 clicked = activated = false;
431 void Button::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
433 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
435 if (text.length() > 0) // Simple text button
438 for(uint32 y=0; y<extents.h; y++)
440 for(uint32 x=0; x<extents.w; x++)
442 // Doesn't clip in y axis! !!! FIX !!!
443 if (extents.x + x < pitch)
444 screenBuffer[addr + x + (y * pitch)]
445 // = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
446 //43F0 -> 010000 11111 10000 -> 0100 0001 1111 1111 1000 0100 -> 41 FF 84
447 = (clicked && inside ? fgColor : (inside ? 0xFF84FF41 : bgColor));
451 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
453 else // Graphical button
455 uint32 * picToShow = pic;
457 if (picHover != NULL && inside && !clicked)
458 picToShow = picHover;
460 if (picDown != NULL && inside && clicked)
463 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, picToShow);
472 class PushButton: public Element
475 // Save state externally?
476 //We pass in a state variable if we want to track it externally, otherwise we use our own
477 //internal state var. Still need to do some kind of callback for pushbuttons that do things
478 //like change from fullscreen to windowed... !!! FIX !!!
481 // PushButton(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
482 // activated(false), clicked(false), inside(false), fgColor(0xFFFF),
483 // bgColor(0x03E0), pic(NULL), elementToTell(NULL) {}
484 // PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 8, 8), state(st),
485 // inside(false), text(s) { if (st == NULL) state = &internalState; }
486 PushButton(uint32 x, uint32 y, bool * st, string s): Element(x, y, 16, 16), state(st),
487 inside(false), text(s) { if (st == NULL) state = &internalState; }
488 /* Button(uint32 x, uint32 y, uint32 w, uint32 h, uint32 * p): Element(x, y, w, h),
489 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
490 bgColor(0x03E0), pic(p), elementToTell(NULL) {}
491 Button(uint32 x, uint32 y, uint32 * p): Element(x, y, 0, 0),
492 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
493 bgColor(0x03E0), pic(p), elementToTell(NULL)
494 { if (pic) extents.w = pic[0], extents.h = pic[1]; }
495 Button(uint32 x, uint32 y, uint32 w, uint32 h, string s): Element(x, y, w, h),
496 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
497 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL) {}
498 PushButton(uint32 x, uint32 y, string s): Element(x, y, 0, 8),
499 activated(false), clicked(false), inside(false), fgColor(0xFFFF),
500 bgColor(0x03E0), pic(NULL), text(s), elementToTell(NULL)
501 { extents.w = s.length() * 8; }*/
502 virtual void HandleKey(SDLKey key) {}
503 virtual void HandleMouseMove(uint32 x, uint32 y);
504 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
505 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
506 virtual void Notify(Element *) {}
507 // bool ButtonClicked(void) { return activated; }
508 // void SetNotificationElement(Element * e) { elementToTell = e; }
513 // bool activated, clicked, inside;
514 // uint16 fgColor, bgColor;
517 // Element * elementToTell;
521 void PushButton::HandleMouseMove(uint32 x, uint32 y)
523 inside = Inside(x, y);
526 void PushButton::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
528 if (inside && mouseDown)
533 if (clicked && !mouseDown)
535 clicked = false, activated = true;
537 // Send a message that we're activated (if there's someone to tell, that is)
539 elementToTell->Notify(this);
544 // clicked = activated = false;
547 void PushButton::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
549 /* uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
551 for(uint32 y=0; y<extents.h; y++)
553 for(uint32 x=0; x<extents.w; x++)
555 // Doesn't clip in y axis! !!! FIX !!!
556 if (extents.x + x < pitch)
557 screenBuffer[addr + x + (y * pitch)]
558 = (clicked && inside ? fgColor : (inside ? 0x43F0 : bgColor));
563 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbDown);
565 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, &pbUp);
567 if (text.length() > 0)
568 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text.c_str());
576 class SlideSwitch: public Element
579 // Save state externally?
580 //Seems to be handled the same as PushButton, but without sanity checks. !!! FIX !!!
583 SlideSwitch(uint32 x, uint32 y, bool * st, string s1, string s2): Element(x, y, 16, 32), state(st),
584 inside(false), text1(s1), text2(s2) {}
585 virtual void HandleKey(SDLKey key) {}
586 virtual void HandleMouseMove(uint32 x, uint32 y);
587 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
588 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
589 virtual void Notify(Element *) {}
590 // bool ButtonClicked(void) { return activated; }
591 // void SetNotificationElement(Element * e) { elementToTell = e; }
596 // bool activated, clicked, inside;
597 // uint16 fgColor, bgColor;
600 // Element * elementToTell;
603 void SlideSwitch::HandleMouseMove(uint32 x, uint32 y)
605 inside = Inside(x, y);
608 void SlideSwitch::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
610 if (inside && mouseDown)
615 if (clicked && !mouseDown)
617 clicked = false, activated = true;
619 // Send a message that we're activated (if there's someone to tell, that is)
621 elementToTell->Notify(this);
626 // clicked = activated = false;
629 void SlideSwitch::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
631 DrawTransparentBitmapDeprecated(screenBuffer, extents.x + offsetX, extents.y + offsetY, (*state ? slideSwitchDown : slideSwitchUp));
633 if (text1.length() > 0)
634 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY, false, "%s", text1.c_str());
636 if (text2.length() > 0)
637 DrawString(screenBuffer, extents.x + offsetX + 24, extents.y + offsetY + 16, false, "%s", text2.c_str());
645 class Window: public Element
648 /* Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
649 fgColor(0x4FF0), bgColor(0xFE10)
650 { close = new Button(w - 8, 1, closeBox); list.push_back(close); }*/
651 Window(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0,
652 void (* f)(Element *) = NULL): Element(x, y, w, h),
653 // /*clicked(false), inside(false),*/ fgColor(0x4FF0), bgColor(0x1E10),
654 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
655 //1E10 -> 000111 10000 10000 -> 0001 1111 1000 0100 1000 0100 -> 1F 84 84
656 /*clicked(false), inside(false),*/ fgColor(0xFF84FF4D), bgColor(0xFF84841F),
658 { close = new Button(w - (CLOSEBOX_WIDTH + 1), 1, closeBox, closeBoxHover, closeBoxDown);
659 list.push_back(close);
660 close->SetNotificationElement(this); }
662 virtual void HandleKey(SDLKey key);
663 virtual void HandleMouseMove(uint32 x, uint32 y);
664 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
665 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
666 virtual void Notify(Element * e);
667 void AddElement(Element * e);
668 // bool WindowActive(void) { return true; }//return !close->ButtonClicked(); }
671 // bool clicked, inside;
672 uint32 fgColor, bgColor;
673 void (* handler)(Element *);
675 //We have to use a list of Element *pointers* because we can't make a list that will hold
676 //all the different object types in the same list...
677 vector<Element *> list;
682 for(uint32 i=0; i<list.size(); i++)
687 void Window::HandleKey(SDLKey key)
689 if (key == SDLK_ESCAPE)
692 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
693 SDL_PushEvent(&event);
696 // Handle the items this window contains...
697 for(uint32 i=0; i<list.size(); i++)
698 // Make coords relative to upper right corner of this window...
699 list[i]->HandleKey(key);
702 void Window::HandleMouseMove(uint32 x, uint32 y)
704 // Handle the items this window contains...
705 for(uint32 i=0; i<list.size(); i++)
706 // Make coords relative to upper right corner of this window...
707 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
710 void Window::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
712 // Handle the items this window contains...
713 for(uint32 i=0; i<list.size(); i++)
714 // Make coords relative to upper right corner of this window...
715 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
718 void Window::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
720 uint32 addr = (extents.x + offsetX) + ((extents.y + offsetY) * pitch);
722 for(uint32 y=0; y<extents.h; y++)
724 for(uint32 x=0; x<extents.w; x++)
726 // Doesn't clip in y axis! !!! FIX !!!
727 if (extents.x + x < pitch)
728 screenBuffer[addr + x + (y * pitch)] = bgColor;
732 // Handle the items this window contains...
733 for(uint32 i=0; i<list.size(); i++)
734 list[i]->Draw(extents.x, extents.y);
737 void Window::AddElement(Element * e)
742 void Window::Notify(Element * e)
747 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
748 SDL_PushEvent(&event);
757 class Text: public Element
760 // Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
761 // fgColor(0x4FF0), bgColor(0xFE10) {}
762 // Text(uint32 x, uint32 y, string s, uint16 fg = 0x4FF0, uint16 bg = 0xFE10): Element(x, y, 0, 0),
763 // fgColor(fg), bgColor(bg), text(s) {}
764 //4FF0 -> 010011 11111 10000 -> 0100 1101 1111 1111 1000 0100 -> 4D FF 84
765 //FE10 -> 111111 10000 10000 -> 1111 1111 1000 0100 1000 0100 -> FF 84 84
766 Text(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
767 fgColor(0xFF8484FF), bgColor(0xFF84FF4D) {}
768 Text(uint32 x, uint32 y, string s, uint32 fg = 0xFF8484FF, uint32 bg = 0xFF84FF4D):
769 Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s) {}
770 virtual void HandleKey(SDLKey key) {}
771 virtual void HandleMouseMove(uint32 x, uint32 y) {}
772 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
773 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
774 virtual void Notify(Element *) {}
777 uint32 fgColor, bgColor;
781 void Text::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
783 if (text.length() > 0)
784 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
785 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
790 // Static image class
793 class Image: public Element
796 Image(uint32 x, uint32 y, const void * img): Element(x, y, 0, 0), image(img) {}
797 virtual void HandleKey(SDLKey key) {}
798 virtual void HandleMouseMove(uint32 x, uint32 y) {}
799 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
800 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
801 virtual void Notify(Element *) {}
804 uint32 fgColor, bgColor;
808 void Image::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
811 DrawTransparentBitmap(screenBuffer, extents.x + offsetX, extents.y + offsetY, image);
819 class TextEdit: public Element
822 TextEdit(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
823 fgColor(0xFF8484FF), bgColor(0xFF84FF4D), text(""), caretPos(0),
825 TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
826 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
827 caretPos(0), maxScreenSize(mss) {}
828 virtual void HandleKey(SDLKey key);
829 virtual void HandleMouseMove(uint32 x, uint32 y) {}
830 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
831 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
832 virtual void Notify(Element *) {}
835 uint32 fgColor, bgColor;
838 uint32 maxScreenSize;
841 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
842 void TextEdit::HandleKey(SDLKey key)
844 if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9) || key == SDLK_PERIOD
845 || key == SDLK_SLASH)
847 //Need to handle shift key as well...
848 text[caretPos++] = key;
851 else if (key == SDLK_BACKSPACE)
855 else if (key == SDLK_DELETE)
861 void TextEdit::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
863 if (text.length() > 0)
865 FillScreenRectangle(screenBuffer, extents.x + offsetX, extents.y + offsetY, FONT_WIDTH * maxScreenSize, FONT_HEIGHT, bgColor);
866 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY, false, "%s", text.c_str());
867 DrawStringOpaque(screenBuffer, extents.x + offsetX, extents.y + offsetY, fgColor, bgColor, "%s", text.c_str());
870 // Draw the caret (underscore? or vertical line?)
878 class ListBox: public Element
879 //class ListBox: public Window
882 // ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0): Element(x, y, w, h),
883 ListBox(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);//: Window(x, y, w, h),
884 // windowPtr(0), cursor(0), limit(0), charWidth((w / 8) - 1), charHeight(h / 8),
885 // elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
886 // downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox) {}
887 virtual void HandleKey(SDLKey key);
888 virtual void HandleMouseMove(uint32 x, uint32 y);
889 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
890 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
891 virtual void Notify(Element * e);
892 void SetNotificationElement(Element * e) { elementToTell = e; }
893 void AddItem(string s);
894 string GetSelectedItem(void);
898 uint32 windowPtr, cursor, limit;
899 uint32 charWidth, charHeight; // Box width/height in characters
900 Element * elementToTell;
901 Button upArrow, downArrow, upArrow2;
905 uint32 yRelativePoint;
908 ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h),
909 thumbClicked(false), windowPtr(0), cursor(0), limit(0), charWidth((w / FONT_WIDTH) - 1),
910 charHeight(h / FONT_HEIGHT), elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
911 downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox)
913 upArrow.SetNotificationElement(this);
914 downArrow.SetNotificationElement(this);
915 upArrow2.SetNotificationElement(this);
916 extents.w -= 8; // Make room for scrollbar...
919 void ListBox::HandleKey(SDLKey key)
921 if (key == SDLK_DOWN)
923 if (cursor != limit - 1) // Cursor is within its window
925 else // Otherwise, scroll the window...
927 if (cursor + windowPtr != item.size() - 1)
931 else if (key == SDLK_UP)
941 else if (key == SDLK_PAGEDOWN)
943 if (cursor != limit - 1)
948 if (windowPtr > item.size() - limit)
949 windowPtr = item.size() - limit;
952 else if (key == SDLK_PAGEUP)
958 if (windowPtr < limit)
964 else if (key >= SDLK_a && key <= SDLK_z)
966 // Advance cursor to filename with first letter pressed...
967 uint8 which = (key - SDLK_a) + 65; // Convert key to A-Z char
969 for(uint32 i=0; i<item.size(); i++)
971 if ((item[i][0] & 0xDF) == which)
973 cursor = i - windowPtr;
974 if (i > windowPtr + limit - 1)
975 windowPtr = i - limit + 1, cursor = limit - 1;
977 windowPtr = i, cursor = 0;
984 void ListBox::HandleMouseMove(uint32 x, uint32 y)
986 upArrow.HandleMouseMove(x - extents.x, y - extents.y);
987 downArrow.HandleMouseMove(x - extents.x, y - extents.y);
988 upArrow2.HandleMouseMove(x - extents.x, y - extents.y);
992 uint32 sbHeight = extents.h - 24,
993 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight);
995 //yRelativePoint is the spot on the thumb where we clicked...
996 int32 newThumbStart = y - yRelativePoint;
998 if (newThumbStart < 0)
1001 if ((uint32)newThumbStart > sbHeight - thumb)
1002 newThumbStart = sbHeight - thumb;
1004 windowPtr = (uint32)(((float)newThumbStart / (float)sbHeight) * (float)item.size());
1005 //Check for cursor bounds as well... Or do we need to???
1006 //Actually, we don't...!
1010 void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1012 if (Inside(x, y) && mouseDown)
1014 // Why do we have to do this??? (- extents.y?)
1015 // I guess it's because only the Window class has offsetting implemented... !!! FIX !!!
1016 // cursor = (y - extents.y) / 8;
1017 cursor = (y - extents.y) / FONT_HEIGHT;
1020 // Check for a hit on the scrollbar...
1021 if (x > (uint32)(extents.x + extents.w) && x <= (uint32)(extents.x + extents.w + 8)
1022 && y > (uint32)(extents.y + 8) && y <= (uint32)(extents.y + extents.h - 16))
1026 // This shiaut should be calculated in AddItem(), not here... (or in Draw() for that matter)
1027 uint32 sbHeight = extents.h - 24,
1028 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1029 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1031 // Did we hit the thumb?
1032 if (y >= (extents.y + 8 + thumbStart) && y < (extents.y + 8 + thumbStart + thumb))
1033 thumbClicked = true, yRelativePoint = y - thumbStart;
1035 //Seems that this is useless--never reached except in rare cases and that the code outside is
1038 // thumbClicked = false;
1042 thumbClicked = false;
1044 upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1045 downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1046 upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
1049 void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1051 for(uint32 i=0; i<limit; i++)
1053 // Strip off the extension
1054 // (extension stripping should be an option, not default!)
1055 string s(item[windowPtr + i], 0, item[windowPtr + i].length() - 4);
1056 // DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*8,
1057 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*FONT_HEIGHT,
1058 (cursor == i ? true : false), "%-*.*s", charWidth, charWidth, s.c_str());
1061 upArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1062 downArrow.Draw(extents.x + offsetX, extents.y + offsetY);
1063 upArrow2.Draw(extents.x + offsetX, extents.y + offsetY);
1065 uint32 sbHeight = extents.h - 24,
1066 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
1067 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
1069 for(uint32 y=extents.y+offsetY+8; y<extents.y+offsetY+extents.h-16; y++)
1071 // for(uint32 x=extents.x+offsetX+extents.w-8; x<extents.x+offsetX+extents.w; x++)
1072 for(uint32 x=extents.x+offsetX+extents.w; x<extents.x+offsetX+extents.w+8; x++)
1074 if (y >= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8))
1075 // screenBuffer[x + (y * pitch)] = (thumbClicked ? 0x458E : 0xFFFF);
1076 //458E -> 01 0001 0 1100 0 1110 -> 0100 0101 0110 0011 0111 0011 -> 45 63 73
1077 screenBuffer[x + (y * pitch)] = (thumbClicked ? 0xFF736345 : 0xFFFFFFFF);
1079 // screenBuffer[x + (y * pitch)] = 0x0200;
1080 //0200 -> 000000 10000 00000 -> 00 1000 0100 00
1081 screenBuffer[x + (y * pitch)] = 0xFF008400;
1086 void ListBox::Notify(Element * e)
1088 if (e == &upArrow || e == &upArrow2)
1094 if (cursor < limit - 1)
1098 else if (e == &downArrow)
1100 if (windowPtr < item.size() - limit)
1110 void ListBox::AddItem(string s)
1112 // Do a simple insertion sort
1113 bool inserted = false;
1115 for(vector<string>::iterator i=item.begin(); i<item.end(); i++)
1117 if (stringCmpi(s, *i) == -1)
1128 limit = (item.size() > charHeight ? charHeight : item.size());
1131 string ListBox::GetSelectedItem(void)
1133 return item[windowPtr + cursor];
1141 class FileList: public Window
1144 FileList(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = 0);
1145 virtual ~FileList() {}
1146 virtual void HandleKey(SDLKey key);
1147 virtual void HandleMouseMove(uint32 x, uint32 y) { Window::HandleMouseMove(x, y); }
1148 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) { Window::HandleMouseButton(x, y, mouseDown); }
1149 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) { Window::Draw(offsetX, offsetY); }
1150 virtual void Notify(Element * e);
1157 //Need 4 buttons, one scrollbar...
1158 FileList::FileList(uint32 x, uint32 y, uint32 w, uint32 h): Window(x, y, w, h)
1160 files = new ListBox(8, 8, w - 16, h - 32);
1162 load = new Button(8, h - 16, " Load ");
1164 load->SetNotificationElement(this);
1166 //!!! FIX !!! Directory might not exist--this shouldn't cause VJ to crash!
1167 DIR * dp = opendir(vjs.ROMPath);
1172 while ((de = readdir(dp)) != NULL)
1174 char * ext = strrchr(de->d_name, '.');
1177 if (strcasecmp(ext, ".zip") == 0 || strcasecmp(ext, ".j64") == 0
1178 || strcasecmp(ext, ".abs") == 0 || strcasecmp(ext, ".jag") == 0
1179 || strcasecmp(ext, ".rom") == 0)
1180 files->AddItem(string(de->d_name));
1187 //Give a diagnostic message here so that the (l)user can figure out what went wrong. !!! FIX !!!
1191 void FileList::HandleKey(SDLKey key)
1193 if (key == SDLK_RETURN)
1196 Window::HandleKey(key);
1199 void FileList::Notify(Element * e)
1203 char filename[MAX_PATH];
1204 strcpy(filename, vjs.ROMPath);
1206 if (strlen(filename) > 0)
1207 if (filename[strlen(filename) - 1] != '/')
1208 strcat(filename, "/");
1210 strcat(filename, files->GetSelectedItem().c_str());
1212 // uint32 romSize = JaguarLoadROM(jaguar_mainRom, filename);
1213 // JaguarLoadCart(jaguar_mainRom, filename);
1214 if (JaguarLoadFile(filename))
1217 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1218 SDL_PushEvent(&event);
1220 event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1221 event.user.data1 = (void *)ResetJaguar;
1222 SDL_PushEvent(&event);
1227 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
1228 SDL_PushEvent(&event);
1230 // Handle the error, but don't run...
1231 // Tell the user that we couldn't run their file for some reason... !!! FIX !!!
1232 //how to kludge: Make a function like ResetJaguar which creates the dialog window
1241 // Menu class & supporting structs/classes
1247 Window * (* action)(void);
1250 NameAction(string n, Window * (* a)(void) = NULL, SDLKey k = SDLK_UNKNOWN): name(n),
1251 action(a), hotKey(k) {}
1257 MenuItems(): charLength(0) {}
1258 bool Inside(uint32 x, uint32 y)
1259 { return (x >= (uint32)extents.x && x < (uint32)(extents.x + extents.w)
1260 && y >= (uint32)extents.y && y < (uint32)(extents.y + extents.h) ? true : false); }
1263 vector<NameAction> item;
1268 class Menu: public Element
1271 // 1CFF -> 0 001 11 00 111 1 1111
1272 // 421F -> 0 100 00 10 000 1 1111
1273 Menu(uint32 x = 0, uint32 y = 0, uint32 w = 0, uint32 h = FONT_HEIGHT,
1274 /* uint16 fgc = 0x1CFF, uint16 bgc = 0x000F, uint16 fgch = 0x421F,
1275 uint16 bgch = 0x1CFF): Element(x, y, w, h), activated(false), clicked(false),*/
1276 /* uint32 fgc = 0xFF3F3F00, uint32 bgc = 0x7F000000, uint32 fgch = 0xFF878700,
1277 uint32 bgch = 0xFF3F3F00): Element(x, y, w, h), activated(false), clicked(false),*/
1278 /* uint32 fgc = 0xFFFF3F3F, uint32 bgc = 0xFF7F0000, uint32 fgch = 0xFFFF8787,
1279 uint32 bgch = 0xFFFF3F3F): Element(x, y, w, h), activated(false), clicked(false),*/
1280 uint32 fgc = 0xFF7F0000, uint32 bgc = 0xFFFF3F3F, uint32 fgch = 0xFFFF3F3F,
1281 uint32 bgch = 0xFFFF8787): Element(x, y, w, h), activated(false), clicked(false),
1282 inside(0), insidePopup(0), fgColor(fgc), bgColor(bgc), fgColorHL(fgch),
1283 bgColorHL(bgch), menuChosen(-1), menuItemChosen(-1) {}
1284 virtual void HandleKey(SDLKey key);
1285 virtual void HandleMouseMove(uint32 x, uint32 y);
1286 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown);
1287 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0);
1288 virtual void Notify(Element *) {}
1289 void Add(MenuItems mi);
1292 bool activated, clicked;
1293 uint32 inside, insidePopup;
1294 // uint16 fgColor, bgColor, fgColorHL, bgColorHL;
1295 uint32 fgColor, bgColor, fgColorHL, bgColorHL;
1296 int menuChosen, menuItemChosen;
1299 vector<MenuItems> itemList;
1302 void Menu::HandleKey(SDLKey key)
1304 for(uint32 i=0; i<itemList.size(); i++)
1306 for(uint32 j=0; j<itemList[i].item.size(); j++)
1308 if (itemList[i].item[j].hotKey == key)
1311 event.type = SDL_USEREVENT;
1312 event.user.code = MENU_ITEM_CHOSEN;
1313 event.user.data1 = (void *)itemList[i].item[j].action;
1314 SDL_PushEvent(&event);
1316 clicked = false, menuChosen = menuItemChosen = -1;
1323 void Menu::HandleMouseMove(uint32 x, uint32 y)
1325 inside = insidePopup = 0;
1329 // Find out *where* we are inside the menu bar
1330 uint32 xpos = extents.x;
1332 for(uint32 i=0; i<itemList.size(); i++)
1334 uint32 width = (itemList[i].title.length() + 2) * FONT_WIDTH;
1336 if (x >= xpos && x < xpos + width)
1347 if (!Inside(x, y) && !clicked)
1352 if (itemList[menuChosen].Inside(x, y) && clicked)
1354 insidePopup = ((y - itemList[menuChosen].extents.y) / FONT_HEIGHT) + 1;
1355 menuItemChosen = insidePopup - 1;
1359 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
1368 menuChosen = -1; // clicked is already false...!
1371 else // clicked == true
1373 if (insidePopup && !mouseDown) // I.e., mouse-button-up
1376 if (itemList[menuChosen].item[menuItemChosen].action != NULL)
1378 // itemList[menuChosen].item[menuItemChosen].action();
1380 event.type = SDL_USEREVENT;
1381 event.user.code = MENU_ITEM_CHOSEN;
1382 event.user.data1 = (void *)itemList[menuChosen].item[menuItemChosen].action;
1383 SDL_PushEvent(&event);
1385 clicked = false, menuChosen = menuItemChosen = -1;
1388 while (SDL_PollEvent(&event)); // Flush the event queue...
1389 event.type = SDL_MOUSEMOTION;
1391 SDL_GetMouseState(&mx, &my);
1392 event.motion.x = mx, event.motion.y = my;
1393 SDL_PushEvent(&event); // & update mouse position...!
1397 if (!inside && !insidePopup && mouseDown)
1398 clicked = false, menuChosen = menuItemChosen = -1;
1402 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
1404 uint32 xpos = extents.x + offsetX;
1406 for(uint32 i=0; i<itemList.size(); i++)
1408 // uint16 color1 = fgColor, color2 = bgColor;
1409 uint32 color1 = fgColor, color2 = bgColor;
1410 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
1411 color1 = fgColorHL, color2 = bgColorHL;
1413 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
1414 " %s ", itemList[i].title.c_str());
1415 xpos += (itemList[i].title.length() + 2) * FONT_WIDTH;
1418 // Draw sub menu (but only if active)
1421 uint32 ypos = extents.y + FONT_HEIGHT + 1;
1423 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
1425 // uint16 color1 = fgColor, color2 = bgColor;
1426 uint32 color1 = fgColor, color2 = bgColor;
1428 if (insidePopup == i + 1)
1429 color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
1431 if (itemList[menuChosen].item[i].name.length() > 0)
1432 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1433 color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
1434 itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
1436 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
1437 fgColor, bgColor, "%.*s", itemList[menuChosen].charLength + 2, separator);
1439 ypos += FONT_HEIGHT;
1444 void Menu::Add(MenuItems mi)
1446 for(uint32 i=0; i<mi.item.size(); i++)
1447 if (mi.item[i].name.length() > mi.charLength)
1448 mi.charLength = mi.item[i].name.length();
1450 // Set extents here as well...
1451 mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + FONT_HEIGHT + 1;
1452 mi.extents.w = (mi.charLength + 2) * FONT_WIDTH, mi.extents.h = mi.item.size() * FONT_HEIGHT;
1454 itemList.push_back(mi);
1455 extents.w += (mi.title.length() + 2) * FONT_WIDTH;
1459 //Do we even *need* this?
1460 //Doesn't seem like it...
1461 /*class RootWindow: public Window
1464 RootWindow(Menu * m, Window * w = NULL): menu(m), window(w) {}
1465 //Do we even need to care about this crap?
1466 // { extents.x = extents.y = 0, extents.w = 320, extents.h = 240; }
1467 virtual void HandleKey(SDLKey key) {}
1468 virtual void HandleMouseMove(uint32 x, uint32 y) {}
1469 virtual void HandleMouseButton(uint32 x, uint32 y, bool mouseDown) {}
1470 virtual void Draw(uint32 offsetX = 0, uint32 offsetY = 0) {}
1471 virtual void Notify(Element *) {}
1476 int16 * rootImage[1280 * 240 * 2];
1481 // Draw text at the given x/y coordinates. Can invert text as well.
1483 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
1488 va_start(arg, text);
1489 vsprintf(string, text, arg);
1492 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1493 uint32 length = strlen(string), address = x + (y * pitch);
1495 uint32 color1 = 0x0080FF;
1496 uint8 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1497 uint8 xorMask = (invert ? 0xFF : 0x00);
1499 for(uint32 i=0; i<length; i++)
1501 uint8 c = string[i];
1502 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * FONT_WIDTH * FONT_HEIGHT;
1504 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1506 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1508 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1510 uint8 eBlue = (existingColor >> 16) & 0xFF,
1511 eGreen = (existingColor >> 8) & 0xFF,
1512 eRed = existingColor & 0xFF;
1514 uint8 trans = font2[fontAddr] ^ xorMask;
1515 uint8 invTrans = trans ^ 0xFF;
1517 uint32 bRed = (eRed * invTrans + nRed * trans) / 255,
1518 bGreen = (eGreen * invTrans + nGreen * trans) / 255,
1519 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1521 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1526 address += FONT_WIDTH;
1531 // Draw text at the given x/y coordinates, using FG/BG colors.
1533 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...)
1538 va_start(arg, text);
1539 vsprintf(string, text, arg);
1542 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1543 uint32 length = strlen(string), address = x + (y * pitch);
1545 uint8 eBlue = (color2 >> 16) & 0xFF, eGreen = (color2 >> 8) & 0xFF, eRed = color2 & 0xFF,
1546 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
1548 for(uint32 i=0; i<length; i++)
1550 uint8 c = string[i];
1551 c = (c < 32 ? 0 : c - 32);
1552 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1554 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1556 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1558 uint8 trans = font2[fontAddr++];
1559 uint8 invTrans = trans ^ 0xFF;
1561 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1562 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1563 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1565 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1569 address += FONT_WIDTH;
1574 // Draw text at the given x/y coordinates with transparency (0 is fully opaque, 32 is fully transparent).
1576 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 trans, const char * text, ...)
1581 va_start(arg, text);
1582 vsprintf(string, text, arg);
1585 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1586 uint32 length = strlen(string), address = x + (y * pitch);
1588 for(uint32 i=0; i<length; i++)
1590 uint32 fontAddr = (uint32)string[i] * 64;
1592 for(uint32 yy=0; yy<8; yy++)
1594 for(uint32 xx=0; xx<8; xx++)
1596 if (font1[fontAddr])
1598 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1600 uint8 eBlue = (existingColor >> 16) & 0xFF,
1601 eGreen = (existingColor >> 8) & 0xFF,
1602 eRed = existingColor & 0xFF,
1603 //This could be done ahead of time, instead of on each pixel...
1604 nBlue = (color >> 16) & 0xFF,
1605 nGreen = (color >> 8) & 0xFF,
1606 nRed = color & 0xFF;
1608 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
1609 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
1610 //because dividing by 32 is faster than dividing by 31...!
1611 uint8 invTrans = 32 - trans;
1613 uint32 bRed = (eRed * trans + nRed * invTrans) / 32;
1614 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
1615 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
1617 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
1629 // Draw text at the given x/y coordinates, using FG color and overlay alpha blending.
1631 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...)
1636 va_start(arg, text);
1637 vsprintf(string, text, arg);
1640 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1641 uint32 length = strlen(string), address = x + (y * pitch);
1643 color &= 0x00FFFFFF; // Just in case alpha was passed in...
1645 for(uint32 i=0; i<length; i++)
1647 uint8 c = string[i];
1648 c = (c < 32 ? 0 : c - 32);
1649 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
1651 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
1653 for(uint32 xx=0; xx<FONT_WIDTH; xx++)
1655 uint8 fontTrans = font2[fontAddr++];
1656 uint32 newTrans = (fontTrans * transparency / 255) << 24;
1657 uint32 pixel = newTrans | color;
1659 *(screen + address + xx + (yy * pitch)) = pixel;
1663 address += FONT_WIDTH;
1669 // Uses zero as transparent color
1670 // Can also use an optional alpha channel
1671 // Alpha channel is now mandatory! ;-)
1673 //void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap, uint8 * alpha/*=NULL*/)
1674 /*void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha)
1676 uint32 width = bitmap[0], height = bitmap[1];
1679 // uint32 pitch = GetSDLScreenPitch() / 2; // Returns pitch in bytes but we need words...
1680 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1681 uint32 address = x + (y * pitch);
1683 for(uint32 yy=0; yy<height; yy++)
1685 for(uint32 xx=0; xx<width; xx++)
1689 if (*bitmap && x + xx < pitch) // NOTE: Still doesn't clip the Y val...
1690 *(screen + address + xx + (yy * pitch)) = *bitmap;
1694 uint8 trans = *alpha;
1695 uint32 color = *bitmap;
1696 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1698 uint8 eRed = existingColor & 0xFF,
1699 eGreen = (existingColor >> 8) & 0xFF,
1700 eBlue = (existingColor >> 16) & 0xFF,
1702 nRed = color & 0xFF,
1703 nGreen = (color >> 8) & 0xFF,
1704 nBlue = (color >> 16) & 0xFF;
1706 uint8 invTrans = 255 - trans;
1707 uint32 bRed = (eRed * trans + nRed * invTrans) / 255;
1708 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 255;
1709 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 255;
1711 uint32 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1713 *(screen + address + xx + (yy * pitch)) = blendedColor;
1722 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap)
1724 uint32 width = bitmap[0], height = bitmap[1];
1727 uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
1728 uint32 address = x + (y * pitch);
1730 for(uint32 yy=0; yy<height; yy++)
1732 for(uint32 xx=0; xx<width; xx++)
1734 uint32 color = *bitmap;
1735 uint32 blendedColor = color;
1736 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1738 if (existingColor >> 24 != 0x00) // Pixel needs blending
1740 uint8 trans = color >> 24;
1741 uint8 invTrans = trans ^ 0xFF;//255 - trans;
1743 uint8 eRed = existingColor & 0xFF,
1744 eGreen = (existingColor >> 8) & 0xFF,
1745 eBlue = (existingColor >> 16) & 0xFF,
1747 nRed = color & 0xFF,
1748 nGreen = (color >> 8) & 0xFF,
1749 nBlue = (color >> 16) & 0xFF;
1751 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1752 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1753 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1755 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1758 *(screen + address + xx + (yy * pitch)) = blendedColor;
1764 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1766 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1767 uint32 address = x + (y * pitch);
1770 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1772 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1774 uint32 color = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1775 uint32 blendedColor = color;
1776 uint32 existingColor = *(screen + address + xx + (yy * pitch));
1778 if (existingColor >> 24 != 0x00) // Pixel needs blending
1780 uint8 trans = color >> 24;
1781 uint8 invTrans = trans ^ 0xFF;
1783 uint8 eRed = existingColor & 0xFF,
1784 eGreen = (existingColor >> 8) & 0xFF,
1785 eBlue = (existingColor >> 16) & 0xFF,
1787 nRed = color & 0xFF,
1788 nGreen = (color >> 8) & 0xFF,
1789 nBlue = (color >> 16) & 0xFF;
1791 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
1792 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
1793 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
1795 // Instead of $FF, should use the alpha from the destination pixel as the final alpha value...
1796 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
1799 *(screen + address + xx + (yy * pitch)) = blendedColor;
1806 // Draw a bitmap without using blending
1808 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
1810 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1811 uint32 address = x + (y * pitch);
1814 for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
1816 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
1818 *(screen + address + xx + (yy * pitch)) = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
1825 // Fill a portion of the screen with the passed in color
1827 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color)
1828 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h)
1830 uint32 pitch = sdlemuGetOverlayWidthInPixels();
1831 uint32 address = x + (y * pitch);
1833 for(uint32 yy=0; yy<h; yy++)
1834 for(uint32 xx=0; xx<w; xx++)
1835 *(screen + address + xx + (yy * pitch)) = color;
1840 // GUI stuff--it's not crunchy, it's GUI! ;-)
1845 SDL_ShowCursor(SDL_DISABLE);
1846 SDL_GetMouseState(&mouseX, &mouseY);
1856 //bool GUIMain(void)
1857 bool GUIMain(char * filename)
1859 WriteLog("GUI: Inside GUIMain...\n");
1861 uint32 pointerBGSave[6 * 8 + 2];
1862 pointerBGSave[0] = 6;
1863 pointerBGSave[1] = 8;
1865 // Need to set things up so that it loads and runs a file if given on the command line. !!! FIX !!! [DONE]
1866 extern uint32 * backbuffer;
1867 // bool done = false;
1869 Window * mainWindow = NULL;
1871 // Set up the GUI classes...
1872 // Element::SetScreenAndPitch(backbuffer, GetSDLScreenWidthInPixels());
1873 Element::SetScreenAndPitch((uint32 *)sdlemuGetOverlayPixels(), sdlemuGetOverlayWidthInPixels());
1874 sdlemuEnableOverlay();
1878 mi.title = "Jaguar";
1879 mi.item.push_back(NameAction("Load...", LoadROM, SDLK_l));
1880 mi.item.push_back(NameAction("Reset", ResetJaguar, SDLK_r));
1882 mi.item.push_back(NameAction("Reset CD", ResetJaguarCD, SDLK_c));
1883 mi.item.push_back(NameAction("Run", RunEmu, SDLK_ESCAPE));
1884 mi.item.push_back(NameAction(""));
1885 mi.item.push_back(NameAction("Quit", Quit, SDLK_q));
1887 mi.title = "Settings";
1889 mi.item.push_back(NameAction("Video..."));
1890 mi.item.push_back(NameAction("Audio..."));
1891 mi.item.push_back(NameAction("Misc...", MiscOptions, SDLK_m));
1895 mi.item.push_back(NameAction("About...", About));
1898 bool showMouse = true;
1900 // Grab the BG where the mouse will be painted (prime the backstore)
1904 Bitmap ptr = { 6, 8, 4,
1905 ""//"000011112222333344445555"
1906 //"000011112222333344445555"
1907 //"000011112222333344445555"
1908 //"000011112222333344445555"
1909 //"000011112222333344445555"
1910 //"000011112222333344445555"
1911 //"000011112222333344445555"
1912 //"000011112222333344445555"
1914 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
1917 for(uint32 y=0; y<pointerBGSave[1]; y++)
1918 for(uint32 x=0; x<pointerBGSave[0]; x++)
1919 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
1921 uint32 oldMouseX = mouseX, oldMouseY = mouseY;
1923 //This is crappy!!! !!! FIX !!!
1924 //Is this even needed any more? Hmm. Maybe. Dunno.
1925 WriteLog("GUI: Resetting Jaguar...\n");
1928 WriteLog("GUI: Clearing BG save...\n");
1929 // Set up our background save...
1930 // memset(background, 0x11, tom_getVideoModeWidth() * 240 * 2);
1931 //1111 -> 000100 01000 10001 -> 0001 0000 0100 0010 1000 1100 -> 10 42 8C
1932 for(uint32 i=0; i<tom_getVideoModeWidth()*240; i++)
1933 // background[i] = 0xFF8C4210;
1934 backbuffer[i] = 0xFF8C4210;
1936 /* uint32 * overlayPix = (uint32 *)sdlemuGetOverlayPixels();
1937 for(uint32 i=0; i<sdlemuGetOverlayWidthInPixels()*480; i++)
1938 overlayPix[i] = 0x00000000;*/
1940 // Handle loading file passed in on the command line...! [DONE]
1944 if (JaguarLoadFile(filename))
1946 // event.type = SDL_USEREVENT, event.user.code = MENU_ITEM_CHOSEN;
1947 // event.user.data1 = (void *)ResetJaguar;
1948 // SDL_PushEvent(&event);
1949 // Make it so that if passed in on the command line, we quit right
1950 // away when pressing ESC
1951 WriteLog("GUI: Bypassing GUI since ROM passed in on command line...\n");
1957 // Create error dialog...
1959 sprintf(errText, "The file %40s could not be loaded.", filename);
1961 mainWindow = new Window(8, 16, 304, 160);
1962 mainWindow->AddElement(new Text(8, 8, "Error!"));
1963 mainWindow->AddElement(new Text(8, 24, errText));
1967 WriteLog("GUI: Entering main loop...\n");
1970 if (SDL_PollEvent(&event))
1972 if (event.type == SDL_USEREVENT)
1974 if (event.user.code == WINDOW_CLOSE)
1979 else if (event.user.code == MENU_ITEM_CHOSEN)
1981 // Confused? Let me enlighten... What we're doing here is casting
1982 // data1 as a pointer to a function which returns a Window pointer and
1983 // which takes no parameters (the "(Window *(*)(void))" part), then
1984 // derefencing it (the "*" in front of that) in order to call the
1985 // function that it points to. Clear as mud? Yeah, I hate function
1986 // pointers too, but what else are you gonna do?
1987 mainWindow = (*(Window *(*)(void))event.user.data1)();
1989 while (SDL_PollEvent(&event)); // Flush the event queue...
1990 event.type = SDL_MOUSEMOTION;
1992 SDL_GetMouseState(&mx, &my);
1993 event.motion.x = mx, event.motion.y = my;
1994 SDL_PushEvent(&event); // & update mouse position...!
1996 oldMouseX = mouseX, oldMouseY = mouseY;
1997 mouseX = mx, mouseY = my; // This prevents "mouse flash"...
2000 else if (event.type == SDL_ACTIVEEVENT)
2002 if (event.active.state == SDL_APPMOUSEFOCUS)
2003 showMouse = (event.active.gain ? true : false);
2005 else if (event.type == SDL_KEYDOWN)
2008 mainWindow->HandleKey(event.key.keysym.sym);
2010 mainMenu.HandleKey(event.key.keysym.sym);
2012 else if (event.type == SDL_MOUSEMOTION)
2014 oldMouseX = mouseX, oldMouseY = mouseY;
2015 mouseX = event.motion.x, mouseY = event.motion.y;
2018 mainWindow->HandleMouseMove(mouseX, mouseY);
2020 mainMenu.HandleMouseMove(mouseX, mouseY);
2022 else if (event.type == SDL_MOUSEBUTTONDOWN)
2024 uint32 mx = event.button.x, my = event.button.y;
2027 mainWindow->HandleMouseButton(mx, my, true);
2029 mainMenu.HandleMouseButton(mx, my, true);
2031 else if (event.type == SDL_MOUSEBUTTONUP)
2033 uint32 mx = event.button.x, my = event.button.y;
2036 mainWindow->HandleMouseButton(mx, my, false);
2038 mainMenu.HandleMouseButton(mx, my, false);
2041 //PROBLEM: In order to use the dirty rectangle approach here, we need some way of
2042 // handling it in mainMenu.Draw() and mainWindow->Draw(). !!! FIX !!!
2043 //POSSIBLE SOLUTION:
2044 // When mouse is moving and not on menu or window, can do straight dirty rect.
2045 // When mouse is on menu, need to update screen. Same for buttons on windows...
2046 // What the menu & windows should do is only redraw on a state change. IOW, they
2047 // should call their own/child window's Draw() function instead of doing it top
2049 //#define NEW_BACKSTORE_METHOD
2052 // The way we do things here is kinda stupid (redrawing the screen every frame), but
2053 // it's simple. Perhaps there may be a reason down the road to be more selective with
2054 // our clearing, but for now, this will suffice.
2055 // memset(backbuffer, 0x11, tom_getVideoModeWidth() * 240 * 2);
2056 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 2);
2057 // memcpy(backbuffer, background, tom_getVideoModeWidth() * 256 * 4);
2058 #ifndef NEW_BACKSTORE_METHOD
2059 memset(sdlemuGetOverlayPixels(), 0, sdlemuGetOverlayWidthInPixels() * 480 * 4);
2062 //Could do multiple windows here by using a vector + priority info...
2063 //Though the way ZSNES does it seems to be by a bool (i.e., they're always active, just not shown)
2068 /*uint32 pBGS[6 * 8 + 3] = { 6, 8, 4,
2078 //This isn't working... Why????
2079 //It's because DrawTransparentBitmap does alpha blending if it detects zero in the alpha channel.
2080 //So why do it that way? Hm.
2081 overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2083 #ifdef NEW_BACKSTORE_METHOD
2084 // DrawTransparentBitmapDeprecated(overlayPixels, oldMouseX, oldMouseY, pointerBGSave);
2085 // DrawTransparentBitmap(overlayPixels, oldMouseX, oldMouseY, pBGS);
2086 for(uint32 y=0; y<pointerBGSave[1]; y++)
2087 for(uint32 x=0; x<pointerBGSave[0]; x++)
2088 overlayPixels[((oldMouseY + y) * sdlemuGetOverlayWidthInPixels()) + (oldMouseX + x)] = 0x00000000;
2092 for(uint32 y=0; y<pointerBGSave[1]; y++)
2093 for(uint32 x=0; x<pointerBGSave[0]; x++)
2094 pointerBGSave[count++] = overlayPixels[((mouseY + y) * sdlemuGetOverlayWidthInPixels()) + (mouseX + x)];
2098 // DrawTransparentBitmapDeprecated(backbuffer, mouseX, mouseY, mousePic);
2099 DrawTransparentBitmapDeprecated(overlayPixels, mouseX, mouseY, mousePic);
2109 // GUI "action" functions
2112 Window * LoadROM(void)
2114 FileList * fileList = new FileList(20, 20, 600, 440);
2116 return (Window *)fileList;
2119 Window * ResetJaguar(void)
2126 Window * ResetJaguarCD(void)
2128 memcpy(jaguar_mainRom, jaguar_CDBootROM, 0x40000);
2129 jaguarRunAddress = 0x802000;
2130 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, 0x40000);
2132 //This is a quick kludge to get the CDBIOS to boot properly...
2133 //Wild speculation: It could be that this memory location is wired into the CD unit
2134 //somehow, which lets it know whether or not a cart is present in the unit...
2135 jaguar_mainRom[0x0040B] = 0x03;
2143 bool debounceRunKey = true;
2144 Window * RunEmu(void)
2146 extern uint32 * backbuffer;
2147 //Temporary, to test the new timer based code...
2148 sdlemuDisableOverlay();
2150 sdlemuEnableOverlay();
2151 // Save the background for the GUI...
2152 // In this case, we squash the color to monochrome, then force it to blue + green...
2153 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2155 uint32 pixel = backbuffer[i];
2156 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2157 pixel = ((r + g + b) / 3) & 0x00FF;
2158 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2162 //This is crappy... !!! FIX !!!
2163 extern bool finished, showGUI;
2165 // uint32 nFrame = 0, nFrameskip = 0;
2166 uint32 totalFrames = 0;
2168 bool showMessage = true;
2169 uint32 showMsgFrames = 120;
2170 uint8 transparency = 0;
2171 // Pass a message to the "joystick" code to debounce the ESC key...
2172 debounceRunKey = true;
2174 uint32 cartType = 4;
2175 if (jaguarRomSize == 0x200000)
2177 else if (jaguarRomSize == 0x400000)
2179 else if (jaguar_mainRom_crc32 == 0x687068D5)
2181 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2184 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2185 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2189 // Set up new backbuffer with new pixels and data
2190 JaguarExecute(backbuffer, true);
2191 // JaguarExecuteNew();
2193 //WriteLog("Frame #%u...\n", totalFrames);
2194 //extern bool doDSPDis;
2195 //if (totalFrames == 373)
2198 //This sucks... !!! FIX !!!
2200 //This is done here so that the crud below doesn't get on our GUI background...
2204 // Some QnD GUI stuff here...
2207 extern uint32 gpu_pc, dsp_pc;
2208 DrawString(backbuffer, 8, 8, false, "GPU PC: %08X", gpu_pc);
2209 DrawString(backbuffer, 8, 16, false, "DSP PC: %08X", dsp_pc);
2210 DrawString(backbuffer, 8, 32, false, "%u FPS", framesPerSecond);
2215 // FF0F -> 1111 11 11 000 0 1111 -> 3F 18 0F
2216 // 3FE3 -> 0011 11 11 111 0 0011 -> 0F 3F 03
2217 /* DrawStringTrans((uint32 *)backbuffer, 8, 24*8, 0xFF0F, transparency, "Running...");
2218 DrawStringTrans((uint32 *)backbuffer, 8, 26*8, 0x3FE3, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2219 DrawStringTrans((uint32 *)backbuffer, 8, 27*8, 0x3FE3, transparency, "CRC: %08X", jaguar_mainRom_crc32);//*/
2220 //first has wrong color. !!! FIX !!!
2221 DrawStringTrans(backbuffer, 8, 24*8, 0xFF7F63FF, transparency, "Running...");
2222 DrawStringTrans(backbuffer, 8, 26*8, 0xFF1FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2223 DrawStringTrans(backbuffer, 8, 27*8, 0xFF1FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2225 if (showMsgFrames == 0)
2229 if (transparency == 33)
2231 showMessage = false;
2232 /*extern bool doGPUDis;
2233 doGPUDis = true;//*/
2244 if (SDL_GetTicks() - elapsedTicks > 250)
2245 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2248 // Reset the pitch, since it may have been changed in-game...
2249 Element::SetScreenAndPitch((uint32 *)backbuffer, GetSDLScreenWidthInPixels());
2251 // Save the background for the GUI...
2252 // memcpy(background, backbuffer, tom_getVideoModeWidth() * 240 * 2);
2253 // In this case, we squash the color to monochrome, then force it to blue + green...
2254 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2256 uint32 pixel = backbuffer[i];
2257 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2258 pixel = ((r + g + b) / 3) & 0x00FF;
2259 background[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2267 bool debounceRunKey = true;
2268 Window * RunEmu(void)
2270 extern uint32 * backbuffer;
2271 uint32 * overlayPixels = (uint32 *)sdlemuGetOverlayPixels();
2272 memset(overlayPixels, 0x00, 640 * 480 * 4); // Clear out overlay...
2274 //This is crappy... !!! FIX !!!
2275 extern bool finished, showGUI;
2277 sdlemuDisableOverlay();
2279 // uint32 nFrame = 0, nFrameskip = 0;
2280 uint32 totalFrames = 0;
2282 bool showMessage = true;
2283 uint32 showMsgFrames = 120;
2284 uint8 transparency = 0xFF;
2285 // Pass a message to the "joystick" code to debounce the ESC key...
2286 debounceRunKey = true;
2288 uint32 cartType = 4;
2289 if (jaguarRomSize == 0x200000)
2291 else if (jaguarRomSize == 0x400000)
2293 else if (jaguar_mainRom_crc32 == 0x687068D5)
2295 else if (jaguar_mainRom_crc32 == 0x55A0669C)
2298 char * cartTypeName[5] = { "2M Cartridge", "4M Cartridge", "CD BIOS", "CD Dev BIOS", "Homebrew" };
2299 uint32 elapsedTicks = SDL_GetTicks(), frameCount = 0, framesPerSecond = 0;
2303 // Set up new backbuffer with new pixels and data
2306 //WriteLog("Frame #%u...\n", totalFrames);
2307 //extern bool doDSPDis;
2308 //if (totalFrames == 373)
2311 //Problem: Need to do this *only* when the state changes from visible to not...
2312 //Also, need to clear out the GUI when not on (when showMessage is active...)
2313 if (showGUI || showMessage)
2314 sdlemuEnableOverlay();
2316 sdlemuDisableOverlay();
2318 //Add in a new function for clearing patches of screen (ClearOverlayRect)
2320 // Some QnD GUI stuff here...
2323 FillScreenRectangle(overlayPixels, 8, 1*FONT_HEIGHT, 128, 4*FONT_HEIGHT, 0x00000000);
2324 extern uint32 gpu_pc, dsp_pc;
2325 DrawString(overlayPixels, 8, 1*FONT_HEIGHT, false, "GPU PC: %08X", gpu_pc);
2326 DrawString(overlayPixels, 8, 2*FONT_HEIGHT, false, "DSP PC: %08X", dsp_pc);
2327 DrawString(overlayPixels, 8, 4*FONT_HEIGHT, false, "%u FPS", framesPerSecond);
2332 DrawString2(overlayPixels, 8, 24*FONT_HEIGHT, 0x007F63FF, transparency, "Running...");
2333 DrawString2(overlayPixels, 8, 26*FONT_HEIGHT, 0x001FFF3F, transparency, "%s, run address: %06X", cartTypeName[cartType], jaguarRunAddress);
2334 DrawString2(overlayPixels, 8, 27*FONT_HEIGHT, 0x001FFF3F, transparency, "CRC: %08X", jaguar_mainRom_crc32);
2336 if (showMsgFrames == 0)
2340 if (transparency == 0)
2342 showMessage = false;
2343 /*extern bool doGPUDis;
2344 doGPUDis = true;//*/
2354 if (SDL_GetTicks() - elapsedTicks > 250)
2355 elapsedTicks += 250, framesPerSecond = frameCount * 4, frameCount = 0;
2358 // Save the background for the GUI...
2359 // In this case, we squash the color to monochrome, then force it to blue + green...
2360 for(uint32 i=0; i<tom_getVideoModeWidth() * 256; i++)
2362 uint32 pixel = backbuffer[i];
2363 uint8 b = (pixel >> 16) & 0xFF, g = (pixel >> 8) & 0xFF, r = pixel & 0xFF;
2364 pixel = ((r + g + b) / 3) & 0x00FF;
2365 backbuffer[i] = 0xFF000000 | (pixel << 16) | (pixel << 8);
2368 sdlemuEnableOverlay();
2378 WriteLog("GUI: Quitting due to user request.\n");
2384 Window * About(void)
2387 // sprintf(buf, "Virtual Jaguar CVS %s", __DATE__);
2388 sprintf(buf, "CVS %s", __DATE__);
2389 //fprintf(fp, "VirtualJaguar v1.0.8 (Last full build was on %s %s)\n", __DATE__, __TIME__);
2390 //VirtualJaguar v1.0.8 (Last full build was on Dec 30 2004 20:01:31)
2391 //Hardwired, bleh... !!! FIX !!!
2392 uint32 width = 55 * FONT_WIDTH, height = 18 * FONT_HEIGHT;
2393 uint32 xpos = (640 - width) / 2, ypos = (480 - height) / 2;
2394 // Window * window = new Window(8, 16, 50 * FONT_WIDTH, 21 * FONT_HEIGHT);
2395 Window * window = new Window(xpos, ypos, width, height);
2396 // window->AddElement(new Text(8, 8, "Virtual Jaguar 1.0.8"));
2397 // window->AddElement(new Text(8, 8, "Virtual Jaguar CVS 20050110", 0xFF3030FF, 0xFF000000));
2398 // window->AddElement(new Text(208, 8+0*FONT_HEIGHT, buf, 0xFF3030FF, 0xFF000000));
2399 window->AddElement(new Text(248, 8+4*FONT_HEIGHT+5, buf, 0xFF3030FF, 0xFF000000));
2400 window->AddElement(new Text(8, 8+0*FONT_HEIGHT, "Coders:"));
2401 window->AddElement(new Text(16, 8+1*FONT_HEIGHT, "James L. Hammons (shamus)"));
2402 window->AddElement(new Text(16, 8+2*FONT_HEIGHT, "Niels Wagenaar (nwagenaar)"));
2403 window->AddElement(new Text(16, 8+3*FONT_HEIGHT, "Carwin Jones (Caz)"));
2404 window->AddElement(new Text(16, 8+4*FONT_HEIGHT, "Adam Green"));
2405 window->AddElement(new Text(8, 8+6*FONT_HEIGHT, "Testers:"));
2406 window->AddElement(new Text(16, 8+7*FONT_HEIGHT, "Guruma"));
2407 window->AddElement(new Text(8, 8+9*FONT_HEIGHT, "Thanks go out to:"));
2408 window->AddElement(new Text(16, 8+10*FONT_HEIGHT, "Aaron Giles for the original CoJag"));
2409 window->AddElement(new Text(16, 8+11*FONT_HEIGHT, "David Raingeard for the original VJ"));
2410 window->AddElement(new Text(16, 8+12*FONT_HEIGHT, "Karl Stenerud for his Musashi 68K emu"));
2411 window->AddElement(new Text(16, 8+13*FONT_HEIGHT, "Sam Lantinga for his amazing SDL libs"));
2412 window->AddElement(new Text(16, 8+14*FONT_HEIGHT, "Ryan C. Gordon for VJ's web presence"));
2413 window->AddElement(new Text(16, 8+15*FONT_HEIGHT, "Curt Vendel for various Jaguar goodies"));
2414 window->AddElement(new Text(16, 8+16*FONT_HEIGHT, "The guys over at Atari Age ;-)"));
2415 // window->AddElement(new Image(8, 8, &vj_title_small));
2416 window->AddElement(new Image(width - (vj_title_small.width + 8), 8, &vj_title_small));
2421 Window * MiscOptions(void)
2423 Window * window = new Window(8, 16, 304, 192);
2424 window->AddElement(new PushButton(8, 8, &vjs.useJaguarBIOS, "BIOS"));
2425 window->AddElement(new SlideSwitch(8, 32, &vjs.hardwareTypeNTSC, "PAL", "NTSC"));
2426 window->AddElement(new PushButton(8, 64, &vjs.DSPEnabled, "DSP"));
2427 window->AddElement(new SlideSwitch(24, 88, &vjs.usePipelinedDSP, "Original", "Pipelined"));
2428 window->AddElement(new SlideSwitch(8, 120, (bool *)&vjs.glFilter, "Sharp", "Blurry"));
2429 window->AddElement(new SlideSwitch(8, 152, (bool *)&vjs.renderType, "Normal render", "TV style"));
2431 window->AddElement(new TextEdit(88, 8, vjs.ROMPath, 20, 0xFF8484FF, 0xFF000000));
2433 /*TextEdit(uint32 x, uint32 y, string s, uint32 mss = 10, uint32 fg = 0xFF8484FF,
2434 uint32 bg = 0xFF84FF4D): Element(x, y, 0, 0), fgColor(fg), bgColor(bg), text(s),
2435 caretPos(0), maxScreenSize(mss) {}*/
2444 // * Window/fullscreen
2445 // * Key definitions
2452 // Generic ROM loading
2454 uint32 JaguarLoadROM(uint8 * rom, char * path)
2456 // We really should have some kind of sanity checking for the ROM size here to prevent
2457 // a buffer overflow... !!! FIX !!!
2460 WriteLog("JaguarLoadROM: Attempting to load file '%s'...", path);
2461 char * ext = strrchr(path, '.');
2463 WriteLog("FAILED!\n");
2465 WriteLog("Succeeded in finding extension (%s)!\n", ext);
2469 WriteLog("VJ: Loading \"%s\"...", path);
2471 if (strcasecmp(ext, ".zip") == 0)
2473 // Handle ZIP file loading here...
2474 WriteLog("(ZIPped)...");
2476 if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1)
2478 WriteLog("Failed!\n");
2484 /* FILE * fp = fopen(path, "rb");
2488 WriteLog("Failed!\n");
2492 fseek(fp, 0, SEEK_END);
2493 romSize = ftell(fp);
2494 fseek(fp, 0, SEEK_SET);
2495 fread(rom, 1, romSize, fp);
2498 // Handle gzipped files transparently [Adam Green]...
2500 gzFile fp = gzopen(path, "rb");
2504 WriteLog("Failed!\n");
2508 romSize = gzfilelength(fp);
2509 gzseek(fp, 0, SEEK_SET);
2510 gzread(fp, rom, romSize);
2514 WriteLog("OK (%i bytes)\n", romSize);
2521 // Jaguar file loading
2523 bool JaguarLoadFile(char * path)
2525 // jaguarRomSize = JaguarLoadROM(mem, path);
2526 jaguarRomSize = JaguarLoadROM(jaguar_mainRom, path);
2528 /*//This is not *nix friendly for some reason...
2529 // if (!UserSelectFile(path, newPath))
2530 if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath))
2532 WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path);
2537 if (jaguarRomSize == 0)
2539 // WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath);
2540 WriteLog("GUI: Could not load ROM from file \"%s\"...\nAborting load!\n", path);
2541 // Need to do something else here, like throw up an error dialog instead of aborting. !!! FIX !!!
2544 return false; // This is a start...
2547 jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, jaguarRomSize);
2548 WriteLog("CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32);
2551 jaguarRunAddress = 0x802000;
2553 char * ext = strrchr(path, '.'); // Get the file's extension for non-cartridge checking
2555 //NOTE: Should fix JaguarLoadROM() to replace .zip with what's *in* the zip (.abs, .j64, etc.)
2556 if (strcasecmp(ext, ".rom") == 0)
2558 // File extension ".ROM": Alpine image that loads/runs at $802000
2559 WriteLog("GUI: Setting up homebrew (ROM)... Run address: 00802000, length: %08X\n", jaguarRomSize);
2561 for(int i=jaguarRomSize-1; i>=0; i--)
2562 jaguar_mainRom[0x2000 + i] = jaguar_mainRom[i];
2564 memset(jaguar_mainRom, 0xFF, 0x2000);
2565 /* memcpy(jaguar_mainRam, jaguar_mainRom, jaguarRomSize);
2566 memset(jaguar_mainRom, 0xFF, 0x600000);
2567 memcpy(jaguar_mainRom + 0x2000, jaguar_mainRam, jaguarRomSize);
2568 memset(jaguar_mainRam, 0x00, 0x400000);*/
2571 Stubulator ROM vectors...
2572 handler 001 at $00E00008
2573 handler 002 at $00E008DE
2574 handler 003 at $00E008E2
2575 handler 004 at $00E008E6
2576 handler 005 at $00E008EA
2577 handler 006 at $00E008EE
2578 handler 007 at $00E008F2
2579 handler 008 at $00E0054A
2580 handler 009 at $00E008FA
2581 handler 010 at $00000000
2582 handler 011 at $00000000
2583 handler 012 at $00E008FE
2584 handler 013 at $00E00902
2585 handler 014 at $00E00906
2586 handler 015 at $00E0090A
2587 handler 016 at $00E0090E
2588 handler 017 at $00E00912
2589 handler 018 at $00E00916
2590 handler 019 at $00E0091A
2591 handler 020 at $00E0091E
2592 handler 021 at $00E00922
2593 handler 022 at $00E00926
2594 handler 023 at $00E0092A
2595 handler 024 at $00E0092E
2596 handler 025 at $00E0107A
2597 handler 026 at $00E0107A
2598 handler 027 at $00E0107A
2599 handler 028 at $00E008DA
2600 handler 029 at $00E0107A
2601 handler 030 at $00E0107A
2602 handler 031 at $00E0107A
2603 handler 032 at $00000000
2605 Let's try setting up the illegal instruction vector for a stubulated jaguar...
2607 /* SET32(jaguar_mainRam, 0x08, 0x00E008DE);
2608 SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
2609 SET32(jaguar_mainRam, 0x10, 0x00E008E6); // <-- Should be here (it is)...
2610 SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
2612 // Try setting the vector to say, $1000 and putting an instruction there that loops forever:
2613 // This kludge works! Yeah!
2614 SET32(jaguar_mainRam, 0x10, 0x00001000);
2615 SET16(jaguar_mainRam, 0x1000, 0x60FE); // Here: bra Here
2617 else if (strcasecmp(ext, ".abs") == 0)
2619 // File extension ".ABS": Atari linker output file with header (w/o is useless to us here)
2622 ABS Format sleuthing (LBUGDEMO.ABS):
2624 000000 60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
2625 000010 12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
2628 DRI-format file detected...
2629 Text segment size = 0x0000050c bytes
2630 Data segment size = 0x000462c0 bytes
2631 BSS Segment size = 0x00000428 bytes
2632 Symbol Table size = 0x000012a6 bytes
2633 Absolute Address for text segment = 0x00802000
2634 Absolute Address for data segment = 0x0080250c
2635 Absolute Address for BSS segment = 0x00004000
2638 000000 01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
2639 000010 00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
2640 000020 00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
2642 000030 2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
2643 000040 00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
2644 000050 00 00 00 00 00 00 00 20
2645 000058 2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
2646 000068 00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
2647 000078 00 00 00 00 00 00 00 40
2648 000080 2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
2649 000090 00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
2650 0000a0 00 00 00 00 00 00 00 80
2652 Header size is $A8 bytes...
2654 BSD/COFF format file detected...
2655 3 sections specified
2656 Symbol Table offset = 230160 ($00038310)
2657 Symbol Table contains 1339 symbol entries ($0000053B)
2658 The additional header size is 28 bytes ($001C)
2659 Magic Number for RUN_HDR = 0x00000107
2660 Text Segment Size = 7632 ($00001DD0)
2661 Data Segment Size = 222360 ($00036498)
2662 BSS Segment Size = 428928 ($00068B80)
2663 Starting Address for executable = 0x00802000
2664 Start of Text Segment = 0x00802000
2665 Start of Data Segment = 0x00803dd0
2667 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1B)
2669 uint32 loadAddress = GET32(jaguar_mainRom, 0x16), //runAddress = GET32(jaguar_mainRom, 0x2A),
2670 codeSize = GET32(jaguar_mainRom, 0x02) + GET32(jaguar_mainRom, 0x06);
2671 WriteLog("GUI: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize);
2673 if (loadAddress < 0x800000)
2674 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x24, codeSize);
2677 for(int i=codeSize-1; i>=0; i--)
2678 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0x24];
2679 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0x24, codeSize);
2680 memset(jaguar_mainRom, 0xFF, 0x600000);
2681 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2682 memset(jaguar_mainRam, 0x00, 0x400000);*/
2685 jaguarRunAddress = loadAddress;
2687 else if (jaguar_mainRom[0] == 0x01 && jaguar_mainRom[1] == 0x50)
2689 uint32 loadAddress = GET32(jaguar_mainRom, 0x28), runAddress = GET32(jaguar_mainRom, 0x24),
2690 codeSize = GET32(jaguar_mainRom, 0x18) + GET32(jaguar_mainRom, 0x1C);
2691 WriteLog("GUI: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize);
2693 if (loadAddress < 0x800000)
2694 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0xA8, codeSize);
2697 for(int i=codeSize-1; i>=0; i--)
2698 jaguar_mainRom[(loadAddress - 0x800000) + i] = jaguar_mainRom[i + 0xA8];
2699 /* memcpy(jaguar_mainRam, jaguar_mainRom + 0xA8, codeSize);
2700 memset(jaguar_mainRom, 0xFF, 0x600000);
2701 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
2702 memset(jaguar_mainRam, 0x00, 0x400000);*/
2705 jaguarRunAddress = runAddress;
2709 WriteLog("GUI: Couldn't find correct ABS format: %02X %02X\n", jaguar_mainRom[0], jaguar_mainRom[1]);
2713 else if (strcasecmp(ext, ".jag") == 0)
2715 // File extension ".JAG": Atari server file with header
2716 //NOTE: The bytes 'JAGR' should also be at position $1C...
2717 // Also, there's *always* a $601A header at position $00...
2718 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
2720 uint32 loadAddress = GET32(jaguar_mainRom, 0x22), runAddress = GET32(jaguar_mainRom, 0x2A);
2721 //This is not always right! Especially when converted via bin2jag1!!!
2722 //We should have access to the length of the furshlumiger file that was loaded anyway!
2724 // uint32 progLength = GET32(jaguar_mainRom, 0x02);
2727 // WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
2728 // memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, progLength);
2729 WriteLog("GUI: Setting up homebrew (JAG)... Run address: %08X, length: %08X\n", runAddress, jaguarRomSize - 0x2E);
2730 memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, jaguarRomSize - 0x2E);
2731 // SET32(jaguar_mainRam, 4, runAddress);
2732 jaguarRunAddress = runAddress;
2737 // .J64 (Jaguar cartridge ROM image) is implied by the FileList object...
2743 // Get the length of a (possibly) gzipped file
2745 int gzfilelength(gzFile gd)
2747 int size = 0, length = 0;
2748 unsigned char buffer[0x10000];
2754 // Read in chunks until EOF
2755 size = gzread(gd, buffer, 0x10000);