Use Switch hardware acceleration (#162)

* preliminar changes

* enhance hid logic

* refactor switch UI
This commit is contained in:
Bernardo Giordano 2018-10-10 23:20:05 +02:00 committed by GitHub
parent e3796b04f8
commit dd69a50441
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 3017 additions and 1790 deletions

View file

@ -30,6 +30,8 @@
#include <3ds.h>
#include "ihid.hpp"
#define DELAY_TICKS 50000000
class Hid : public IHid
{
public:
@ -50,10 +52,11 @@ public:
void update(size_t count)
{
IHid::update(count);
if (mSleep)
mCurrentTime = svcGetSystemTick();
if ((mCurrentTime > mLastTime + DELAY_TICKS))
{
svcSleepThread(FASTSCROLL_WAIT);
IHid::update(count);
mLastTime = mCurrentTime;
}
}

View file

@ -36,8 +36,6 @@
#include <string.h>
#include <time.h>
#define FASTSCROLL_WAIT 1.5e8
namespace DateTime
{
std::string timeStr(void);

View file

@ -96,7 +96,6 @@ void IHid::update(size_t count) {
u64 kHeld = held();
u64 kDown = down();
mSleep = false;
if (kDown & _KEY_ZL())
{
@ -127,7 +126,6 @@ void IHid::update(size_t count) {
page_back();
mIndex = maxEntries(count);
}
mSleep = true;
}
else if (kHeld & _KEY_RIGHT())
{
@ -140,7 +138,6 @@ void IHid::update(size_t count) {
page_forward();
mIndex = 0;
}
mSleep = true;
}
else if (kHeld & _KEY_UP())
{
@ -164,7 +161,6 @@ void IHid::update(size_t count) {
{
mIndex -= mColumns;
}
mSleep = true;
}
else if (kHeld & _KEY_DOWN())
{
@ -189,7 +185,6 @@ void IHid::update(size_t count) {
mIndex = maxEntries(count);
}
}
mSleep = true;
}
}
}
@ -206,7 +201,6 @@ void IHid::update(size_t count) {
page_back();
mIndex = maxEntries(count);
}
mSleep = true;
}
else if (kHeld & _KEY_DOWN())
{
@ -219,7 +213,6 @@ void IHid::update(size_t count) {
page_forward();
mIndex = 0;
}
mSleep = true;
}
}
}

View file

@ -28,12 +28,11 @@
#define IHID_HPP
#include <cstdint>
typedef uint64_t u64;
#include <cmath>
#include "common.hpp"
typedef uint64_t u64;
class IHid
{
public:
@ -42,6 +41,8 @@ public:
{
reset();
mMaxPages = 0;
mCurrentTime = 0;
mLastTime = 0;
}
virtual ~IHid(void) { }
@ -74,7 +75,8 @@ protected:
size_t mMaxPages;
size_t mMaxVisibleEntries;
size_t mColumns;
bool mSleep;
u64 mCurrentTime;
u64 mLastTime;
};
#endif

View file

@ -98,6 +98,11 @@ def putSave():
if not serial or not metadata or not attachment:
return createAndLogResult("INVALID_PARAMETERS")
# TODO: check consistenza valori in metadata
if metadata.hash and len(metadata.hash) == 32 \
and metadata.name \
and metadata.serial and len(metadata.serial) == 64 \
and metadata.type:
print(metadata.name)
# mockRequest = "{hash, private, product_code, serial, title_id, type, username}"
result = createSave(metadata)
# TODO: se result positivo, salva file su disco
@ -217,6 +222,7 @@ def createDatabase(hostname, username, password):
PRIMARY KEY (id))
""")
except mysql.connector.errors.ProgrammingError as e:
trace(e)
print("Couldn't setup database. Closing...")
exit()
finally:

View file

@ -52,12 +52,14 @@ ROMFS := romfs
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O3 -ffunction-sections \
CFLAGS := -g -O3 -ffunction-sections \
-Wall -Wno-write-strings \
$(ARCH) $(DEFINES) \
-DVERSION_MAJOR=${VERSION_MAJOR} \
-DVERSION_MINOR=${VERSION_MINOR} \
-DVERSION_MICRO=${VERSION_MICRO} \
`freetype-config --cflags`
`freetype-config --cflags` \
`sdl2-config --cflags`
CFLAGS += $(INCLUDE) -D__SWITCH__ -D_GNU_SOURCE=1
@ -66,7 +68,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-no-as-needed,-Map,$(notdir $*.map)
LIBS := `freetype-config --libs`
LIBS := -lSDL2_ttf -lSDL2_gfx -lSDL2_image -lpng -ljpeg `sdl2-config --libs` `freetype-config --libs` -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -33,16 +33,15 @@
#include <utility>
#include <vector>
#include "clickable.hpp"
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "util.hpp"
extern u8* framebuf;
extern u32 framebuf_width;
#define DELAY_TICKS 3500000
class HbkbdButton : public Clickable
{
public:
HbkbdButton(u32 x, u32 y, u16 w, u16 h, color_t colorBg, color_t colorText, const std::string& message, bool centered)
HbkbdButton(u32 x, u32 y, u16 w, u16 h, SDL_Color colorBg, SDL_Color colorText, const std::string& message, bool centered)
: Clickable(x, y, w, h, colorBg, colorText, message, centered)
{
mSelected = false;
@ -59,12 +58,12 @@ public:
// outline
if (mSelected)
{
color_t color = MakeColor(138, 138, 138, 255);
SDL_Color color = FC_MakeColor(138, 138, 138, 255);
static const size_t size = 2;
rectangled(mx - size, my - size, mw + 2*size, size, color); // top
rectangled(mx - size, my, size, mh, color); // left
rectangled(mx + mw, my, size, mh, color); // right
rectangled(mx - size, my + mh, mw + 2*size, size, color); // bottom
SDLH_DrawRect(mx - size, my - size, mw + 2*size, size, color); // top
SDLH_DrawRect(mx - size, my, size, mh, color); // left
SDLH_DrawRect(mx + mw, my, size, mh, color); // right
SDLH_DrawRect(mx - size, my + mh, mw + 2*size, size, color); // bottom
}
}
@ -110,6 +109,9 @@ private:
const u32 marginlr = 54;
const u32 starty = 720 - 356 + margintb;
u64 currentTime = 0;
u64 lastTime = 0;
const std::string letters = "1234567890@qwertyuiop+asdfghjkl_:zxcvbnm,.-/";
std::vector<HbkbdButton*> buttons;
size_t prevSelectedButtonIndex;

View file

@ -0,0 +1,28 @@
#ifndef SDLHELPER_HPP
#define SDLHELPER_HPP
#include <switch.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <unordered_map>
#include "SDL_FontCache.h"
bool SDLH_Init(void);
void SDLH_Exit(void);
void SDLH_ClearScreen(SDL_Color color);
void SDLH_DrawRect(int x, int y, int w, int h, SDL_Color color);
void SDLH_DrawCircle(int x, int y, int r, SDL_Color color);
void SDLH_DrawText(int size, int x, int y, SDL_Color color, const char *text);
void SDLH_LoadImage(SDL_Texture **texture, char *path);
void SDLH_LoadImage(SDL_Texture** texture, u8* buff, size_t size);
void SDLH_DrawImage(SDL_Texture *texture, int x, int y);
void SDLH_DrawImageScale(SDL_Texture *texture, int x, int y, int w, int h);
void SDLH_DrawIcon(std::string icon, int x, int y);
void SDLH_GetTextDimensions(int size, const char* text, u32* w, u32* h);
void SDLH_DrawTextBox(int size, int x, int y, SDL_Color color, int max, const char* text);
void SDLH_Render(void);
#endif

View file

@ -0,0 +1,268 @@
/*
SDL_FontCache v0.9.0: A font cache for SDL and SDL_ttf
by Jonathan Dearborn
Dedicated to the memory of Florian Hufsky
License:
The short:
Use it however you'd like, but keep the copyright and license notice
whenever these files or parts of them are distributed in uncompiled form.
The long:
Copyright (c) 2016 Jonathan Dearborn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _SDL_FONTCACHE_H__
#define _SDL_FONTCACHE_H__
#include "SDL.h"
#include "SDL_ttf.h"
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
// Let's pretend this exists...
#define TTF_STYLE_OUTLINE 16
#define FC_Rect SDL_Rect
#define FC_Target SDL_Renderer
#define FC_Image SDL_Texture
#define FC_Log SDL_Log
// SDL_FontCache types
typedef enum
{
FC_ALIGN_LEFT,
FC_ALIGN_CENTER,
FC_ALIGN_RIGHT
} FC_AlignEnum;
typedef enum
{
FC_FILTER_NEAREST,
FC_FILTER_LINEAR
} FC_FilterEnum;
typedef struct FC_Scale
{
float x;
float y;
} FC_Scale;
typedef struct FC_Effect
{
FC_AlignEnum alignment;
FC_Scale scale;
SDL_Color color;
} FC_Effect;
// Opaque type
typedef struct FC_Font FC_Font;
typedef struct FC_GlyphData
{
SDL_Rect rect;
int cache_level;
} FC_GlyphData;
// Object creation
FC_Rect FC_MakeRect(float x, float y, float w, float h);
FC_Scale FC_MakeScale(float x, float y);
SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color);
FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h);
// Font object
FC_Font* FC_CreateFont(void);
Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, TTF_Font* ext, SDL_Color color);
Uint8 FC_LoadFont_RW(FC_Font* font, SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, SDL_RWops* file_rwops_ext, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style);
void FC_ClearFont(FC_Font* font);
void FC_FreeFont(FC_Font* font);
// Built-in loading strings
char* FC_GetStringASCII(void);
// UTF-8 to SDL_FontCache codepoint conversion
/*!
Returns the Uint32 codepoint (not UTF-32) parsed from the given UTF-8 string.
\param c A pointer to a string of proper UTF-8 character values.
\param advance_pointer If true, the source pointer will be incremented to skip the extra bytes from multibyte codepoints.
*/
Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer);
/*!
Parses the given codepoint and stores the UTF-8 bytes in 'result'. The result is NULL terminated.
\param result A memory buffer for the UTF-8 values. Must be at least 5 bytes long.
\param codepoint The Uint32 codepoint to parse (not UTF-32).
*/
void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint);
// UTF-8 string operations
/*! Allocates a new string of 'size' bytes that is already NULL-terminated. The NULL byte counts toward the size limit, as usual. Returns NULL if size is 0. */
char* U8_alloc(unsigned int size);
/*! Deallocates the given string. */
void U8_free(char* string);
/*! Allocates a copy of the given string. */
char* U8_strdup(const char* string);
/*! Returns the number of UTF-8 characters in the given string. */
int U8_strlen(const char* string);
/*! Returns the number of bytes in the UTF-8 multibyte character pointed at by 'character'. */
int U8_charsize(const char* character);
/*! Copies the source multibyte character into the given buffer without overrunning it. Returns 0 on failure. */
int U8_charcpy(char* buffer, const char* source, int buffer_size);
/*! Returns a pointer to the next UTF-8 character. */
const char* U8_next(const char* string);
/*! Inserts a UTF-8 string into 'string' at the given position. Use a position of -1 to append. Returns 0 when unable to insert the string. */
int U8_strinsert(char* string, int position, const char* source, int max_bytes);
/*! Erases the UTF-8 character at the given position, moving the subsequent characters down. */
void U8_strdel(char* string, int position);
// Internal settings
/*! Sets the string from which to load the initial glyphs. Use this if you need upfront loading for any reason (such as lack of render-target support). */
void FC_SetLoadingString(FC_Font* font, const char* string);
/*! Returns the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
unsigned int FC_GetBufferSize(void);
/*! Changes the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
void FC_SetBufferSize(unsigned int size);
void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale));
FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale);
// Custom caching
/*! Returns the number of cache levels that are active. */
int FC_GetNumCacheLevels(FC_Font* font);
/*! Returns the cache source texture at the given cache level. */
FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level);
// TODO: Specify ownership of the texture (should be shareable)
/*! Sets a cache source texture for rendering. New cache levels must be sequential. */
Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture);
/*! Copies the given surface to the given cache level as a texture. New cache levels must be sequential. */
Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface);
/*! Returns the number of codepoints that are stored in the font's glyph data map. */
unsigned int FC_GetNumCodepoints(FC_Font* font);
/*! Copies the stored codepoints into the given array. */
void FC_GetCodepoints(FC_Font* font, Uint32* result);
/*! Stores the glyph data for the given codepoint in 'result'. Returns 0 if the codepoint was not found in the cache. */
Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint);
/*! Sets the glyph data for the given codepoint. Duplicates are not checked. Returns a pointer to the stored data. */
FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data);
// Rendering
FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...);
FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...);
FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...);
FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...);
FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...);
FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...);
// Getters
FC_FilterEnum FC_GetFilterMode(FC_Font* font);
Uint16 FC_GetLineHeight(FC_Font* font);
Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...);
Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...);
// Returns a 1-pixel wide box in front of the character in the given position (index)
FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...);
Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...);
int FC_GetAscent(FC_Font* font, const char* formatted_text, ...);
int FC_GetDescent(FC_Font* font, const char* formatted_text, ...);
int FC_GetBaseline(FC_Font* font);
int FC_GetSpacing(FC_Font* font);
int FC_GetLineSpacing(FC_Font* font);
Uint16 FC_GetMaxWidth(FC_Font* font);
SDL_Color FC_GetDefaultColor(FC_Font* font);
Uint8 FC_InRect(float x, float y, FC_Rect input_rect);
// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index)
Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...);
// Setters
void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter);
void FC_SetSpacing(FC_Font* font, int LetterSpacing);
void FC_SetLineSpacing(FC_Font* font, int LineSpacing);
void FC_SetDefaultColor(FC_Font* font, SDL_Color color);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -32,19 +32,15 @@
#include <switch.h>
#include <map>
#include <vector>
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "types.hpp"
extern "C" {
#include "nanojpeg.h"
}
#define USER_ICON_SIZE 80
struct User {
u128 id;
std::string name;
u8* icon;
u128 id;
std::string name;
SDL_Texture* icon;
};
namespace Account
@ -53,9 +49,9 @@ namespace Account
void exit(void);
std::vector
<u128> ids(void);
u8* icon(u128 id);
std::string username(u128 id);
<u128> ids(void);
SDL_Texture* icon(u128 id);
std::string username(u128 id);
}
#endif

View file

@ -30,12 +30,12 @@
#include <string>
#include <switch.h>
#include "iclickable.hpp"
#include "draw.hpp"
#include "SDLHelper.hpp"
class Clickable : public IClickable<color_t>
class Clickable : public IClickable<SDL_Color>
{
public:
Clickable(int x, int y, u16 w, u16 h, color_t colorBg, color_t colorText, const std::string& message, bool centered)
Clickable(int x, int y, u16 w, u16 h, SDL_Color colorBg, SDL_Color colorText, const std::string& message, bool centered)
: IClickable(x, y, w, h, colorBg, colorText, message, centered) { }
virtual ~Clickable(void) { };

View file

@ -1,18 +1,19 @@
#ifndef COLORS_HPP
#define COLORS_HPP
#include "draw.hpp"
#include "SDLHelper.hpp"
#define COLOR_WHITE MakeColor(255, 255, 255, 255)
#define COLOR_BLACK MakeColor(0, 0, 0, 255)
#define COLOR_BLUE MakeColor(29, 50, 243, 255)
#define COLOR_GREEN MakeColor(0, 254, 197, 255)
#define COLOR_RED MakeColor(255, 81, 48, 255)
#define COLOR_GOLD MakeColor(255, 215, 0, 255)
#define COLOR_WHITE FC_MakeColor(255, 255, 255, 255)
#define COLOR_BLACK FC_MakeColor(0, 0, 0, 255)
#define COLOR_BLUE FC_MakeColor(29, 50, 243, 255)
#define COLOR_GREEN FC_MakeColor(0, 254, 197, 255)
#define COLOR_RED FC_MakeColor(255, 81, 48, 255)
#define COLOR_GOLD FC_MakeColor(255, 215, 0, 255)
#define COLOR_GREY_DARKER MakeColor(70, 70, 70, 255)
#define COLOR_GREY_DARK MakeColor(79, 79, 79, 255)
#define COLOR_GREY_MEDIUM MakeColor(94, 94, 94, 255)
#define COLOR_GREY_LIGHT MakeColor(138, 138, 138, 255)
#define COLOR_GREY_BG FC_MakeColor(51, 51, 51, 255)
#define COLOR_GREY_DARKER FC_MakeColor(70, 70, 70, 255)
#define COLOR_GREY_DARK FC_MakeColor(79, 79, 79, 255)
#define COLOR_GREY_MEDIUM FC_MakeColor(94, 94, 94, 255)
#define COLOR_GREY_LIGHT FC_MakeColor(138, 138, 138, 255)
#endif

View file

@ -1,83 +0,0 @@
/*
* Copyright 2017-2018 nx-hbmenu Authors
*
* Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
* OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef DRAW_HPP
#define DRAW_HPP
#include <ft2build.h>
#include FT_FREETYPE_H
#include <switch.h>
#include "types.hpp"
#define FONT_FACES_MAX PlSharedFontType_Total
extern u8* framebuf;
extern u32 framebuf_width;
// the following code is from nx-hbmenu
// https://github.com/switchbrew/nx-hbmenu/blob/master/common/common.h#L63
static inline u8 BlendColor(u32 src, u32 dst, u8 alpha)
{
u8 one_minus_alpha = (u8)255 - alpha;
return (dst*alpha + src*one_minus_alpha)/(u8)255;
}
static inline color_t MakeColor(u8 r, u8 g, u8 b, u8 a)
{
color_t clr;
clr.r = r;
clr.g = g;
clr.b = b;
clr.a = a;
return clr;
}
static inline void DrawPixel(u32 x, u32 y, color_t clr)
{
if (x >= 1280 || y >= 720)
return;
u32 off = (y * framebuf_width + x)*4;
framebuf[off] = BlendColor(framebuf[off], clr.r, clr.a); off++;
framebuf[off] = BlendColor(framebuf[off], clr.g, clr.a); off++;
framebuf[off] = BlendColor(framebuf[off], clr.b, clr.a); off++;
framebuf[off] = 0xff;
}
static inline void Draw4PixelsRaw(u32 x, u32 y, color_t clr)
{
if (x >= 1280 || y >= 720 || x > 1280-4)
return;
u32 color = clr.r | (clr.g<<8) | (clr.b<<16) | (0xff<<24);
u128 val = color | ((u128)color<<32) | ((u128)color<<64) | ((u128)color<<96);
u32 off = (y * framebuf_width + x)*4;
*((u128*)&framebuf[off]) = val;
}
Result textInit(void);
bool fontInitialize(void);
void fontExit();
void rectangle(u32 x, u32 y, u32 w, u32 h, color_t color);
void rectangled(u32 x, u32 y, u32 w, u32 h, color_t color);
void DrawPixel(u32 x, u32 y, color_t clr);
void DrawText(u32 font, u32 x, u32 y, color_t clr, const char* text);
void DrawTextTruncate(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text);
void GetTextDimensions(u32 font, const char* text, u32* width_out, u32* height_out);
void DrawImage(int x, int y, int width, int height, const u8 *image, ImageMode mode);
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight);
#endif

View file

@ -33,7 +33,7 @@
#include "account.hpp"
#include "colors.hpp"
#include "clickable.hpp"
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "info.hpp"
#include "hid.hpp"
#include "main.hpp"
@ -43,10 +43,6 @@
#include "types.hpp"
#include "util.hpp"
#include "checkbox_bin.h"
#include "flag_bin.h"
#include "star_bin.h"
namespace Gui
{
void init(void);

View file

@ -30,6 +30,8 @@
#include <switch.h>
#include "ihid.hpp"
#define DELAY_TICKS 3500000
class Hid : public IHid
{
public:
@ -50,10 +52,11 @@ public:
void update(size_t count)
{
IHid::update(count);
if (mSleep)
mCurrentTime = armGetSystemTick();
if ((mCurrentTime > mLastTime + DELAY_TICKS))
{
svcSleepThread(FASTSCROLL_WAIT);
IHid::update(count);
mLastTime = mCurrentTime;
}
}

View file

@ -29,7 +29,7 @@
#include <switch.h>
#include <string>
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "util.hpp"
typedef enum {

View file

@ -31,13 +31,13 @@
#include <string>
#include <switch.h>
#include <vector>
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "colors.hpp"
class MessageBox
{
public:
MessageBox(color_t colorbg, color_t colormessage);
MessageBox(SDL_Color colorbg, SDL_Color colormessage);
~MessageBox() { };
void push_message(const std::string& str);
@ -47,8 +47,8 @@ public:
private:
std::vector
<std::string> mList;
color_t mColorBg;
color_t mColorText;
SDL_Color mColorBg;
SDL_Color mColorText;
};
#endif

View file

@ -1,66 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// HEADER SECTION //
// copy and paste this into nanojpeg.h if you want //
///////////////////////////////////////////////////////////////////////////////
#ifndef _NANOJPEG_H
#define _NANOJPEG_H
// nj_result_t: Result codes for njDecode().
typedef enum _nj_result {
NJ_OK = 0, // no error, decoding successful
NJ_NO_JPEG, // not a JPEG file
NJ_UNSUPPORTED, // unsupported format
NJ_OUT_OF_MEM, // out of memory
NJ_INTERNAL_ERR, // internal error
NJ_SYNTAX_ERROR, // syntax error
__NJ_FINISHED, // used internally, will never be reported
} nj_result_t;
// njInit: Initialize NanoJPEG.
// For safety reasons, this should be called at least one time before using
// using any of the other NanoJPEG functions.
void njInit(void);
// njDecode: Decode a JPEG image.
// Decodes a memory dump of a JPEG file into internal buffers.
// Parameters:
// jpeg = The pointer to the memory dump.
// size = The size of the JPEG file.
// Return value: The error code in case of failure, or NJ_OK (zero) on success.
nj_result_t njDecode(const void* jpeg, const int size);
// njGetWidth: Return the width (in pixels) of the most recently decoded
// image. If njDecode() failed, the result of njGetWidth() is undefined.
int njGetWidth(void);
// njGetHeight: Return the height (in pixels) of the most recently decoded
// image. If njDecode() failed, the result of njGetHeight() is undefined.
int njGetHeight(void);
// njIsColor: Return 1 if the most recently decoded image is a color image
// (RGB) or 0 if it is a grayscale image. If njDecode() failed, the result
// of njGetWidth() is undefined.
int njIsColor(void);
// njGetImage: Returns the decoded image data.
// Returns a pointer to the most recently image. The memory layout it byte-
// oriented, top-down, without any padding between lines. Pixels of color
// images will be stored as three consecutive bytes for the red, green and
// blue channels. This data format is thus compatible with the PGM or PPM
// file formats and the OpenGL texture formats GL_LUMINANCE8 or GL_RGB8.
// If njDecode() failed, the result of njGetImage() is undefined.
unsigned char* njGetImage(void);
// njGetImageSize: Returns the size (in bytes) of the image data returned
// by njGetImage(). If njDecode() failed, the result of njGetImageSize() is
// undefined.
int njGetImageSize(void);
// njDone: Uninitialize NanoJPEG.
// Resets NanoJPEG's internal state and frees all memory that has been
// allocated at run-time by NanoJPEG. It is still possible to decode another
// image after a njDone() call.
void njDone(void);
#endif//_NANOJPEG_H

View file

@ -32,10 +32,10 @@
#include "iscrollable.hpp"
#include "clickable.hpp"
#include "colors.hpp"
#include "draw.hpp"
#include "SDLHelper.hpp"
#include "hid.hpp"
class Scrollable : public IScrollable<color_t>
class Scrollable : public IScrollable<SDL_Color>
{
public:
Scrollable(u32 x, u32 y, u32 w, u32 h, size_t visibleEntries)
@ -51,7 +51,7 @@ public:
void draw(void) override;
void setIndex(size_t i);
void push_back(color_t color, color_t colorMessage, const std::string& message) override;
void push_back(SDL_Color color, SDL_Color colorMessage, const std::string& message) override;
void resetIndex(void) override;
void updateSelection(void) override;

View file

@ -34,14 +34,11 @@
#include <utility>
#include <vector>
#include <unordered_map>
#include "SDLHelper.hpp"
#include "configuration.hpp"
#include "filesystem.hpp"
#include "io.hpp"
extern "C" {
#include "nanojpeg.h"
}
class Title
{
public:
@ -49,8 +46,7 @@ public:
~Title(void) { };
std::string author(void);
u8* smallIcon(void);
u8* icon(void);
SDL_Texture* icon(void);
u64 id(void);
std::string name(void);
std::string path(void);
@ -82,8 +78,8 @@ void getTitle(Title &dst, u128 uid, size_t i);
size_t getTitleCount(u128 uid);
void loadTitles(void);
void refreshDirectories(u64 id);
u8* smallIcon(u128 id, size_t i);
bool favorite(u128 uid, int i);
void freeIcons(void);
SDL_Texture* smallIcon(u128 uid, size_t i);
#endif

View file

@ -6,23 +6,4 @@ typedef enum {
CELLS
} entryType_t;
typedef union {
u32 abgr;
struct {
u8 r,g,b,a;
};
} color_t;
typedef enum
{
IMAGE_MODE_RGB24,
IMAGE_MODE_RGBA32
} ImageMode;
typedef struct {
u8 width, height;
int8_t posX, posY, advance, pitch;
const u8* data;
} glyph_t;
#endif

BIN
switch/romfs/checkbox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

BIN
switch/romfs/flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

BIN
switch/romfs/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

View file

@ -31,7 +31,16 @@ void KeyboardManager::hid(size_t& currentEntry)
static const size_t columns = 11;
u64 kHeld = hidKeysHeld(CONTROLLER_P1_AUTO);
bool sleep = false;
currentTime = armGetSystemTick();
if ((currentTime > lastTime + DELAY_TICKS))
{
lastTime = currentTime;
}
else
{
kHeld &= 0;
}
if (kHeld & KEY_LEFT)
{
@ -58,7 +67,6 @@ void KeyboardManager::hid(size_t& currentEntry)
default:
currentEntry--;
}
sleep = true;
}
else if (kHeld & KEY_RIGHT)
{
@ -85,7 +93,6 @@ void KeyboardManager::hid(size_t& currentEntry)
default:
currentEntry++;
}
sleep = true;
}
else if (kHeld & KEY_UP)
{
@ -109,7 +116,6 @@ void KeyboardManager::hid(size_t& currentEntry)
default:
currentEntry -= 11;
}
sleep = true;
}
else if (kHeld & KEY_DOWN)
{
@ -134,12 +140,6 @@ void KeyboardManager::hid(size_t& currentEntry)
default:
currentEntry += 11;
}
sleep = true;
}
if (sleep)
{
svcSleepThread(FASTSCROLL_WAIT);
}
}
@ -312,24 +312,23 @@ std::pair<bool, std::string> KeyboardManager::keyboard(const std::string& sugges
}
}
framebuf = gfxGetFramebuffer(&framebuf_width, NULL);
memset(framebuf, 51, gfxGetFramebufferSize());
SDLH_ClearScreen(COLOR_GREY_BG);
rectangle(marginlr, 140, 1280 - marginlr*2, 84, COLOR_GREY_MEDIUM);
rectangle(0, starty - margintb, 1280, 356, COLOR_GREY_DARKER);
SDLH_DrawRect(marginlr, 140, 1280 - marginlr*2, 84, COLOR_GREY_MEDIUM);
SDLH_DrawRect(0, starty - margintb, 1280, 356, COLOR_GREY_DARKER);
u32 texth, counter_width;
std::string counter = StringUtils::format("Custom name length: %d/%d", str.empty() ? suggestion.length() : str.length(), CUSTOM_PATH_LEN);
GetTextDimensions(7, " ", NULL, &texth);
GetTextDimensions(4, counter.c_str(), &counter_width, NULL);
DrawText(4, 1280 - marginlr - counter_width, 236, COLOR_WHITE, counter.c_str());
SDLH_GetTextDimensions(30, " ", NULL, &texth);
SDLH_GetTextDimensions(20, counter.c_str(), &counter_width, NULL);
SDLH_DrawText(20, 1280 - marginlr - counter_width, 236, COLOR_WHITE, counter.c_str());
if (str.empty())
{
DrawText(7, marginlr*2, 140 + (84 - texth) / 2, COLOR_GREY_LIGHT, suggestion.c_str());
SDLH_DrawTextBox(30, marginlr*2, 140 + (84 - texth) / 2, COLOR_GREY_LIGHT, 1280 - marginlr*2, suggestion.c_str());
}
else
{
DrawText(7, marginlr*2, 140 + (84 - texth) / 2, COLOR_WHITE, str.c_str());
SDLH_DrawTextBox(30, marginlr*2, 140 + (84 - texth) / 2, COLOR_WHITE, 1280 - marginlr*2, str.c_str());
}
for (size_t i = 0, sz = buttons.size(); i < sz; i++)
@ -356,8 +355,7 @@ std::pair<bool, std::string> KeyboardManager::keyboard(const std::string& sugges
buttons.at(i)->draw();
}
gfxFlushBuffers();
gfxSwapBuffers();
SDLH_Render();
}
return std::make_pair(false, suggestion);

166
switch/source/SDLHelper.cpp Normal file
View file

@ -0,0 +1,166 @@
#include "SDLHelper.hpp"
static SDL_Window* s_window;
static SDL_Renderer* s_renderer;
static SDL_Texture* s_star;
static SDL_Texture* s_checkbox;
static SDL_Texture* s_flag;
static PlFontData fontData, fontExtData;
static std::unordered_map<int, FC_Font*> s_fonts;
static FC_Font* getFontFromMap(int size)
{
std::unordered_map<int, FC_Font*>::const_iterator got = s_fonts.find(size);
if (got == s_fonts.end() || got->second == NULL)
{
FC_Font* f = FC_CreateFont();
FC_LoadFont_RW(f, s_renderer, SDL_RWFromMem((void*)fontData.address, fontData.size), SDL_RWFromMem((void*)fontExtData.address, fontExtData.size), 1, size, FC_MakeColor(0, 0, 0, 255), TTF_STYLE_NORMAL);
s_fonts.insert({size, f});
return f;
}
return got->second;
}
bool SDLH_Init(void)
{
bool ok = false;
SDL_Init(SDL_INIT_EVERYTHING);
s_window = SDL_CreateWindow("Checkpoint", 0, 0, 1280, 720, SDL_WINDOW_FULLSCREEN);
s_renderer = SDL_CreateRenderer(s_window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawBlendMode(s_renderer, SDL_BLENDMODE_BLEND);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
plGetSharedFontByType(&fontData, PlSharedFontType_Standard);
plGetSharedFontByType(&fontExtData, PlSharedFontType_NintendoExt);
SDLH_LoadImage(&s_flag, "romfs:/flag.png");
SDLH_LoadImage(&s_star, "romfs:/star.png");
SDLH_LoadImage(&s_checkbox, "romfs:/checkbox.png");
return true;
}
void SDLH_Exit(void)
{
for (auto& value : s_fonts)
{
FC_FreeFont(value.second);
}
TTF_Quit();
SDL_DestroyTexture(s_flag);
SDL_DestroyTexture(s_star);
SDL_DestroyTexture(s_checkbox);
IMG_Quit();
SDL_DestroyRenderer(s_renderer);
SDL_DestroyWindow(s_window);
SDL_Quit();
}
void SDLH_ClearScreen(SDL_Color color)
{
SDL_SetRenderDrawColor(s_renderer, color.r, color.g, color.b, color.a);
SDL_RenderClear(s_renderer);
}
void SDLH_Render(void)
{
SDL_RenderPresent(s_renderer);
}
void SDLH_DrawRect(int x, int y, int w, int h, SDL_Color color)
{
SDL_Rect rect;
rect.x = x; rect.y = y; rect.w = w; rect.h = h;
SDL_SetRenderDrawColor(s_renderer, color.r, color.g, color.b, color.a);
SDL_RenderFillRect(s_renderer, &rect);
}
void SDLH_DrawCircle(int x, int y, int r, SDL_Color color)
{
filledCircleRGBA(s_renderer, x, y, r, color.r, color.g, color.b, color.a);
}
void SDLH_DrawText(int size, int x, int y, SDL_Color color, const char* text)
{
FC_DrawColor(getFontFromMap(size), s_renderer, x, y, color, text);
}
void SDLH_DrawTextBox(int size, int x, int y, SDL_Color color, int max, const char* text)
{
u32 h;
FC_Font* font = getFontFromMap(size);
SDLH_GetTextDimensions(size, text, NULL, &h);
FC_Rect rect = FC_MakeRect(x, y, max, h);
FC_DrawBoxColor(font, s_renderer, rect, color, text);
}
void SDLH_LoadImage(SDL_Texture** texture, char* path)
{
SDL_Surface* loaded_surface = NULL;
loaded_surface = IMG_Load(path);
if (loaded_surface)
{
Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0);
SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey);
*texture = SDL_CreateTextureFromSurface(s_renderer, loaded_surface);
}
SDL_FreeSurface(loaded_surface);
}
void SDLH_LoadImage(SDL_Texture** texture, u8* buff, size_t size)
{
SDL_Surface* loaded_surface = NULL;
loaded_surface = IMG_Load_RW(SDL_RWFromMem(buff, size), 1);
if (loaded_surface)
{
Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0);
SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey);
*texture = SDL_CreateTextureFromSurface(s_renderer, loaded_surface);
}
SDL_FreeSurface(loaded_surface);
}
void SDLH_DrawImage(SDL_Texture* texture, int x, int y)
{
SDL_Rect position;
position.x = x; position.y = y;
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h);
SDL_RenderCopy(s_renderer, texture, NULL, &position);
}
void SDLH_DrawImageScale(SDL_Texture* texture, int x, int y, int w, int h)
{
SDL_Rect position;
position.x = x; position.y = y; position.w = w; position.h = h;
SDL_RenderCopy(s_renderer, texture, NULL, &position);
}
void SDLH_GetTextDimensions(int size, const char* text, u32* w, u32* h)
{
FC_Font* f = getFontFromMap(size);
if (w != NULL) *w = FC_GetWidth(f, text);
if (h != NULL) *h = FC_GetHeight(f, text);
}
void SDLH_DrawIcon(std::string icon, int x, int y)
{
SDL_Texture* t = nullptr;
if (icon.compare("flag") == 0) {
t = s_flag;
} else if (icon.compare("checkbox") == 0) {
t = s_checkbox;
} else if (icon.compare("star") == 0) {
t = s_star;
}
if (t != nullptr) {
SDLH_DrawImage(t, x, y);
}
}

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,7 @@ void Account::exit(void)
{
for (auto& value : mUsers)
{
free(value.second.icon);
SDL_DestroyTexture(value.second.icon);
}
accountExit();
}
@ -71,21 +71,8 @@ static User getUser(u128 id)
(buffer = (u8*)malloc(image_size)) != NULL &&
R_SUCCEEDED(accountProfileLoadImage(&profile, buffer, image_size, &real_size)))
{
njInit();
size_t fullsize = 256*256*3;
if (njDecode(buffer, real_size) == NJ_OK &&
njGetWidth() == 256 &&
njGetHeight() == 256 &&
(size_t)njGetImageSize() == fullsize &&
njIsColor() == 1)
{
u8* decoded_buffer = njGetImage();
user.icon = (u8*)malloc(USER_ICON_SIZE*USER_ICON_SIZE*3);
downscaleRGBImg(decoded_buffer, user.icon, 256, 256, USER_ICON_SIZE, USER_ICON_SIZE);
decoded_buffer = NULL;
}
SDLH_LoadImage(&user.icon, buffer, image_size);
free(buffer);
njDone();
}
}
@ -106,9 +93,10 @@ std::string Account::username(u128 id)
return got->second.name;
}
u8* Account::icon(u128 id)
SDL_Texture* Account::icon(u128 id)
{
std::map<u128, User>::const_iterator got = mUsers.find(id);
// TODO: remove the null check
// the null check in the icon is to handle the bad memory issue that isn't yet fixed
if (got == mUsers.end() || got->second.icon == NULL)
{
@ -116,6 +104,5 @@ u8* Account::icon(u128 id)
mUsers.insert({id, user});
return user.icon;
}
return got->second.icon;
}

View file

@ -59,23 +59,22 @@ bool Clickable::released(void)
void Clickable::draw(void)
{
u32 textw, texth;
GetTextDimensions(7, mText.c_str(), &textw, &texth);
SDLH_GetTextDimensions(36, mText.c_str(), &textw, &texth);
const u32 messageWidth = mCentered ? textw : mw - 8;
bool hld = held();
const color_t bgColor = hld ? mColorText : mColorBg;
const color_t msgColor = hld ? mColorBg : mColorText;
const SDL_Color bgColor = hld ? mColorText : mColorBg;
const SDL_Color msgColor = hld ? mColorBg : mColorText;
rectangle(mx, my, mw, mh, bgColor);
DrawText(7, mx + (mw - messageWidth)/2, my + (mh - texth)/2, msgColor, mText.c_str());
SDLH_DrawRect(mx, my, mw, mh, bgColor);
SDLH_DrawText(36, mx + (mw - messageWidth)/2, my + (mh - texth)/2, msgColor, mText.c_str());
}
void Clickable::draw(float font)
{
u32 textw, texth, dotlen;
GetTextDimensions(font, mText.c_str(), &textw, &texth);
GetTextDimensions(font, "...", &dotlen, NULL);
u32 textw, texth;
SDLH_GetTextDimensions(font, mText.c_str(), &textw, &texth);
const u32 messageWidth = mCentered ? textw : mw - 8;
rectangled(mx, my, mw, mh, mColorBg);
DrawTextTruncate(font, mx + (mw - messageWidth)/2, my + (mh - texth)/2, mColorText, mText.c_str(), mw - 4*2 - 40 - dotlen, "...");
SDLH_DrawRect(mx, my, mw, mh, mColorBg);
SDLH_DrawTextBox(font, mx + (mw - messageWidth)/2, my + (mh - texth)/2, mColorText, mw - 4*2, mText.c_str());
}

View file

@ -1,422 +0,0 @@
/*
* Copyright 2017-2018 nx-hbmenu Authors
*
* Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
* OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "draw.hpp"
static FT_Error s_font_libret = 1;
static FT_Error s_font_facesret[FONT_FACES_MAX];
static FT_Library s_font_library;
static FT_Face s_font_faces[FONT_FACES_MAX];
static FT_Face s_font_lastusedface;
static size_t s_font_faces_total = 0;
static u64 s_textLanguageCode = 0;
Result textInit(void)
{
Result res = setInitialize();
if (R_SUCCEEDED(res))
{
res = setGetSystemLanguage(&s_textLanguageCode);
}
setExit();
return res;
}
static bool FontSetType(u32 scale)
{
FT_Error ret = 0;
for (u32 i = 0; i < s_font_faces_total; i++)
{
ret = FT_Set_Char_Size(s_font_faces[i], 0, scale*64, 300, 300);
if (ret) return false;
}
return true;
}
static inline bool FontLoadGlyph(glyph_t* glyph, u32 font, u32 codepoint)
{
FT_Face face;
FT_Error ret = 0;
FT_GlyphSlot slot;
FT_UInt glyph_index;
FT_Bitmap* bitmap;
if (s_font_faces_total == 0) return false;
for (u32 i = 0; i < s_font_faces_total; i++)
{
face = s_font_faces[i];
s_font_lastusedface = face;
glyph_index = FT_Get_Char_Index(face, codepoint);
if (glyph_index == 0) continue;
ret = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (ret == 0)
{
ret = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL);
}
if (ret) return false;
break;
}
slot = face->glyph;
bitmap = &slot->bitmap;
glyph->width = bitmap->width;
glyph->height = bitmap->rows;
glyph->pitch = bitmap->pitch;
glyph->data = bitmap->buffer;
glyph->advance = slot->advance.x >> 6;
glyph->posX = slot->bitmap_left;
glyph->posY = slot->bitmap_top;
return true;
}
static void DrawGlyph(u32 x, u32 y, color_t clr, const glyph_t* glyph)
{
const u8* data = glyph->data;
x += glyph->posX;
y -= glyph->posY;
for (u32 j = 0; j < glyph->height; j ++)
{
for (u32 i = 0; i < glyph->width; i ++)
{
clr.a = data[i];
if (!clr.a) continue;
DrawPixel(x+i, y+j, clr);
}
data += glyph->pitch;
}
}
static inline u8 DecodeByte(const char** ptr)
{
u8 c = (u8)**ptr;
*ptr += 1;
return c;
}
// UTF-8 code adapted from http://www.json.org/JSON_checker/utf8_decode.c
static inline int8_t DecodeUTF8Cont(const char** ptr)
{
int c = DecodeByte(ptr);
return ((c & 0xC0) == 0x80) ? (c & 0x3F) : -1;
}
static inline u32 DecodeUTF8(const char** ptr)
{
u32 r;
u8 c;
int8_t c1, c2, c3;
c = DecodeByte(ptr);
if ((c & 0x80) == 0)
return c;
if ((c & 0xE0) == 0xC0)
{
c1 = DecodeUTF8Cont(ptr);
if (c1 >= 0)
{
r = ((c & 0x1F) << 6) | c1;
if (r >= 0x80)
return r;
}
} else if ((c & 0xF0) == 0xE0)
{
c1 = DecodeUTF8Cont(ptr);
if (c1 >= 0)
{
c2 = DecodeUTF8Cont(ptr);
if (c2 >= 0)
{
r = ((c & 0x0F) << 12) | (c1 << 6) | c2;
if (r >= 0x800 && (r < 0xD800 || r >= 0xE000))
return r;
}
}
} else if ((c & 0xF8) == 0xF0)
{
c1 = DecodeUTF8Cont(ptr);
if (c1 >= 0)
{
c2 = DecodeUTF8Cont(ptr);
if (c2 >= 0)
{
c3 = DecodeUTF8Cont(ptr);
if (c3 >= 0)
{
r = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
if (r >= 0x10000 && r < 0x110000)
return r;
}
}
}
}
return 0xFFFD;
}
static void DrawText_(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text)
{
u32 origX = x;
if (s_font_faces_total == 0) return;
if (!FontSetType(font)) return;
s_font_lastusedface = s_font_faces[0];
while (*text)
{
if (max_width && x-origX >= max_width) {
text = end_text;
max_width = 0;
}
glyph_t glyph;
u32 codepoint = DecodeUTF8(&text);
if (codepoint == '\n')
{
if (max_width) {
text = end_text;
max_width = 0;
continue;
}
x = origX;
y += s_font_lastusedface->size->metrics.height / 64;
continue;
}
if (!FontLoadGlyph(&glyph, font, codepoint))
{
if (!FontLoadGlyph(&glyph, font, '?'))
continue;
}
DrawGlyph(x, y + font*3, clr, &glyph);
x += glyph.advance;
}
}
void DrawText(u32 font, u32 x, u32 y, color_t clr, const char* text)
{
DrawText_(font, x, y, clr, text, 0, NULL);
}
void DrawTextTruncate(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text)
{
DrawText_(font, x, y, clr, text, max_width, end_text);
}
void GetTextDimensions(u32 font, const char* text, u32* width_out, u32* height_out)
{
if (s_font_faces_total == 0) return;
if (!FontSetType(font)) return;
s_font_lastusedface = s_font_faces[0];
u32 x = 0;
u32 width = 0, height = s_font_lastusedface->size->metrics.height / 64 - font*3;
while (*text)
{
glyph_t glyph;
u32 codepoint = DecodeUTF8(&text);
if (codepoint == '\n')
{
x = 0;
height += s_font_lastusedface->size->metrics.height / 64;
height -= font*3;
continue;
}
if (!FontLoadGlyph(&glyph, font, codepoint))
{
if (!FontLoadGlyph(&glyph, font, '?'))
continue;
}
x += glyph.advance;
if (x > width)
width = x;
}
if (width_out)
*width_out = width;
if (height_out)
*height_out = height;
}
bool fontInitialize(void)
{
FT_Error ret = 0;
for (u32 i = 0; i < FONT_FACES_MAX; i++)
{
s_font_facesret[i] = 1;
}
ret = FT_Init_FreeType(&s_font_library);
s_font_libret = ret;
if (s_font_libret) return false;
PlFontData fonts[PlSharedFontType_Total];
Result rc = 0;
rc = plGetSharedFont(s_textLanguageCode, fonts, FONT_FACES_MAX, &s_font_faces_total);
if (R_FAILED(rc)) return false;
for (u32 i = 0; i < s_font_faces_total; i++)
{
ret = FT_New_Memory_Face(
s_font_library,
(const FT_Byte*)fonts[i].address,
fonts[i].size,
0,
&s_font_faces[i]
);
s_font_facesret[i] = ret;
if (ret) return false;
}
return true;
}
void fontExit()
{
for (u32 i = 0; i < s_font_faces_total; i++)
{
if (s_font_facesret[i] == 0)
{
FT_Done_Face(s_font_faces[i]);
}
}
if (s_font_libret == 0)
{
FT_Done_FreeType(s_font_library);
}
}
void DrawImage(int x, int y, int width, int height, const u8 *image, ImageMode mode)
{
int tmpx, tmpy;
int pos;
color_t current_color;
for (tmpy = 0; tmpy < height; tmpy++)
{
for (tmpx = 0; tmpx < width; tmpx++)
{
switch (mode)
{
case IMAGE_MODE_RGB24:
pos = ((tmpy*width) + tmpx) * 3;
current_color = MakeColor(image[pos+0], image[pos+1], image[pos+2], 255);
break;
case IMAGE_MODE_RGBA32:
pos = ((tmpy*width) + tmpx) * 4;
current_color = MakeColor(image[pos+0], image[pos+1], image[pos+2], image[pos+3]);
break;
}
DrawPixel(x+tmpx, y+tmpy, current_color);
}
}
}
void rectangled(u32 x, u32 y, u32 w, u32 h, color_t color)
{
for (u32 j = y; j < y + h; j++)
{
for (u32 i = x; i < x + w; i++)
{
DrawPixel(i, j, color);
}
}
}
void rectangle(u32 x, u32 y, u32 w, u32 h, color_t color)
{
for (u32 j = y; j < y + h; j++)
{
for (u32 i = x; i < x + w; i+=4)
{
Draw4PixelsRaw(i, j, color);
}
}
}
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight)
{
int tmpx, tmpy;
int pos;
float sourceX, sourceY;
float xScale = (float)srcWidth / (float)destWidth;
float yScale = (float)srcHeight / (float)destHeight;
int pixelX, pixelY;
u8 r1, r2, r3, r4;
u8 g1, g2, g3, g4;
u8 b1, b2, b3, b4;
float fx, fy, fx1, fy1;
int w1, w2, w3, w4;
for (tmpx=0; tmpx<destWidth; tmpx++)
{
for (tmpy=0; tmpy<destHeight; tmpy++)
{
sourceX = tmpx * xScale;
sourceY = tmpy * yScale;
pixelX = (int)sourceX;
pixelY = (int)sourceY;
// get colours from four surrounding pixels
pos = ((pixelY + 0) * srcWidth + pixelX + 0) * 3;
r1 = image[pos+0];
g1 = image[pos+1];
b1 = image[pos+2];
pos = ((pixelY + 0) * srcWidth + pixelX + 1) * 3;
r2 = image[pos+0];
g2 = image[pos+1];
b2 = image[pos+2];
pos = ((pixelY + 1) * srcWidth + pixelX + 0) * 3;
r3 = image[pos+0];
g3 = image[pos+1];
b3 = image[pos+2];
pos = ((pixelY + 1) * srcWidth + pixelX + 1) * 3;
r4 = image[pos+0];
g4 = image[pos+1];
b4 = image[pos+2];
// determine weights
fx = sourceX - pixelX;
fy = sourceY - pixelY;
fx1 = 1.0f - fx;
fy1 = 1.0f - fy;
w1 = (int)(fx1*fy1*256.0);
w2 = (int)(fx*fy1*256.0);
w3 = (int)(fx1*fy*256.0);
w4 = (int)(fx*fy*256.0);
// set output pixels
pos = ((tmpy*destWidth) + tmpx) * 3;
out[pos+0] = (u8)((r1 * w1 + r2 * w2 + r3 * w3 + r4 * w4) >> 8);
out[pos+1] = (u8)((g1 * w1 + g2 * w2 + g3 * w3 + g4 * w4) >> 8);
out[pos+2] = (u8)((b1 * w1 + b2 * w2 + b3 * w3 + b4 * w4) >> 8);
}
}
}

View file

@ -26,9 +26,6 @@
#include "gui.hpp"
u8* framebuf;
u32 framebuf_width;
static Info* info;
static Clickable* buttonBackup;
static Clickable* buttonRestore;
@ -43,7 +40,7 @@ static bool backupScrollEnabled;
static Hid* hid;
static entryType_t type;
static float timer = 0;
static float currentTime = 0;
static int selectorX(size_t i);
static int selectorY(size_t i);
@ -146,34 +143,33 @@ void Gui::addSelectedEntry(size_t idx)
/// Gui implementation
static void drawOutline(u32 x, u32 y, u16 w, u16 h, u8 size, color_t color)
static void drawOutline(u32 x, u32 y, u16 w, u16 h, u8 size, SDL_Color color)
{
rectangled(x - size, y - size, w + 2*size, size, color); // top
rectangled(x - size, y, size, h, color); // left
rectangled(x + w, y, size, h, color); // right
rectangled(x - size, y + h, w + 2*size, size, color); // bottom
SDLH_DrawRect(x - size, y - size, w + 2*size, size, color); // top
SDLH_DrawRect(x - size, y, size, h, color); // left
SDLH_DrawRect(x + w, y, size, h, color); // right
SDLH_DrawRect(x - size, y + h, w + 2*size, size, color); // bottom
}
static void drawBackground(void)
{
framebuf = gfxGetFramebuffer(&framebuf_width, NULL);
memset(framebuf, 51, gfxGetFramebufferSize());
SDLH_ClearScreen(COLOR_GREY_BG);
const u8 bar_height = 28;
const u8 image_dim = 32;
rectangle(0, 0, 1280, bar_height, COLOR_GREY_DARK);
rectangle(0, 720 - bar_height, 1280, bar_height, COLOR_GREY_DARK);
SDLH_DrawRect(0, 0, 1280, bar_height, COLOR_GREY_DARK);
SDLH_DrawRect(0, 720 - bar_height, 1280, bar_height, COLOR_GREY_DARK);
u32 ver_w, ver_h, checkpoint_w;
GetTextDimensions(5, ver, &ver_w, &ver_h);
GetTextDimensions(6, "checkpoint", &checkpoint_w, NULL);
SDLH_GetTextDimensions(23, ver, &ver_w, &ver_h);
SDLH_GetTextDimensions(30, "checkpoint", &checkpoint_w, NULL);
u32 h = (bar_height - ver_h) / 2 - 1;
DrawText(5, 10, h + 3, COLOR_GREY_LIGHT, DateTime::timeStr().c_str());
DrawText(6, 1280 - 10 - ver_w - image_dim - 12 - checkpoint_w, h, COLOR_WHITE, "checkpoint");
DrawText(5, 1280 - 10 - ver_w, h + 3, COLOR_GREY_LIGHT, ver);
DrawImage(1280 - 10 - ver_w - image_dim - 6, -2, image_dim, image_dim, flag_bin, IMAGE_MODE_RGBA32);
SDLH_DrawText(23, 10, h + 3, COLOR_GREY_LIGHT, DateTime::timeStr().c_str());
SDLH_DrawText(30, 1280 - 10 - ver_w - image_dim - 12 - checkpoint_w, h, COLOR_WHITE, "checkpoint");
SDLH_DrawText(23, 1280 - 10 - ver_w, h + 3, COLOR_GREY_LIGHT, ver);
SDLH_DrawIcon("flag", 1280 - 10 - ver_w - image_dim - 6, -2);
// shadow
rectangle(0, bar_height, 1280, 2, COLOR_GREY_DARKER);
SDLH_DrawRect(0, bar_height, 1280, 2, COLOR_GREY_DARKER);
}
void Gui::drawCopy(const std::string& src, u64 offset, u64 size)
@ -190,25 +186,23 @@ void Gui::drawCopy(const std::string& src, u64 offset, u64 size)
static const int spacingFromBars = 220 + (720 - barHeight * 2 - progressBarHeight) / 2;
static const int width = 1280 - spacingFromSides * 2;
rectangle(spacingFromSides - 2, barHeight + spacingFromBars - 2, width + 4, progressBarHeight + 4, COLOR_GREY_LIGHT);
rectangle(spacingFromSides, barHeight + spacingFromBars, width, progressBarHeight, COLOR_WHITE);
rectangle(spacingFromSides, barHeight + spacingFromBars, (float)offset / (float)size * width, progressBarHeight, MakeColor(116, 222, 126, 255));
SDLH_DrawRect(spacingFromSides - 2, barHeight + spacingFromBars - 2, width + 4, progressBarHeight + 4, COLOR_GREY_LIGHT);
SDLH_DrawRect(spacingFromSides, barHeight + spacingFromBars, width, progressBarHeight, COLOR_WHITE);
SDLH_DrawRect(spacingFromSides, barHeight + spacingFromBars, (float)offset / (float)size * width, progressBarHeight, FC_MakeColor(116, 222, 126, 255));
std::string sizeString = StringUtils::sizeString(offset) + " of " + StringUtils::sizeString(size);
u32 textw, texth;
GetTextDimensions(6, sizeString.c_str(), &textw, &texth);
DrawText(6, ceilf((1280 - textw)/2), spacingFromBars + barHeight + (progressBarHeight - texth) / 2, COLOR_BLACK, sizeString.c_str());
gfxFlushBuffers();
gfxSwapBuffers();
SDLH_GetTextDimensions(30, sizeString.c_str(), &textw, &texth);
SDLH_DrawText(30, ceilf((1280 - textw)/2), spacingFromBars + barHeight + (progressBarHeight - texth) / 2, COLOR_BLACK, sizeString.c_str());
SDLH_Render();
}
bool Gui::askForConfirmation(const std::string& text)
{
bool ret = false;
Clickable* buttonYes = new Clickable(293, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "Yes \uE000", true);
Clickable* buttonNo = new Clickable(786, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "No \uE001", true);
Clickable* buttonYes = new Clickable(293, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "Yes \ue000", true);
Clickable* buttonNo = new Clickable(786, 540, 200, 80, COLOR_WHITE, COLOR_BLACK, "No \ue001", true);
MessageBox* message = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
message->push_message(text);
@ -229,8 +223,7 @@ bool Gui::askForConfirmation(const std::string& text)
buttonYes->draw();
buttonNo->draw();
gfxFlushBuffers();
gfxSwapBuffers();
SDLH_Render();
}
delete message;
@ -241,26 +234,26 @@ bool Gui::askForConfirmation(const std::string& text)
void Gui::init(void)
{
gfxInitDefault();
SDLH_Init();
sprintf(ver, "v%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
backupScrollEnabled = false;
info = new Info();
info->init("", "", 0, TYPE_INFO);
hid = new Hid(rowlen * collen, collen);
backupList = new Scrollable(540, 462, 506, 222, cols);
buttonBackup = new Clickable(1050, 462, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Backup \uE004", true);
buttonRestore = new Clickable(1050, 575, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Restore \uE005", true);
buttonBackup = new Clickable(1050, 462, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Backup \ue004", true);
buttonRestore = new Clickable(1050, 575, 220, 109, COLOR_WHITE, COLOR_GREY_LIGHT, "Restore \ue005", true);
copyList = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
messageBox = new MessageBox(COLOR_GREY_DARK, COLOR_WHITE);
messageBox->push_message("Press \uE000 to enter target.");
messageBox->push_message("Press \uE001 to exit target or deselect all titles.");
messageBox->push_message("Press \uE004 to backup target.");
messageBox->push_message("Press \uE005 to restore target.");
messageBox->push_message("Press \uE002 to delete a backup.");
messageBox->push_message("Press \uE003 to multiselect a title.");
messageBox->push_message("Hold \uE003 to multiselect all titles.");
messageBox->push_message("Press \uE041 to move between titles.");
messageBox->push_message("Press \uE085/\uE086 to switch user.");
messageBox->push_message("Press \ue000 to enter target.");
messageBox->push_message("Press \ue001 to exit target or deselect all titles.");
messageBox->push_message("Press \ue004 to backup target.");
messageBox->push_message("Press \ue005 to restore target.");
messageBox->push_message("Press \ue002 to delete a backup.");
messageBox->push_message("Press \ue003 to multiselect a title.");
messageBox->push_message("Hold \ue003 to multiselect all titles.");
messageBox->push_message("Press \ue041 to move between titles.");
messageBox->push_message("Press \ue085/\ue086 to switch user.");
}
void Gui::exit(void)
@ -272,7 +265,7 @@ void Gui::exit(void)
delete buttonBackup;
delete buttonRestore;
delete messageBox;
gfxExit();
SDLH_Exit();
}
void Gui::draw(u128 uid)
@ -284,7 +277,7 @@ void Gui::draw(u128 uid)
// draw
drawBackground();
rectangled(0, bar_height + 2, 532, 720 - 2*bar_height - 2, MakeColor(55, 55, 55, 255));
SDLH_DrawRect(0, bar_height + 2, 532, 720 - 2*bar_height - 2, FC_MakeColor(55, 55, 55, 255));
// user icons
std::vector<u128> userIds = Account::ids();
@ -294,19 +287,19 @@ void Gui::draw(u128 uid)
const u32 y = bar_height + spacing;
if (i == g_currentUserIndex)
{
float highlight_multiplier = fmax(0.0, fabs(fmod(timer, 1.0) - 0.5) / 0.5);
color_t color = COLOR_GREEN;
color = MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
float highlight_multiplier = fmax(0.0, fabs(fmod(currentTime, 1.0) - 0.5) / 0.5);
SDL_Color color = COLOR_GREEN;
color = FC_MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
drawOutline(x, y, USER_ICON_SIZE, USER_ICON_SIZE, 4, color);
}
if (Account::icon(userIds.at(i)) != NULL)
{
DrawImage(x, y, USER_ICON_SIZE, USER_ICON_SIZE, Account::icon(userIds.at(i)), IMAGE_MODE_RGB24);
SDLH_DrawImageScale(Account::icon(userIds.at(i)), x, y, USER_ICON_SIZE, USER_ICON_SIZE);
}
else
{
rectangle(x, y, USER_ICON_SIZE, USER_ICON_SIZE, COLOR_BLACK);
SDLH_DrawRect(x, y, USER_ICON_SIZE, USER_ICON_SIZE, COLOR_BLACK);
}
}
@ -317,22 +310,22 @@ void Gui::draw(u128 uid)
int selectory = selectorY(k);
if (smallIcon(g_currentUId, k) != NULL)
{
DrawImage(selectorx, selectory, 128, 128, smallIcon(g_currentUId, k), IMAGE_MODE_RGB24);
SDLH_DrawImageScale(smallIcon(g_currentUId, k), selectorx, selectory, 128, 128);
}
else
{
rectangle(selectorx, selectory, 128, 128, COLOR_BLACK);
SDLH_DrawRect(selectorx, selectory, 128, 128, COLOR_BLACK);
}
if (!selEnt.empty() && std::find(selEnt.begin(), selEnt.end(), k) != selEnt.end())
{
DrawImage(selectorx + 86, selectory + 86, 40, 40, checkbox_bin, IMAGE_MODE_RGBA32);
SDLH_DrawIcon("checkbox", selectorx + 86, selectory + 86);
}
if (favorite(g_currentUId, k))
{
rectangle(selectorx + 94, selectory + 8, 24, 24, COLOR_GOLD);
DrawImage(selectorx + 86, selectory, 40, 40, star_bin, IMAGE_MODE_RGBA32);
SDLH_DrawRect(selectorx + 94, selectory + 8, 24, 24, COLOR_GOLD);
SDLH_DrawIcon("star", selectorx + 86, selectory);
}
}
@ -341,11 +334,11 @@ void Gui::draw(u128 uid)
{
const int x = selectorX(hid->index()) + spacing/2;
const int y = selectorY(hid->index()) + spacing/2;
float highlight_multiplier = fmax(0.0, fabs(fmod(timer, 1.0) - 0.5) / 0.5);
color_t color = COLOR_BLUE;
color = MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
float highlight_multiplier = fmax(0.0, fabs(fmod(currentTime, 1.0) - 0.5) / 0.5);
SDL_Color color = COLOR_BLUE;
color = FC_MakeColor(color.r + (255 - color.r) * highlight_multiplier, color.g + (255 - color.g) * highlight_multiplier, color.b + (255 - color.b) * highlight_multiplier, 255);
drawOutline(x, y, 124, 124, spacing, color);
rectangled(x, y, 124, 124, MakeColor(255, 255, 255, 80));
SDLH_DrawRect(x, y, 124, 124, FC_MakeColor(255, 255, 255, 80));
}
if (getTitleCount(g_currentUId) > 0)
@ -368,38 +361,37 @@ void Gui::draw(u128 uid)
if (title.icon() != NULL)
{
drawOutline(1016, 157, 256, 256, 4, COLOR_BLACK);
DrawImage(1016, 157, 256, 256, title.icon(), IMAGE_MODE_RGB24);
SDLH_DrawImage(title.icon(), 1016, 157);
}
// draw infos
u32 info_w, info_h, title_w, h, dotlen, titleid_w, producer_w, user_w;
GetTextDimensions(7, "Title Information", &info_w, &info_h);
GetTextDimensions(5, "...", &dotlen, NULL);
GetTextDimensions(5, "Title: ", &title_w, &h);
GetTextDimensions(5, "Title ID: ", &titleid_w, NULL);
GetTextDimensions(5, "Author: ", &producer_w, NULL);
GetTextDimensions(5, "User: ", &user_w, NULL);
u32 info_w, info_h, title_w, h, titleid_w, producer_w, user_w;
SDLH_GetTextDimensions(36, "Title Information", &info_w, &info_h);
SDLH_GetTextDimensions(23, "Title: ", &title_w, &h);
SDLH_GetTextDimensions(23, "Title ID: ", &titleid_w, NULL);
SDLH_GetTextDimensions(23, "Author: ", &producer_w, NULL);
SDLH_GetTextDimensions(23, "User: ", &user_w, NULL);
h += 12;
u32 offset = 159 + 16 + info_h + h/2;
rectangle(536, 159, 468, 16 + info_h, COLOR_GREY_DARK);
rectangle(536, offset - h/2, 468, h*4 + h/2, COLOR_GREY_DARKER);
SDLH_DrawRect(536, 159, 468, 16 + info_h, COLOR_GREY_DARK);
SDLH_DrawRect(536, offset - h/2, 468, h*4 + h/2, COLOR_GREY_DARKER);
DrawText(7, 540 - 12 + 468 - info_w, 169, COLOR_GREY_LIGHT, "Title Information");
DrawText(5, 540, offset, COLOR_GREY_LIGHT, "Title: ");
DrawText(5, 540, offset + h, COLOR_GREY_LIGHT, "Title ID: ");
DrawText(5, 540, offset + h*2, COLOR_GREY_LIGHT, "Author: ");
DrawText(5, 540, offset + h*3, COLOR_GREY_LIGHT, "User: ");
SDLH_DrawText(36, 540 - 12 + 468 - info_w, 169, COLOR_GREY_LIGHT, "Title Information");
SDLH_DrawText(23, 540, offset, COLOR_GREY_LIGHT, "Title: ");
SDLH_DrawText(23, 540, offset + h, COLOR_GREY_LIGHT, "Title ID: ");
SDLH_DrawText(23, 540, offset + h*2, COLOR_GREY_LIGHT, "Author: ");
SDLH_DrawText(23, 540, offset + h*3, COLOR_GREY_LIGHT, "User: ");
DrawTextTruncate(5, 540 + title_w, offset, COLOR_WHITE, title.name().c_str(), 1012 - 540 - title_w - 4*2 - 20 - dotlen, "...");
DrawTextTruncate(5, 540 + titleid_w, offset + h, COLOR_WHITE, StringUtils::format("0x%016llX", title.id()).c_str(), 1012 - 540 - titleid_w - 4*2 - 20 - dotlen, "...");
DrawTextTruncate(5, 540 + producer_w, offset + h*2, COLOR_WHITE, title.author().c_str(), 1012 - 540 - producer_w - 4*2 - 20 - dotlen, "...");
DrawTextTruncate(5, 540 + user_w, offset + h*3, COLOR_WHITE, title.userName().c_str(), 1012 - 540 - user_w - 4*2 - 20 - dotlen, "...");
SDLH_DrawTextBox(23, 540 + title_w, offset, COLOR_WHITE, 1012 - 540 - title_w - 4*2, title.name().c_str());
SDLH_DrawTextBox(23, 540 + titleid_w, offset + h, COLOR_WHITE, 1012 - 540 - titleid_w - 4*2, StringUtils::format("0x%016llX", title.id()).c_str());
SDLH_DrawTextBox(23, 540 + producer_w, offset + h*2, COLOR_WHITE, 1012 - 540 - producer_w - 4*2, title.author().c_str());
SDLH_DrawTextBox(23, 540 + user_w, offset + h*3, COLOR_WHITE, 1012 - 540 - user_w - 4*2, title.userName().c_str());
drawOutline(540, 462, 730, 222, 4, COLOR_GREY_LIGHT);
rectangled(1046, 462, 4, 222, COLOR_GREY_LIGHT);
rectangled(1048, 571, 222, 4, COLOR_GREY_LIGHT);
SDLH_DrawRect(1046, 462, 4, 222, COLOR_GREY_LIGHT);
SDLH_DrawRect(1048, 571, 222, 4, COLOR_GREY_LIGHT);
backupList->draw();
buttonBackup->draw();
buttonRestore->draw();
@ -413,15 +405,14 @@ void Gui::draw(u128 uid)
}
u32 ins_w, ins_h;
const char* instructions = "Hold \uE046 to see commands. Press \uE045 to exit.";
GetTextDimensions(5, instructions, &ins_w, &ins_h);
DrawText(5, ceil((1280 - ins_w) / 2), 720 - bar_height + (bar_height - ins_h) / 2, COLOR_WHITE, instructions);
const char* instructions = "Hold \ue046 to see commands. Press \ue045 to exit.";
SDLH_GetTextDimensions(23, instructions, &ins_w, &ins_h);
SDLH_DrawText(23, ceil((1280 - ins_w) / 2), 720 - bar_height + (bar_height - ins_h) / 2, COLOR_WHITE, instructions);
// increase timer
timer += 0.05f;
// increase currentTime
currentTime = SDL_GetTicks() / 1000.f;
gfxFlushBuffers();
gfxSwapBuffers();
SDLH_Render();
}
bool Gui::isBackupReleased(void)

View file

@ -58,27 +58,27 @@ void Info::draw(void)
{
u32 w, hres = 44, hmessage;
u8 alpha = mTTL > 255 ? 255 : mTTL;
color_t color, bordercolor, bgcolor;
SDL_Color color, bordercolor, bgcolor;
if (mType == TYPE_ERROR)
{
color = MakeColor(255, 255, 255, alpha);
bordercolor = MakeColor(70, 70, 70, alpha);
bgcolor = MakeColor(79, 79, 79, alpha);
color = FC_MakeColor(255, 255, 255, alpha);
bordercolor = FC_MakeColor(70, 70, 70, alpha);
bgcolor = FC_MakeColor(79, 79, 79, alpha);
}
else if (mType == TYPE_INFO)
{
color = MakeColor(255, 255, 255, alpha);
bordercolor = MakeColor(70, 70, 70, alpha);
bgcolor = MakeColor(138, 138, 138, alpha);
color = FC_MakeColor(255, 255, 255, alpha);
bordercolor = FC_MakeColor(70, 70, 70, alpha);
bgcolor = FC_MakeColor(138, 138, 138, alpha);
}
GetTextDimensions(7, mTitle.c_str(), &w, &hmessage);
SDLH_GetTextDimensions(36, mTitle.c_str(), &w, &hmessage);
const u32 spacing = (mh - hres - hmessage) / 3;
rectangle(mx - 2, my - 2, mw + 4, mh + 4, bordercolor);
rectangle(mx, my, mw, mh, bgcolor);
DrawText(7, mx + (mw - w) / 2, my + spacing, color, mTitle.c_str());
DrawText(4, mx + 10, my + 2*spacing + hres, color, mMessage.c_str());
SDLH_DrawRect(mx - 2, my - 2, mw + 4, mh + 4, bordercolor);
SDLH_DrawRect(mx, my, mw, mh, bgcolor);
SDLH_DrawText(36, mx + (mw - w) / 2, my + spacing, color, mTitle.c_str());
SDLH_DrawText(20, mx + 10, my + 2*spacing + hres, color, mMessage.c_str());
mTTL--;
}

View file

@ -26,7 +26,7 @@
#include "messagebox.hpp"
MessageBox::MessageBox(color_t colorBg, color_t colorText)
MessageBox::MessageBox(SDL_Color colorBg, SDL_Color colorText)
{
mColorBg = colorBg;
mColorText = colorText;
@ -52,7 +52,7 @@ void MessageBox::draw(void)
u32 widths[mList.size()];
for (size_t i = 0, sz = mList.size(); i < sz; i++)
{
GetTextDimensions(6, mList.at(i).c_str(), &widths[i], &mh);
SDLH_GetTextDimensions(30, mList.at(i).c_str(), &widths[i], &mh);
if (widths[i] > w)
{
w = widths[i];
@ -65,11 +65,11 @@ void MessageBox::draw(void)
const u32 x = (1280-w)/2;
const u32 y = (720-h)/2;
rectangle(x - 2, y - 2, w + 4, h + 4, COLOR_BLACK);
rectangle(x, y, w, h, mColorBg);
SDLH_DrawRect(x - 2, y - 2, w + 4, h + 4, COLOR_BLACK);
SDLH_DrawRect(x, y, w, h, mColorBg);
for (size_t i = 0, sz = mList.size(); i < sz; i++)
{
DrawText(6, ceil((1280 - widths[i]) / 2), y + spacingFromEdges + mh*i, mColorText, mList.at(i).c_str());
SDLH_DrawText(30, ceil((1280 - widths[i]) / 2), y + spacingFromEdges + mh*i, mColorText, mList.at(i).c_str());
}
}

View file

@ -1,916 +0,0 @@
// NanoJPEG -- KeyJ's Tiny Baseline JPEG Decoder
// version 1.3.5 (2016-11-14)
// Copyright (c) 2009-2016 Martin J. Fiedler <martin.fiedler@gmx.net>
// published under the terms of the MIT license
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////////////////////////////////////////
// DOCUMENTATION SECTION //
// read this if you want to know what this is all about //
///////////////////////////////////////////////////////////////////////////////
// INTRODUCTION
// ============
//
// This is a minimal decoder for baseline JPEG images. It accepts memory dumps
// of JPEG files as input and generates either 8-bit grayscale or packed 24-bit
// RGB images as output. It does not parse JFIF or Exif headers; all JPEG files
// are assumed to be either grayscale or YCbCr. CMYK or other color spaces are
// not supported. All YCbCr subsampling schemes with power-of-two ratios are
// supported, as are restart intervals. Progressive or lossless JPEG is not
// supported.
// Summed up, NanoJPEG should be able to decode all images from digital cameras
// and most common forms of other non-progressive JPEG images.
// The decoder is not optimized for speed, it's optimized for simplicity and
// small code. Image quality should be at a reasonable level. A bicubic chroma
// upsampling filter ensures that subsampled YCbCr images are rendered in
// decent quality. The decoder is not meant to deal with broken JPEG files in
// a graceful manner; if anything is wrong with the bitstream, decoding will
// simply fail.
// The code should work with every modern C compiler without problems and
// should not emit any warnings. It uses only (at least) 32-bit integer
// arithmetic and is supposed to be endianness independent and 64-bit clean.
// However, it is not thread-safe.
// COMPILE-TIME CONFIGURATION
// ==========================
//
// The following aspects of NanoJPEG can be controlled with preprocessor
// defines:
//
// _NJ_EXAMPLE_PROGRAM = Compile a main() function with an example
// program.
// _NJ_INCLUDE_HEADER_ONLY = Don't compile anything, just act as a header
// file for NanoJPEG. Example:
// #define _NJ_INCLUDE_HEADER_ONLY
// #include "nanojpeg.c"
// int main(void) {
// njInit();
// // your code here
// njDone();
// }
// NJ_USE_LIBC=1 = Use the malloc(), free(), memset() and memcpy()
// functions from the standard C library (default).
// NJ_USE_LIBC=0 = Don't use the standard C library. In this mode,
// external functions njAlloc(), njFreeMem(),
// njFillMem() and njCopyMem() need to be defined
// and implemented somewhere.
// NJ_USE_WIN32=0 = Normal mode (default).
// NJ_USE_WIN32=1 = If compiling with MSVC for Win32 and
// NJ_USE_LIBC=0, NanoJPEG will use its own
// implementations of the required C library
// functions (default if compiling with MSVC and
// NJ_USE_LIBC=0).
// NJ_CHROMA_FILTER=1 = Use the bicubic chroma upsampling filter
// (default).
// NJ_CHROMA_FILTER=0 = Use simple pixel repetition for chroma upsampling
// (bad quality, but faster and less code).
// API
// ===
//
// For API documentation, read the "header section" below.
// EXAMPLE
// =======
//
// A few pages below, you can find an example program that uses NanoJPEG to
// convert JPEG files into PGM or PPM. To compile it, use something like
// gcc -O3 -D_NJ_EXAMPLE_PROGRAM -o nanojpeg nanojpeg.c
// You may also add -std=c99 -Wall -Wextra -pedantic -Werror, if you want :)
// The only thing you might need is -Wno-shift-negative-value, because this
// code relies on the target machine using two's complement arithmetic, but
// the C standard does not, even though *any* practically useful machine
// nowadays uses two's complement.
///////////////////////////////////////////////////////////////////////////////
// HEADER SECTION //
// copy and pase this into nanojpeg.h if you want //
///////////////////////////////////////////////////////////////////////////////
#ifndef _NANOJPEG_H
#define _NANOJPEG_H
// nj_result_t: Result codes for njDecode().
typedef enum _nj_result {
NJ_OK = 0, // no error, decoding successful
NJ_NO_JPEG, // not a JPEG file
NJ_UNSUPPORTED, // unsupported format
NJ_OUT_OF_MEM, // out of memory
NJ_INTERNAL_ERR, // internal error
NJ_SYNTAX_ERROR, // syntax error
__NJ_FINISHED, // used internally, will never be reported
} nj_result_t;
// njInit: Initialize NanoJPEG.
// For safety reasons, this should be called at least one time before using
// using any of the other NanoJPEG functions.
void njInit(void);
// njDecode: Decode a JPEG image.
// Decodes a memory dump of a JPEG file into internal buffers.
// Parameters:
// jpeg = The pointer to the memory dump.
// size = The size of the JPEG file.
// Return value: The error code in case of failure, or NJ_OK (zero) on success.
nj_result_t njDecode(const void* jpeg, const int size);
// njGetWidth: Return the width (in pixels) of the most recently decoded
// image. If njDecode() failed, the result of njGetWidth() is undefined.
int njGetWidth(void);
// njGetHeight: Return the height (in pixels) of the most recently decoded
// image. If njDecode() failed, the result of njGetHeight() is undefined.
int njGetHeight(void);
// njIsColor: Return 1 if the most recently decoded image is a color image
// (RGB) or 0 if it is a grayscale image. If njDecode() failed, the result
// of njGetWidth() is undefined.
int njIsColor(void);
// njGetImage: Returns the decoded image data.
// Returns a pointer to the most recently image. The memory layout it byte-
// oriented, top-down, without any padding between lines. Pixels of color
// images will be stored as three consecutive bytes for the red, green and
// blue channels. This data format is thus compatible with the PGM or PPM
// file formats and the OpenGL texture formats GL_LUMINANCE8 or GL_RGB8.
// If njDecode() failed, the result of njGetImage() is undefined.
unsigned char* njGetImage(void);
// njGetImageSize: Returns the size (in bytes) of the image data returned
// by njGetImage(). If njDecode() failed, the result of njGetImageSize() is
// undefined.
int njGetImageSize(void);
// njDone: Uninitialize NanoJPEG.
// Resets NanoJPEG's internal state and frees all memory that has been
// allocated at run-time by NanoJPEG. It is still possible to decode another
// image after a njDone() call.
void njDone(void);
#endif//_NANOJPEG_H
///////////////////////////////////////////////////////////////////////////////
// CONFIGURATION SECTION //
// adjust the default settings for the NJ_ defines here //
///////////////////////////////////////////////////////////////////////////////
#ifndef NJ_USE_LIBC
#define NJ_USE_LIBC 1
#endif
#ifndef NJ_USE_WIN32
#ifdef _MSC_VER
#define NJ_USE_WIN32 (!NJ_USE_LIBC)
#else
#define NJ_USE_WIN32 0
#endif
#endif
#ifndef NJ_CHROMA_FILTER
#define NJ_CHROMA_FILTER 1
#endif
///////////////////////////////////////////////////////////////////////////////
// EXAMPLE PROGRAM //
// just define _NJ_EXAMPLE_PROGRAM to compile this (requires NJ_USE_LIBC) //
///////////////////////////////////////////////////////////////////////////////
#ifdef _NJ_EXAMPLE_PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
int size;
char *buf;
FILE *f;
if (argc < 2) {
printf("Usage: %s <input.jpg> [<output.ppm>]\n", argv[0]);
return 2;
}
f = fopen(argv[1], "rb");
if (!f) {
printf("Error opening the input file.\n");
return 1;
}
fseek(f, 0, SEEK_END);
size = (int) ftell(f);
buf = (char*) malloc(size);
fseek(f, 0, SEEK_SET);
size = (int) fread(buf, 1, size, f);
fclose(f);
njInit();
if (njDecode(buf, size)) {
free((void*)buf);
printf("Error decoding the input file.\n");
return 1;
}
free((void*)buf);
f = fopen((argc > 2) ? argv[2] : (njIsColor() ? "nanojpeg_out.ppm" : "nanojpeg_out.pgm"), "wb");
if (!f) {
printf("Error opening the output file.\n");
return 1;
}
fprintf(f, "P%d\n%d %d\n255\n", njIsColor() ? 6 : 5, njGetWidth(), njGetHeight());
fwrite(njGetImage(), 1, njGetImageSize(), f);
fclose(f);
njDone();
return 0;
}
#endif
///////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION SECTION //
// you may stop reading here //
///////////////////////////////////////////////////////////////////////////////
#ifndef _NJ_INCLUDE_HEADER_ONLY
#ifdef _MSC_VER
#define NJ_INLINE static __inline
#define NJ_FORCE_INLINE static __forceinline
#else
#define NJ_INLINE static inline
#define NJ_FORCE_INLINE static inline
#endif
#if NJ_USE_LIBC
#include <stdlib.h>
#include <string.h>
#define njAllocMem malloc
#define njFreeMem free
#define njFillMem memset
#define njCopyMem memcpy
#elif NJ_USE_WIN32
#include <windows.h>
#define njAllocMem(size) ((void*) LocalAlloc(LMEM_FIXED, (SIZE_T)(size)))
#define njFreeMem(block) ((void) LocalFree((HLOCAL) block))
NJ_INLINE void njFillMem(void* block, unsigned char value, int count) { __asm {
mov edi, block
mov al, value
mov ecx, count
rep stosb
} }
NJ_INLINE void njCopyMem(void* dest, const void* src, int count) { __asm {
mov edi, dest
mov esi, src
mov ecx, count
rep movsb
} }
#else
extern void* njAllocMem(int size);
extern void njFreeMem(void* block);
extern void njFillMem(void* block, unsigned char byte, int size);
extern void njCopyMem(void* dest, const void* src, int size);
#endif
typedef struct _nj_code {
unsigned char bits, code;
} nj_vlc_code_t;
typedef struct _nj_cmp {
int cid;
int ssx, ssy;
int width, height;
int stride;
int qtsel;
int actabsel, dctabsel;
int dcpred;
unsigned char *pixels;
} nj_component_t;
typedef struct _nj_ctx {
nj_result_t error;
const unsigned char *pos;
int size;
int length;
int width, height;
int mbwidth, mbheight;
int mbsizex, mbsizey;
int ncomp;
nj_component_t comp[3];
int qtused, qtavail;
unsigned char qtab[4][64];
nj_vlc_code_t vlctab[4][65536];
int buf, bufbits;
int block[64];
int rstinterval;
unsigned char *rgb;
} nj_context_t;
static nj_context_t nj;
static const char njZZ[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
NJ_FORCE_INLINE unsigned char njClip(const int x) {
return (x < 0) ? 0 : ((x > 0xFF) ? 0xFF : (unsigned char) x);
}
#define W1 2841
#define W2 2676
#define W3 2408
#define W5 1609
#define W6 1108
#define W7 565
NJ_INLINE void njRowIDCT(int* blk) {
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
if (!((x1 = blk[4] << 11)
| (x2 = blk[6])
| (x3 = blk[2])
| (x4 = blk[1])
| (x5 = blk[7])
| (x6 = blk[5])
| (x7 = blk[3])))
{
blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
return;
}
x0 = (blk[0] << 11) + 128;
x8 = W7 * (x4 + x5);
x4 = x8 + (W1 - W7) * x4;
x5 = x8 - (W1 + W7) * x5;
x8 = W3 * (x6 + x7);
x6 = x8 - (W3 - W5) * x6;
x7 = x8 - (W3 + W5) * x7;
x8 = x0 + x1;
x0 -= x1;
x1 = W6 * (x3 + x2);
x2 = x1 - (W2 + W6) * x2;
x3 = x1 + (W2 - W6) * x3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181 * (x4 + x5) + 128) >> 8;
x4 = (181 * (x4 - x5) + 128) >> 8;
blk[0] = (x7 + x1) >> 8;
blk[1] = (x3 + x2) >> 8;
blk[2] = (x0 + x4) >> 8;
blk[3] = (x8 + x6) >> 8;
blk[4] = (x8 - x6) >> 8;
blk[5] = (x0 - x4) >> 8;
blk[6] = (x3 - x2) >> 8;
blk[7] = (x7 - x1) >> 8;
}
NJ_INLINE void njColIDCT(const int* blk, unsigned char *out, int stride) {
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
if (!((x1 = blk[8*4] << 8)
| (x2 = blk[8*6])
| (x3 = blk[8*2])
| (x4 = blk[8*1])
| (x5 = blk[8*7])
| (x6 = blk[8*5])
| (x7 = blk[8*3])))
{
x1 = njClip(((blk[0] + 32) >> 6) + 128);
for (x0 = 8; x0; --x0) {
*out = (unsigned char) x1;
out += stride;
}
return;
}
x0 = (blk[0] << 8) + 8192;
x8 = W7 * (x4 + x5) + 4;
x4 = (x8 + (W1 - W7) * x4) >> 3;
x5 = (x8 - (W1 + W7) * x5) >> 3;
x8 = W3 * (x6 + x7) + 4;
x6 = (x8 - (W3 - W5) * x6) >> 3;
x7 = (x8 - (W3 + W5) * x7) >> 3;
x8 = x0 + x1;
x0 -= x1;
x1 = W6 * (x3 + x2) + 4;
x2 = (x1 - (W2 + W6) * x2) >> 3;
x3 = (x1 + (W2 - W6) * x3) >> 3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181 * (x4 + x5) + 128) >> 8;
x4 = (181 * (x4 - x5) + 128) >> 8;
*out = njClip(((x7 + x1) >> 14) + 128); out += stride;
*out = njClip(((x3 + x2) >> 14) + 128); out += stride;
*out = njClip(((x0 + x4) >> 14) + 128); out += stride;
*out = njClip(((x8 + x6) >> 14) + 128); out += stride;
*out = njClip(((x8 - x6) >> 14) + 128); out += stride;
*out = njClip(((x0 - x4) >> 14) + 128); out += stride;
*out = njClip(((x3 - x2) >> 14) + 128); out += stride;
*out = njClip(((x7 - x1) >> 14) + 128);
}
#define njThrow(e) do { nj.error = e; return; } while (0)
#define njCheckError() do { if (nj.error) return; } while (0)
static int njShowBits(int bits) {
unsigned char newbyte;
if (!bits) return 0;
while (nj.bufbits < bits) {
if (nj.size <= 0) {
nj.buf = (nj.buf << 8) | 0xFF;
nj.bufbits += 8;
continue;
}
newbyte = *nj.pos++;
nj.size--;
nj.bufbits += 8;
nj.buf = (nj.buf << 8) | newbyte;
if (newbyte == 0xFF) {
if (nj.size) {
unsigned char marker = *nj.pos++;
nj.size--;
switch (marker) {
case 0x00:
case 0xFF:
break;
case 0xD9: nj.size = 0; break;
default:
if ((marker & 0xF8) != 0xD0)
nj.error = NJ_SYNTAX_ERROR;
else {
nj.buf = (nj.buf << 8) | marker;
nj.bufbits += 8;
}
}
} else
nj.error = NJ_SYNTAX_ERROR;
}
}
return (nj.buf >> (nj.bufbits - bits)) & ((1 << bits) - 1);
}
NJ_INLINE void njSkipBits(int bits) {
if (nj.bufbits < bits)
(void) njShowBits(bits);
nj.bufbits -= bits;
}
NJ_INLINE int njGetBits(int bits) {
int res = njShowBits(bits);
njSkipBits(bits);
return res;
}
NJ_INLINE void njByteAlign(void) {
nj.bufbits &= 0xF8;
}
static void njSkip(int count) {
nj.pos += count;
nj.size -= count;
nj.length -= count;
if (nj.size < 0) nj.error = NJ_SYNTAX_ERROR;
}
NJ_INLINE unsigned short njDecode16(const unsigned char *pos) {
return (pos[0] << 8) | pos[1];
}
static void njDecodeLength(void) {
if (nj.size < 2) njThrow(NJ_SYNTAX_ERROR);
nj.length = njDecode16(nj.pos);
if (nj.length > nj.size) njThrow(NJ_SYNTAX_ERROR);
njSkip(2);
}
NJ_INLINE void njSkipMarker(void) {
njDecodeLength();
njSkip(nj.length);
}
NJ_INLINE void njDecodeSOF(void) {
int i, ssxmax = 0, ssymax = 0;
nj_component_t* c;
njDecodeLength();
njCheckError();
if (nj.length < 9) njThrow(NJ_SYNTAX_ERROR);
if (nj.pos[0] != 8) njThrow(NJ_UNSUPPORTED);
nj.height = njDecode16(nj.pos+1);
nj.width = njDecode16(nj.pos+3);
if (!nj.width || !nj.height) njThrow(NJ_SYNTAX_ERROR);
nj.ncomp = nj.pos[5];
njSkip(6);
switch (nj.ncomp) {
case 1:
case 3:
break;
default:
njThrow(NJ_UNSUPPORTED);
}
if (nj.length < (nj.ncomp * 3)) njThrow(NJ_SYNTAX_ERROR);
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
c->cid = nj.pos[0];
if (!(c->ssx = nj.pos[1] >> 4)) njThrow(NJ_SYNTAX_ERROR);
if (c->ssx & (c->ssx - 1)) njThrow(NJ_UNSUPPORTED); // non-power of two
if (!(c->ssy = nj.pos[1] & 15)) njThrow(NJ_SYNTAX_ERROR);
if (c->ssy & (c->ssy - 1)) njThrow(NJ_UNSUPPORTED); // non-power of two
if ((c->qtsel = nj.pos[2]) & 0xFC) njThrow(NJ_SYNTAX_ERROR);
njSkip(3);
nj.qtused |= 1 << c->qtsel;
if (c->ssx > ssxmax) ssxmax = c->ssx;
if (c->ssy > ssymax) ssymax = c->ssy;
}
if (nj.ncomp == 1) {
c = nj.comp;
c->ssx = c->ssy = ssxmax = ssymax = 1;
}
nj.mbsizex = ssxmax << 3;
nj.mbsizey = ssymax << 3;
nj.mbwidth = (nj.width + nj.mbsizex - 1) / nj.mbsizex;
nj.mbheight = (nj.height + nj.mbsizey - 1) / nj.mbsizey;
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
c->width = (nj.width * c->ssx + ssxmax - 1) / ssxmax;
c->height = (nj.height * c->ssy + ssymax - 1) / ssymax;
c->stride = nj.mbwidth * c->ssx << 3;
if (((c->width < 3) && (c->ssx != ssxmax)) || ((c->height < 3) && (c->ssy != ssymax))) njThrow(NJ_UNSUPPORTED);
if (!(c->pixels = (unsigned char*) njAllocMem(c->stride * nj.mbheight * c->ssy << 3))) njThrow(NJ_OUT_OF_MEM);
}
if (nj.ncomp == 3) {
nj.rgb = (unsigned char*) njAllocMem(nj.width * nj.height * nj.ncomp);
if (!nj.rgb) njThrow(NJ_OUT_OF_MEM);
}
njSkip(nj.length);
}
NJ_INLINE void njDecodeDHT(void) {
int codelen, currcnt, remain, spread, i, j;
nj_vlc_code_t *vlc;
static unsigned char counts[16];
njDecodeLength();
njCheckError();
while (nj.length >= 17) {
i = nj.pos[0];
if (i & 0xEC) njThrow(NJ_SYNTAX_ERROR);
if (i & 0x02) njThrow(NJ_UNSUPPORTED);
i = (i | (i >> 3)) & 3; // combined DC/AC + tableid value
for (codelen = 1; codelen <= 16; ++codelen)
counts[codelen - 1] = nj.pos[codelen];
njSkip(17);
vlc = &nj.vlctab[i][0];
remain = spread = 65536;
for (codelen = 1; codelen <= 16; ++codelen) {
spread >>= 1;
currcnt = counts[codelen - 1];
if (!currcnt) continue;
if (nj.length < currcnt) njThrow(NJ_SYNTAX_ERROR);
remain -= currcnt << (16 - codelen);
if (remain < 0) njThrow(NJ_SYNTAX_ERROR);
for (i = 0; i < currcnt; ++i) {
register unsigned char code = nj.pos[i];
for (j = spread; j; --j) {
vlc->bits = (unsigned char) codelen;
vlc->code = code;
++vlc;
}
}
njSkip(currcnt);
}
while (remain--) {
vlc->bits = 0;
++vlc;
}
}
if (nj.length) njThrow(NJ_SYNTAX_ERROR);
}
NJ_INLINE void njDecodeDQT(void) {
int i;
unsigned char *t;
njDecodeLength();
njCheckError();
while (nj.length >= 65) {
i = nj.pos[0];
if (i & 0xFC) njThrow(NJ_SYNTAX_ERROR);
nj.qtavail |= 1 << i;
t = &nj.qtab[i][0];
for (i = 0; i < 64; ++i)
t[i] = nj.pos[i + 1];
njSkip(65);
}
if (nj.length) njThrow(NJ_SYNTAX_ERROR);
}
NJ_INLINE void njDecodeDRI(void) {
njDecodeLength();
njCheckError();
if (nj.length < 2) njThrow(NJ_SYNTAX_ERROR);
nj.rstinterval = njDecode16(nj.pos);
njSkip(nj.length);
}
static int njGetVLC(nj_vlc_code_t* vlc, unsigned char* code) {
int value = njShowBits(16);
int bits = vlc[value].bits;
if (!bits) { nj.error = NJ_SYNTAX_ERROR; return 0; }
njSkipBits(bits);
value = vlc[value].code;
if (code) *code = (unsigned char) value;
bits = value & 15;
if (!bits) return 0;
value = njGetBits(bits);
if (value < (1 << (bits - 1)))
value += ((-1) << bits) + 1;
return value;
}
NJ_INLINE void njDecodeBlock(nj_component_t* c, unsigned char* out) {
unsigned char code = 0;
int value, coef = 0;
njFillMem(nj.block, 0, sizeof(nj.block));
c->dcpred += njGetVLC(&nj.vlctab[c->dctabsel][0], NULL);
nj.block[0] = (c->dcpred) * nj.qtab[c->qtsel][0];
do {
value = njGetVLC(&nj.vlctab[c->actabsel][0], &code);
if (!code) break; // EOB
if (!(code & 0x0F) && (code != 0xF0)) njThrow(NJ_SYNTAX_ERROR);
coef += (code >> 4) + 1;
if (coef > 63) njThrow(NJ_SYNTAX_ERROR);
nj.block[(int) njZZ[coef]] = value * nj.qtab[c->qtsel][coef];
} while (coef < 63);
for (coef = 0; coef < 64; coef += 8)
njRowIDCT(&nj.block[coef]);
for (coef = 0; coef < 8; ++coef)
njColIDCT(&nj.block[coef], &out[coef], c->stride);
}
NJ_INLINE void njDecodeScan(void) {
int i, mbx, mby, sbx, sby;
int rstcount = nj.rstinterval, nextrst = 0;
nj_component_t* c;
njDecodeLength();
njCheckError();
if (nj.length < (4 + 2 * nj.ncomp)) njThrow(NJ_SYNTAX_ERROR);
if (nj.pos[0] != nj.ncomp) njThrow(NJ_UNSUPPORTED);
njSkip(1);
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
if (nj.pos[0] != c->cid) njThrow(NJ_SYNTAX_ERROR);
if (nj.pos[1] & 0xEE) njThrow(NJ_SYNTAX_ERROR);
c->dctabsel = nj.pos[1] >> 4;
c->actabsel = (nj.pos[1] & 1) | 2;
njSkip(2);
}
if (nj.pos[0] || (nj.pos[1] != 63) || nj.pos[2]) njThrow(NJ_UNSUPPORTED);
njSkip(nj.length);
for (mbx = mby = 0;;) {
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c)
for (sby = 0; sby < c->ssy; ++sby)
for (sbx = 0; sbx < c->ssx; ++sbx) {
njDecodeBlock(c, &c->pixels[((mby * c->ssy + sby) * c->stride + mbx * c->ssx + sbx) << 3]);
njCheckError();
}
if (++mbx >= nj.mbwidth) {
mbx = 0;
if (++mby >= nj.mbheight) break;
}
if (nj.rstinterval && !(--rstcount)) {
njByteAlign();
i = njGetBits(16);
if (((i & 0xFFF8) != 0xFFD0) || ((i & 7) != nextrst)) njThrow(NJ_SYNTAX_ERROR);
nextrst = (nextrst + 1) & 7;
rstcount = nj.rstinterval;
for (i = 0; i < 3; ++i)
nj.comp[i].dcpred = 0;
}
}
nj.error = __NJ_FINISHED;
}
#if NJ_CHROMA_FILTER
#define CF4A (-9)
#define CF4B (111)
#define CF4C (29)
#define CF4D (-3)
#define CF3A (28)
#define CF3B (109)
#define CF3C (-9)
#define CF3X (104)
#define CF3Y (27)
#define CF3Z (-3)
#define CF2A (139)
#define CF2B (-11)
#define CF(x) njClip(((x) + 64) >> 7)
NJ_INLINE void njUpsampleH(nj_component_t* c) {
const int xmax = c->width - 3;
unsigned char *out, *lin, *lout;
int x, y;
out = (unsigned char*) njAllocMem((c->width * c->height) << 1);
if (!out) njThrow(NJ_OUT_OF_MEM);
lin = c->pixels;
lout = out;
for (y = c->height; y; --y) {
lout[0] = CF(CF2A * lin[0] + CF2B * lin[1]);
lout[1] = CF(CF3X * lin[0] + CF3Y * lin[1] + CF3Z * lin[2]);
lout[2] = CF(CF3A * lin[0] + CF3B * lin[1] + CF3C * lin[2]);
for (x = 0; x < xmax; ++x) {
lout[(x << 1) + 3] = CF(CF4A * lin[x] + CF4B * lin[x + 1] + CF4C * lin[x + 2] + CF4D * lin[x + 3]);
lout[(x << 1) + 4] = CF(CF4D * lin[x] + CF4C * lin[x + 1] + CF4B * lin[x + 2] + CF4A * lin[x + 3]);
}
lin += c->stride;
lout += c->width << 1;
lout[-3] = CF(CF3A * lin[-1] + CF3B * lin[-2] + CF3C * lin[-3]);
lout[-2] = CF(CF3X * lin[-1] + CF3Y * lin[-2] + CF3Z * lin[-3]);
lout[-1] = CF(CF2A * lin[-1] + CF2B * lin[-2]);
}
c->width <<= 1;
c->stride = c->width;
njFreeMem((void*)c->pixels);
c->pixels = out;
}
NJ_INLINE void njUpsampleV(nj_component_t* c) {
const int w = c->width, s1 = c->stride, s2 = s1 + s1;
unsigned char *out, *cin, *cout;
int x, y;
out = (unsigned char*) njAllocMem((c->width * c->height) << 1);
if (!out) njThrow(NJ_OUT_OF_MEM);
for (x = 0; x < w; ++x) {
cin = &c->pixels[x];
cout = &out[x];
*cout = CF(CF2A * cin[0] + CF2B * cin[s1]); cout += w;
*cout = CF(CF3X * cin[0] + CF3Y * cin[s1] + CF3Z * cin[s2]); cout += w;
*cout = CF(CF3A * cin[0] + CF3B * cin[s1] + CF3C * cin[s2]); cout += w;
cin += s1;
for (y = c->height - 3; y; --y) {
*cout = CF(CF4A * cin[-s1] + CF4B * cin[0] + CF4C * cin[s1] + CF4D * cin[s2]); cout += w;
*cout = CF(CF4D * cin[-s1] + CF4C * cin[0] + CF4B * cin[s1] + CF4A * cin[s2]); cout += w;
cin += s1;
}
cin += s1;
*cout = CF(CF3A * cin[0] + CF3B * cin[-s1] + CF3C * cin[-s2]); cout += w;
*cout = CF(CF3X * cin[0] + CF3Y * cin[-s1] + CF3Z * cin[-s2]); cout += w;
*cout = CF(CF2A * cin[0] + CF2B * cin[-s1]);
}
c->height <<= 1;
c->stride = c->width;
njFreeMem((void*) c->pixels);
c->pixels = out;
}
#else
NJ_INLINE void njUpsample(nj_component_t* c) {
int x, y, xshift = 0, yshift = 0;
unsigned char *out, *lin, *lout;
while (c->width < nj.width) { c->width <<= 1; ++xshift; }
while (c->height < nj.height) { c->height <<= 1; ++yshift; }
out = (unsigned char*) njAllocMem(c->width * c->height);
if (!out) njThrow(NJ_OUT_OF_MEM);
lin = c->pixels;
lout = out;
for (y = 0; y < c->height; ++y) {
lin = &c->pixels[(y >> yshift) * c->stride];
for (x = 0; x < c->width; ++x)
lout[x] = lin[x >> xshift];
lout += c->width;
}
c->stride = c->width;
njFreeMem((void*) c->pixels);
c->pixels = out;
}
#endif
NJ_INLINE void njConvert(void) {
int i;
nj_component_t* c;
for (i = 0, c = nj.comp; i < nj.ncomp; ++i, ++c) {
#if NJ_CHROMA_FILTER
while ((c->width < nj.width) || (c->height < nj.height)) {
if (c->width < nj.width) njUpsampleH(c);
njCheckError();
if (c->height < nj.height) njUpsampleV(c);
njCheckError();
}
#else
if ((c->width < nj.width) || (c->height < nj.height))
njUpsample(c);
#endif
if ((c->width < nj.width) || (c->height < nj.height)) njThrow(NJ_INTERNAL_ERR);
}
if (nj.ncomp == 3) {
// convert to RGB
int x, yy;
unsigned char *prgb = nj.rgb;
const unsigned char *py = nj.comp[0].pixels;
const unsigned char *pcb = nj.comp[1].pixels;
const unsigned char *pcr = nj.comp[2].pixels;
for (yy = nj.height; yy; --yy) {
for (x = 0; x < nj.width; ++x) {
register int y = py[x] << 8;
register int cb = pcb[x] - 128;
register int cr = pcr[x] - 128;
*prgb++ = njClip((y + 359 * cr + 128) >> 8);
*prgb++ = njClip((y - 88 * cb - 183 * cr + 128) >> 8);
*prgb++ = njClip((y + 454 * cb + 128) >> 8);
}
py += nj.comp[0].stride;
pcb += nj.comp[1].stride;
pcr += nj.comp[2].stride;
}
} else if (nj.comp[0].width != nj.comp[0].stride) {
// grayscale -> only remove stride
unsigned char *pin = &nj.comp[0].pixels[nj.comp[0].stride];
unsigned char *pout = &nj.comp[0].pixels[nj.comp[0].width];
int y;
for (y = nj.comp[0].height - 1; y; --y) {
njCopyMem(pout, pin, nj.comp[0].width);
pin += nj.comp[0].stride;
pout += nj.comp[0].width;
}
nj.comp[0].stride = nj.comp[0].width;
}
}
void njInit(void) {
njFillMem(&nj, 0, sizeof(nj_context_t));
}
void njDone(void) {
int i;
for (i = 0; i < 3; ++i)
if (nj.comp[i].pixels) njFreeMem((void*) nj.comp[i].pixels);
if (nj.rgb) njFreeMem((void*) nj.rgb);
njInit();
}
nj_result_t njDecode(const void* jpeg, const int size) {
njDone();
nj.pos = (const unsigned char*) jpeg;
nj.size = size & 0x7FFFFFFF;
if (nj.size < 2) return NJ_NO_JPEG;
if ((nj.pos[0] ^ 0xFF) | (nj.pos[1] ^ 0xD8)) return NJ_NO_JPEG;
njSkip(2);
while (!nj.error) {
if ((nj.size < 2) || (nj.pos[0] != 0xFF)) return NJ_SYNTAX_ERROR;
njSkip(2);
switch (nj.pos[-1]) {
case 0xC0: njDecodeSOF(); break;
case 0xC4: njDecodeDHT(); break;
case 0xDB: njDecodeDQT(); break;
case 0xDD: njDecodeDRI(); break;
case 0xDA: njDecodeScan(); break;
case 0xFE: njSkipMarker(); break;
default:
if ((nj.pos[-1] & 0xF0) == 0xE0)
njSkipMarker();
else
return NJ_UNSUPPORTED;
}
}
if (nj.error != __NJ_FINISHED) return nj.error;
nj.error = NJ_OK;
njConvert();
return nj.error;
}
int njGetWidth(void) { return nj.width; }
int njGetHeight(void) { return nj.height; }
int njIsColor(void) { return (nj.ncomp != 1); }
unsigned char* njGetImage(void) { return (nj.ncomp == 1) ? nj.comp[0].pixels : nj.rgb; }
int njGetImageSize(void) { return nj.width * nj.height * nj.ncomp; }
#endif // _NJ_INCLUDE_HEADER_ONLY

View file

@ -39,7 +39,7 @@ void Scrollable::resetIndex(void)
mHid->page(0);
}
void Scrollable::push_back(color_t color, color_t colorMessage, const std::string& message)
void Scrollable::push_back(SDL_Color color, SDL_Color colorMessage, const std::string& message)
{
static const float spacing = mh / mVisibleEntries;
Clickable* cell = new Clickable(mx, my + (size() % mVisibleEntries)*spacing, mw, spacing, color, colorMessage, message, false);
@ -68,10 +68,10 @@ void Scrollable::draw(void)
const size_t sz = size() - baseIndex > mVisibleEntries ? mVisibleEntries : size() - baseIndex;
for (size_t i = baseIndex; i < baseIndex + sz; i++)
{
mCells.at(i)->draw(4);
mCells.at(i)->draw(20);
}
size_t blankRows = mVisibleEntries - sz;
size_t rowHeight = mh / mVisibleEntries;
rectangled(mx, my + sz * rowHeight, mw, rowHeight * blankRows, COLOR_GREY_DARKER);
SDLH_DrawRect(mx, my + sz * rowHeight, mw, rowHeight * blankRows, COLOR_GREY_DARKER);
}

View file

@ -27,14 +27,13 @@
#include "title.hpp"
static std::unordered_map<u128, std::vector<Title>> titles;
static std::unordered_map<u64, std::pair<u8*, u8*>> icons;
static std::unordered_map<u64, SDL_Texture*> icons;
void freeIcons(void)
{
for (auto& i : icons)
{
free(i.second.first);
free(i.second.second);
SDL_DestroyTexture(i.second);
}
}
@ -43,39 +42,9 @@ static void loadIcon(u64 id, NsApplicationControlData* nsacd, size_t iconsize)
auto it = icons.find(id);
if (it == icons.end())
{
uint8_t* imageptr = NULL;
size_t imagesize = 256*256*3;
njInit();
if (njDecode(nsacd->icon, iconsize) != NJ_OK)
{
njDone();
return;
}
if (njGetWidth() != 256 || njGetHeight() != 256 || (size_t)njGetImageSize() != imagesize || njIsColor() != 1)
{
njDone();
return;
}
imageptr = njGetImage();
if (imageptr == NULL)
{
njDone();
return;
}
u8* mIcon = (u8*)malloc(imagesize);
std::copy(imageptr, imageptr + imagesize, mIcon);
u8* mSmallIcon = (u8*)malloc(128*128*3);
downscaleRGBImg(mIcon, mSmallIcon, 256, 256, 128, 128);
icons.insert({id, std::make_pair(mIcon, mSmallIcon)});
imageptr = NULL;
njDone();
SDL_Texture* texture;
SDLH_LoadImage(&texture, nsacd->icon, iconsize);
icons.insert({id, texture});
}
}
@ -148,16 +117,10 @@ std::vector<std::string> Title::saves()
return mSaves;
}
u8* Title::icon(void)
SDL_Texture* Title::icon(void)
{
auto it = icons.find(mId);
return it != icons.end() ? it->second.first : NULL;
}
u8* Title::smallIcon(void)
{
auto it = icons.find(mId);
return it != icons.end() ? it->second.second : NULL;
return it != icons.end() ? it->second : NULL;
}
void Title::refreshDirectories(void)
@ -323,8 +286,8 @@ void refreshDirectories(u64 id)
}
}
u8* smallIcon(u128 uid, size_t i)
SDL_Texture* smallIcon(u128 uid, size_t i)
{
std::unordered_map<u128, std::vector<Title>>::iterator it = titles.find(uid);
return it != titles.end() ? it->second.at(i).smallIcon() : NULL;
return it != titles.end() ? it->second.at(i).icon() : NULL;
}

View file

@ -34,7 +34,6 @@ void servicesExit(void)
nsExit();
Account::exit();
Gui::exit();
fontExit();
plExit();
romfsExit();
}
@ -56,11 +55,6 @@ Result servicesInit(void)
return res;
}
if (!fontInitialize())
{
return -1;
}
if (R_FAILED(res = Account::init()))
{
return res;