Add splash screen and FAQ/troubleshooting page

This commit is contained in:
spicyjpeg 2024-07-12 20:14:35 +02:00
parent e9b389a82f
commit 57139b87b5
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
15 changed files with 218 additions and 99 deletions

View File

@ -1,6 +1,6 @@
<p align="center"> <p align="center">
<img alt="573in1 logo" src="doc/assets/logo.png" width="512" height="336" /> <img alt="573in1 logo" src="doc/assets/logo.png" width="512" />
</p> </p>
573in1 is a full-featured homebrew maintenance and troubleshooting tool, game 573in1 is a full-featured homebrew maintenance and troubleshooting tool, game
@ -43,17 +43,17 @@ instructions. **Reading the documentation before proceeding is highly**
## Screenshots ## Screenshots
<p align="center"> <p align="center">
<img alt="Main menu" src="doc/assets/mainMenu.png" width="320" height="240" /> <img alt="Main menu" src="doc/assets/mainMenu.png" width="320" />
<img alt="Cartridge information screen" src="doc/assets/cartInfo.png" <img alt="Cartridge information screen" src="doc/assets/cartInfo.png"
width="320" height="240" /> width="320" />
<img alt="Cartridge system ID editor" src="doc/assets/editSystemID.png" <img alt="Cartridge system ID editor" src="doc/assets/editSystemID.png"
width="320" height="240" /> width="320" />
<img alt="Storage device information screen" src="doc/assets/storageInfo.png" <img alt="Storage device information screen" src="doc/assets/storageInfo.png"
width="320" height="240" /> width="320" />
<img alt="IDE drive file picker" src="doc/assets/ideDrivePicker.png" <img alt="IDE drive file picker" src="doc/assets/ideDrivePicker.png"
width="320" height="240" /> width="320" />
<img alt="Monitor test pattern" src="doc/assets/monitorTestPattern.png" <img alt="Monitor test pattern" src="doc/assets/monitorTestPattern.png"
width="320" height="240" /> width="320" />
</p> </p>
## Project status ## Project status
@ -78,6 +78,8 @@ to lowest priority:
flash or a PCMCIA card, allowing the 573 BIOS to boot them automatically even flash or a PCMCIA card, allowing the 573 BIOS to boot them automatically even
with no CD-ROM drive present. with no CD-ROM drive present.
- Cleaning up the codebase, which currently contains *many* bad practices. - Cleaning up the codebase, which currently contains *many* bad practices.
- Adding support for JVS bus scanning and using JVS I/O boards in place of the
JAMMA button inputs.
- Adding UTF-8 support to the font and text rendering code. This is a rather low - Adding UTF-8 support to the font and text rendering code. This is a rather low
priority feature, but it would allow 573in1 to be translated to other priority feature, but it would allow 573in1 to be translated to other
languages. languages.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

67
doc/faq.md Normal file
View File

@ -0,0 +1,67 @@
# FAQ and troubleshooting
## Running 573in1
### I cannot get past the BIOS "hardware error" screen and into the main menu
- Make sure the disc image has been burned correctly (and not by e.g. dragging
the image file onto the disc). The disc should appear as `573IN1_xxxxx` and
contain a bunch of files named `README.TXT`, `PSX.EXE` and so on.
- Try using a different disc and/or another CD-ROM drive. A list of drives known
to be compatible with the stock System 573 BIOS can be found
[here](https://psx-spx.consoledev.net/konamisystem573/#known-working-replacement-drives).
- Ensure the BIOS is not reporting an actual hardware error with the 573. A
CD-ROM error will result in `CDR BAD` being displayed, while other errors will
be reported under the PCB location of the chip that failed (e.g. `18E BAD` for
a JVS MCU error). A list of BIOS errors can be found
[here](https://psx-spx.consoledev.net/konamisystem573/#boot-sequence).
### I get an error about a missing file or the CD-ROM being incorrect
- You have booted into the game currently installed on the 573's internal flash
rather than from the disc. Turn off DIP switch 4 (the rightmost one) and power
cycle the 573.
## Security cartridges
### My cartridge does not get recognized
- Make sure the cartridge's contacts are clean and the security cartridge
connector on the 573 has no bent pins and is not worn out, corroded or
otherwise damaged.
## IDE devices
### My IDE cable does not fit into the 573
- The 573 motherboard has pin 20 populated on the IDE connector, but most cables
use it as a keying pin (as per later versions of the IDE specification) and
thus have it blocked off. You may either try to find another cable or drill a
small hole in the cable's connector.
- You can also cut or desolder pin 20 on the 573, however this is not
recommended.
### My IDE drive, CF card or adapter does not show up
- Try using a different drive or adapter. Some CF cards, SD card adapters and
IDE-to-SATA converters are known to be problematic.
### My IDE drive, CF card or adapter shows up but is unreadable
- Ensure the drive supports LBA addressing. All CF cards, SD card adapters and
the vast majority of hard drives do, however older hard drives (typically ones
with a capacity lower than 8 GB or manufactured before the mid 1990s) may only
support CHS addressing.
- Ensure the drive is formatted with a single FAT12, FAT16, FAT32 or exFAT
partition. Other filesystems such as NTFS or ext4 are not supported.
## Miscellaneous
### How do I obtain more information about an error that happened?
- You may press the test button on your 573 or cabinet at any time to toggle the
log window, which will contain detailed information about errors.
- If an IDE hard drive is connected you can also take screenshots by holding
down the test button. Screenshots are saved to the `573in1` directory in the
root of the filesystem.

View File

@ -8,7 +8,7 @@
- TODO: ~~[Installing games and working with flash memory devices](flash.md)~~ - TODO: ~~[Installing games and working with flash memory devices](flash.md)~~
- TODO: ~~[Connecting an IDE hard drive](hdd.md)~~ - TODO: ~~[Connecting an IDE hard drive](hdd.md)~~
- TODO: ~~[Installing 573in1 as a BIOS ROM](bios.md)~~ - TODO: ~~[Installing 573in1 as a BIOS ROM](bios.md)~~
- TODO: ~~[FAQ and troubleshooting](faq.md)~~ - [FAQ and troubleshooting](faq.md)
## Development resources ## Development resources

View File

@ -326,11 +326,6 @@ void Context::drawGradientRectD(
cmd[7] = gp0_xy(x + width, y + height); cmd[7] = gp0_xy(x + width, y + height);
} }
void Context::drawBackdrop(Color color, BlendMode blendMode) {
setBlendMode(blendMode, true);
drawRect(0, 0, width, height, color, true);
}
/* Image class */ /* Image class */
void Image::initFromVRAMRect( void Image::initFromVRAMRect(

View File

@ -143,6 +143,14 @@ public:
); );
} }
inline void drawBackdrop(Color color) {
drawRect(0, 0, width, height, color);
}
inline void drawBackdrop(Color color, BlendMode blendMode) {
setBlendMode(blendMode, true);
drawRect(0, 0, width, height, color, true);
}
void setResolution( void setResolution(
VideoMode mode, int width, int height, bool forceInterlace = false, VideoMode mode, int width, int height, bool forceInterlace = false,
bool sideBySide = false bool sideBySide = false
@ -169,7 +177,6 @@ public:
int x, int y, int width, int height, Color top, Color middle, int x, int y, int width, int height, Color top, Color middle,
Color bottom, bool blend = false Color bottom, bool blend = false
); );
void drawBackdrop(Color color, BlendMode blendMode);
}; };
/* Image class */ /* Image class */

View File

@ -180,6 +180,8 @@ void FileIOManager::closeResourceFile(void) {
static constexpr size_t _WORKER_STACK_SIZE = 0x20000; static constexpr size_t _WORKER_STACK_SIZE = 0x20000;
static constexpr int _SPLASH_SCREEN_TIMEOUT = 5;
App::App(ui::Context &ctx) App::App(ui::Context &ctx)
#ifdef ENABLE_LOG_BUFFER #ifdef ENABLE_LOG_BUFFER
: _logOverlay(_logBuffer), : _logOverlay(_logBuffer),
@ -238,6 +240,7 @@ void App::_loadResources(void) {
res.loadTIM(_background.tile, "assets/textures/background.tim"); res.loadTIM(_background.tile, "assets/textures/background.tim");
res.loadTIM(_ctx.font.image, "assets/textures/font.tim"); res.loadTIM(_ctx.font.image, "assets/textures/font.tim");
res.loadStruct(_ctx.font.metrics, "assets/textures/font.metrics"); res.loadStruct(_ctx.font.metrics, "assets/textures/font.metrics");
res.loadTIM(_splashOverlay.image, "assets/textures/splash.tim");
res.loadStruct(_ctx.colors, "assets/app.palette"); res.loadStruct(_ctx.colors, "assets/app.palette");
res.loadData(_stringTable, "assets/app.strings"); res.loadData(_stringTable, "assets/app.strings");
@ -303,6 +306,36 @@ bool App::_takeScreenshot(void) {
return true; return true;
} }
void App::_updateOverlays(void) {
// Date and time overlay
static char dateString[24];
util::Date date;
io::getRTCTime(date);
date.toString(dateString);
_textOverlay.leftText = dateString;
// Splash screen overlay
int timeout = _ctx.gpuCtx.refreshRate * _SPLASH_SCREEN_TIMEOUT;
if ((_workerStatus.status == WORKER_DONE) || (_ctx.time > timeout))
_splashOverlay.hide(_ctx);
// Log overlay
if (
_ctx.buttons.released(ui::BTN_DEBUG) &&
!_ctx.buttons.longReleased(ui::BTN_DEBUG)
)
_logOverlay.toggle(_ctx);
// Screenshot overlay
if (_ctx.buttons.longPressed(ui::BTN_DEBUG)) {
if (_takeScreenshot())
_screenshotOverlay.animate(_ctx);
}
}
void App::_runWorker( void App::_runWorker(
bool (App::*func)(void), ui::Screen &next, bool goBack, bool playSound bool (App::*func)(void), ui::Screen &next, bool goBack, bool playSound
) { ) {
@ -361,40 +394,27 @@ void App::_interruptHandler(void) {
_fileIO.loadResourceFile(nullptr); _fileIO.loadResourceFile(nullptr);
_loadResources(); _loadResources();
char dateString[24]; _textOverlay.rightText = "v" VERSION_STRING;
_textOverlay.leftText = dateString;
_textOverlay.rightText = "v" VERSION_STRING;
_screenshotOverlay.callback = [](ui::Context &ctx) -> bool {
return APP->_takeScreenshot();
};
_ctx.backgrounds[0] = &_background; _ctx.backgrounds[0] = &_background;
_ctx.backgrounds[1] = &_textOverlay; _ctx.backgrounds[1] = &_textOverlay;
_ctx.overlays[0] = &_splashOverlay;
#ifdef ENABLE_LOG_BUFFER #ifdef ENABLE_LOG_BUFFER
_ctx.overlays[0] = &_logOverlay; _ctx.overlays[1] = &_logOverlay;
#endif #endif
_ctx.overlays[1] = &_screenshotOverlay; _ctx.overlays[2] = &_screenshotOverlay;
#ifdef ENABLE_AUTOBOOT
_runWorker(&App::_ideInitWorker, _warningScreen); _runWorker(&App::_ideInitWorker, _warningScreen);
#else
// If autoboot is disabled, show the warning screen before initializing the
// drives in order to give them enough time to spin up.
_runWorker(nullptr, _warningScreen);
#endif
_setupInterrupts(); _setupInterrupts();
_splashOverlay.show(_ctx);
_ctx.sounds[ui::SOUND_STARTUP].play(); _ctx.sounds[ui::SOUND_STARTUP].play();
for (;;) { for (;;) {
util::Date date;
io::getRTCTime(date);
date.toString(dateString);
_ctx.update(); _ctx.update();
_ctx.draw(); _updateOverlays();
_ctx.draw();
switchThreadImmediate(&_workerThread); switchThreadImmediate(&_workerThread);
_ctx.gpuCtx.flip(); _ctx.gpuCtx.flip();
} }

View File

@ -180,12 +180,13 @@ private:
ResolutionScreen _resolutionScreen; ResolutionScreen _resolutionScreen;
AboutScreen _aboutScreen; AboutScreen _aboutScreen;
ui::TiledBackground _background;
ui::TextOverlay _textOverlay;
ui::SplashOverlay _splashOverlay;
#ifdef ENABLE_LOG_BUFFER #ifdef ENABLE_LOG_BUFFER
util::LogBuffer _logBuffer; util::LogBuffer _logBuffer;
ui::LogOverlay _logOverlay; ui::LogOverlay _logOverlay;
#endif #endif
ui::TiledBackground _background;
ui::TextOverlay _textOverlay;
ui::ScreenshotOverlay _screenshotOverlay; ui::ScreenshotOverlay _screenshotOverlay;
ui::Context &_ctx; ui::Context &_ctx;
@ -214,6 +215,7 @@ private:
char *output, size_t length, const char *path, int maxIndex = 9999 char *output, size_t length, const char *path, int maxIndex = 9999
); );
bool _takeScreenshot(void); bool _takeScreenshot(void);
void _updateOverlays(void);
void _runWorker( void _runWorker(
bool (App::*func)(void), ui::Screen &next, bool goBack = false, bool (App::*func)(void), ui::Screen &next, bool goBack = false,
bool playSound = false bool playSound = false

View File

@ -239,6 +239,7 @@ void QRCodeScreen::show(ui::Context &ctx, bool goBack) {
_title = STR("QRCodeScreen.title"); _title = STR("QRCodeScreen.title");
_prompt = STR("QRCodeScreen.prompt"); _prompt = STR("QRCodeScreen.prompt");
_image = &_code;
_imageScale = _QR_CODE_SCALE; _imageScale = _QR_CODE_SCALE;
_imagePadding = _QR_CODE_SCALE * _QR_CODE_PADDING; _imagePadding = _QR_CODE_SCALE * _QR_CODE_PADDING;
_backdropColor = 0xffffff; _backdropColor = 0xffffff;

View File

@ -45,6 +45,9 @@ public:
}; };
class QRCodeScreen : public ui::ImageScreen { class QRCodeScreen : public ui::ImageScreen {
private:
gpu::Image _code;
public: public:
bool valid; bool valid;
@ -52,14 +55,14 @@ public:
: valid(false) {} : valid(false) {}
inline bool generateCode(const char *textInput) { inline bool generateCode(const char *textInput) {
if (!gpu::generateQRCode(_image, 960, 256, textInput)) if (!gpu::generateQRCode(_code, 960, 256, textInput))
return false; return false;
valid = true; valid = true;
return true; return true;
} }
inline bool generateCode(const uint8_t *binaryInput, size_t length) { inline bool generateCode(const uint8_t *binaryInput, size_t length) {
if (!gpu::generateQRCode(_image, 960, 256, binaryInput, length)) if (!gpu::generateQRCode(_code, 960, 256, binaryInput, length))
return false; return false;
valid = true; valid = true;

View File

@ -303,9 +303,7 @@ void TestPatternScreen::_drawTextOverlay(
void TestPatternScreen::draw(ui::Context &ctx, bool active) const { void TestPatternScreen::draw(ui::Context &ctx, bool active) const {
_newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height); _newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height);
ctx.gpuCtx.drawRect( ctx.gpuCtx.drawBackdrop(_BACKGROUND_COLOR);
0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height, _BACKGROUND_COLOR
);
} }
void TestPatternScreen::update(ui::Context &ctx) { void TestPatternScreen::update(ui::Context &ctx) {

View File

@ -234,11 +234,6 @@ void Context::draw(void) {
void Context::update(void) { void Context::update(void) {
buttons.update(); buttons.update();
for (auto layer : overlays) {
if (layer)
layer->update(*this);
}
auto screen = getCurrentScreen(); auto screen = getCurrentScreen();
if (screen) if (screen)
@ -294,22 +289,56 @@ void TextOverlay::draw(Context &ctx, bool active) const {
} }
} }
LogOverlay::LogOverlay(util::LogBuffer &buffer) void SplashOverlay::draw(Context &ctx, bool active) const {
: _buffer(buffer) { int brightness = _fadeAnim.getValue(ctx.time);
_slideAnim.setValue(0);
if (!brightness)
return;
// Backdrop
_newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height);
ctx.gpuCtx.drawBackdrop(
gp0_rgb(brightness, brightness, brightness), GP0_BLEND_SUBTRACT
);
if (brightness < 0xff)
return;
// Image
int x = (ctx.gpuCtx.width - image.width) / 2;
int y = (ctx.gpuCtx.height - image.height) / 2;
image.draw(ctx.gpuCtx, x, y);
}
void SplashOverlay::show(Context &ctx) {
if (!_fadeAnim.getTargetValue())
#if 0
_fadeAnim.setValue(ctx.time, 0, 0xff, SPEED_SLOWEST);
#else
_fadeAnim.setValue(0xff);
#endif
}
void SplashOverlay::hide(Context &ctx) {
if (_fadeAnim.getTargetValue())
_fadeAnim.setValue(ctx.time, 0xff, 0, SPEED_SLOWEST);
} }
void LogOverlay::draw(Context &ctx, bool active) const { void LogOverlay::draw(Context &ctx, bool active) const {
int offset = _slideAnim.getValue(ctx.time); int offset = _slideAnim.getValue(ctx.time);
if (!offset) if (!offset)
return; return;
// Backdrop
_newLayer( _newLayer(
ctx, 0, offset - ctx.gpuCtx.height, ctx.gpuCtx.width, ctx, 0, offset - ctx.gpuCtx.height, ctx.gpuCtx.width,
ctx.gpuCtx.height ctx.gpuCtx.height
); );
ctx.gpuCtx.drawBackdrop(ctx.colors[COLOR_BACKDROP], GP0_BLEND_SUBTRACT); ctx.gpuCtx.drawBackdrop(ctx.colors[COLOR_BACKDROP], GP0_BLEND_SUBTRACT);
// Text
int screenHeight = ctx.gpuCtx.height - SCREEN_MIN_MARGIN_Y * 2; int screenHeight = ctx.gpuCtx.height - SCREEN_MIN_MARGIN_Y * 2;
int linesShown = screenHeight / ctx.font.metrics.lineHeight; int linesShown = screenHeight / ctx.font.metrics.lineHeight;
@ -330,15 +359,11 @@ void LogOverlay::draw(Context &ctx, bool active) const {
} }
} }
void LogOverlay::update(Context &ctx) { void LogOverlay::toggle(Context &ctx) {
if ( bool shown = !_slideAnim.getTargetValue();
ctx.buttons.released(BTN_DEBUG) && !ctx.buttons.longReleased(BTN_DEBUG)
) {
bool shown = !_slideAnim.getTargetValue();
_slideAnim.setValue(ctx.time, shown ? ctx.gpuCtx.height : 0, SPEED_SLOW); _slideAnim.setValue(ctx.time, shown ? ctx.gpuCtx.height : 0, SPEED_SLOW);
ctx.sounds[shown ? SOUND_ENTER : SOUND_EXIT].play(); ctx.sounds[shown ? SOUND_ENTER : SOUND_EXIT].play();
}
} }
void ScreenshotOverlay::draw(Context &ctx, bool active) const { void ScreenshotOverlay::draw(Context &ctx, bool active) const {
@ -353,13 +378,9 @@ void ScreenshotOverlay::draw(Context &ctx, bool active) const {
); );
} }
void ScreenshotOverlay::update(Context &ctx) { void ScreenshotOverlay::animate(Context &ctx) {
if (ctx.buttons.longPressed(BTN_DEBUG)) { _flashAnim.setValue(ctx.time, 0xff, 0, SPEED_SLOW);
if (callback(ctx)) { ctx.sounds[ui::SOUND_SCREENSHOT].play();
_flashAnim.setValue(ctx.time, 0xff, 0, SPEED_SLOW);
ctx.sounds[ui::SOUND_SCREENSHOT].play();
}
}
} }
/* Base screen classes */ /* Base screen classes */
@ -381,15 +402,17 @@ void AnimatedScreen::hide(Context &ctx, bool goBack) {
} }
void BackdropScreen::show(Context &ctx, bool goBack) { void BackdropScreen::show(Context &ctx, bool goBack) {
_backdropAnim.setValue(ctx.time, 0, 0x50, SPEED_FAST); if (!_fadeAnim.getTargetValue())
_fadeAnim.setValue(ctx.time, 0, 0x50, SPEED_FAST);
} }
void BackdropScreen::hide(Context &ctx, bool goBack) { void BackdropScreen::hide(Context &ctx, bool goBack) {
_backdropAnim.setValue(ctx.time, 0x50, 0, SPEED_FAST); if (_fadeAnim.getTargetValue())
_fadeAnim.setValue(ctx.time, 0x50, 0, SPEED_FAST);
} }
void BackdropScreen::draw(Context &ctx, bool active) const { void BackdropScreen::draw(Context &ctx, bool active) const {
int brightness = _backdropAnim.getValue(ctx.time); int brightness = _fadeAnim.getValue(ctx.time);
if (!brightness) if (!brightness)
return; return;

View File

@ -64,7 +64,8 @@ enum Sound {
enum AnimationSpeed { enum AnimationSpeed {
SPEED_FASTEST = 10, SPEED_FASTEST = 10,
SPEED_FAST = 15, SPEED_FAST = 15,
SPEED_SLOW = 20 SPEED_SLOW = 20,
SPEED_SLOWEST = 30
}; };
static constexpr int SCREEN_MARGIN_X = 16; static constexpr int SCREEN_MARGIN_X = 16;
@ -214,7 +215,6 @@ protected:
public: public:
virtual void draw(Context &ctx, bool active = true) const {} virtual void draw(Context &ctx, bool active = true) const {}
virtual void update(Context &ctx) {}
}; };
class TiledBackground : public Layer { class TiledBackground : public Layer {
@ -234,15 +234,29 @@ public:
void draw(Context &ctx, bool active = true) const; void draw(Context &ctx, bool active = true) const;
}; };
class SplashOverlay : public Layer {
private:
util::Tween<int, util::QuadOutEasing> _fadeAnim;
public:
gpu::Image image;
void draw(Context &ctx, bool active = true) const;
void show(Context &ctx);
void hide(Context &ctx);
};
class LogOverlay : public Layer { class LogOverlay : public Layer {
private: private:
util::LogBuffer &_buffer; util::LogBuffer &_buffer;
util::Tween<int, util::QuadOutEasing> _slideAnim; util::Tween<int, util::QuadOutEasing> _slideAnim;
public: public:
LogOverlay(util::LogBuffer &buffer); inline LogOverlay(util::LogBuffer &buffer)
: _buffer(buffer) {}
void draw(Context &ctx, bool active = true) const; void draw(Context &ctx, bool active = true) const;
void update(Context &ctx); void toggle(Context &ctx);
}; };
class ScreenshotOverlay : public Layer { class ScreenshotOverlay : public Layer {
@ -250,13 +264,8 @@ private:
util::Tween<int, util::QuadOutEasing> _flashAnim; util::Tween<int, util::QuadOutEasing> _flashAnim;
public: public:
bool (*callback)(ui::Context &ctx);
inline ScreenshotOverlay(void)
: callback(nullptr) {}
void draw(Context &ctx, bool active = true) const; void draw(Context &ctx, bool active = true) const;
void update(Context &ctx); void animate(Context &ctx);
}; };
/* Base screen classes */ /* Base screen classes */
@ -286,7 +295,7 @@ public:
class BackdropScreen : public Screen { class BackdropScreen : public Screen {
private: private:
util::Tween<int, util::LinearEasing> _backdropAnim; util::Tween<int, util::LinearEasing> _fadeAnim;
public: public:
virtual void show(Context &ctx, bool goBack = false); virtual void show(Context &ctx, bool goBack = false);

View File

@ -24,13 +24,6 @@ namespace ui {
/* Common screens */ /* Common screens */
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, ctx.colors[COLOR_WINDOW2]
);
}
TextScreen::TextScreen(void) TextScreen::TextScreen(void)
: _title(nullptr), _body(nullptr), _prompt(nullptr) {} : _title(nullptr), _body(nullptr), _prompt(nullptr) {}
@ -128,16 +121,17 @@ void TextScreen::update(Context &ctx) {
} }
ImageScreen::ImageScreen(void) ImageScreen::ImageScreen(void)
: _imageScale(1), _imagePadding(0), _title(nullptr), _prompt(nullptr) {} : _image(nullptr), _imageScale(1), _imagePadding(0), _title(nullptr),
_prompt(nullptr) {}
void ImageScreen::draw(Context &ctx, bool active) const { void ImageScreen::draw(Context &ctx, bool active) const {
_newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height); _newLayer(ctx, 0, 0, ctx.gpuCtx.width, ctx.gpuCtx.height);
if (_image.width && _image.height) { if (_image) {
int x = ctx.gpuCtx.width / 2; int x = ctx.gpuCtx.width / 2;
int y = ctx.gpuCtx.height / 2; int y = ctx.gpuCtx.height / 2;
int width = _image.width * _imageScale / 2; int width = _image->width * _imageScale / 2;
int height = _image.height * _imageScale / 2; int height = _image->height * _imageScale / 2;
if (_prompt) if (_prompt)
y -= (SCREEN_PROMPT_HEIGHT - ctx.font.metrics.lineHeight) / 2; y -= (SCREEN_PROMPT_HEIGHT - ctx.font.metrics.lineHeight) / 2;
@ -153,9 +147,12 @@ void ImageScreen::draw(Context &ctx, bool active) const {
} }
// Image // Image
_image.drawScaled( if (_imageScale > 1)
ctx.gpuCtx, x - width - 1, y - height - 1, width * 2, height * 2 _image->drawScaled(
); ctx.gpuCtx, x - width - 1, y - height - 1, width * 2, height * 2
);
else
_image->draw(ctx.gpuCtx, x - width, y - height);
} }
// Text // Text

View File

@ -25,11 +25,6 @@ namespace ui {
/* Common screens */ /* Common screens */
class PlaceholderScreen : public AnimatedScreen {
public:
void draw(Context &ctx, bool active) const;
};
class TextScreen : public AnimatedScreen { class TextScreen : public AnimatedScreen {
private: private:
util::Tween<int, util::QuadOutEasing> _scrollAnim; util::Tween<int, util::QuadOutEasing> _scrollAnim;
@ -54,7 +49,7 @@ public:
class ImageScreen : public AnimatedScreen { class ImageScreen : public AnimatedScreen {
protected: protected:
gpu::Image _image; gpu::Image *_image;
int _imageScale, _imagePadding; int _imageScale, _imagePadding;
gpu::Color _backdropColor; gpu::Color _backdropColor;