FxLibcTest/src/string/memarray.c

210 lines
5.7 KiB
C

#include <gint/defs/types.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/exc.h>
#include <gint/defs/call.h>
#include <justui/jpainted.h>
#include <ft/util.h>
#include "memarray.h"
#include <string.h>
//---
// Utilities
//---
/* Code of exception that occurs during a memory access */
static uint32_t exception = 0;
/* Exception-catching function */
static int catch_exc(uint32_t code)
{
if(code == 0x100 || code == 0x0e0)
{
exception = code;
gint_exc_skip(1);
return 0;
}
return 1;
}
/* memory_protected_call(): Wrapper that protects against access errors */
static int memory_protected_call(gint_call_t function)
{
exception = 0;
gint_exc_catch(catch_exc);
int rc = gint_call(function);
gint_exc_catch(NULL);
return rc || (exception != 0);
}
//---
// Public API
//---
void memarray_set(uint8_t *rc, int position, int value)
{
int index = 1 + (position >> 3);
uint8_t byte = 0x80 >> (position & 7);
if(index >= rc[0]) return;
if(value) rc[index] |= byte;
else rc[index] &= ~byte;
}
int memarray_get(uint8_t *rc, int position)
{
int index = 1 + (position >> 3);
uint8_t byte = 0x80 >> (position & 7);
if(index >= rc[0]) return -1;
return (rc[index] & byte) != 0;
}
void memarray_assert(uint8_t *rc, ft_test *test)
{
for(int i = 0; true; i++) {
int v = memarray_get(rc, i);
if(v < 0) return;
ft_assert(test, v == 0);
}
}
void memarray_single(uint8_t *rc, memarray_func_t f)
{
uint8_t buf1[128], buf2[128];
int counter = 0;
rc[0] = MEMARRAY_RC_SINGLE;
memarray_args_t args = {
.full_buf1 = buf1,
.full_buf2 = buf2,
.full_size = 128,
};
gint_call_t call = GINT_CALL(f, (void *)&args);
for(int buf_al = 0; buf_al < 4; buf_al++)
for(int len_al = 0; len_al < 4; len_al++)
{
args.buf1 = buf1 + 8 + buf_al;
args.buf2 = buf2 + 8 + buf_al;
args.size = 12 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
args.buf1 = buf1 + 8 + buf_al;
args.buf2 = buf2 + 8 + buf_al;
args.size = 92 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
}
}
void memarray_double(uint8_t *rc, bool overlap, memarray_func_t f)
{
uint8_t left1[128], left2[128], right1[128], right2[128];
int counter = 0;
rc[0] = overlap ? MEMARRAY_RC_DOUBLE_OVERLAP : MEMARRAY_RC_DOUBLE;
memarray_args_t args = {
.full_left1 = left1,
.full_left2 = left2,
.full_right1 = right1,
.full_right2 = right2,
.full_size = 128,
};
gint_call_t call = GINT_CALL(f, (void *)&args);
for(int left_al = 0; left_al < 4; left_al++)
for(int right_al = 0; right_al < 4; right_al++)
for(int len_al = 0; len_al < 4; len_al++)
{
args.left1 = left1 + 8 + left_al;
args.left2 = left2 + 8 + left_al;
args.right1 = right1 + 8 + right_al;
args.right2 = right2 + 8 + right_al;
args.size = 12 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
args.left1 = left1 + 8 + left_al;
args.left2 = left2 + 8 + left_al;
args.right1 = right1 + 8 + right_al;
args.right2 = right2 + 8 + right_al;
args.size = 92 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
if(!overlap) continue;
/* In overlap mode, only use left1 and left2 to create an overlap */
args.left1 = left1 + left_al;
args.left2 = left2 + left_al;
args.right1 = left1 + 28 + right_al;
args.right2 = left2 + 28 + right_al;
args.size = 92 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
args.left1 = left1 + 28 + left_al;
args.left2 = left2 + 28 + left_al;
args.right1 = left1 + right_al;
args.right2 = left2 + right_al;
args.size = 92 + len_al;
memarray_set(rc, counter++, memory_protected_call(call));
}
}
//---
// Visualization widget
//---
static void paint_results(int x, int y, uint8_t *rc)
{
dprint_opt(x+222, y, C_BLACK, C_NONE, DTEXT_CENTER, DTEXT_TOP,
"Source align and destination align");
for(int i = 0; i < 16; i++)
dprint(x + 74 + 18*i + 3*(i/4), y+12, C_BLACK, "%d%d", i/4, i & 3);
int sizes = 0;
if(rc[0] == MEMARRAY_RC_SINGLE) sizes = 2;
if(rc[0] == MEMARRAY_RC_DOUBLE) sizes = 2;
if(rc[0] == MEMARRAY_RC_DOUBLE_OVERLAP) sizes = 4;
char const *size_names[4] = { "Small", "Large", "Over-L", "Over-R" };
for(int i = 0; i < 4; i++) {
dprint_opt(x+55, y + 43 + 42*i, C_BLACK, C_NONE, DTEXT_RIGHT,
DTEXT_MIDDLE, "%s", size_names[i]);
}
for(int i = 0; i < 16; i++)
dprint_opt(x+64, y + 25 + 10*i + 2*(i/4), C_BLACK, C_NONE,
DTEXT_CENTER, DTEXT_TOP, "%d", i & 3);
for(int row = 0; row < 16; row++)
for(int col = 0; col < 16; col++)
{
int x1 = x + 72 + 18*col + 3*(col/4);
int y1 = y + 24 + 10*row + 2*(row/4);
int value = -1;
if(row < 4*sizes) value = memarray_get(rc, 4*sizes * col + row);
#ifdef FX9860G
if(value >= 0) {
for(int y = y1; y <= y1+10; y++)
for(int x = x1; x <= x1+19; x++)
dpixel(x, y, (x&1)^(y&1) ? C_BLACK : (value != 0));
}
#else
int fg = (value == -1) ? C_WHITE : (value == 0) ? C_GREEN : C_RED;
drect_border(x1, y1, x1+19, y1+10, fg, 1, C_BLACK);
#endif
}
}
jwidget *memarray_widget(uint8_t *rc)
{
jpainted *p = jpainted_create(paint_results, rc, 377, 185, NULL);
if(!p) return NULL;
jwidget_set_margin(p, 4, 4, 4, 4);
return &p->widget;
}