201 lines
5.4 KiB
C
201 lines
5.4 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);
|
|
int fg = (value == -1) ? C_WHITE : (value == 0) ? C_GREEN : C_RED;
|
|
drect_border(x1, y1, x1+19, y1+10, fg, 1, C_BLACK);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|