u8g2-copy/tools/ugl/ugl_bc.c

415 lines
10 KiB
C

/*
ugl_bc.c
items can be at three places
1) map
2) inventory
3) hero
map --> inventory take
inventory --> map drop
inventory --> hero equip
hero --> inventory unequip
hero --> map drop
inputs:
hDir() // direction into which the hero wants to walk, had waked or looks
iDir() // direction into which the item/creatue/missel wants to go, went or looks
hX() // hero X position
hY() // hero Y position
posByH // set current position to the position of the hero
posByI // set current position to the position of the current item
posAppyDir(dir) // change the possition going one step into the specified direction
*/
#include "ugl_bc.h"
#include <stdio.h>
#include <assert.h>
#ifndef UGL_TEST
#include "item.h"
#include "map.h"
#endif
void bc_push_on_arg_stack(bc_t *bc, uint16_t val)
{
bc->arg_stack[bc->arg_stack_pointer] = val;
bc->arg_stack_pointer++;
}
uint16_t bc_pop_from_arg_stack(bc_t *bc)
{
assert( bc->arg_stack_pointer > 0 );
bc->arg_stack_pointer--;
return bc->arg_stack[bc->arg_stack_pointer] ;
}
void bc_duplicate_arg_stack_top_value(bc_t *bc)
{
bc->arg_stack[bc->arg_stack_pointer] = bc->arg_stack[bc->arg_stack_pointer-1];
bc->arg_stack_pointer++;
}
void bc_push_on_return_stack(bc_t *bc, uint16_t val)
{
bc->return_stack[bc->return_stack_pointer] = val;
bc->return_stack_pointer++;
}
uint16_t bc_pop_from_return_stack(bc_t *bc)
{
assert( bc->return_stack_pointer > 0 );
bc->return_stack_pointer--;
return bc->return_stack[bc->return_stack_pointer];
}
uint16_t bc_get_value(uint8_t *code)
{
uint16_t val;
val = *code;
code++;
val <<= 8;
val |= *code;
code++;
return val;
}
void bc_init(bc_t *bc)
{
bc->arg_stack_pointer = 0;
bc->return_stack_pointer = 0;
}
#define BC_DBG_OUT_POS(pos) printf("%05d ", (int)(pos))
#define BC_DBG_OUT_HEX(c) printf("0x%02x ", (int)(c))
#define BC_DBG_OUT_STR(str) printf("%s ", (str))
#define BC_DBG_OUT_NUM(n) printf("%d ", (int)(n))
#define BC_DBG_OUT_NUM3(n) printf("%03d ", (int)(n))
#define BC_DBG_OUT_CR() printf("\n")
void bc_exec(bc_t *bc, uint8_t *code, uint16_t pos)
{
uint16_t val;
uint8_t cmd;
bc_init(bc);
bc->code = code;
bc->code_pos = pos;
for(;;)
{
cmd = bc->code[bc->code_pos];
BC_DBG_OUT_POS(bc->code_pos);
BC_DBG_OUT_NUM3(bc->arg_stack_pointer);
BC_DBG_OUT_HEX(cmd);
bc->code_pos++;
val = cmd;
val &=0x0f0; /* put upper four bit as upper 4bit of the 12bit value into val */
val <<= 4;
switch(cmd&15)
{
case BC_CMD_LOAD_12BIT:
BC_DBG_OUT_STR("LOAD12");
val |= bc->code[bc->code_pos];
BC_DBG_OUT_NUM(val);
bc->code_pos++;
bc_push_on_arg_stack(bc, val);
BC_DBG_OUT_CR();
break;
case BC_CMD_CALL_BUILDIN:
BC_DBG_OUT_STR("CALL BUILDIN");
val |= bc->code[bc->code_pos];
BC_DBG_OUT_NUM(val);
bc->code_pos++;
BC_DBG_OUT_CR();
bc_buildin_list[val](bc);
break;
case BC_CMD_CALL_BUILDIN_POP_STACK:
BC_DBG_OUT_STR("CALL BUILDIN POP ARG STACK");
val |= bc->code[bc->code_pos];
BC_DBG_OUT_NUM(val);
bc->code_pos++;
BC_DBG_OUT_CR();
bc_buildin_list[val](bc);
bc_pop_from_arg_stack(bc);
break;
case BC_CMD_BRANCH:
BC_DBG_OUT_STR("BRANCH");
val |= bc->code[bc->code_pos];
bc->code_pos++;
if ( val < 0x0800 )
{
bc->code_pos += val;
}
else
{
val = 0x1000 - val;
bc->code_pos -= val;
}
BC_DBG_OUT_POS(bc->code_pos);
BC_DBG_OUT_CR();
case BC_CMD_POP_ARG_STACK:
cmd >>= 4; /* in this case we need the lower 4 bit */
BC_DBG_OUT_STR("POP ARG STACK");
cmd++; /* cmd is reused as a counter for the number of stack pops */
BC_DBG_OUT_NUM(cmd);
do
{
bc_pop_from_arg_stack(bc);
cmd--;
} while( cmd > 0 );
BC_DBG_OUT_CR();
break;
case BC_CMD_PUSH_ARG_STACK:
cmd >>= 4; /* in this case we need the lower 4 bit */
BC_DBG_OUT_STR("PUSH ARG STACK");
cmd++; /* cmd is reused as a counter for the number of stack pops */
BC_DBG_OUT_NUM(cmd);
do
{
bc_push_on_arg_stack(bc, 0);
cmd--;
} while( cmd > 0 );
BC_DBG_OUT_CR();
break;
case BC_CMD_CALL_PROCEDURE:
BC_DBG_OUT_STR("CALL PROC");
cmd >>= 4; /* in this case we need the lower 4 bit--> number of args */
BC_DBG_OUT_NUM(cmd); /* output number of args */
val = bc->code[bc->code_pos];
bc->code_pos++;
val <<= 8;
val |= bc->code[bc->code_pos];
bc->code_pos++;
bc_push_on_return_stack(bc, bc->code_pos); /* return position */
bc_push_on_return_stack(bc, bc->arg_stack_pointer - cmd -1); /* store the start pos of the return value and the args */
bc->code_pos = val;
BC_DBG_OUT_NUM(bc->code_pos);
BC_DBG_OUT_CR();
break;
default: /* assume 0x0f, extended command */
switch( cmd )
{
case BC_CMD_LOAD_0:
BC_DBG_OUT_STR("LOAD#0");
bc_push_on_arg_stack(bc, 0);
BC_DBG_OUT_CR();
break;
case BC_CMD_LOAD_1:
BC_DBG_OUT_STR("LOAD#1");
bc_push_on_arg_stack(bc, 1);
BC_DBG_OUT_CR();
break;
case BC_CMD_LOAD_16BIT:
BC_DBG_OUT_STR("LOAD16");
val = bc->code[bc->code_pos];
bc->code_pos++;
val <<= 8;
val |= bc->code[bc->code_pos];
bc->code_pos++;
bc_push_on_arg_stack(bc, val);
BC_DBG_OUT_NUM(val);
BC_DBG_OUT_CR();
break;
case BC_CMD_RETURN_FROM_PROCEDURE:
BC_DBG_OUT_STR("RETURN to");
if ( bc->return_stack_pointer == 0 )
{
BC_DBG_OUT_STR("exit");
BC_DBG_OUT_CR();
BC_DBG_OUT_STR("arg stack: ");
BC_DBG_OUT_NUM(bc->arg_stack_pointer);
BC_DBG_OUT_CR();
BC_DBG_OUT_STR("return stack: ");
BC_DBG_OUT_NUM(bc->return_stack_pointer);
BC_DBG_OUT_CR();
return; /* stop execution */
}
//bc_push_on_arg_stack(bc, bc_pop_from_return_stack(bc)); /* copy return value on arg stack */
bc->arg_stack_pointer = bc_pop_from_return_stack(bc) + 1; /* restore the arg stack pointer, leave return value on stack */
bc->code_pos = bc_pop_from_return_stack(bc);
BC_DBG_OUT_NUM(bc->code_pos);
BC_DBG_OUT_CR();
break;
case BC_CMD_JUMP_NOT_ZERO:
BC_DBG_OUT_STR("JUMP NZ");
val = bc->code[bc->code_pos];
bc->code_pos++;
val <<= 8;
val |= bc->code[bc->code_pos];
bc->code_pos++;
if ( bc_pop_from_arg_stack(bc) != 0 )
bc->code_pos = val;
break;
BC_DBG_OUT_NUM(bc->code_pos);
BC_DBG_OUT_CR();
case BC_CMD_JUMP_ZERO:
BC_DBG_OUT_STR("JUMP Z");
val = bc->code[bc->code_pos];
bc->code_pos++;
val <<= 8;
val |= bc->code[bc->code_pos];
bc->code_pos++;
if ( bc_pop_from_arg_stack(bc) == 0 )
bc->code_pos = val;
BC_DBG_OUT_NUM(bc->code_pos);
BC_DBG_OUT_CR();
break;
case BC_CMD_CALL_PROCEDURE:
BC_DBG_OUT_STR("CALL PROC");
val = bc->code[bc->code_pos];
bc->code_pos++;
val <<= 8;
val |= bc->code[bc->code_pos];
bc->code_pos++;
bc_push_on_return_stack(bc, bc->code_pos); /* return position */
bc_push_on_return_stack(bc, 0); /* return value */
bc->code_pos = val;
BC_DBG_OUT_NUM(bc->code_pos);
BC_DBG_OUT_CR();
break;
/*
case BC_CMD_POP_ARG_STACK:
BC_DBG_OUT_STR("POP ARG STACK");
BC_DBG_OUT_CR();
bc_pop_from_arg_stack(bc);
break;
*/
default:
break;
}
break;
} /* switch() */
} /* for(;;) */
}
/*======================================================*/
/* put top of stack into register a, reduce stack */
//void bc_pop_a(bc_t *bc)
//{
// bc->stack_pointer--;
// bc->a = bc->stack[bc->stack_pointer];
//}
/*======================================================*/
/* return a pointer to a variable on the arg stack within the current stack frame */
/* pos = 0 is the return value of a user function, pos = 1... are the args for that function */
uint16_t *bc_get_stack_frame_address(bc_t *bc, uint8_t pos)
{
return bc->arg_stack + bc->return_stack[bc->return_stack_pointer-1] + pos ;
}
void bc_fn_nop(bc_t *bc)
{
bc_push_on_arg_stack(bc, 0);
}
/* description: "return" sets the return value of a procedure. If used inside an expresion, it returns its argument */
/* assign return value for a user defined function */
/* identical to arg(0) */
void bc_fn_return(bc_t *bc)
{
bc_duplicate_arg_stack_top_value(bc); /* goal is to leave a value on the stack */
*bc_get_stack_frame_address(bc, 0) = bc_pop_from_arg_stack(bc);
/*
v = bc_pop_from_arg_stack(bc);
bc_push_on_arg_stack(bc, v);
bc_pop_from_return_stack(bc);
bc_push_on_return_stack(bc, v);
*/
}
void bc_fn_print(bc_t *bc)
{
bc_duplicate_arg_stack_top_value(bc); /* goal is to leave a value on the stack */
printf("%u\n", bc_pop_from_arg_stack(bc));
}
/* return an argument of a user defined procedure */
void bc_fn_arg1(bc_t *bc)
{
bc_push_on_arg_stack(bc, *bc_get_stack_frame_address(bc, bc_pop_from_arg_stack(bc)));
}
/* remove the top element from the stack and return the same */
void bc_fn_arg2(bc_t *bc)
{
uint16_t v = bc_pop_from_arg_stack(bc); /* the value, which should be assigned */
*bc_get_stack_frame_address(bc, bc_pop_from_arg_stack(bc)) = v;
bc_push_on_arg_stack(bc, v); /* push the value back on the stack */
}
void bc_fn_add(bc_t *bc)
{
uint16_t v;
v = bc_pop_from_arg_stack(bc);
v += bc_pop_from_arg_stack(bc);
bc_push_on_arg_stack(bc, v);
}
#ifndef UGL_TEST
pos_t bc_pos;
#endif
void bc_fn_setPos(bc_t *bc)
{
uint8_t x, y;
y = bc_pop_from_arg_stack(bc);
x = bc_pop_from_arg_stack(bc);
#ifndef UGL_TEST
bc_pos.x = x;
bc_pos.y = y;
#endif
bc_push_on_arg_stack(bc, 0);
}
void bc_fn_setItemPos(bc_t *bc)
{
uint8_t i;
i = bc_pop_from_arg_stack(bc);
#ifndef UGL_TEST
pool_GetItem(i)->pos = bc_pos;
printf("item %d new x=%d y=%d\n", i, bc_pos.x, bc_pos.y);
#endif
bc_push_on_arg_stack(bc, i);
}
/*======================================================*/
bc_buildin_fn bc_buildin_list[] =
{
/* 0 */ bc_fn_nop,
/* 1 */ bc_fn_return,
/* 2 */ bc_fn_arg1, /* one argument */
/* 3 */ bc_fn_arg2, /* two arguments */
/* 4 */ bc_fn_add,
/* 5 */ bc_fn_print,
/* 6 */ bc_fn_setPos, /* two args: x & y*/
/* 7 */ bc_fn_setItemPos, /* one args: item */
};