[go: nahoru, domu]

Skip to content

Commit

Permalink
Fix drawing beyond ss edge in spr and sspr
Browse files Browse the repository at this point in the history
If coords over 127 (x) and 63(y) are passed, don't draw anything. Old
behavior if the x overflowed was to wrap to the next line.
  • Loading branch information
jtothebell committed Aug 9, 2022
1 parent 92546fc commit 5221164
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 14 deletions.
42 changes: 34 additions & 8 deletions source/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ void Graphics::copySpriteToScreen(
while (x < scr_w) {
int abs_spr_x = spr_x + (flip_x ? spr_w - (x + 1) : x);
int abs_spr_y = spr_y + (flip_y ? spr_h - (y + 1) : y);
if (!IS_VALID_SPR_IDX(abs_spr_x, abs_spr_y)){
++x;
continue;
}
uint8_t bothPix = spritebuffer[COMBINED_IDX(abs_spr_x, abs_spr_y)];

//uint8_t c = (BITMASK(0) & abs_spr_x)== 0
Expand Down Expand Up @@ -298,21 +302,28 @@ void Graphics::copyStretchSpriteToScreen(
if (hwState.colorBitmask == 0xff){
for (int y = 0; y < scr_h; y++) {
int sprY = ((spr_y + y * dy) >> 16);
uint8_t* spr = spritebuffer + (sprY & 0x7f) * 64;
if (sprY > 63) {
continue;
}
uint8_t* spr = spritebuffer + (sprY * 64);

if (skipStretchPx && prevSprY == sprY){
continue;
}

prevSprY = sprY;

if (!flip_x) {
for (int x = 0; x < scr_w; x++) {
int shiftedPixIndex = (spr_x + x * dx) >> 16;
if (shiftedPixIndex > 127) {
continue;
}
if (skipStretchPx && prevSprX == shiftedPixIndex){
continue;
}
prevSprX = shiftedPixIndex;
int preShiftedCombinedPixIndex = (shiftedPixIndex / 2) & 0x7f;
int preShiftedCombinedPixIndex = (shiftedPixIndex / 2);
uint8_t bothPix = spr[preShiftedCombinedPixIndex];

uint8_t c = shiftedPixIndex % 2 == 0
Expand All @@ -328,7 +339,11 @@ void Graphics::copyStretchSpriteToScreen(
} else {
for (int x = 0; x < scr_w; x++) {
int pixIndex = (spr_x + spr_w - (x + 1) * dx);
int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
int shiftedPixIndex = pixIndex >> 16;
if (shiftedPixIndex > 127) {
continue;
}
int combinedPixIdx = shiftedPixIndex / 2;
uint8_t bothPix = spr[combinedPixIdx];

uint8_t c = (pixIndex >> 16) % 2 == 0
Expand All @@ -346,15 +361,22 @@ void Graphics::copyStretchSpriteToScreen(
}
else {
for (int y = 0; y < scr_h; y++) {
uint8_t* spr = spritebuffer + (((spr_y + y * dy) >> 16) & 0x7f) * 64;
int sprY = ((spr_y + y * dy) >> 16);
if (sprY > 63) {
continue;
}
uint8_t* spr = spritebuffer + (sprY) * 64;

if (!flip_x) {
for (int x = 0; x < scr_w; x++) {
int pixIndex = (spr_x + x * dx);
int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
int shiftedPixIndex = (spr_x + x * dx) >> 16;
if (shiftedPixIndex > 127) {
continue;
}
int combinedPixIdx = (shiftedPixIndex / 2);
uint8_t bothPix = spr[combinedPixIdx];

uint8_t c = (pixIndex >> 16) % 2 == 0
uint8_t c = shiftedPixIndex % 2 == 0
? bothPix & 0x0f //just first 4 bits
: bothPix >> 4; //just last 4 bits

Expand All @@ -377,7 +399,11 @@ void Graphics::copyStretchSpriteToScreen(
} else {
for (int x = 0; x < scr_w; x++) {
int pixIndex = (spr_x + spr_w - (x + 1) * dx);
int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
int shiftedPixIndex = pixIndex >> 16;
if (shiftedPixIndex > 127) {
continue;
}
int combinedPixIdx = (shiftedPixIndex / 2);
uint8_t bothPix = spr[combinedPixIdx];

uint8_t c = (pixIndex >> 16) % 2 == 0
Expand Down
5 changes: 5 additions & 0 deletions source/nibblehelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ int getCombinedIdx(const int x, const int y){
//return (y << 6) | (x >> 1);
return COMBINED_IDX(x, y);
}

int isValidSprIdx(int x, int y){
return IS_VALID_SPR_IDX(x, y);
}

//try look up table to optimize?

void setPixelNibble(const int x, const int y, uint8_t value, uint8_t* targetBuffer) {
Expand Down
3 changes: 3 additions & 0 deletions source/nibblehelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//for 1 byte (8 bit) indexes, 128x64
//should be the equivalent of return y * 64 + (x / 2);
#define COMBINED_IDX(x, y) ((y) << 6) | ((x) >> 1)
#define IS_VALID_SPR_IDX(x, y) (y >= 0 && y < 64 && x >= 0 && x < 128)
//I think this should work if you cast the buffer to a uint32_t* pointer, but not tested
//for 4 byte (32 bit) inexes, 16x8
//should be the equivalent of return y * 16 + (x / 8);
Expand All @@ -15,6 +16,8 @@

int getCombinedIdx(int x, int y);

int isValidSprIdx(int x, int y);

void setPixelNibble(const int x, const int y, uint8_t value, uint8_t* targetBuffer);

uint8_t getPixelNibble(const int x, const int y, const uint8_t* targetBuffer);
3 changes: 2 additions & 1 deletion test/cartloadingtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ TEST_CASE("Loading and running carts") {


//TODO: build library of carts to test- set up compiler flag?
std::string _cartDirectory = "/Users/jon/p8carts/archive/carts";
//std::string _cartDirectory = "/Users/jon/p8carts/archive/carts";
std::string _cartDirectory = "";

DIR *dir;
struct dirent *ent;
Expand Down
45 changes: 45 additions & 0 deletions test/graphicstests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,28 @@ TEST_CASE("graphics class behaves as expected") {

checkPoints(graphics, expectedPoints);
}
SUBCASE("spr(...) draws doesn't repeat sprites if spritesheet width is exceeded") {
graphics->cls();
for(int y = 0; y < 128; y++) {
for(int x = 0; x < 128; x++) {
graphics->sset(x, y, (x+y)%15+1);
}
}

//sprite 6, but a width and height of 16 pixels goes off the edge.
//it should end instead of wrapping
graphics->spr(6, 0, 40, 16, 16, false, false);

std::vector<coloredPoint> expectedPoints = {
{81, 40, 0},
{81, 41, 0},
{81, 42, 0},
{81, 43, 0},
{81, 44, 0},
};

checkPoints(graphics, expectedPoints);
}
SUBCASE("sspr(...) draws to screen at odd numbered location") {
graphics->cls();

Expand Down Expand Up @@ -924,6 +946,29 @@ TEST_CASE("graphics class behaves as expected") {

checkPoints(graphics, expectedPoints);
}
SUBCASE("sspr(...) draws doesn't repeat sprites if spritesheet width is exceeded") {
graphics->cls();
for(int y = 0; y < 128; y++) {
for(int x = 0; x < 128; x++) {
graphics->sset(x, y, (x+y)%15+1);
}
}

//sprite 6, but a width and height of 16 pixels goes off the edge.
//it should end instead of wrapping
graphics->sspr(48, 0, 128, 32, 100, 50, 3, -4, false, false);
graphics->spr(6, 0, 40, 16, 16, false, false);

std::vector<coloredPoint> expectedPoints = {
{81, 40, 0},
{81, 41, 0},
{81, 42, 0},
{81, 43, 0},
{81, 44, 0},
};

checkPoints(graphics, expectedPoints);
}
/*//TODO: come back and make SSPR stretch exactly how pico 8 does
SUBCASE("sspr(...) draws unevenly stretched sprite") {
graphics->cls();
Expand Down
28 changes: 23 additions & 5 deletions test/nibblehelperstests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,37 @@
#include "../source/nibblehelpers.h"

TEST_CASE("Get Combined pixel index") {
SUBCASE("0,0") {
SUBCASE("getCombinedIdx 0,0") {
CHECK_EQ(getCombinedIdx(0, 0), 0);
}
SUBCASE("1,0") {
SUBCASE("getCombinedIdx 1,0") {
CHECK_EQ(getCombinedIdx(1, 0), 0);
}
SUBCASE("127, 127") {
SUBCASE("getCombinedIdx 127, 127") {
CHECK_EQ(getCombinedIdx(127, 127), 8191);
}
SUBCASE("126, 127") {
SUBCASE("getCombinedIdx 126, 127") {
CHECK_EQ(getCombinedIdx(127, 127), 8191);
}
SUBCASE("37, 99") {
SUBCASE("getCombinedIdx 37, 99") {
CHECK_EQ(getCombinedIdx(37, 99), 6354);
}
SUBCASE("isValidSprIdx 0,0 true") {
CHECK(isValidSprIdx(0, 0));
}
SUBCASE("isValidSprIdx 1,0 true") {
CHECK(isValidSprIdx(1, 0));
}
SUBCASE("isValidSprIdx 127, 127 true") {
CHECK(isValidSprIdx(127, 63));
}
SUBCASE("isValidSprIdx -1,0 false") {
CHECK_FALSE(isValidSprIdx(-1, 0));
}
SUBCASE("isValidSprIdx 128, 127 false") {
CHECK_FALSE(isValidSprIdx(128, 63));
}
SUBCASE("isValidSprIdx 127, 64 false") {
CHECK_FALSE(isValidSprIdx(127, 64));
}
}

0 comments on commit 5221164

Please sign in to comment.