mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-23 10:52:13 +00:00
Fatal: Implement basic background drawing.
This commit is contained in:
parent
caf9d11c8c
commit
9f6ff2ed6e
4 changed files with 159 additions and 4 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) { }
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue