4 // Floppy disk selector GUI
6 // © 2014 Underground Software
8 // JLH = James Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 10/13/2013 Created this file
18 #include "diskselector.h"
30 enum { DSS_SHOWING, DSS_HIDING, DSS_SHOWN, DSS_HIDDEN };
37 int diskSelectorState = DSS_HIDDEN;
38 int diskSelected = -1;
39 int lastDiskSelected = -1;
43 // Case insensitve string comparison voodoo
45 struct ci_char_traits : public std::char_traits<char>
47 static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
48 static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
49 static bool lt(char c1, char c2) { return toupper(c1) < toupper(c2); }
50 static int compare(const char * s1, const char * s2, size_t n)
54 if (toupper(*s1) < toupper(*s2)) return -1;
55 if (toupper(*s1) > toupper(*s2)) return 1;
60 static const char * find(const char * s, int n, char a)
62 while (n-- > 0 && toupper(*s) != toupper(a))
70 typedef std::basic_string<char, ci_char_traits> ci_string;
72 // END Case insensitve string comparison voodoo
76 static SDL_Texture * window = NULL;
77 static SDL_Texture * charStamp = NULL;
78 static uint32_t windowPixels[DS_WIDTH * DS_HEIGHT];
79 static uint32_t stamp[FONT_WIDTH * FONT_HEIGHT];
80 bool DiskSelector::showWindow = false;
81 std::vector<ci_string> imageList;
84 void DiskSelector::Init(SDL_Renderer * renderer)
86 window = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
87 SDL_TEXTUREACCESS_TARGET, DS_WIDTH, DS_HEIGHT);
88 charStamp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
89 SDL_TEXTUREACCESS_TARGET, FONT_WIDTH, FONT_HEIGHT);
93 WriteLog("GUI (DiskSelector): Could not create window!\n");
97 if (SDL_SetTextureBlendMode(window, SDL_BLENDMODE_BLEND) == -1)
98 WriteLog("GUI (DiskSelector): Could not set blend mode for window.\n");
100 if (SDL_SetTextureBlendMode(charStamp, SDL_BLENDMODE_BLEND) == -1)
101 WriteLog("GUI (DiskSelector): Could not set blend mode for charStamp.\n");
103 for(uint32_t i=0; i<DS_WIDTH*DS_HEIGHT; i++)
104 windowPixels[i] = 0xEF00FF00;
106 SDL_UpdateTexture(window, NULL, windowPixels, 128 * sizeof(Uint32));
108 DrawFilenames(renderer);
112 void DiskSelector::FindDisks(const char * path)
114 DIR * dir = opendir(settings.disksPath);
118 WriteLog("GUI (DiskSelector)::FindDisks: Could not open directory \"%s\%!\n", settings.disksPath);
125 while ((ent = readdir(dir)) != NULL)
127 if (HasLegalExtension(ent->d_name))
128 imageList.push_back(ci_string(ent->d_name));
132 std::sort(imageList.begin(), imageList.end());
136 bool DiskSelector::HasLegalExtension(const char * name)
138 const char * ext = strrchr(name, '.');
140 if ((strcasecmp(ext, ".dsk") == 0) || (strcasecmp(ext, ".do") == 0)
141 || (strcasecmp(ext, ".po") == 0) || (strcasecmp(ext, ".nib") == 0))
148 void DiskSelector::DrawFilenames(SDL_Renderer * renderer)
150 if (SDL_SetRenderTarget(renderer, window) < 0)
152 WriteLog("GUI: Could not set Render Target to overlay... (%s)\n", SDL_GetError());
156 // 3 columns of 16 chars apiece (with 8X16 font), 18 rows
157 // 3 columns of 18 chars apiece (with 7X12 font), 24 rows
158 // 3 columns of 21 chars apiece (with 6X11 font), 27 rows
160 unsigned int count = 0;
162 while (count < imageList.size())
164 // int currentX = (count / 18) * 17;
165 // int currentY = (count % 18);
166 // int currentX = (count / 24) * 19;
167 // int currentY = (count % 24);
168 int currentX = (count / 27) * 22;
169 int currentY = (count % 27);
171 // for(unsigned int i=0; i<16; i++)
172 // for(unsigned int i=0; i<18; i++)
173 for(unsigned int i=0; i<21; i++)
175 if (i >= imageList[count].length())
178 bool invert = (diskSelected == (int)count ? true : false);
179 DrawCharacter(renderer, currentX + i, currentY, imageList[count][i], invert);
184 // if (count >= (18 * 3))
185 // if (count >= (24 * 3))
186 if (count >= (27 * 3))
190 // Set render target back to default
191 SDL_SetRenderTarget(renderer, NULL);
195 void DiskSelector::DrawCharacter(SDL_Renderer * renderer, int x, int y, uint8_t c, bool invert/*=false*/)
197 uint32_t inv = (invert ? 0x000000FF : 0x00000000);
198 uint32_t pixel = 0xFFFFC000; // RRGGBBAA
199 uint8_t * ptr = (uint8_t *)&font10pt[(c - 0x20) * FONT_WIDTH * FONT_HEIGHT];
201 dst.x = x * FONT_WIDTH, dst.y = y * FONT_HEIGHT, dst.w = FONT_WIDTH, dst.h = FONT_HEIGHT;
203 for(int i=0; i<FONT_WIDTH*FONT_HEIGHT; i++)
204 stamp[i] = (pixel | ptr[i]) ^ inv;
206 SDL_UpdateTexture(charStamp, NULL, stamp, FONT_WIDTH * sizeof(Uint32));
207 SDL_RenderCopy(renderer, charStamp, NULL, &dst);
211 void DiskSelector::ShowWindow(int drive)
219 void DiskSelector::MouseDown(int32_t x, int32_t y, uint32_t buttons)
227 if (diskSelected != -1)
230 sprintf(buffer, "%s/%s", settings.disksPath, &imageList[diskSelected][0]);
231 floppyDrive.LoadImage(buffer, driveNumber);
238 void DiskSelector::MouseUp(int32_t x, int32_t y, uint32_t buttons)
246 #define DS_XPOS ((VIRTUAL_SCREEN_WIDTH - DS_WIDTH) / 2)
247 #define DS_YPOS ((VIRTUAL_SCREEN_HEIGHT - DS_HEIGHT) / 2)
248 void DiskSelector::MouseMove(int32_t x, int32_t y, uint32_t buttons)
253 if (!entered && ((x >= DS_XPOS) && (x <= (DS_XPOS + DS_WIDTH))
254 && (y >= DS_YPOS) && (y <= (DS_YPOS + DS_HEIGHT))))
257 if (entered && ((x < DS_XPOS) || (x > (DS_XPOS + DS_WIDTH))
258 || (y < DS_YPOS) || (y > (DS_YPOS + DS_HEIGHT))))
264 int xChar = (x - DS_XPOS) / FONT_WIDTH;
265 int yChar = (y - DS_YPOS) / FONT_HEIGHT;
266 diskSelected = ((xChar / 22) * 27) + yChar;
268 if ((yChar >= 27) || (diskSelected >= (int)imageList.size()))
271 if (diskSelected != lastDiskSelected)
273 HandleSelection(sdlRenderer);
274 lastDiskSelected = diskSelected;
279 void DiskSelector::HandleSelection(SDL_Renderer * renderer)
281 SDL_UpdateTexture(window, NULL, windowPixels, 128 * sizeof(Uint32));
282 DrawFilenames(renderer);
286 void DiskSelector::Render(SDL_Renderer * renderer)
288 if (!(window && showWindow))
291 SDL_Rect dst = { DS_XPOS, DS_YPOS, DS_WIDTH, DS_HEIGHT };
292 SDL_RenderCopy(renderer, window, NULL, &dst);