9#include "DrawUtils.hpp"
10#include "RootDisplay.hpp"
12char* musicData = NULL;
16 int sdl2Flags = SDL_INIT_GAMECONTROLLER;
18 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | sdl2Flags) < 0)
20 printf(
"Failed to initialize SDL2 drawing library: %s\n", SDL_GetError());
24 CST_SetQualityHint(
"linear");
27 printf(
"Failed to initialize TTF font library: %s\n", SDL_GetError());
34 SDLFlags |= SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
35 windowFlags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
37 root->window = SDL_CreateWindow(
38 NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
39 SCREEN_WIDTH, SCREEN_HEIGHT, windowFlags);
40 root->renderer = SDL_CreateRenderer(root->window, -1, SDLFlags);
42 SDL_SetRenderTarget(root->renderer, NULL);
44 if (root->renderer == NULL || root->window == NULL)
50 RootDisplay::mainDisplay = root;
52 for (
int i = 0; i < SDL_NumJoysticks(); i++)
54 if (SDL_JoystickOpen(i) == NULL)
56 printf(
"SDL_JoystickOpen: %s\n", SDL_GetError());
63 root->needsRender.type = SDL_USEREVENT;
73 SDL_DestroyWindow(RootDisplay::mainDisplay->window);
74 SDL_QuitSubSystem(SDL_INIT_VIDEO);
77 auto root = RootDisplay::mainDisplay;
78 if (root->music != NULL)
80 Mix_FreeMusic(root->music);
83 if (musicData != NULL)
96 Mix_Init(MIX_INIT_MP3);
97 if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) != 0) {
98 printf(
"Failed to initialize SDL2 mixer: %s\n", Mix_GetError());
103 const char* filename =
"background.mp3";
104 FILE* f = fopen(filename,
"rb");
108 fseek(f, 0, SEEK_END);
109 long fsize = ftell(f);
115 fseek(f, 0, SEEK_SET);
117 musicData = (
char*)(malloc(fsize + 1));
118 fread(musicData, fsize, 1, f);
121 musicData[fsize] = 0;
123 root->music = Mix_LoadMUS_RW(SDL_RWFromMem(musicData, fsize), 1);
128void CST_GetRGBA(Uint32 pixel, SDL_PixelFormat* format, CST_Color* cstColor)
130 SDL_GetRGBA(pixel, format, &cstColor->r, &cstColor->g, &cstColor->b, &cstColor->a);
134bool CST_SavePNG(CST_Texture* texture,
const char* file_name)
136 auto renderer = RootDisplay::mainDisplay->renderer;
137 SDL_Texture* target = SDL_GetRenderTarget(renderer);
138 SDL_SetRenderTarget(renderer, texture);
139 printf(
"Error: %s\n", SDL_GetError());
141 SDL_QueryTexture(texture, NULL, NULL, &width, &height);
142 SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
143 SDL_RenderReadPixels(renderer, NULL, surface->format->format, surface->pixels, surface->pitch);
144 IMG_SavePNG(surface, file_name);
145 SDL_FreeSurface(surface);
146 SDL_SetRenderTarget(renderer, target);
155 Mix_VolumeMusic(0.85 * MIX_MAX_VOLUME);
156 Mix_PlayMusic(root->music, -1);
157 Mix_VolumeMusic(0.85 * MIX_MAX_VOLUME);
162void CST_RenderPresent(CST_Renderer* renderer)
166 CST_SetDrawColorRGBA(renderer, 0, 0, 0, 255);
167 CST_Rect rect = { 0, 240, 40, 240 };
168 CST_FillRect(renderer, &rect);
169 CST_Rect rect2 = { 360, 240, 40, 240 };
170 CST_FillRect(renderer, &rect2);
171 CST_Rect rect3 = { 0, 240, 400, 240 };
172 CST_DrawRect(renderer, &rect3);
175 SDL_RenderPresent(renderer);
178void CST_FreeSurface(CST_Surface* surface)
180 SDL_FreeSurface(surface);
183void CST_RenderCopy(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect)
185 SDL_RenderCopy(dest, src, src_rect, dest_rect);
188void CST_RenderCopyRotate(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect,
int angle)
190 SDL_RenderCopyEx(dest, src, src_rect, dest_rect, angle, NULL, SDL_FLIP_NONE);
193void CST_SetDrawColor(CST_Renderer* renderer, CST_Color c)
195 CST_SetDrawColorRGBA(renderer, c.r, c.g, c.b, c.a);
198void CST_SetDrawColorRGBA(CST_Renderer* renderer, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
200 SDL_SetRenderDrawColor(renderer, r, g, b, a);
203void CST_FillRect(CST_Renderer* renderer, CST_Rect* dimens)
205 SDL_RenderFillRect(renderer, dimens);
208void CST_DrawRect(CST_Renderer* renderer, CST_Rect* dimens)
210 SDL_RenderDrawRect(renderer, dimens);
213void CST_DrawLine(CST_Renderer* renderer,
int x,
int y,
int w,
int h)
215 SDL_RenderDrawLine(renderer, x, y, w, h);
218void CST_SetDrawBlend(CST_Renderer* renderer,
bool enabled)
220 SDL_BlendMode mode = enabled ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE;
221 SDL_SetRenderDrawBlendMode(renderer, mode);
224void CST_QueryTexture(CST_Texture* texture,
int* w,
int* h)
226 SDL_QueryTexture(texture,
nullptr,
nullptr, w, h);
229CST_Texture* CST_CreateTextureFromSurface(CST_Renderer* renderer, CST_Surface* surface,
bool isAccessible )
231 return SDL_CreateTextureFromSurface(renderer, surface);
234void CST_SetQualityHint(
const char* quality)
236 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality);
239void CST_filledCircleRGBA(CST_Renderer* renderer, uint32_t x, uint32_t y, uint32_t radius, uint32_t r, uint32_t g, uint32_t b, uint32_t a)
241 #if !defined(_3DS) && !defined(_3DS_MOCK)
243 filledCircleRGBA(renderer, x, y, radius, r, g, b, a);
247void CST_SetWindowSize(CST_Window* window,
int w,
int h)
250 SDL_SetWindowSize(window, w, h);
254void CST_Delay(
int time)
261 return SDL_GetTicks();
266 auto joystick = SDL_JoystickFromInstanceID(event->event.jdevice.which);
267 if (joystick && SDL_JoystickGetAttached(joystick)) {
268 SDL_JoystickRumble(joystick, 0x400, 0x400, 200);
272void CST_SetCursor(
int cursor)
274 if (cursor == CST_CURSOR_NONE) {
275 SDL_ShowCursor(SDL_DISABLE);
279 SDL_ShowCursor(SDL_ENABLE);
280 auto sdlCursor = SDL_SYSTEM_CURSOR_ARROW;
281 if (cursor == CST_CURSOR_HAND) {
282 sdlCursor = SDL_SYSTEM_CURSOR_HAND;
283 }
else if (cursor == CST_CURSOR_TEXT) {
284 sdlCursor = SDL_SYSTEM_CURSOR_IBEAM;
285 }
else if (cursor == CST_CURSOR_SPINNER) {
286 sdlCursor = SDL_SYSTEM_CURSOR_WAIT;
289 SDL_SetCursor(SDL_CreateSystemCursor(sdlCursor));
292bool CST_isRectOffscreen(CST_Rect* rect)
295 if (rect->x > SCREEN_WIDTH + 10 || rect->y > SCREEN_HEIGHT + 10)
300 if (rect->x + rect->w < -10 || rect->y + rect->h < -10)
307float CST_GetDpiScale()
310 SDL_GetWindowSize(RootDisplay::window, &w, &h);
312 SDL_GL_GetDrawableSize(RootDisplay::window, &dw, &dh);
313 return (dw / (
float) w);
316void CST_SetWindowTitle(
const char* title)
318 SDL_SetWindowTitle(RootDisplay::mainDisplay->window, title);
321void CST_roundedBoxRGBA (
322 CST_Renderer *renderer,
323 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
324 Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
326 #if !defined(_3DS) && !defined(_3DS_MOCK)
328 roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
332void CST_roundedRectangleRGBA (
333 CST_Renderer *renderer,
334 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
335 Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
337 #if !defined(_3DS) && !defined(_3DS_MOCK)
339 roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
343void CST_rectangleRGBA (
344 CST_Renderer *renderer,
345 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
346 Uint8 r, Uint8 g, Uint8 b, Uint8 a
348 #if !defined(_3DS) && !defined(_3DS_MOCK)
350 rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
357std::vector<std::string> CST_GetMusicInfo(CST_Music* music) {
358 std::vector<std::string> info;
367 auto m = mpg123_new(NULL, NULL);
368 mpg123_open(m,
"./background.mp3");
369 mpg123_seek(m, 0, SEEK_SET);
370 auto meta = mpg123_meta_check(m);
375 if (meta == MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK) {
378 info.push_back(v2->title && v2->title->p ? v2->title->p :
"");
379 info.push_back(v2->artist && v2->artist->p ? v2->artist->p :
"");
380 info.push_back(v2->album && v2->album->p ? v2->album->p :
"");
386 info.push_back(v1->title[0] ? v1->title :
"");
387 info.push_back(v1->artist[0] ? v1->artist :
"");
388 info.push_back(v1->album[0] ? v1->album :
"");
405void chdirForPlatform()
407 auto basePath = SDL_GetBasePath();
408 if (basePath != NULL) {
414std::string replaceAll(std::string str,
const std::string& from,
const std::string& to) {
415 size_t start_pos = 0;
416 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
417 str.replace(start_pos, from.length(), to);
418 start_pos += to.length();