mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-01-22 19:52:05 +01:00
Bump to 0.3.4, load color palette from resources
This commit is contained in:
parent
998d2e6349
commit
f8a21070f1
@ -6,7 +6,7 @@ set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain.cmake")
|
||||
project(
|
||||
cart_tool_private
|
||||
LANGUAGES C CXX ASM
|
||||
VERSION 0.3.3
|
||||
VERSION 0.3.4
|
||||
DESCRIPTION "Konami System 573 security cartridge tool"
|
||||
)
|
||||
|
||||
|
20
assets/app.palette.json
Normal file
20
assets/app.palette.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"default": "#808080",
|
||||
"shadow": "#000000",
|
||||
"backdrop": "#b0b0b0",
|
||||
"accent1": "#f0d050",
|
||||
"accent2": "#a08830",
|
||||
"window1": "#505050",
|
||||
"window2": "#242424",
|
||||
"window3": "#080808",
|
||||
"highlight1": "#c8b040",
|
||||
"highlight2": "#a08830",
|
||||
"progress1": "#48c010",
|
||||
"progress2": "#207800",
|
||||
"box1": "#000000",
|
||||
"box2": "#282828",
|
||||
"text1": "#707070",
|
||||
"text2": "#383838",
|
||||
"title": "#808080",
|
||||
"subtitle": "#a07840"
|
||||
}
|
@ -44,6 +44,11 @@
|
||||
"source": "assets/sounds/click.vag",
|
||||
"compress": null
|
||||
},
|
||||
{
|
||||
"type": "palette",
|
||||
"name": "assets/app.palette",
|
||||
"source": "assets/app.palette.json"
|
||||
},
|
||||
{
|
||||
"type": "strings",
|
||||
"name": "assets/app.strings",
|
||||
|
@ -180,10 +180,7 @@ void CartActionsScreen::update(ui::Context &ctx) {
|
||||
|
||||
if (ctx.buttons.pressed(ui::BTN_START))
|
||||
(this->*action.target)(ctx);
|
||||
if (
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
)
|
||||
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT))
|
||||
ctx.show(APP->_cartInfoScreen, true, true);
|
||||
}
|
||||
|
||||
@ -204,8 +201,7 @@ void QRCodeScreen::show(ui::Context &ctx, bool goBack) {
|
||||
void QRCodeScreen::update(ui::Context &ctx) {
|
||||
if (
|
||||
ctx.buttons.pressed(ui::BTN_START) ||
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
|
||||
)
|
||||
ctx.show(APP->_cartActionsScreen, true, true);
|
||||
}
|
||||
@ -235,8 +231,7 @@ void HexdumpScreen::update(ui::Context &ctx) {
|
||||
|
||||
if (
|
||||
ctx.buttons.pressed(ui::BTN_START) ||
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
|
||||
)
|
||||
ctx.show(APP->_cartActionsScreen, true, true);
|
||||
}
|
||||
@ -273,10 +268,7 @@ void ReflashGameScreen::update(ui::Context &ctx) {
|
||||
|
||||
APP->_selectedEntry = APP->_db.get(_activeItem);
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
} else if (
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
) {
|
||||
} else if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)) {
|
||||
ctx.show(APP->_cartActionsScreen, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -213,10 +213,7 @@ void CartInfoScreen::update(ui::Context &ctx) {
|
||||
else
|
||||
ctx.show(APP->_unlockKeyScreen, false, true);
|
||||
}
|
||||
if (
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
)
|
||||
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT))
|
||||
ctx.show(APP->_mainMenuScreen, true, true);
|
||||
}
|
||||
|
||||
@ -344,10 +341,7 @@ void UnlockKeyScreen::update(ui::Context &ctx) {
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
}
|
||||
}
|
||||
if (
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
) {
|
||||
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)) {
|
||||
ctx.show(APP->_cartInfoScreen, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -214,8 +214,7 @@ void AboutScreen::update(ui::Context &ctx) {
|
||||
|
||||
if (
|
||||
ctx.buttons.pressed(ui::BTN_START) ||
|
||||
(ctx.buttons.held(ui::BTN_LEFT) && ctx.buttons.pressed(ui::BTN_RIGHT)) ||
|
||||
(ctx.buttons.pressed(ui::BTN_LEFT) && ctx.buttons.held(ui::BTN_RIGHT))
|
||||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
|
||||
)
|
||||
ctx.show(APP->_mainMenuScreen, true, true);
|
||||
}
|
||||
|
31
src/gpu.cpp
31
src/gpu.cpp
@ -58,9 +58,9 @@ size_t upload(const RectWH &rect, const void *data, bool wait) {
|
||||
|
||||
void Context::_applyResolution(VideoMode mode, int shiftX, int shiftY) const {
|
||||
GP1HorizontalRes hres;
|
||||
GP1VerticalRes vres = (height > 256) ? GP1_VRES_512 : GP1_VRES_256;
|
||||
GP1VerticalRes vres;
|
||||
|
||||
int span;
|
||||
int span, is480;
|
||||
|
||||
if (width < 320) {
|
||||
hres = GP1_HRES_256;
|
||||
@ -79,10 +79,18 @@ void Context::_applyResolution(VideoMode mode, int shiftX, int shiftY) const {
|
||||
span = width * 4;
|
||||
}
|
||||
|
||||
int x = shiftX + 0x760, offsetX = span / 2;
|
||||
int y = shiftY + (mode ? 0xa3 : 0x88), offsetY = height / (vres ? 4 : 2);
|
||||
if (height <= 256) {
|
||||
vres = GP1_VRES_256;
|
||||
is480 = false;
|
||||
} else {
|
||||
vres = GP1_VRES_512;
|
||||
is480 = true;
|
||||
}
|
||||
|
||||
GPU_GP1 = gp1_fbMode(hres, vres, mode, height > 256, GP1_COLOR_16BPP);
|
||||
int x = shiftX + 0x760, offsetX = span / 2;
|
||||
int y = shiftY + (mode ? 0xa3 : 0x88), offsetY = height / (2 << is480);
|
||||
|
||||
GPU_GP1 = gp1_fbMode(hres, vres, mode, is480, GP1_COLOR_16BPP);
|
||||
GPU_GP1 = gp1_fbRangeH(x - offsetX, x + offsetX);
|
||||
GPU_GP1 = gp1_fbRangeV(y - offsetY, y + offsetY);
|
||||
}
|
||||
@ -117,8 +125,17 @@ void Context::setResolution(
|
||||
for (int fb = 1; fb >= 0; fb--) {
|
||||
auto &clip = _buffers[fb].clip;
|
||||
|
||||
clip.x1 = sideBySide ? (_width * fb) : 0;
|
||||
clip.y1 = sideBySide ? 0 : (_height * fb);
|
||||
if (_height > 256) {
|
||||
clip.x1 = 0;
|
||||
clip.y1 = 0;
|
||||
} else if (sideBySide) {
|
||||
clip.x1 = fb ? _width : 0;
|
||||
clip.y1 = 0;
|
||||
} else {
|
||||
clip.x1 = 0;
|
||||
clip.y1 = fb ? _height : 0;
|
||||
}
|
||||
|
||||
clip.x2 = clip.x1 + _width - 1;
|
||||
clip.y2 = clip.y1 + _height - 1;
|
||||
}
|
||||
|
15
src/main.cpp
15
src/main.cpp
@ -121,13 +121,11 @@ _fileInitDone:
|
||||
goto _resourceInitDone;
|
||||
}
|
||||
|
||||
if (fileProvider.fileExists(resPath)) {
|
||||
zipFile = fileProvider.openFile(resPath, file::READ);
|
||||
zipFile = fileProvider.openFile(resPath, file::READ);
|
||||
|
||||
if (zipFile) {
|
||||
if (resourceProvider.init(zipFile))
|
||||
goto _resourceInitDone;
|
||||
}
|
||||
if (zipFile) {
|
||||
if (resourceProvider.init(zipFile))
|
||||
goto _resourceInitDone;
|
||||
}
|
||||
|
||||
resourceProvider.init(_resources, _resourcesSize);
|
||||
@ -135,7 +133,7 @@ _fileInitDone:
|
||||
_resourceInitDone:
|
||||
io::clearWatchdog();
|
||||
|
||||
gpu::Context gpuCtx(GP1_MODE_NTSC, width, height, height > 256);
|
||||
gpu::Context gpuCtx(GP1_MODE_NTSC, width, height);
|
||||
ui::Context uiCtx(gpuCtx);
|
||||
|
||||
ui::TiledBackground background;
|
||||
@ -153,6 +151,9 @@ _resourceInitDone:
|
||||
!resourceProvider.loadStruct(
|
||||
uiCtx.font.metrics, "assets/textures/font.metrics"
|
||||
) ||
|
||||
!resourceProvider.loadStruct(
|
||||
uiCtx.colors, "assets/app.palette"
|
||||
) ||
|
||||
!resourceProvider.loadData(
|
||||
strings, "assets/app.strings"
|
||||
)
|
||||
|
@ -240,9 +240,9 @@ typedef enum {
|
||||
} GP1HorizontalRes;
|
||||
|
||||
typedef enum {
|
||||
GP1_VRES_BITMASK = 1 << 2,
|
||||
GP1_VRES_256 = 0 << 2,
|
||||
GP1_VRES_512 = 1 << 2
|
||||
GP1_VRES_BITMASK = 1,
|
||||
GP1_VRES_256 = 0,
|
||||
GP1_VRES_512 = 1
|
||||
} GP1VerticalRes;
|
||||
|
||||
typedef enum {
|
||||
|
@ -34,7 +34,7 @@
|
||||
typedef enum {
|
||||
DEV0_BASE = 0xbf000000,
|
||||
EXP1_BASE = 0xbf000000,
|
||||
CACHE_BASE = 0xbf800000,
|
||||
CACHE_BASE = 0x1f800000, // Cannot be accessed from KSEG1
|
||||
IO_BASE = 0xbf801000,
|
||||
EXP2_BASE = 0xbf802000,
|
||||
EXP3_BASE = 0xbfa00000,
|
||||
|
@ -125,6 +125,15 @@ void ButtonState::update(void) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonState::bothPressed(Button buttonA, Button buttonB) {
|
||||
if (pressed(buttonA) && held(buttonB))
|
||||
return true;
|
||||
if (held(buttonA) && pressed(buttonB))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UI context */
|
||||
|
||||
Context::Context(gpu::Context &gpuCtx, void *screenData)
|
||||
@ -205,7 +214,7 @@ void TiledBackground::draw(Context &ctx) const {
|
||||
rect.y = ctx.gpuCtx.height - (8 + gpu::FONT_LINE_HEIGHT);
|
||||
rect.w = width;
|
||||
rect.h = gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, COLOR_TEXT2);
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, ctx.colors[COLOR_TEXT2]);
|
||||
}
|
||||
|
||||
LogOverlay::LogOverlay(util::Logger &logger)
|
||||
@ -222,7 +231,7 @@ void LogOverlay::draw(Context &ctx) const {
|
||||
ctx, 0, offset - ctx.gpuCtx.height, ctx.gpuCtx.width,
|
||||
ctx.gpuCtx.height
|
||||
);
|
||||
ctx.gpuCtx.drawBackdrop(COLOR_BACKDROP, GP0_BLEND_SUBTRACT);
|
||||
ctx.gpuCtx.drawBackdrop(ctx.colors[COLOR_BACKDROP], GP0_BLEND_SUBTRACT);
|
||||
|
||||
int screenHeight = ctx.gpuCtx.height - SCREEN_MARGIN_Y * 2;
|
||||
int linesShown = screenHeight / gpu::FONT_LINE_HEIGHT;
|
||||
@ -235,7 +244,9 @@ void LogOverlay::draw(Context &ctx) const {
|
||||
rect.y2 = SCREEN_MARGIN_Y + gpu::FONT_LINE_HEIGHT;
|
||||
|
||||
for (int i = linesShown - 1; i >= 0; i--) {
|
||||
ctx.font.draw(ctx.gpuCtx, _logger.getLine(i), rect, COLOR_TEXT1);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, _logger.getLine(i), rect, ctx.colors[COLOR_TEXT1]
|
||||
);
|
||||
|
||||
rect.y1 = rect.y2;
|
||||
rect.y2 += gpu::FONT_LINE_HEIGHT;
|
||||
@ -312,20 +323,20 @@ void ModalScreen::draw(Context &ctx, bool active) const {
|
||||
|
||||
// Window
|
||||
ctx.gpuCtx.drawGradientRectD(
|
||||
0, 0, _width, windowHeight, COLOR_WINDOW1, COLOR_WINDOW2,
|
||||
COLOR_WINDOW3
|
||||
0, 0, _width, windowHeight, ctx.colors[COLOR_WINDOW1],
|
||||
ctx.colors[COLOR_WINDOW2], ctx.colors[COLOR_WINDOW3]
|
||||
);
|
||||
ctx.gpuCtx.drawGradientRectH(
|
||||
0, 0, _titleBarAnim.getValue(ctx.time), TITLE_BAR_HEIGHT,
|
||||
COLOR_ACCENT1, COLOR_ACCENT2
|
||||
ctx.colors[COLOR_ACCENT1], ctx.colors[COLOR_ACCENT2]
|
||||
);
|
||||
ctx.gpuCtx.drawRect(
|
||||
_width, SHADOW_OFFSET, SHADOW_OFFSET, windowHeight, COLOR_SHADOW,
|
||||
true
|
||||
_width, SHADOW_OFFSET, SHADOW_OFFSET, windowHeight,
|
||||
ctx.colors[COLOR_SHADOW], true
|
||||
);
|
||||
ctx.gpuCtx.drawRect(
|
||||
SHADOW_OFFSET, windowHeight, _width - SHADOW_OFFSET, SHADOW_OFFSET,
|
||||
COLOR_SHADOW, true
|
||||
ctx.colors[COLOR_SHADOW], true
|
||||
);
|
||||
|
||||
// Text
|
||||
@ -336,11 +347,11 @@ void ModalScreen::draw(Context &ctx, bool active) const {
|
||||
rect.x2 = _width - TITLE_BAR_PADDING;
|
||||
rect.y2 = TITLE_BAR_PADDING + gpu::FONT_LINE_HEIGHT;
|
||||
//rect.y2 = TITLE_BAR_HEIGHT - TITLE_BAR_PADDING;
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, COLOR_TITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, ctx.colors[COLOR_TITLE]);
|
||||
|
||||
rect.y1 = TITLE_BAR_HEIGHT + MODAL_PADDING;
|
||||
rect.y2 = _height - MODAL_PADDING;
|
||||
ctx.font.draw(ctx.gpuCtx, _body, rect, COLOR_TEXT1, true);
|
||||
ctx.font.draw(ctx.gpuCtx, _body, rect, ctx.colors[COLOR_TEXT1], true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,29 +11,30 @@ namespace ui {
|
||||
|
||||
/* Public constants */
|
||||
|
||||
enum Color : gpu::Color {
|
||||
COLOR_DEFAULT = 0x808080,
|
||||
COLOR_SHADOW = 0x000000,
|
||||
COLOR_BACKDROP = 0xb0b0b0,
|
||||
COLOR_ACCENT1 = 0x50d0f0,
|
||||
COLOR_ACCENT2 = 0x3088a0,
|
||||
COLOR_WINDOW1 = 0x505050,
|
||||
COLOR_WINDOW2 = 0x242424,
|
||||
COLOR_WINDOW3 = 0x080808,
|
||||
COLOR_HIGHLIGHT1 = 0x40b0c8,
|
||||
COLOR_HIGHLIGHT2 = 0x3088a0,
|
||||
COLOR_PROGRESS1 = 0x10c048,
|
||||
COLOR_PROGRESS2 = 0x007820,
|
||||
COLOR_BOX1 = 0x000000,
|
||||
COLOR_BOX2 = 0x282828,
|
||||
COLOR_TEXT1 = 0x707070,
|
||||
COLOR_TEXT2 = 0x383838,
|
||||
COLOR_TITLE = 0x808080,
|
||||
COLOR_SUBTITLE = 0x4078a0
|
||||
};
|
||||
|
||||
static constexpr int NUM_UI_COLORS = 18;
|
||||
static constexpr int NUM_UI_SOUNDS = 6;
|
||||
|
||||
enum Color {
|
||||
COLOR_DEFAULT = 0,
|
||||
COLOR_SHADOW = 1,
|
||||
COLOR_BACKDROP = 2,
|
||||
COLOR_ACCENT1 = 3,
|
||||
COLOR_ACCENT2 = 4,
|
||||
COLOR_WINDOW1 = 5,
|
||||
COLOR_WINDOW2 = 6,
|
||||
COLOR_WINDOW3 = 7,
|
||||
COLOR_HIGHLIGHT1 = 8,
|
||||
COLOR_HIGHLIGHT2 = 9,
|
||||
COLOR_PROGRESS1 = 10,
|
||||
COLOR_PROGRESS2 = 11,
|
||||
COLOR_BOX1 = 12,
|
||||
COLOR_BOX2 = 13,
|
||||
COLOR_TEXT1 = 14,
|
||||
COLOR_TEXT2 = 15,
|
||||
COLOR_TITLE = 16,
|
||||
COLOR_SUBTITLE = 17
|
||||
};
|
||||
|
||||
enum Sound {
|
||||
SOUND_STARTUP = 0,
|
||||
SOUND_ERROR = 1,
|
||||
@ -127,6 +128,7 @@ public:
|
||||
|
||||
ButtonState(void);
|
||||
void update(void);
|
||||
bool bothPressed(Button buttonA, Button buttonB);
|
||||
};
|
||||
|
||||
/* UI context */
|
||||
@ -144,6 +146,7 @@ public:
|
||||
gpu::Context &gpuCtx;
|
||||
|
||||
gpu::Font font;
|
||||
gpu::Color colors[NUM_UI_COLORS];
|
||||
spu::Sound sounds[NUM_UI_SOUNDS];
|
||||
|
||||
ButtonState buttons;
|
||||
|
@ -13,7 +13,7 @@ namespace ui {
|
||||
void PlaceholderScreen::draw(Context &ctx, bool active) const {
|
||||
_newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height);
|
||||
ctx.gpuCtx.drawRect(
|
||||
0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height, COLOR_WINDOW2
|
||||
0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height, ctx.colors[COLOR_WINDOW2]
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,26 +51,33 @@ void MessageBoxScreen::draw(Context &ctx, bool active) const {
|
||||
|
||||
if (_locked) {
|
||||
ctx.gpuCtx.drawRect(
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT, COLOR_SHADOW, true
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT,
|
||||
ctx.colors[COLOR_SHADOW], true
|
||||
);
|
||||
|
||||
ctx.font.draw(ctx.gpuCtx, _buttons[i], rect, COLOR_TEXT2);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, _buttons[i], rect, ctx.colors[COLOR_TEXT2]
|
||||
);
|
||||
} else {
|
||||
if (i == activeButton) {
|
||||
ctx.gpuCtx.drawRect(
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT, COLOR_HIGHLIGHT2
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT,
|
||||
ctx.colors[COLOR_HIGHLIGHT2]
|
||||
);
|
||||
ctx.gpuCtx.drawRect(
|
||||
buttonX, buttonY, _buttonAnim.getValue(ctx.time), BUTTON_HEIGHT,
|
||||
COLOR_HIGHLIGHT1
|
||||
buttonX, buttonY, _buttonAnim.getValue(ctx.time),
|
||||
BUTTON_HEIGHT, ctx.colors[COLOR_HIGHLIGHT1]
|
||||
);
|
||||
} else {
|
||||
ctx.gpuCtx.drawRect(
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT, COLOR_WINDOW3
|
||||
buttonX, buttonY, rect.w, BUTTON_HEIGHT,
|
||||
ctx.colors[COLOR_WINDOW3]
|
||||
);
|
||||
}
|
||||
|
||||
ctx.font.draw(ctx.gpuCtx, _buttons[i], rect, COLOR_TITLE);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, _buttons[i], rect, ctx.colors[COLOR_TITLE]
|
||||
);
|
||||
}
|
||||
|
||||
buttonX += rect.w + BUTTON_SPACING;
|
||||
@ -138,7 +145,7 @@ void HexEntryScreen::draw(Context &ctx, bool active) const {
|
||||
|
||||
// Text box
|
||||
ctx.gpuCtx.drawRect(
|
||||
MODAL_PADDING, boxY, boxWidth, BUTTON_HEIGHT, COLOR_BOX1
|
||||
MODAL_PADDING, boxY, boxWidth, BUTTON_HEIGHT, ctx.colors[COLOR_BOX1]
|
||||
);
|
||||
|
||||
char text[128];
|
||||
@ -154,8 +161,8 @@ void HexEntryScreen::draw(Context &ctx, bool active) const {
|
||||
if (_activeButton < _buttonIndexOffset)
|
||||
ctx.gpuCtx.drawGradientRectV(
|
||||
textOffset + _cursorAnim.getValue(ctx.time),
|
||||
boxY + BUTTON_HEIGHT / 2, digitWidth, BUTTON_HEIGHT / 2, COLOR_BOX1,
|
||||
COLOR_HIGHLIGHT1
|
||||
boxY + BUTTON_HEIGHT / 2, digitWidth, BUTTON_HEIGHT / 2,
|
||||
ctx.colors[COLOR_BOX1], ctx.colors[COLOR_HIGHLIGHT1]
|
||||
);
|
||||
|
||||
// Text
|
||||
@ -163,7 +170,7 @@ void HexEntryScreen::draw(Context &ctx, bool active) const {
|
||||
rect.y1 = boxY + BUTTON_PADDING;
|
||||
rect.x2 = _width - MODAL_PADDING;
|
||||
rect.y2 = boxY + BUTTON_PADDING + gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, COLOR_TITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, ctx.colors[COLOR_TITLE]);
|
||||
|
||||
// Highlighted digit
|
||||
if (_activeButton < _buttonIndexOffset) {
|
||||
@ -171,7 +178,7 @@ void HexEntryScreen::draw(Context &ctx, bool active) const {
|
||||
text[1] = 0;
|
||||
|
||||
rect.x1 = textOffset + _cursorAnim.getTargetValue();
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, COLOR_SUBTITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, text, rect, ctx.colors[COLOR_SUBTITLE]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,11 +269,11 @@ void ProgressScreen::draw(Context &ctx, bool active) const {
|
||||
_setBlendMode(ctx, GP0_BLEND_SEMITRANS, true);
|
||||
|
||||
ctx.gpuCtx.drawRect(
|
||||
barX, barY, fullBarWidth, PROGRESS_BAR_HEIGHT, COLOR_WINDOW3
|
||||
barX, barY, fullBarWidth, PROGRESS_BAR_HEIGHT, ctx.colors[COLOR_WINDOW3]
|
||||
);
|
||||
ctx.gpuCtx.drawGradientRectH(
|
||||
barX, barY, _progressBarAnim.getValue(ctx.time), PROGRESS_BAR_HEIGHT,
|
||||
COLOR_PROGRESS2, COLOR_PROGRESS1
|
||||
ctx.colors[COLOR_PROGRESS2], ctx.colors[COLOR_PROGRESS1]
|
||||
);
|
||||
}
|
||||
|
||||
@ -295,11 +302,11 @@ void TextScreen::draw(Context &ctx, bool active) const {
|
||||
rect.y1 = 0;
|
||||
rect.x2 = screenWidth;
|
||||
rect.y2 = gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, COLOR_TITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, ctx.colors[COLOR_TITLE]);
|
||||
|
||||
rect.y1 = screenHeight - SCREEN_PROMPT_HEIGHT_MIN;
|
||||
rect.y2 = screenHeight;
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, COLOR_TEXT1, true);
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, ctx.colors[COLOR_TEXT1], true);
|
||||
|
||||
int bodyOffset = gpu::FONT_LINE_HEIGHT + SCREEN_BLOCK_MARGIN;
|
||||
int bodyHeight = screenHeight -
|
||||
@ -319,7 +326,7 @@ void TextScreen::draw(Context &ctx, bool active) const {
|
||||
clip.y1 = 0;
|
||||
clip.x2 = screenWidth;
|
||||
clip.y2 = bodyHeight;
|
||||
ctx.font.draw(ctx.gpuCtx, _body, rect, clip, COLOR_TEXT1, true);
|
||||
ctx.font.draw(ctx.gpuCtx, _body, rect, clip, ctx.colors[COLOR_TEXT1], true);
|
||||
}
|
||||
|
||||
void TextScreen::update(Context &ctx) {
|
||||
@ -404,11 +411,11 @@ void ImageScreen::draw(Context &ctx, bool active) const {
|
||||
rect.y1 = SCREEN_MARGIN_Y;
|
||||
rect.x2 = ctx.gpuCtx.width - SCREEN_MARGIN_X;
|
||||
rect.y2 = SCREEN_MARGIN_Y + gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, COLOR_TITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, ctx.colors[COLOR_TITLE]);
|
||||
|
||||
rect.y1 = ctx.gpuCtx.height - (SCREEN_MARGIN_Y + SCREEN_PROMPT_HEIGHT);
|
||||
rect.y2 = ctx.gpuCtx.height - SCREEN_MARGIN_Y;
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, COLOR_TEXT1, true);
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, ctx.colors[COLOR_TEXT1], true);
|
||||
}
|
||||
|
||||
ListScreen::ListScreen(void)
|
||||
@ -435,21 +442,25 @@ void ListScreen::_drawItems(Context &ctx) const {
|
||||
if (i == _activeItem) {
|
||||
ctx.gpuCtx.drawRect(
|
||||
LIST_BOX_PADDING, itemY, itemWidth, itemHeight,
|
||||
COLOR_HIGHLIGHT2
|
||||
ctx.colors[COLOR_HIGHLIGHT2]
|
||||
);
|
||||
ctx.gpuCtx.drawRect(
|
||||
LIST_BOX_PADDING, itemY, _itemAnim.getValue(ctx.time),
|
||||
itemHeight, COLOR_HIGHLIGHT1
|
||||
itemHeight, ctx.colors[COLOR_HIGHLIGHT1]
|
||||
);
|
||||
|
||||
rect.y1 = itemY + LIST_ITEM_PADDING + gpu::FONT_LINE_HEIGHT;
|
||||
rect.y2 = rect.y1 + gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, _itemPrompt, rect, COLOR_SUBTITLE);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, _itemPrompt, rect, ctx.colors[COLOR_SUBTITLE]
|
||||
);
|
||||
}
|
||||
|
||||
rect.y1 = itemY + LIST_ITEM_PADDING;
|
||||
rect.y2 = rect.y1 + gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, _getItemName(ctx, i), rect, COLOR_TITLE);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, _getItemName(ctx, i), rect, ctx.colors[COLOR_TITLE]
|
||||
);
|
||||
}
|
||||
|
||||
itemY += itemHeight;
|
||||
@ -480,11 +491,11 @@ void ListScreen::draw(Context &ctx, bool active) const {
|
||||
rect.y1 = 0;
|
||||
rect.x2 = screenWidth;
|
||||
rect.y2 = gpu::FONT_LINE_HEIGHT;
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, COLOR_TITLE);
|
||||
ctx.font.draw(ctx.gpuCtx, _title, rect, ctx.colors[COLOR_TITLE]);
|
||||
|
||||
rect.y1 = screenHeight - SCREEN_PROMPT_HEIGHT;
|
||||
rect.y2 = screenHeight;
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, COLOR_TEXT1, true);
|
||||
ctx.font.draw(ctx.gpuCtx, _prompt, rect, ctx.colors[COLOR_TEXT1], true);
|
||||
|
||||
_newLayer(
|
||||
ctx, SCREEN_MARGIN_X,
|
||||
@ -494,9 +505,12 @@ void ListScreen::draw(Context &ctx, bool active) const {
|
||||
_setBlendMode(ctx, GP0_BLEND_SEMITRANS, true);
|
||||
|
||||
// List box
|
||||
ctx.gpuCtx.drawRect(0, 0, screenWidth / 2, listHeight, COLOR_BOX1);
|
||||
ctx.gpuCtx.drawRect(
|
||||
0, 0, screenWidth / 2, listHeight, ctx.colors[COLOR_BOX1]
|
||||
);
|
||||
ctx.gpuCtx.drawGradientRectH(
|
||||
screenWidth / 2, 0, screenWidth / 2, listHeight, COLOR_BOX1, COLOR_BOX2
|
||||
screenWidth / 2, 0, screenWidth / 2, listHeight, ctx.colors[COLOR_BOX1],
|
||||
ctx.colors[COLOR_BOX2]
|
||||
);
|
||||
|
||||
if (_listLength) {
|
||||
@ -511,11 +525,15 @@ void ListScreen::draw(Context &ctx, bool active) const {
|
||||
|
||||
if (_activeItem) {
|
||||
iconRect.y = LIST_BOX_PADDING;
|
||||
ctx.font.draw(ctx.gpuCtx, CH_UP_ARROW, iconRect, COLOR_TEXT1);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, CH_UP_ARROW, iconRect, ctx.colors[COLOR_TEXT1]
|
||||
);
|
||||
}
|
||||
if (_activeItem < (_listLength - 1)) {
|
||||
iconRect.y = listHeight - (gpu::FONT_LINE_HEIGHT + LIST_BOX_PADDING);
|
||||
ctx.font.draw(ctx.gpuCtx, CH_DOWN_ARROW, iconRect, COLOR_TEXT1);
|
||||
ctx.font.draw(
|
||||
ctx.gpuCtx, CH_DOWN_ARROW, iconRect, ctx.colors[COLOR_TEXT1]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__version__ = "0.3.0"
|
||||
__version__ = "0.3.4"
|
||||
__author__ = "spicyjpeg"
|
||||
|
||||
import json, re
|
||||
@ -10,7 +10,7 @@ from collections import defaultdict
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
from struct import Struct
|
||||
from typing import Any, ByteString, Generator, Mapping
|
||||
from typing import Any, ByteString, Generator, Mapping, Sequence
|
||||
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
||||
|
||||
import numpy
|
||||
@ -149,6 +149,50 @@ def generateFontMetrics(
|
||||
|
||||
return data
|
||||
|
||||
## Color palette generator
|
||||
|
||||
PALETTE_COLOR_REGEX: re.Pattern = re.compile(r"^#?([0-9A-Fa-f]{6})$")
|
||||
PALETTE_COLORS: Sequence[str] = (
|
||||
"default",
|
||||
"shadow",
|
||||
"backdrop",
|
||||
"accent1",
|
||||
"accent2",
|
||||
"window1",
|
||||
"window2",
|
||||
"window3",
|
||||
"highlight1",
|
||||
"highlight2",
|
||||
"progress1",
|
||||
"progress2",
|
||||
"box1",
|
||||
"box2",
|
||||
"text1",
|
||||
"text2",
|
||||
"title",
|
||||
"subtitle"
|
||||
)
|
||||
|
||||
PALETTE_ENTRY_STRUCT: Struct = Struct("< 3s x")
|
||||
|
||||
def generateColorPalette(palette: Mapping[str, str]) -> bytearray:
|
||||
data: bytearray = bytearray()
|
||||
|
||||
for entry in PALETTE_COLORS:
|
||||
color: str | None = palette.get(entry, None)
|
||||
|
||||
if color is None:
|
||||
raise ValueError(f"no entry found for {entry}")
|
||||
|
||||
matched: re.Match | None = PALETTE_COLOR_REGEX.match(color)
|
||||
|
||||
if matched is None:
|
||||
raise ValueError(f"invalid color value: {color}")
|
||||
|
||||
data.extend(PALETTE_ENTRY_STRUCT.pack(bytes.fromhex(matched.group(1))))
|
||||
|
||||
return data
|
||||
|
||||
## String table generator
|
||||
|
||||
TABLE_ENTRY_STRUCT: Struct = Struct("< I 2H")
|
||||
@ -353,7 +397,7 @@ def main():
|
||||
|
||||
if image.mode != "P":
|
||||
image = image.quantize(
|
||||
int(asset["quantize"]), dither = Image.Dither.NONE
|
||||
int(asset["quantize"]), dither = Image.NONE
|
||||
)
|
||||
|
||||
data: ByteString = generateIndexedTIM(image, ix, iy, cx, cy)
|
||||
@ -367,6 +411,15 @@ def main():
|
||||
|
||||
data: ByteString = generateFontMetrics(metrics)
|
||||
|
||||
case "palette":
|
||||
if "palette" in asset:
|
||||
palette: dict = asset["palette"]
|
||||
else:
|
||||
with open(sourceDir / asset["source"], "rt") as _file:
|
||||
palette: dict = json.load(_file)
|
||||
|
||||
data: ByteString = generateColorPalette(palette)
|
||||
|
||||
case "strings":
|
||||
if "strings" in asset:
|
||||
strings: dict = asset["strings"]
|
||||
@ -380,7 +433,8 @@ def main():
|
||||
raise KeyError(f"unsupported asset type '{_type}'")
|
||||
|
||||
gzipLevel: int | None = asset.get("compress", args.compress_level)
|
||||
disallow: bool = (gzipLevel is None) or args.no_compression
|
||||
disallow: bool = \
|
||||
(len(data) < 1024) or (gzipLevel is None) or args.no_compression
|
||||
|
||||
_zip.writestr(
|
||||
asset["name"], data,
|
||||
|
Loading…
x
Reference in New Issue
Block a user