/**
* @file script.c
* Provides script library for using calculator hardware
*
* Copyright (C) 2018 Clyne Sullivan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define igetarg_integer(it, n) ((int)igetarg(it, n)->value.f)
int script_puts(instance *it);
int script_putchar(instance *it);
int script_gets(instance *it);
int script_getf(instance *it);
int script_delay(instance *it);
int script_rect(instance *it);
int script_ppos(instance *it);
int script_rpos(instance *it);
int script_line(instance *it);
int script_color(instance *it);
int script_rand(instance *it);
int script_getkey(instance *it);
int script_pixel(instance *it);
int script_menu(instance *it);
int script_filemenu(instance *it);
int script_program(instance *it);
int script_free(instance *it);
int script_clear(instance *it);
int script_tty(instance *it);
int math_sin(instance *it);
int math_cos(instance *it);
int math_tan(instance *it);
void script_loadlib(instance *it)
{
inew_number(it, "pi", 3.1415926535f);
inew_cfunc(it, "print", script_puts);
inew_cfunc(it, "putchar", script_putchar);
inew_cfunc(it, "gets", script_gets);
inew_cfunc(it, "getf", script_getf);
inew_cfunc(it, "getkey", script_getkey);
inew_cfunc(it, "ppos", script_ppos);
inew_cfunc(it, "rpos", script_rpos);
inew_cfunc(it, "pixel", script_pixel);
inew_cfunc(it, "line", script_line);
inew_cfunc(it, "rect", script_rect);
inew_cfunc(it, "color", script_color);
inew_cfunc(it, "clear", script_clear);
inew_cfunc(it, "rand", script_rand);
inew_cfunc(it, "delay", script_delay);
inew_cfunc(it, "menu", script_menu);
inew_cfunc(it, "filemenu", script_filemenu);
inew_cfunc(it, "program", script_program);
inew_cfunc(it, "freemem", script_free);
inew_cfunc(it, "tty", script_tty);
inew_cfunc(it, "sin", math_sin);
inew_cfunc(it, "cos", math_cos);
inew_cfunc(it, "tan", math_tan);
}
int math_sin(instance *it)
{
variable *n = igetarg(it, 0);
variable *v = make_varf(0, sinf(n->value.f));
ipush(it, (uint32_t)v);
return 0;
}
int math_cos(instance *it)
{
variable *n = igetarg(it, 0);
variable *v = make_varf(0, cosf(n->value.f));
ipush(it, (uint32_t)v);
return 0;
}
int math_tan(instance *it)
{
variable *n = igetarg(it, 0);
variable *v = make_varf(0, tanf(n->value.f));
ipush(it, (uint32_t)v);
return 0;
}
int script_menu(instance *it)
{
char listbuf[4];
int nargs = igetarg_integer(it, 0);
float *resps = (float *)calloc(nargs, sizeof(float));
strncpy(listbuf, " : \0", 4);
text_switch(1);
text_clear();
for (int i = 0; i < nargs; i++) {
listbuf[0] = i + '0';
text_puts(listbuf);
text_puts((char *)igetarg(it, 1 + i * 2)->value.p);
text_puts("\n");
resps[i] = igetarg(it, 2 + i * 2)->value.f;
}
int c;
do c = keypad_get();
while (c == 0);
variable *v = make_varf(0, isdigit(c) ? c - '0' : -1.0f);
ipush(it, (uint32_t)v);
text_switch(0);
free(resps);
return 0;
}
#include
int script_filemenu(instance *it)
{
char listbuf[4];
char *fname;
strncpy(listbuf, " : \0", 4);
//text_switch(1);
//text_clear();
text_puts("Choose a file: \n");
for (unsigned int i = 0; (fname = fat_getname(i)) != 0; i++) {
listbuf[0] = i + '0';
text_puts(listbuf);
text_puts(fname);
free(fname);
text_puts("\n");
}
int c;
do c = keypad_get();
while (c == 0);
variable *v = make_varf(0, isdigit(c) ? c - '0' : -1.0f);
ipush(it, (uint32_t)v);
//text_switch(0);
return 0;
}
int script_puts(instance *it)
{
variable *v = igetarg(it, 0);
if (v->type == NUMBER) {
char buf[33];
//snprintf(buf, 33, "%d", (int)v->value.f); // TODO
ftostr(buf, v->value.f);
text_puts(buf);
} else if (v->type == STRING) {
text_puts((const char *)v->value.p);
}
return 0;
}
int script_putchar(instance *it)
{
variable *v = igetarg(it, 0);
char buf[2];
buf[0] = (int)v->value.f;
buf[1] = '\0';
text_puts(buf);
return 0;
}
int script_getf(instance *it)
{
if (script_gets(it) != 0)
return -1;
variable *s = (variable *)ipop(it);
s->value.f = strtof((char *)s->value.p, 0);
s->type = NUMBER;
ipush(it, (uint32_t)s);
return 0;
}
int script_gets(instance *it)
{
char *s = malloc(64);
char c[2] = {0, 0};
int index = 0;
int furthest = 0;
do {
do {
c[0] = keypad_get();
delay(1);
} while (c[0] == 0);
// fn keys
if (c[0] == 0x11 || c[0] == 0x12 || c[0] == 0x13) {
/*s[index] = c[0];
if (furthest == 0)
furthest = 1;
break;*/
continue;
}
if (c[0] == 0x7F) {
it->lnidx = 998;
break;
} else if (c[0] == K_LEFT) {
if (index > 0) {
text_relpos(-1, 0);
index--;
}
continue;
} else if (c[0] == K_RIGHT) {
if (index < furthest) {
text_relpos(1, 0);
index++;
}
continue;
} else if (c[0] == K_UP || c[0] == K_DOWN)
continue;
if (c[0] == '\n')
break;
extern int keypad_insert;
if (keypad_insert != 0 && index < furthest) {
for (int i = furthest; i >= index; i--)
s[i] = s[i - 1];
}
s[index] = c[0];
if (c[0] == '\b' || c[0] == 127) {
index--;
if (index > -1) {
text_puts("\b");
index--;
}
} else if (keypad_insert != 0) {
text_relpos(-index, 0);
s[furthest + 1] = '\0';
text_puts(s);
text_relpos(-(furthest - index), 0);
furthest++;
} else if (c[0] != '\n'/*'\r'*/) {
text_puts(c);
}
if (++index > furthest)
furthest = index;
} while (furthest < 63);
s[furthest] = '\0';
variable *r = make_vars(0, s);
ipush(it, (uint32_t)r);
free(s);
return 0;
}
int script_delay(instance *it)
{
int ms = (int)igetarg(it, 0)->value.f;
delay(ms);
return 0;
}
int script_rect(instance *it)
{
dsp_rect(igetarg_integer(it, 0), igetarg_integer(it, 1),
igetarg_integer(it, 2), igetarg_integer(it, 3),
igetarg_integer(it, 4));
return 0;
}
int script_line(instance *it)
{
int x = igetarg_integer(it, 0);
int y = igetarg_integer(it, 1);
int i = igetarg_integer(it, 2);
int j = igetarg_integer(it, 3);
int c = igetarg_integer(it, 4);
dsp_line(x, y, i, j, c);
return 0;
}
int script_ppos(instance *it)
{
text_setpos(igetarg_integer(it, 0), igetarg_integer(it, 1));
return 0;
}
int script_rpos(instance *it)
{
text_relpos(igetarg_integer(it, 0), igetarg_integer(it, 1));
return 0;
}
int script_color(instance *it)
{
uint16_t c = dsp_color(igetarg_integer(it, 0), igetarg_integer(it, 1),
igetarg_integer(it, 2));
variable *v = make_varf(0, (float)c);
ipush(it, (uint32_t)v);
return 0;
}
int script_rand(instance *it)
{
unsigned int mod = igetarg_integer(it, 0);
unsigned int val = random_get();
variable *v = make_varf(0, (float)(val % mod));
ipush(it, (uint32_t)v);
return 0;
}
int script_getkey(instance *it)
{
char c = keypad_get();
if (c == 0x7F)
it->lnidx = 998;
variable *v = make_varf(0, c);
ipush(it, (uint32_t)v);
return 0;
}
int script_pixel(instance *it)
{
dsp_pixel(igetarg_integer(it, 0), igetarg_integer(it, 1),
igetarg_integer(it, 2));
return 0;
}
extern instance *load_program(const char *name);
int script_program(instance *it)
{
int offset = (int)igetarg(it, 0)->value.f;
char *name = fat_getname(offset);
instance *it2 = load_program(name);
free(name);
text_clear();
int ret = irun(it2);
if (ret != 0)
return -1;
idelinstance(it2);
return 0;
}
int script_free(instance *it)
{
extern uint32_t heap_used;
ipush(it, (uint32_t)make_varf(0, 98303 - heap_used));
return 0;
}
int script_clear(instance *it)
{
(void)it;
text_clear();
return 0;
}
int script_tty(instance *it)
{
text_switch(igetarg_integer(it, 0));
return 0;
}