Skip to content

Commit

Permalink
add inverted rotation screen mode (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
headshot2017 committed Jul 10, 2024
1 parent fa4e263 commit 2ec56be
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 48 deletions.
38 changes: 24 additions & 14 deletions arm9/src/nds_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ static u32 nudgeKey, launchKey, leftKey, rightKey, upKey;

void nds_input::Initialize()
{
if (!ndsfb_graphics::isRotated())
switch (ndsfb_graphics::getRotation())
{
nudgeKey = KEY_X;
launchKey = KEY_DOWN | KEY_B;
leftKey = KEY_LEFT | KEY_Y | KEY_L;
rightKey = KEY_RIGHT | KEY_A | KEY_R;
upKey = KEY_UP;
}
else
{
nudgeKey = KEY_L;
launchKey = KEY_LEFT;
leftKey = KEY_UP;
rightKey = KEY_DOWN;
upKey = KEY_RIGHT;
case 0: // default
nudgeKey = KEY_X;
launchKey = KEY_DOWN | KEY_B;
leftKey = KEY_LEFT | KEY_Y | KEY_L;
rightKey = KEY_RIGHT | KEY_A | KEY_R;
upKey = KEY_UP;
break;

case 1: // portrait (90° CCW)
nudgeKey = KEY_L;
launchKey = KEY_LEFT;
leftKey = KEY_UP;
rightKey = KEY_DOWN;
upKey = KEY_RIGHT;
break;

case 2: // inverted portrait (90° CW)
nudgeKey = KEY_R;
launchKey = KEY_A;
leftKey = KEY_B;
rightKey = KEY_X;
upKey = KEY_Y;
break;
}
}

Expand Down
177 changes: 145 additions & 32 deletions arm9/src/ndsfb_graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@

#include "bg_screenmode.h"
#include "bg_screenmode2.h"
#include "bg_screenmode3.h"

#include <array>
#include <cstdio>
#include <cstring>
#include <malloc.h>

static int tableStartPos = (0) * 256 + (256-1-16); // pinbal table start position for rotated screen mode
typedef void (*voidCallback)();

static int tableStartPos1 = (0) * 256 + (256-1-16); // pinball table start position for rotated screen mode
static int tableStartPos2 = (192-1-0) * 256 + (16); // pinball table start position for inv. rotated screen mode
static std::array<voidCallback, 3> rotationCb;


bool ndsfb_graphics::isConsoleInitialized = false;
bool ndsfb_graphics::rotated = false;
int ndsfb_graphics::rotation = 0;
int ndsfb_graphics::bgMainID = 0;
int ndsfb_graphics::bgSubID = 0;

Expand All @@ -30,6 +36,10 @@ void ndsfb_graphics::Initialize()

vramSetBankA(VRAM_A_LCD);
vramSetBankC(VRAM_C_SUB_BG);

rotationCb[0] = UpdateNormalMode;
rotationCb[1] = UpdateRotatedMode;
rotationCb[2] = UpdateInvRotatedMode;
}

void ndsfb_graphics::SwapBuffers()
Expand All @@ -43,17 +53,17 @@ void ndsfb_graphics::AskRotationMode()
vramSetBankC(VRAM_C_SUB_BG);
int bgID = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 0, 1);

const unsigned* bgTiles[] = {bg_screenmodeTiles, bg_screenmode2Tiles};
const u16* bgMap[] = {bg_screenmodeMap, bg_screenmode2Map};
const u16* bgPal[] = {bg_screenmodePal, bg_screenmode2Pal};
u32 bgTilesLen[] = {bg_screenmodeTilesLen, bg_screenmode2TilesLen};
const unsigned* bgTiles[] = {bg_screenmodeTiles, bg_screenmode2Tiles, bg_screenmode3Tiles};
const u16* bgMap[] = {bg_screenmodeMap, bg_screenmode2Map, bg_screenmode3Map};
const u16* bgPal[] = {bg_screenmodePal, bg_screenmode2Pal, bg_screenmode3Pal};
u32 bgTilesLen[] = {bg_screenmodeTilesLen, bg_screenmode2TilesLen, bg_screenmode3TilesLen};

bool selected = false;
int selection = 0;

while (!selected)
{
rotated = (selection == 1);
rotation = selection;

dmaCopy(bgTiles[selection], bgGetGfxPtr(bgID), bgTilesLen[selection]);
dmaCopy(bgMap[selection], bgGetMapPtr(bgID), 1536);
Expand All @@ -68,13 +78,13 @@ void ndsfb_graphics::AskRotationMode()
int key = keysDown();
if (key & KEY_RIGHT)
{
selection = (selection+1) % 2;
selection = (selection+1) % 3;
break;
}
if (key & KEY_LEFT)
{
selection = (selection-1) % 2;
if (selection < 0) selection = -selection;
selection--;
if (selection < 0) selection += 3;
break;
}
if (key & KEY_A)
Expand All @@ -90,7 +100,7 @@ void ndsfb_graphics::AskRotationMode()
void ndsfb_graphics::UpdateFull(bool sub)
{
// copy full bitmap to screen, depending on rotation mode
if (!rotated)
if (rotation == 0) // default rotation
{
// Full bitmap
for (int y = 0; y < 192; y++)
Expand All @@ -107,40 +117,84 @@ void ndsfb_graphics::UpdateFull(bool sub)
return;
}

// Rotated 90° CCW index: (x) * 256 + (256 - 1 - y)
if (rotation == 1) // rotated 90° CCW
{
// Rotated 90° CCW index: (x) * 256 + (256 - 1 - y)

// Table bitmap
int vwidth = 360;
if (!dsi::isDSi()) vwidth /= 2;
// Table bitmap
int vwidth = 360;
if (!dsi::isDSi()) vwidth /= 2;

for (int y = 0; y < 224; y++)
{
for (int x = 0; x < 360; x++)
for (int y = 0; y < 224; y++)
{
int px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(vwidth) ) );
int py = f32toint( mulf32( divf32( inttof32(y), inttof32(224) ), inttof32(render::vscreen->Height) ) );
for (int x = 0; x < 360; x++)
{
int px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(vwidth) ) );
int py = f32toint( mulf32( divf32( inttof32(y), inttof32(224) ), inttof32(render::vscreen->Height) ) );

Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;
int ind = tableStartPos + ((x-3) * 256 + (256-1-y));
VRAM_A[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;
int ind = tableStartPos1 + ((x-3) * 256 + (256-1-y));
VRAM_A[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}

if (!sub) return;

// Info bitmap
vwidth = 380;
if (!dsi::isDSi()) vwidth /= 2;
for (int y = 0; y < 256; y++)
{
for (int x = 328; x < 328+192; x++)
{
int px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(render::vscreen->Width-vwidth) ) );
int py = f32toint( mulf32( divf32( inttof32(y), inttof32(256) ), inttof32(render::vscreen->Height) ) );
u16* vram_ptr = bgGetGfxPtr(bgSubID);

Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;
int ind = (x-328) * 256 + (256-1-y);
vram_ptr[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}

return;
}

if (!sub) return;
// Inverted rotation (90° CW) index: (192 - 1 - x) * 256 + (y)

// Info bitmap
vwidth = 380;
int vwidth = 380;
if (!dsi::isDSi()) vwidth /= 2;

for (int y = 0; y < 256; y++)
{
for (int x = 328; x < 328+192; x++)
{
int px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(render::vscreen->Width-vwidth) ) );
int py = f32toint( mulf32( divf32( inttof32(y), inttof32(256) ), inttof32(render::vscreen->Height) ) );

Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;
int ind = (192-1-(x-328)) * 256 + (y);
VRAM_A[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}

if (!sub) return;

// Table bitmap
vwidth = 360;
if (!dsi::isDSi()) vwidth /= 2;

for (int y = 0; y < 224; y++)
{
for (int x = 0; x < 360; x++)
{
int px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(vwidth) ) );
int py = f32toint( mulf32( divf32( inttof32(y), inttof32(224) ), inttof32(render::vscreen->Height) ) );
u16* vram_ptr = bgGetGfxPtr(bgSubID);

Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;
int ind = (x-328) * 256 + (256-1-y);
int ind = tableStartPos2 - ((x-2) * 256) + (y+1);
vram_ptr[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}
Expand All @@ -149,10 +203,7 @@ void ndsfb_graphics::UpdateFull(bool sub)
void ndsfb_graphics::Update()
{
// update dirty bitmap regions, depending on rotation mode
if (!rotated)
UpdateNormalMode();
else
UpdateRotatedMode();
rotationCb[rotation]();

render::get_dirty_regions().clear();
}
Expand Down Expand Up @@ -254,10 +305,72 @@ void ndsfb_graphics::UpdateRotatedMode()
Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;

ind = (vram_ptr == VRAM_A) ?
tableStartPos + ((x-3) * 256 + (256-1-y)) :
tableStartPos1 + ((x-3) * 256 + (256-1-y)) :
(x-328) * 256 + (256-1-y);
vram_ptr[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}
}
}
}

void ndsfb_graphics::UpdateInvRotatedMode()
{
int vwidthTable = 360;
int vwidthInfo = 380;
int xPosCheck = 370;
if (!dsi::isDSi())
{
vwidthTable /= 2;
vwidthInfo /= 2;
xPosCheck /= 2;
}

for (u32 i=0; i<render::get_dirty_regions().size(); i++)
{
rectangle_type dirty = render::get_dirty_regions()[i];
u16* vram_ptr = (dirty.XPosition < xPosCheck) ? bgGetGfxPtr(bgSubID) : VRAM_A;

if (vram_ptr != VRAM_A)
{
dirty.XPosition = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.XPosition), inttof32(vwidthTable) ), inttof32(192) ) ) )-1;
dirty.YPosition = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.YPosition), inttof32(render::vscreen->Height) ), inttof32(224) ) ) )-1;
dirty.Width = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.Width), inttof32(vwidthTable) ), inttof32(192) ) ) )+1;
dirty.Height = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.Height), inttof32(render::vscreen->Height) ), inttof32(224) ) ) )+1;
}
else
{
dirty.XPosition = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.XPosition), inttof32(render::vscreen->Width-vwidthInfo) ), inttof32(192) ) ) )-1;
dirty.YPosition = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.YPosition), inttof32(render::vscreen->Height) ), inttof32(256) ) ) )-1;
dirty.Width = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.Width), inttof32(render::vscreen->Width-vwidthInfo) ), inttof32(192) ) ) )+1;
dirty.Height = f32toint( maths::ceilf32(mulf32( divf32( inttof32(dirty.Height), inttof32(render::vscreen->Height) ), inttof32(256) ) ) )+1;
}

for (int y = dirty.YPosition; y < dirty.YPosition+dirty.Height; y++)
{
for (int x = dirty.XPosition; x < dirty.XPosition+dirty.Width; x++)
{
int px, py, ind;

if (vram_ptr != VRAM_A)
{
px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(vwidthTable) ) );
py = f32toint( mulf32( divf32( inttof32(y), inttof32(224) ), inttof32(render::vscreen->Height) ) );
if (px >= vwidthTable) px = vwidthTable-1;
if (py >= render::vscreen->Height) py = render::vscreen->Height-1;
}
else
{
px = f32toint( mulf32( divf32( inttof32(x), inttof32(192) ), inttof32(render::vscreen->Width-vwidthInfo) ) );
py = f32toint( mulf32( divf32( inttof32(y), inttof32(256) ), inttof32(render::vscreen->Height) ) );
}

Rgba color = render::vscreen->BmpBufPtr1[py * render::vscreen->Width + px].rgba;

ind = (vram_ptr == VRAM_A) ?
(192-1-(x-328)) * 256 + (y) :
tableStartPos2 - ((x-2) * 256) + (y+1);
vram_ptr[ind] = (!color.Alpha) ? 0 : ARGB16(1, color.Blue>>3, color.Green>>3, color.Red>>3);
}
}
}
}
5 changes: 3 additions & 2 deletions arm9/src/ndsfb_graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class ndsfb_graphics
{
static bool isConsoleInitialized;
static bool rotated;
static int rotation;
static int bgMainID;
static int bgSubID;

Expand All @@ -14,7 +14,7 @@ class ndsfb_graphics
static void SwapBuffers();

static void AskRotationMode();
static bool isRotated() {return rotated;}
static int getRotation() {return rotation;}

static void UpdateFull(bool sub=true);
static void Update();
Expand All @@ -24,4 +24,5 @@ class ndsfb_graphics
private:
static void UpdateNormalMode();
static void UpdateRotatedMode();
static void UpdateInvRotatedMode();
};
2 changes: 2 additions & 0 deletions graphics/bg_screenmode3.grit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# 8-bit tiles
-g -gt -gB8 -m -p
Binary file added graphics/bg_screenmode3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2ec56be

Please sign in to comment.