Fatal: Implement basic background drawing.

This commit is contained in:
Michael Scire 2018-11-12 22:26:13 -08:00
parent caf9d11c8c
commit 9f6ff2ed6e
4 changed files with 159 additions and 4 deletions

View file

@ -39,7 +39,7 @@ extern "C" {
char nx_inner_heap[INNER_HEAP_SIZE]; char nx_inner_heap[INNER_HEAP_SIZE];
u32 __nx_nv_transfermem_size = 0x40000; u32 __nx_nv_transfermem_size = 0x40000;
ViServiceType __nx_gfx_vi_service_type = ViServiceType_Manager; ViLayerFlags __nx_vi_stray_layer_flags = (ViLayerFlags)0;
void __libnx_initheap(void); void __libnx_initheap(void);
void __appInit(void); void __appInit(void);

View file

@ -18,10 +18,157 @@
#include "fatal_task_screen.hpp" #include "fatal_task_screen.hpp"
#include "fatal_config.hpp" #include "fatal_config.hpp"
Result ShowFatalTask::SetupDisplayInternal() {
Result rc;
ViDisplay display;
/* Try to open the display. */
if (R_FAILED((rc = viOpenDisplay("Internal", &display)))) {
if (rc == 0xE72) {
return 0;
} else {
return rc;
}
}
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&display); };
/* Turn on the screen. */
if (R_FAILED((rc = viSetDisplayPowerState(&display, ViPowerState_On)))) {
return rc;
}
/* Set alpha to 1.0f. */
if (R_FAILED((rc = viSetDisplayAlpha(&display, 1.0f)))) {
return rc;
}
return rc;
}
Result ShowFatalTask::SetupDisplayExternal() {
Result rc;
ViDisplay display;
/* Try to open the display. */
if (R_FAILED((rc = viOpenDisplay("External", &display)))) {
if (rc == 0xE72) {
return 0;
} else {
return rc;
}
}
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&display); };
/* Set alpha to 1.0f. */
if (R_FAILED((rc = viSetDisplayAlpha(&display, 1.0f)))) {
return rc;
}
return rc;
}
Result ShowFatalTask::PrepareScreenForDrawing() {
Result rc = 0;
/* Connect to vi. */
if (R_FAILED((rc = viInitialize(ViServiceType_Manager)))) {
return rc;
}
/* Close other content. */
viSetContentVisibility(false);
/* Setup the two displays. */
if (R_FAILED((rc = SetupDisplayInternal())) || R_FAILED((rc = SetupDisplayExternal()))) {
return rc;
}
/* Open the default display. */
if (R_FAILED((rc = viOpenDefaultDisplay(&this->display)))) {
return rc;
}
/* Reset the display magnification to its default value. */
u32 display_width, display_height;
if (R_FAILED((rc = viGetDisplayLogicalResolution(&this->display, &display_width, &display_height)))) {
return rc;
}
if (R_FAILED((rc = viSetDisplayMagnification(&this->display, 0, 0, display_width, display_height)))) {
return rc;
}
/* Create layer to draw to. */
if (R_FAILED((rc = viCreateLayer(&this->display, &this->layer)))) {
return rc;
}
/* Setup the layer. */
{
/* Display a layer of 1280 x 720 at 1.5x magnification */
/* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */
/* We use a single 1280x720 tiled RGB565 buffer. */
constexpr u32 raw_width = 1280;
constexpr u32 raw_height = 720;
constexpr u32 layer_width = ((raw_width) * 3) / 2;
constexpr u32 layer_height = ((raw_height) * 3) / 2;
const float layer_x = static_cast<float>((display_width - layer_width) / 2);
const float layer_y = static_cast<float>((display_height - layer_height) / 2);
u64 layer_z;
if (R_FAILED((rc = viSetLayerSize(&this->layer, layer_width, layer_height)))) {
return rc;
}
/* Set the layer's Z at display maximum, to be above everything else .*/
/* NOTE: Fatal hardcodes 100 here. */
if (R_SUCCEEDED((rc = viGetDisplayMaximumZ(&this->display, &layer_z)))) {
if (R_FAILED((rc = viSetLayerZ(&this->layer, layer_z)))) {
return rc;
}
}
/* Center the layer in the screen. */
if (R_FAILED((rc = viSetLayerPosition(&this->layer, layer_x, layer_y)))) {
return rc;
}
/* Create framebuffer. */
if (R_FAILED(rc = nwindowCreateFromLayer(&this->win, &this->layer))) {
return rc;
}
if (R_FAILED(rc = framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1))) {
return rc;
}
}
return rc;
}
Result ShowFatalTask::ShowFatal() { Result ShowFatalTask::ShowFatal() {
Result rc = 0; Result rc = 0;
/* TODO: Get graphics to work, draw fatal screen. */ if (R_FAILED((rc = PrepareScreenForDrawing()))) {
*(volatile u32 *)(0xCAFEBABE) = rc;
return rc;
}
/* Dequeue a buffer. */
u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL));
if (tiled_buf == nullptr) {
return FatalResult_NullGfxBuffer;
}
/* Draw a background. */
for (size_t i = 0; i < this->fb.fb_size / sizeof(*tiled_buf); i++) {
tiled_buf[i] = 0x39C9;
}
/* TODO: Actually draw meaningful shit here. */
/* Enqueue the buffer. */
framebufferEnd(&fb);
return rc; return rc;
} }

View file

@ -22,7 +22,14 @@
class ShowFatalTask : public IFatalTask { class ShowFatalTask : public IFatalTask {
private: private:
Event *battery_event; Event *battery_event;
ViDisplay display;
ViLayer layer;
NWindow win;
Framebuffer fb;
private: private:
Result SetupDisplayInternal();
Result SetupDisplayExternal();
Result PrepareScreenForDrawing();
Result ShowFatal(); Result ShowFatal();
public: public:
ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { } ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { }

View file

@ -19,6 +19,7 @@
#include <stratosphere.hpp> #include <stratosphere.hpp>
enum FatalResult : Result { enum FatalResult : Result {
FatalResult_NullGfxBuffer = 0x4A3,
FatalResult_AlreadyThrown = 0x6A3, FatalResult_AlreadyThrown = 0x6A3,
FatalResult_TooManyEvents = 0x8A3, FatalResult_TooManyEvents = 0x8A3,
FatalResult_InRepairWithoutVolHeld = 0xAA3, FatalResult_InRepairWithoutVolHeld = 0xAA3,