264 lines
8.1 KiB
C
264 lines
8.1 KiB
C
//---------------------------------------------------------------------------//
|
|
// ____ PythonExtra //
|
|
//.-'`_ o `;__, A community port of MicroPython for CASIO calculators. //
|
|
//.-'` `---` ' License: MIT (except some files; see LICENSE) //
|
|
//---------------------------------------------------------------------------//
|
|
// pe.modkandinsky: Compatibility module for NumWorks Kandinsky library
|
|
|
|
#include "py/obj.h"
|
|
#include "py/runtime.h"
|
|
#include <gint/display.h>
|
|
#include <gint/drivers/r61524.h>
|
|
#include <gint/timer.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
extern font_t numworks;
|
|
|
|
extern bool is_dwindowed;
|
|
extern bool is_timered;
|
|
extern unsigned int timer_altered[9];
|
|
|
|
#define DELTAXNW \
|
|
((DWIDTH - 320) / 2) // we center the NW screen on Casio's screen
|
|
#define DELTAYNW 0 // NW screen will be cut in the bottom
|
|
|
|
/* Definition of color on Numworks */
|
|
|
|
// Data can be found here
|
|
// https://github.com/numworks/epsilon/blob/master/escher/include/escher/palette.h
|
|
// and here
|
|
// https://github.com/numworks/epsilon/blob/master/python/port/port.cpp#L221
|
|
|
|
#define NW_RGB(r, g, b) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3))
|
|
|
|
#define NW_BLUE NW_RGB(0x50, 0x75, 0xF2)
|
|
#define NW_RED NW_RGB(0xFF, 0x00, 0x0C)
|
|
#define NW_GREEN NW_RGB(0x50, 0xC1, 0x02)
|
|
#define NW_WHITE NW_RGB(0xFF, 0xFF, 0xFF)
|
|
#define NW_BLACK NW_RGB(0x00, 0x00, 0x00)
|
|
|
|
#define NW_YELLOW NW_RGB(0xFF, 0xCC, 0x7B)
|
|
#define NW_PURPLE NW_RGB(0x6E, 0x2D, 0x79)
|
|
#define NW_BROWN NW_RGB(0x8D, 0x73, 0x50)
|
|
#define NW_CYAN NW_RGB(0x00, 0xFF, 0xFF)
|
|
#define NW_ORANGE NW_RGB(0xFE, 0x87, 0x1F)
|
|
#define NW_PINK NW_RGB(0xFF, 0xAB, 0xB6)
|
|
#define NW_MAGENTA NW_RGB(0xFF, 0x05, 0x88)
|
|
#define NW_GRAY NW_RGB(0xA7, 0xA7, 0xA7)
|
|
|
|
// There are possibly some others to be listed correctly
|
|
|
|
static int callback(void) {
|
|
dupdate();
|
|
return TIMER_CONTINUE;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_make_color(color_t color) {
|
|
int r, g, b;
|
|
r = (color >> 8) & 0xf8;
|
|
g = (color >> 3) & 0xfc;
|
|
b = (color << 3) & 0xfc;
|
|
|
|
mp_obj_t items[3] = {
|
|
MP_OBJ_NEW_SMALL_INT(r),
|
|
MP_OBJ_NEW_SMALL_INT(g),
|
|
MP_OBJ_NEW_SMALL_INT(b),
|
|
};
|
|
return mp_obj_new_tuple(3, items);
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_init(void) {
|
|
void pe_enter_graphics_mode(void);
|
|
pe_enter_graphics_mode();
|
|
|
|
dclear(NW_WHITE);
|
|
|
|
struct dwindow nw;
|
|
nw.left = DELTAXNW;
|
|
nw.top = DELTAYNW;
|
|
nw.right = 320 + DELTAXNW;
|
|
nw.bottom = 240 + DELTAYNW;
|
|
dwindow_set(nw);
|
|
is_dwindowed = true; // we mark as windowed
|
|
|
|
int t = timer_configure(TIMER_TMU, 33333, GINT_CALL(callback));
|
|
if (t >= 0) {
|
|
timer_start(t);
|
|
is_timered = true; // there is a timer altered from this module
|
|
timer_altered[t] = 1; // we put the corresponding timer at 1 to identify it
|
|
}
|
|
return mp_const_none;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_color(size_t n, mp_obj_t const *args) {
|
|
int r = mp_obj_get_int(args[0]);
|
|
int g = mp_obj_get_int(args[1]);
|
|
int b = mp_obj_get_int(args[2]);
|
|
int color = NW_RGB(r, g, b);
|
|
|
|
return mp_obj_new_int(color);
|
|
}
|
|
|
|
int Internal_Get_Color_From_String(const char *str) {
|
|
|
|
if (strcmp(str, "red") == 0 || strcmp(str, "r") == 0)
|
|
return NW_RED;
|
|
else if (strcmp(str, "green") == 0 || strcmp(str, "g") == 0)
|
|
return NW_GREEN;
|
|
else if (strcmp(str, "blue") == 0 || strcmp(str, "b") == 0)
|
|
return NW_BLUE;
|
|
else if (strcmp(str, "black") == 0 || strcmp(str, "k") == 0)
|
|
return NW_BLACK;
|
|
else if (strcmp(str, "white") == 0 || strcmp(str, "w") == 0)
|
|
return NW_WHITE;
|
|
|
|
else if (strcmp(str, "yellow") == 0 || strcmp(str, "y") == 0)
|
|
return NW_YELLOW;
|
|
else if (strcmp(str, "pink") == 0)
|
|
return NW_PINK;
|
|
else if (strcmp(str, "magenta") == 0)
|
|
return NW_MAGENTA;
|
|
else if (strcmp(str, "grey") == 0 || strcmp(str, "gray") == 0)
|
|
return NW_GRAY;
|
|
else if (strcmp(str, "purple") == 0)
|
|
return NW_PURPLE;
|
|
else if (strcmp(str, "orange") == 0)
|
|
return NW_ORANGE;
|
|
else if (strcmp(str, "cyan") == 0)
|
|
return NW_CYAN;
|
|
else if (strcmp(str, "brown") == 0)
|
|
return NW_BROWN;
|
|
else
|
|
return C_NONE;
|
|
}
|
|
|
|
int Internal_Treat_Color(mp_obj_t color) {
|
|
const mp_obj_type_t *type = mp_obj_get_type(color);
|
|
|
|
if (type == &mp_type_str) {
|
|
size_t text_len;
|
|
char const *text = mp_obj_str_get_data(color, &text_len);
|
|
return Internal_Get_Color_From_String(text);
|
|
}
|
|
|
|
else if (type == &mp_type_int)
|
|
return mp_obj_get_int(color);
|
|
|
|
else if (type == &mp_type_tuple) {
|
|
size_t tuple_len;
|
|
mp_obj_t *items;
|
|
mp_obj_tuple_get(color, &tuple_len, &items);
|
|
int r = mp_obj_get_int(items[0]);
|
|
int g = mp_obj_get_int(items[1]);
|
|
int b = mp_obj_get_int(items[2]);
|
|
return NW_RGB(r, g, b);
|
|
} else
|
|
return NW_BLACK;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_fill_rect(size_t n, mp_obj_t const *args) {
|
|
int x = mp_obj_get_int(args[0]) + DELTAXNW;
|
|
int y = mp_obj_get_int(args[1]) + DELTAYNW;
|
|
int w = mp_obj_get_int(args[2]);
|
|
int h = mp_obj_get_int(args[3]);
|
|
|
|
int color = Internal_Treat_Color(args[4]);
|
|
|
|
drect(x, y, x + w - 1, y + h - 1, color);
|
|
|
|
return mp_const_none;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_set_pixel(size_t n, mp_obj_t const *args) {
|
|
int x = mp_obj_get_int(args[0]) + DELTAXNW;
|
|
int y = mp_obj_get_int(args[1]) + DELTAYNW;
|
|
|
|
int color;
|
|
if (n == 3)
|
|
color = Internal_Treat_Color(args[2]);
|
|
else
|
|
color = NW_BLACK;
|
|
|
|
dpixel(x, y, color);
|
|
return mp_const_none;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_get_pixel(mp_obj_t _x, mp_obj_t _y) {
|
|
int x = mp_obj_get_int(_x) + DELTAXNW;
|
|
int y = mp_obj_get_int(_y) + DELTAYNW;
|
|
|
|
if (x >= 0 && x < DWIDTH && y >= 0 && y < DHEIGHT) {
|
|
color_t color = gint_vram[DWIDTH * y + x];
|
|
return Kandinsky_make_color(color);
|
|
}
|
|
return mp_const_none;
|
|
}
|
|
|
|
static mp_obj_t Kandinsky_draw_string(size_t n, mp_obj_t const *args) {
|
|
int x = mp_obj_get_int(args[1]) + DELTAXNW + 1; // values used to adjust the visual result as per actual NW
|
|
int y = mp_obj_get_int(args[2]) + DELTAYNW + 2; // values used to adjust the visual result as per actual NW
|
|
size_t text_len;
|
|
char const *text = mp_obj_str_get_data(args[0], &text_len);
|
|
|
|
color_t colortext = NW_BLACK;
|
|
if (n >= 4) {
|
|
colortext = Internal_Treat_Color(args[3]);
|
|
}
|
|
|
|
color_t colorback = C_NONE;
|
|
if (n >= 5) {
|
|
colorback = Internal_Treat_Color(args[4]);
|
|
}
|
|
|
|
font_t const *old_font = dfont(&numworks);
|
|
|
|
int u = 0;
|
|
int v = 0;
|
|
for (int l = 0; l < (int)text_len; l++) {
|
|
if (text[l] == '\n') {
|
|
u = 0;
|
|
v += 16;
|
|
} else {
|
|
drect(x + u - 1, y + v - 1, x + u + 9, y + v + 15, colorback);
|
|
dtext_opt(x + u, y + v, colortext, C_NONE, DTEXT_LEFT, DTEXT_TOP,
|
|
&text[l], 1);
|
|
u += 10;
|
|
}
|
|
}
|
|
|
|
dfont(old_font);
|
|
|
|
return mp_const_none;
|
|
}
|
|
|
|
MP_DEFINE_CONST_FUN_OBJ_0(Kandinsky_init_obj, Kandinsky_init);
|
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Kandinsky_set_pixel_obj, 3, 3,
|
|
Kandinsky_set_pixel);
|
|
MP_DEFINE_CONST_FUN_OBJ_2(Kandinsky_get_pixel_obj, Kandinsky_get_pixel);
|
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Kandinsky_draw_string_obj, 3, 5,
|
|
Kandinsky_draw_string);
|
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Kandinsky_fill_rect_obj, 5, 5,
|
|
Kandinsky_fill_rect);
|
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Kandinsky_color_obj, 3, 3, Kandinsky_color);
|
|
|
|
STATIC const mp_rom_map_elem_t kandinsky_module_globals_table[] = {
|
|
{MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_kandinsky)},
|
|
{MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&Kandinsky_init_obj)},
|
|
{MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&Kandinsky_fill_rect_obj)},
|
|
{MP_ROM_QSTR(MP_QSTR_color), MP_ROM_PTR(&Kandinsky_color_obj)},
|
|
{MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&Kandinsky_set_pixel_obj)},
|
|
{MP_ROM_QSTR(MP_QSTR_get_pixel), MP_ROM_PTR(&Kandinsky_get_pixel_obj)},
|
|
{MP_ROM_QSTR(MP_QSTR_draw_string), MP_ROM_PTR(&Kandinsky_draw_string_obj)},
|
|
};
|
|
STATIC MP_DEFINE_CONST_DICT(kandinsky_module_globals,
|
|
kandinsky_module_globals_table);
|
|
|
|
const mp_obj_module_t kandinsky_module = {
|
|
.base = {&mp_type_module},
|
|
.globals = (mp_obj_dict_t *)&kandinsky_module_globals,
|
|
};
|
|
|
|
MP_REGISTER_MODULE(MP_QSTR_kandinsky, kandinsky_module);
|