/** * Enable the I2C bus on 2 GPIO pins. Expect two integer * arguments, this first is the SDA gpio pin number and * the second is the SCL gpio pin number. * @param ctx the duktape context. * @return the name of the created i2c device. */ duk_ret_t i2c_enable_device(duk_context *ctx) { char* buff[256]; // Expect 2 arguments int n = duk_get_top(ctx); if(n != 2) { return DUK_RET_API_ERROR; } // Get the SDA and SDL pin number int sda_pin = duk_to_int(ctx, 0); int scl_pin = duk_to_int(ctx, 1); // Generate the insmod command sprintf(buff, "insmod i2c-gpio-custom bus0=0,%d,%d > /dev/null", sda_pin, scl_pin); // Insert the kernel modules system("insmod i2c-dev > /dev/null"); system(buff); // Push the name of the i2c device to the stack. duk_push_string(ctx, "/dev/i2c-0"); return 1; }
static duk_ret_t duk_btnp(duk_context* duk) { tic_machine* machine = getDukMachine(duk); tic_mem* memory = (tic_mem*)machine; if (duk_is_null_or_undefined(duk, 0)) { duk_push_uint(duk, memory->api.btnp(memory, -1, -1, -1)); } else if(duk_is_null_or_undefined(duk, 1) && duk_is_null_or_undefined(duk, 2)) { s32 index = duk_to_int(duk, 0) & 0x1f; duk_push_boolean(duk, memory->api.btnp(memory, index, -1, -1)); } else { s32 index = duk_to_int(duk, 0) & 0x1f; u32 hold = duk_to_int(duk, 1); u32 period = duk_to_int(duk, 2); duk_push_boolean(duk, memory->api.btnp(memory, index, hold, period)); } return 1; }
static int sys1_poll(duk_context *ctx) { int nfds = duk_to_int(ctx, 1); int timeout = duk_to_int(ctx, 2); int i, rc; struct pollfd *fds; fds = malloc(sizeof(struct pollfd)*nfds); memset(fds, 0, sizeof(struct pollfd)*nfds); for(i=0;i<nfds;i++) { duk_get_prop_index(ctx, 0, i); duk_get_prop_string(ctx, 3, "fd"); fds[i].fd = duk_to_int(ctx, 4); duk_get_prop_string(ctx, 3, "events"); fds[i].events = duk_to_int(ctx, 5); duk_pop_n(ctx, 3); } rc = poll(fds, nfds, timeout); duk_push_object(ctx); duk_push_int(ctx, rc); duk_put_prop_string(ctx, -2, "rc"); duk_dup(ctx, 0); // dup reference to arg0 array for(i=0;i<nfds;i++) { duk_get_prop_index(ctx, -1, i); // fetch object from array at i duk_push_int(ctx, fds[i].revents); duk_put_prop_string(ctx, -2, "revents"); // put revents into object duk_pop(ctx); // remove object from stack } duk_put_prop_string(ctx, -2, "fds"); return 1; }
static s32 duk_keyp(duk_context* duk) { tic_machine* machine = getDukMachine(duk); tic_mem* tic = &machine->memory; if (duk_is_null_or_undefined(duk, 0)) { duk_push_boolean(duk, tic->api.keyp(tic, tic_key_unknown, -1, -1)); } else { tic_key key = duk_to_int(duk, 0); if(key >= tic_key_escape) { return duk_error(duk, DUK_ERR_ERROR, "unknown keyboard code\n"); } else { if(duk_is_null_or_undefined(duk, 1) && duk_is_null_or_undefined(duk, 2)) { duk_push_boolean(duk, tic->api.keyp(tic, key, -1, -1)); } else { u32 hold = duk_to_int(duk, 1); u32 period = duk_to_int(duk, 2); duk_push_boolean(duk, tic->api.keyp(tic, key, hold, period)); } } } return 1; }
static void remapCallback(void* data, s32 x, s32 y, RemapResult* result) { RemapData* remap = (RemapData*)data; duk_context* duk = remap->duk; duk_push_heapptr(duk, remap->remap); duk_push_int(duk, result->index); duk_push_int(duk, x); duk_push_int(duk, y); duk_pcall(duk, 3); if(duk_is_array(duk, -1)) { duk_get_prop_index(duk, -1, 0); result->index = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 1); result->flip = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 2); result->rotate = duk_to_int(duk, -1); duk_pop(duk); } else { result->index = duk_to_int(duk, -1); } duk_pop(duk); }
/** * fd, buffer, offset, length, position */ static int es_file_read(duk_context *ctx) { es_fd_t *efd = es_fd_get(ctx, 0); duk_size_t bufsize; char *buf = duk_require_buffer_data(ctx, 1, &bufsize); const int offset = duk_to_int(ctx, 2); const int len = duk_to_int(ctx, 3); if(offset + len > bufsize) duk_error(ctx, DUK_ERR_ERROR, "Buffer too small %zd < %d + %d", bufsize, offset + len); if(!duk_is_null(ctx, 4)) { // Seek fa_seek(efd->efd_fh, duk_require_number(ctx, 4), SEEK_SET); } int r = fa_read(efd->efd_fh, buf + offset, len); if(r < 0) duk_error(ctx, DUK_ERR_ERROR, "Read error from '%s'", efd->efd_path); duk_push_int(ctx, r); return 1; }
/** * fd, buffer, offset, length, position */ static int es_file_write(duk_context *ctx) { es_fd_t *efd = es_fd_get(ctx, 0); duk_size_t bufsize; char *buf = duk_to_buffer(ctx, 1, &bufsize); int len; const int offset = duk_to_int(ctx, 2); if(duk_is_null(ctx, 3)) { len = bufsize; } else { len = duk_to_int(ctx, 3); } // Don't read past buffer end if(offset + len > bufsize) len = bufsize - offset; if(!duk_is_null(ctx, 4)) { // Seek fa_seek(efd->efd_fh, duk_require_number(ctx, 4), SEEK_SET); } int r = fa_write(efd->efd_fh, buf + offset, len); if(r < 0) duk_error(ctx, DUK_ERR_ERROR, "Write error to '%s'", efd->efd_path); duk_push_int(ctx, r); return 1; }
static int sys1_kill(duk_context *ctx) { int pid = duk_to_int(ctx, 0); int sig = duk_to_int(ctx, 1); int rc; rc = kill(pid, sig); duk_push_int(ctx, rc); return 1; }
static int ncurses_mvprintw(duk_context *ctx) { int y = duk_to_int(ctx, 0); int x = duk_to_int(ctx, 1); const char *str = duk_to_string(ctx, 2); int rc; rc = mvprintw(y, x, "%s", str); duk_push_int(ctx, rc); return 1; }
static duk_ret_t duk_mget(duk_context* duk) { s32 x = duk_is_null_or_undefined(duk, 0) ? 0 : duk_to_int(duk, 0); s32 y = duk_is_null_or_undefined(duk, 1) ? 0 : duk_to_int(duk, 1); tic_mem* memory = (tic_mem*)getDukMachine(duk); u8 value = memory->api.map_get(memory, &memory->ram.map, x, y); duk_push_uint(duk, value); return 1; }
static int sys1_fchmod(duk_context *ctx) { int fd = duk_to_int(ctx, 0); mode_t mode = duk_to_int(ctx, 1); int rc; rc = fchmod(fd, mode); duk_push_int(ctx, rc); return 1; }
static int sys1_lseek(duk_context *ctx) { int fd = duk_to_int(ctx, 0); off_t offset = duk_to_int(ctx, 1); int whence = duk_to_int(ctx, 2); off_t rc; rc = lseek(fd, offset, whence); duk_push_int(ctx, rc); return 1; }
static int sys1_listen(duk_context *ctx) { int rc; int fd = duk_to_int(ctx, 0); int backlog = duk_to_int(ctx, 1); rc = listen(fd, backlog); duk_push_number(ctx, rc); return 1; }
static int sys1_dup2(duk_context *ctx) { int rc; int oldfd = duk_to_int(ctx, 0); int newfd = duk_to_int(ctx, 1); rc = dup2(oldfd, newfd); duk_push_number(ctx, rc); return 1; }
static duk_ret_t duk_rectb(duk_context* duk) { s32 x = duk_to_int(duk, 0); s32 y = duk_to_int(duk, 1); s32 w = duk_to_int(duk, 2); s32 h = duk_to_int(duk, 3); s32 color = duk_to_int(duk, 4); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.rect_border(memory, x, y, w, h, color); return 0; }
static duk_ret_t duk_clip(duk_context* duk) { s32 x = duk_to_int(duk, 0); s32 y = duk_to_int(duk, 1); s32 w = duk_is_null_or_undefined(duk, 2) ? TIC80_WIDTH : duk_to_int(duk, 2); s32 h = duk_is_null_or_undefined(duk, 3) ? TIC80_HEIGHT : duk_to_int(duk, 3); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.clip(memory, x, y, w, h); return 0; }
static int sys1_socket(duk_context *ctx) { int fd; int domain = duk_to_int(ctx, 0); int type = duk_to_int(ctx, 1); int protocol = duk_to_int(ctx, 2); fd = socket(domain, type, protocol); duk_push_number(ctx, fd); return 1; }
static int sys1_write(duk_context *ctx) { int fd = duk_to_int(ctx, 0); size_t bufsize; void *buf = duk_to_buffer(ctx, 1, &bufsize); int len = duk_to_int(ctx, 2); ssize_t rc; rc = write(fd, buf, len); duk_push_int(ctx, rc); return 1; }
static duk_ret_t duk_map(duk_context* duk) { s32 x = duk_is_null_or_undefined(duk, 0) ? 0 : duk_to_int(duk, 0); s32 y = duk_is_null_or_undefined(duk, 1) ? 0 : duk_to_int(duk, 1); s32 w = duk_is_null_or_undefined(duk, 2) ? TIC_MAP_SCREEN_WIDTH : duk_to_int(duk, 2); s32 h = duk_is_null_or_undefined(duk, 3) ? TIC_MAP_SCREEN_HEIGHT : duk_to_int(duk, 3); s32 sx = duk_is_null_or_undefined(duk, 4) ? 0 : duk_to_int(duk, 4); s32 sy = duk_is_null_or_undefined(duk, 5) ? 0 : duk_to_int(duk, 5); u8 chromakey = duk_is_null_or_undefined(duk, 6) ? -1 : duk_to_int(duk, 6); s32 scale = duk_is_null_or_undefined(duk, 7) ? 1 : duk_to_int(duk, 7); tic_mem* memory = (tic_mem*)getDukMachine(duk); if (duk_is_null_or_undefined(duk, 8)) memory->api.map(memory, &memory->ram.map, &memory->ram.tiles, x, y, w, h, sx, sy, chromakey, scale); else { void* remap = duk_get_heapptr(duk, 8); RemapData data = {duk, remap}; memory->api.remap((tic_mem*)getDukMachine(duk), &memory->ram.map, &memory->ram.tiles, x, y, w, h, sx, sy, chromakey, scale, remapCallback, &data); } return 0; }
static duk_ret_t duk_line(duk_context* duk) { s32 x0 = duk_to_int(duk, 0); s32 y0 = duk_to_int(duk, 1); s32 x1 = duk_to_int(duk, 2); s32 y1 = duk_to_int(duk, 3); s32 color = duk_to_int(duk, 4); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.line(memory, x0, y0, x1, y1, color); return 0; }
static duk_ret_t duk_poke(duk_context* duk) { s32 address = duk_to_int(duk, 0); u8 value = duk_to_int(duk, 1) & 0xff; if(address >= 0 && address < sizeof(tic_ram)) { tic_machine* machine = getDukMachine(duk); *((u8*)&machine->memory.ram + address) = value; } return 0; }
static duk_ret_t duk_spr(duk_context* duk) { static u8 colors[TIC_PALETTE_SIZE]; s32 count = 0; s32 index = duk_is_null_or_undefined(duk, 0) ? 0 : duk_to_int(duk, 0); s32 x = duk_is_null_or_undefined(duk, 1) ? 0 : duk_to_int(duk, 1); s32 y = duk_is_null_or_undefined(duk, 2) ? 0 : duk_to_int(duk, 2); { if(!duk_is_null_or_undefined(duk, 3)) { if(duk_is_array(duk, 3)) { for(s32 i = 0; i < TIC_PALETTE_SIZE; i++) { duk_get_prop_index(duk, 3, i); if(duk_is_null_or_undefined(duk, -1)) { duk_pop(duk); break; } else { colors[i] = duk_to_int(duk, -1); count++; duk_pop(duk); } } } else { colors[0] = duk_to_int(duk, 3); count = 1; } } } s32 scale = duk_is_null_or_undefined(duk, 4) ? 1 : duk_to_int(duk, 4); tic_flip flip = duk_is_null_or_undefined(duk, 5) ? tic_no_flip : duk_to_int(duk, 5); tic_rotate rotate = duk_is_null_or_undefined(duk, 6) ? tic_no_rotate : duk_to_int(duk, 6); s32 w = duk_is_null_or_undefined(duk, 7) ? 1 : duk_to_int(duk, 7); s32 h = duk_is_null_or_undefined(duk, 8) ? 1 : duk_to_int(duk, 8); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.sprite_ex(memory, &memory->ram.tiles, index, x, y, w, h, colors, count, scale, flip, rotate); return 0; }
static duk_ret_t duk_tri(duk_context* duk) { s32 pt[6]; for(s32 i = 0; i < COUNT_OF(pt); i++) pt[i] = duk_to_int(duk, i); s32 color = duk_to_int(duk, 6); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.tri(memory, pt[0], pt[1], pt[2], pt[3], pt[4], pt[5], color); return 0; }
static duk_ret_t duk_sync(duk_context* duk) { tic_mem* memory = (tic_mem*)getDukMachine(duk); u32 mask = duk_is_null_or_undefined(duk, 0) ? 0 : duk_to_int(duk, 0); s32 bank = duk_is_null_or_undefined(duk, 1) ? 0 : duk_to_int(duk, 1); bool toCart = duk_is_null_or_undefined(duk, 2) ? false : duk_to_boolean(duk, 2); if(bank >= 0 && bank < TIC_BANKS) memory->api.sync(memory, mask, bank, toCart); else return duk_error(duk, DUK_ERR_ERROR, "sync() error, invalid bank"); return 0; }
static duk_ret_t duk_circb(duk_context* duk) { s32 radius = duk_to_int(duk, 2); if(radius < 0) return 0; s32 x = duk_to_int(duk, 0); s32 y = duk_to_int(duk, 1); s32 color = duk_to_int(duk, 3); tic_mem* memory = (tic_mem*)getDukMachine(duk); memory->api.circle_border(memory, x, y, radius, color); return 0; }
static duk_ret_t duk_memset(duk_context* duk) { s32 dest = duk_to_int(duk, 0); u8 value = duk_to_int(duk, 1); s32 size = duk_to_int(duk, 2); s32 bound = sizeof(tic_ram) - size; if(size >= 0 && size <= sizeof(tic_ram) && dest >= 0 && dest <= bound) { u8* base = (u8*)&getDukMachine(duk)->memory; memset(base + dest, value, size); } return 0; }
static duk_ret_t duk_poke4(duk_context* duk) { s32 address = duk_to_int(duk, 0); u8 value = duk_to_int(duk, 1) & 0xff; if(address >= 0 && address < sizeof(tic_ram)*2) { tic_mem* memory = (tic_mem*)getDukMachine(duk); tic_tool_poke4((u8*)&memory->ram, address, value); } return 0; }
int* getIntArray(duk_context *ctx, int stackIndex) { static int* result = NULL; if(duk_is_array(ctx, stackIndex)) { int resultLen = duk_get_length(ctx, stackIndex); result = (int*)malloc( resultLen * sizeof(int) ); memset(result,0,resultLen); duk_enum(ctx, stackIndex, DUK_ENUM_ARRAY_INDICES_ONLY); // NOT stackIndex because waits enumIndex that is -1 int idx=0; while (duk_next(ctx, -1, 1)) { // in JS/duktape toto[1] <=> toto["1"] // that's why keys are strings const char* k = duk_to_string(ctx, -2); int v = duk_to_int(ctx, -1); //printf("key=%s, value=%d\n", k, v); result[idx++] = v; duk_pop_2(ctx); } duk_pop(ctx); // duk_enum } else { printf("Found NO array\n"); } return result; }
duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) { duk_bool_t frac_undefined; duk_small_int_t frac_digits; duk_double_t d; duk_small_int_t c; duk_small_uint_t n2s_flags; d = duk__push_this_number_plain(ctx); frac_undefined = duk_is_undefined(ctx, 0); duk_to_int(ctx, 0); /* for side effects */ c = (duk_small_int_t) DUK_FPCLASSIFY(d); if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) { goto use_to_string; } frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20); n2s_flags = DUK_N2S_FLAG_FORCE_EXP | (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT); duk_numconv_stringify(ctx, 10 /*radix*/, frac_digits + 1 /*leading digit + fractions*/, n2s_flags /*flags*/); return 1; use_to_string: DUK_ASSERT_TOP(ctx, 2); duk_to_string(ctx, -1); return 1; }
static duk_ret_t duk_pmem(duk_context* duk) { tic_machine* machine = getDukMachine(duk); tic_mem* memory = &machine->memory; u32 index = duk_to_int(duk, 0); if(index < TIC_PERSISTENT_SIZE) { u32 val = memory->persistent.data[index]; if(!duk_is_null_or_undefined(duk, 1)) { memory->persistent.data[index] = duk_to_uint(duk, 1); machine->data->syncPMEM = true; } duk_push_int(duk, val); return 1; } else return duk_error(duk, DUK_ERR_ERROR, "invalid persistent memory index\n"); return 0; }