mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
197 lines
6.6 KiB
C
197 lines
6.6 KiB
C
#include "ws_repeat_rect.h"
|
|
|
|
#ifdef NDEBUG
|
|
#undef NDEBUG
|
|
#endif
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
static void assert_span(const WsRepeatSpan *span, int32_t x, int32_t u,
|
|
int32_t w) {
|
|
assert(span->x == x);
|
|
assert(span->u == u);
|
|
assert(span->w == w);
|
|
}
|
|
|
|
static int emit_spans(int32_t x, int32_t u, int32_t w, int32_t period,
|
|
int32_t left, int32_t width, int32_t margin,
|
|
WsRepeatSpan *out, int capacity) {
|
|
for (int i = 0; i < capacity; i++) {
|
|
out[i].x = 0x12345678;
|
|
out[i].u = 0x12345678;
|
|
out[i].w = 0x12345678;
|
|
}
|
|
return ws_repeat_rect_spans(x, u, w, period, left, width, margin, out,
|
|
capacity);
|
|
}
|
|
|
|
static void test_margin_zero(void) {
|
|
WsRepeatSpan spans[4];
|
|
assert(emit_spans(0, 0, 128, 512, 0, 512, 0, spans, 4) == 0);
|
|
assert(spans[0].x == 0x12345678);
|
|
}
|
|
|
|
static void test_both_sides_and_u_offsets(void) {
|
|
WsRepeatSpan spans[4];
|
|
int count = emit_spans(-10, 0, 20, 512, 0, 512, 20, spans, 4);
|
|
assert(count == 2);
|
|
assert_span(&spans[0], -10, 0, 10);
|
|
assert_span(&spans[1], 512, 10, 10);
|
|
}
|
|
|
|
static void test_xoffset_framebuffer(void) {
|
|
WsRepeatSpan spans[4];
|
|
int count = emit_spans(502, 12, 20, 512, 512, 512, 20, spans, 4);
|
|
assert(count == 2);
|
|
assert_span(&spans[0], 502, 12, 10);
|
|
assert_span(&spans[1], 1024, 22, 10);
|
|
}
|
|
|
|
static void test_negative_x_partial_strip(void) {
|
|
WsRepeatSpan spans[4];
|
|
int count = emit_spans(-30, 10, 60, 512, 0, 512, 64, spans, 4);
|
|
assert(count == 2);
|
|
assert_span(&spans[0], -30, 10, 30);
|
|
assert_span(&spans[1], 512, 40, 30);
|
|
|
|
count = emit_spans(500, 4, 20, 512, 0, 512, 16, spans, 4);
|
|
assert(count == 2);
|
|
assert_span(&spans[0], -12, 4, 12);
|
|
assert_span(&spans[1], 512, 16, 8);
|
|
}
|
|
|
|
static void mark_span_coverage(const WsRepeatSpan *span, int *left_cov,
|
|
int *right_cov) {
|
|
for (int32_t x = span->x; x < span->x + span->w; x++) {
|
|
if (x >= -256 && x < 0)
|
|
left_cov[x + 256]++;
|
|
else if (x >= 512 && x < 768)
|
|
right_cov[x - 512]++;
|
|
else
|
|
assert(0 && "span overlapped canonical area or outer margin");
|
|
}
|
|
}
|
|
|
|
static void test_full_512_composite_all_phases(void) {
|
|
for (int phase = 0; phase < 256; phase++) {
|
|
int left_cov[256] = {0};
|
|
int right_cov[256] = {0};
|
|
WsRepeatSpan spans[4];
|
|
int total = 0;
|
|
|
|
if (phase == 0) {
|
|
const int32_t pieces[2][3] = {
|
|
{0, 0, 256},
|
|
{256, 0, 256},
|
|
};
|
|
for (int i = 0; i < 2; i++) {
|
|
int count = emit_spans(pieces[i][0], pieces[i][1],
|
|
pieces[i][2], 512, 0, 512, 256,
|
|
spans, 4);
|
|
total += count;
|
|
for (int j = 0; j < count; j++)
|
|
mark_span_coverage(&spans[j], left_cov, right_cov);
|
|
}
|
|
} else {
|
|
const int32_t pieces[4][3] = {
|
|
{512 - phase, 0, phase},
|
|
{256, phase, 256 - phase},
|
|
{256 - phase, 0, phase},
|
|
{0, phase, 256 - phase},
|
|
};
|
|
for (int i = 0; i < 4; i++) {
|
|
int count = emit_spans(pieces[i][0], pieces[i][1],
|
|
pieces[i][2], 512, 0, 512, 256,
|
|
spans, 4);
|
|
total += count;
|
|
for (int j = 0; j < count; j++)
|
|
mark_span_coverage(&spans[j], left_cov, right_cov);
|
|
}
|
|
}
|
|
|
|
assert(total == (phase == 0 ? 2 : 4));
|
|
for (int i = 0; i < 256; i++) {
|
|
assert(left_cov[i] == 1);
|
|
assert(right_cov[i] == 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void test_bad_inputs_and_capacity(void) {
|
|
WsRepeatSpan spans[8];
|
|
|
|
assert(emit_spans(0, 0, 20, 0, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 0, 0, 512, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 0, 257, 512, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, -1, 20, 512, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 240, 20, 512, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(9000, 0, 20, 512, 0, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 0, 20, 512, -1, 512, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 0, 20, 512, 0, 0, 32, spans, 8) == 0);
|
|
assert(emit_spans(0, 0, 20, 512, 0, 512, -1, spans, 8) == 0);
|
|
|
|
assert(emit_spans(-10, 0, 20, 512, 0, 512, 20, spans, 1) == 0);
|
|
assert(spans[0].x == 0x12345678);
|
|
|
|
assert(emit_spans(0, 0, 1, 1, 0, 512, 2048, spans, 8) == 0);
|
|
}
|
|
|
|
static void test_tag_table(void) {
|
|
WsRepeatRectTag tags[WS_REPEAT_RECT_TAG_TABLE_SIZE];
|
|
uint32_t packet[] = {
|
|
0x64010203u, 0x00100020u, 0x00040008u, 0x00100010u
|
|
};
|
|
WsPrepassPacketGuard guard = ws_prepass_packet_guard(packet, 4u);
|
|
|
|
ws_repeat_rect_tag_clear(tags);
|
|
ws_repeat_rect_tag_insert(tags, 0x80010004u, 512, &guard, 100u);
|
|
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 100u) ==
|
|
512);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 102u) ==
|
|
512);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 99u) ==
|
|
0);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 103u) ==
|
|
0);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010008u, packet, 4u, 100u) ==
|
|
0);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 3u, 100u) ==
|
|
0);
|
|
|
|
packet[3] = 0x00200010u;
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 100u) ==
|
|
0);
|
|
packet[3] = 0x00100010u;
|
|
|
|
ws_repeat_rect_tag_insert(tags, 0x80010004u, 256, &guard, 104u);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 104u) ==
|
|
256);
|
|
|
|
ws_repeat_rect_tag_insert(tags, 0x80010404u, 128, &guard, 104u);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010404u, packet, 4u, 104u) ==
|
|
128);
|
|
|
|
ws_repeat_rect_tag_insert(tags, 0x80010804u, 0, &guard, 104u);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010804u, packet, 4u, 104u) ==
|
|
0);
|
|
|
|
ws_repeat_rect_tag_clear(tags);
|
|
assert(ws_repeat_rect_tag_lookup(tags, 0x80010004u, packet, 4u, 104u) ==
|
|
0);
|
|
}
|
|
|
|
int main(void) {
|
|
test_margin_zero();
|
|
test_both_sides_and_u_offsets();
|
|
test_xoffset_framebuffer();
|
|
test_negative_x_partial_strip();
|
|
test_full_512_composite_all_phases();
|
|
test_bad_inputs_and_capacity();
|
|
test_tag_table();
|
|
|
|
puts("ws_repeat_rect_test: PASS");
|
|
return 0;
|
|
}
|