Skip to content
Permalink
Browse files

utils: extend_sign bit size now include sign bit

  • Loading branch information
JaCzekanski committed Oct 4, 2019
1 parent 6747f45 commit bb19c3b74ba2a1b45205330c012eac824cd9be3c
Showing with 37 additions and 35 deletions.
  1. +10 −10 src/cpu/gte/opcodes.cpp
  2. +12 −12 src/device/gpu/gpu.cpp
  3. +2 −2 src/device/mdec/algorithm.cpp
  4. +6 −6 src/platform/windows/gui/debug/gpu.cpp
  5. +7 −5 src/utils/logic.h
@@ -18,30 +18,30 @@ int32_t GTE::clip(int32_t value, int32_t max, int32_t min, uint32_t flags) {

template <int bit_size>
void GTE::checkOverflow(int64_t value, uint32_t overflowBits, uint32_t underflowFlags) {
if (value >= (1LL << bit_size)) flag.reg |= overflowBits;
if (value < -(1LL << bit_size)) flag.reg |= underflowFlags;
if (value >= (1LL << (bit_size - 1))) flag.reg |= overflowBits;
if (value < -(1LL << (bit_size - 1))) flag.reg |= underflowFlags;
}

template <int i>
int64_t GTE::checkMacOverflowAndExtend(int64_t value) {
static_assert(i >= 1 && i <= 3, "Invalid mac for GTE::checkMacOverflowAndExtend");

if (i == 1) {
checkOverflow<43>(value, Flag::MAC1_OVERFLOW_POSITIVE, Flag::MAC1_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC1_OVERFLOW_POSITIVE, Flag::MAC1_OVERFLOW_NEGATIVE);
} else if (i == 2) {
checkOverflow<43>(value, Flag::MAC2_OVERFLOW_POSITIVE, Flag::MAC2_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC2_OVERFLOW_POSITIVE, Flag::MAC2_OVERFLOW_NEGATIVE);
} else if (i == 3) {
checkOverflow<43>(value, Flag::MAC3_OVERFLOW_POSITIVE, Flag::MAC3_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC3_OVERFLOW_POSITIVE, Flag::MAC3_OVERFLOW_NEGATIVE);
}

return extend_sign<43, int64_t>(value);
return extend_sign<44, int64_t>(value);
}

#define O(i, value) checkMacOverflowAndExtend<i>(value)

template <>
int64_t GTE::setMac<0>(int64_t value) {
checkOverflow<31>(value, Flag::MAC0_OVERFLOW_POSITIVE, Flag::MAC0_OVERFLOW_NEGATIVE);
checkOverflow<32>(value, Flag::MAC0_OVERFLOW_POSITIVE, Flag::MAC0_OVERFLOW_NEGATIVE);
mac[0] = value;
return value;
}
@@ -51,11 +51,11 @@ int64_t GTE::setMac(int64_t value) {
static_assert(i >= 1 && i <= 3, "Invalid mac for GTE::setMac");

if (i == 1) {
checkOverflow<43>(value, Flag::MAC1_OVERFLOW_POSITIVE, Flag::MAC1_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC1_OVERFLOW_POSITIVE, Flag::MAC1_OVERFLOW_NEGATIVE);
} else if (i == 2) {
checkOverflow<43>(value, Flag::MAC2_OVERFLOW_POSITIVE, Flag::MAC2_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC2_OVERFLOW_POSITIVE, Flag::MAC2_OVERFLOW_NEGATIVE);
} else if (i == 3) {
checkOverflow<43>(value, Flag::MAC3_OVERFLOW_POSITIVE, Flag::MAC3_OVERFLOW_NEGATIVE);
checkOverflow<44>(value, Flag::MAC3_OVERFLOW_POSITIVE, Flag::MAC3_OVERFLOW_NEGATIVE);
}

if (sf) value >>= 12;
@@ -257,8 +257,8 @@ void GPU::cmdPolygon(PolygonArgs arg) {
TextureInfo tex;

for (int i = 0; i < arg.getVertexCount(); i++) {
v[i].pos.x = extend_sign<10>(arguments[ptr] & 0xffff);
v[i].pos.y = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
v[i].pos.x = extend_sign<11>(arguments[ptr] & 0xffff);
v[i].pos.y = extend_sign<11>((arguments[ptr++] & 0xffff0000) >> 16);

if (!arg.isRawTexture && (!arg.gouroudShading || i == 0)) v[i].color.raw = arguments[0] & 0xffffff;
if (arg.isTextureMapped) {
@@ -310,8 +310,8 @@ void GPU::cmdLine(LineArgs arg) {
line.isSemiTransparent = arg.semiTransparency;
line.gouroudShading = arg.gouroudShading;

line.pos[0].x = extend_sign<10>(arguments[ptr] & 0xffff);
line.pos[0].y = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
line.pos[0].x = extend_sign<11>(arguments[ptr] & 0xffff);
line.pos[0].y = extend_sign<11>((arguments[ptr++] & 0xffff0000) >> 16);
line.color[0].raw = (arguments[0] & 0xffffff);

if (arg.gouroudShading) {
@@ -320,8 +320,8 @@ void GPU::cmdLine(LineArgs arg) {
line.color[1] = line.color[0];
}

line.pos[1].x = extend_sign<10>((arguments[ptr] & 0xffff));
line.pos[1].y = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
line.pos[1].x = extend_sign<11>((arguments[ptr] & 0xffff));
line.pos[1].y = extend_sign<11>((arguments[ptr++] & 0xffff0000) >> 16);

drawLine(line);

@@ -353,12 +353,12 @@ void GPU::cmdRectangle(RectangleArgs arg) {
int16_t h = arg.getSize();

if (arg.size == 0) {
w = extend_sign<10>(arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff);
h = extend_sign<10>((arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff0000) >> 16);
w = extend_sign<11>(arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff);
h = extend_sign<11>((arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff0000) >> 16);
}

int16_t x = extend_sign<10>(arguments[1] & 0xffff);
int16_t y = extend_sign<10>((arguments[1] & 0xffff0000) >> 16);
int16_t x = extend_sign<11>(arguments[1] & 0xffff);
int16_t y = extend_sign<11>((arguments[1] & 0xffff0000) >> 16);

primitive::Rect rect;
rect.pos = vec2(x, y);
@@ -630,8 +630,8 @@ void GPU::writeGP0(uint32_t data) {
drawingArea.bottom = (arguments[0] & 0xffc00) >> 10;
} else if (command == 0xe5) {
// Drawing offset
drawingOffsetX = extend_sign<10>(arguments[0] & 0x7ff);
drawingOffsetY = extend_sign<10>((arguments[0] >> 11) & 0x7ff);
drawingOffsetX = extend_sign<11>(arguments[0] & 0x7ff);
drawingOffsetY = extend_sign<11>((arguments[0] >> 11) & 0x7ff);
} else if (command == 0xe6) {
// Mask bit setting
gp0_e6._reg = arguments[0];
@@ -134,7 +134,7 @@ void MDEC::decodeBlock(std::array<int16_t, 64>& blk, std::vector<uint16_t>::iter

if (src == input.end()) return;
DCT dct = *src++;
int32_t current = extend_sign<9>(dct.dc);
int32_t current = extend_sign<10>(dct.dc);

int32_t value = current * table[0];

@@ -153,7 +153,7 @@ void MDEC::decodeBlock(std::array<int16_t, 64>& blk, std::vector<uint16_t>::iter

if (src == input.end()) break;
RLE rle = *src++;
current = extend_sign<9>(rle.ac);
current = extend_sign<10>(rle.ac);
n += rle.zeroes + 1;

value = (current * table[n] * dct.qFactor + 4) / 8;
@@ -126,8 +126,8 @@ void GPU::logWindow(System *sys) {
gpu::TextureInfo tex;

for (int i = 0; i < arg.getVertexCount(); i++) {
v[i].pos.x = extend_sign<10>(arguments[ptr] & 0xffff);
v[i].pos.y = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
v[i].pos.x = extend_sign<11>(arguments[ptr] & 0xffff);
v[i].pos.y = extend_sign<11>((arguments[ptr++] & 0xffff0000) >> 16);

if (!arg.isRawTexture && (!arg.gouroudShading || i == 0)) v[i].color.raw = arguments[0] & 0xffffff;
if (arg.isTextureMapped) {
@@ -208,12 +208,12 @@ void GPU::logWindow(System *sys) {
int16_t h = arg.getSize();

if (arg.size == 0) {
w = extend_sign<10>(arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff);
h = extend_sign<10>((arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff0000) >> 16);
w = extend_sign<11>(arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff);
h = extend_sign<11>((arguments[(arg.isTextureMapped ? 3 : 2)] & 0xffff0000) >> 16);
}

int16_t x = extend_sign<10>(arguments[1] & 0xffff);
int16_t y = extend_sign<10>((arguments[1] & 0xffff0000) >> 16);
int16_t x = extend_sign<11>(arguments[1] & 0xffff);
int16_t y = extend_sign<11>((arguments[1] & 0xffff0000) >> 16);

x += last_offset_x;
y += last_offset_y;
@@ -19,15 +19,17 @@ bool or_range(uint32_t v) {

/**
* Sign extend integer to bigger size.
* eg. 10 bit int to int16_t
* eg. 11 bit int to int16_t
* THPS games does not use upper bits resulting in invalid coords.
*
* bit_size - number of bits INCLUDING sign bit
*/
template <size_t bits, typename T = int16_t>
template <size_t bit_size, typename T = int16_t>
T extend_sign(uint64_t n) {
static_assert(bits > 0 && bits < 63, "bits out of range");
static_assert(bit_size > 0 && bit_size < 63, "bit_size out of range");

T mask = ((1LL << bits) - 1);
bool sign = (n & (1LL << bits)) != 0;
T mask = ((1LL << (bit_size - 1)) - 1);
bool sign = (n & (1LL << (bit_size - 1))) != 0;

T val = n & mask;
if (sign) val |= ~mask;

0 comments on commit bb19c3b

Please sign in to comment.
You can’t perform that action at this time.