void * sml_obj_dup(void *obj) { void **slot, *newobj; size_t obj_size; switch (OBJ_TYPE(obj)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_BOXED_ARRAY: case OBJTYPE_UNBOXED_VECTOR: case OBJTYPE_BOXED_VECTOR: obj_size = OBJ_SIZE(obj); slot = sml_push_tmp_rootset(1); *slot = obj; newobj = sml_obj_alloc(OBJ_TYPE(obj), obj_size); memcpy(newobj, *slot, obj_size); sml_pop_tmp_rootset(slot); return newobj; case OBJTYPE_RECORD: obj_size = OBJ_SIZE(obj); slot = sml_push_tmp_rootset(1); *slot = obj; newobj = sml_record_alloc(obj_size); memcpy(newobj, *slot, obj_size + SIZEOF_BITMAP * OBJ_BITMAPS_LEN(obj_size)); sml_pop_tmp_rootset(slot); return newobj; default: sml_fatal(0, "BUG: invalid object type : %d", OBJ_TYPE(obj)); } }
void sml_obj_enum_ptr(void *obj, void (*trace)(void **, void *), void *data) { unsigned int i; unsigned int *bitmaps; /* DBG("%p: size=%lu, type=%08x", obj, (unsigned long)OBJ_SIZE(obj), (unsigned int)OBJ_TYPE(obj)); */ switch (OBJ_TYPE(obj)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_UNBOXED_VECTOR: case OBJTYPE_INTINF: break; case OBJTYPE_BOXED_ARRAY: case OBJTYPE_BOXED_VECTOR: for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) trace((void**)obj + i, data); break; case OBJTYPE_RECORD: bitmaps = OBJ_BITMAP(obj); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) { if (BITMAP_BIT(bitmaps, i) != TAG_UNBOXED) trace((void**)obj + i, data); } break; default: sml_fatal(0, "BUG: invalid object type : %d", OBJ_TYPE(obj)); } }
/* for debug */ static void obj_dump__(int indent, void *obj) { unsigned int i; unsigned int *bitmap; void **field = obj; char *buf; if (obj == NULL) { sml_debug("%*sNULL\n", indent, ""); return; } switch (OBJ_TYPE(obj)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_UNBOXED_VECTOR: sml_debug("%*s%p:%u:%s\n", indent, "", obj, OBJ_SIZE(obj), (OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY) ? "UNBOXED_ARRAY" : "UNBOXED_VECTOR"); for (i = 0; i < OBJ_SIZE(obj) / sizeof(unsigned int); i++) sml_debug("%*s0x%08x\n", indent + 2, "", ((unsigned int *)field)[i]); for (i = i * sizeof(unsigned int); i < OBJ_SIZE(obj); i++) sml_debug("%*s0x%02x\n", indent + 2, "", ((unsigned char*)field)[i]); break; case OBJTYPE_BOXED_ARRAY: case OBJTYPE_BOXED_VECTOR: sml_debug("%*s%p:%u:%s\n", indent, "", obj, OBJ_SIZE(obj), (OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY) ? "BOXED_ARRAY" : "BOXED_VECTOR"); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) obj_dump__(indent + 2, field[i]); for (i = i * sizeof(void*); i < OBJ_SIZE(obj); i++) sml_debug("%*s0x%02x\n", indent + 2, "", ((char*)field)[i]); break; case OBJTYPE_RECORD: sml_debug("%*s%p:%u:RECORD\n", indent, "", obj, OBJ_SIZE(obj)); bitmap = OBJ_BITMAP(obj); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap, i) != TAG_UNBOXED) obj_dump__(indent + 2, field[i]); else sml_debug("%*s%p\n", indent + 2, "", field[i]); } break; default: sml_debug("%*s%p:%u:unknown type %u", indent, "", obj, OBJ_SIZE(obj), OBJ_TYPE(obj)); break; } }
void SpriteRenderer::update() { for(int i = 0; i < 128; ++i) { // OAM[i].attr0 = OBJ_Y(80) | OBJ_SHAPE(0) | OBJ_256_COLOR; // OAM[i].attr1 = OBJ_X(120) | OBJ_SIZE(2); // OAM[i].attr2 = OBJ_CHAR(8) | OBJ_PALETTE(0) | OBJ_PRIORITY(0); Sprite& sprite = sprites[i]; if (sprite.is_enabled()) { OAM[i].attr0 = OBJ_Y((sprite.get_y() - sprite.get_data().get_y_align() - y_offset) & 0xFF) | OBJ_SHAPE(0) | OBJ_256_COLOR; OAM[i].attr1 = OBJ_X((sprite.get_x() - sprite.get_data().get_x_align() - x_offset) & 0xFF) | OBJ_SIZE(2) | (sprite.get_vflip() ? OBJ_VFLIP : 0) | (sprite.get_hflip() ? OBJ_HFLIP : 0); OAM[i].attr2 = OBJ_CHAR(sprite.get_data().get_char_addr(sprite.get_frame())) | OBJ_PALETTE(0) | OBJ_PRIORITY(0); } else { OAM[i].attr0 = OBJ_DISABLE; // OBJ_Y(80) | OBJ_SHAPE(0) | OBJ_256_COLOR; OAM[i].attr1 = 0; // OBJ_X(120) | OBJ_SIZE(2); OAM[i].attr2 = 0; // OBJ_CHAR(8) | OBJ_PALETTE(0) | OBJ_PRIORITY(0); } } }
int prim_Timer_getTimes(int *ret) { #ifdef HAVE_TIMES struct tms tms; static long clocks_per_sec = 0; clock_t clk; ASSERT(OBJ_TYPE(ret) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(ret) >= sizeof(int) * 6); if (clocks_per_sec == 0) clocks_per_sec = sysconf(_SC_CLK_TCK); clk = times(&tms); ret[0] = tms.tms_stime / clocks_per_sec; ret[1] = (tms.tms_stime % clocks_per_sec) * 1000000 / clocks_per_sec; ret[2] = tms.tms_utime / clocks_per_sec; ret[3] = (tms.tms_utime % clocks_per_sec) * 1000000 / clocks_per_sec; /* FIXME: do we put GC time still here? */ ret[4] = 0; /* GC seconds */ ret[5] = 0; /* GC microseconds */ return (clk == (clock_t)-1 ? -1 : 0); #else struct timeval tv; int err; ASSERT(OBJ_TYPE(ret) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(ret) >= sizeof(int) * 6); err = gettimeofday(&tv, NULL); ret[0] = 0; /* sys seconds */ ret[1] = 0; /* sys microseconds */ ret[2] = tv.tv_sec; ret[3] = tv.tv_usec; /* FIXME: do we put GC time still here? */ ret[4] = 0; /* GC seconds */ ret[5] = 0; /* GC microseconds */ return err; #endif /* HAVE_TIMES */ }
void sprite_init(Sprite* sprite, int gfxID) { const int oamIdx = oam_pool_find_fist_empty(); sprite->gfxID = gfxID; SpriteEntry* oam = &sm_OAMCopy[oamIdx]; sprite->oam = oam; oam->attribute[0] = OBJ_256_COLOR | OBJ_SHAPE(0); oam->attribute[1] = OBJ_SIZE(1); oam->attribute[2] = gfxID; }
int prim_GenericOS_read(int fd, char *buf, unsigned int offset, unsigned int len) { ASSERT(OBJ_TYPE(buf) == OBJTYPE_UNBOXED_ARRAY); ASSERT(offset + len <= OBJ_SIZE(buf)); #ifdef HAVE_INTERACTIVE_MODE if (interactive_mode && fd == 0) return interact_prim_read(fd, buf, offset, len); #endif /* HAVE_INTERACTIVE_MODE */ return read(fd, buf + offset, len); }
int prim_Time_gettimeofday(int *ret) { struct timeval tv; int err; ASSERT(OBJ_TYPE(ret) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(ret) >= sizeof(int) * 2); err = gettimeofday(&tv, NULL); ret[0] = tv.tv_sec; ret[1] = tv.tv_usec; return err; }
void prim_CopyMemory(void *dst, unsigned int doff, const void *src, unsigned int soff, unsigned int len, unsigned int tag) { void **writeaddr, **srcaddr; unsigned int i; ASSERT((tag == TAG_UNBOXED && (OBJ_TYPE(dst) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(dst) == OBJTYPE_UNBOXED_VECTOR)) || (tag == TAG_BOXED && (OBJ_TYPE(dst) == OBJTYPE_BOXED_ARRAY || OBJ_TYPE(dst) == OBJTYPE_BOXED_VECTOR))); ASSERT((tag == TAG_UNBOXED && (OBJ_TYPE(src) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(src) == OBJTYPE_UNBOXED_VECTOR)) || (tag == TAG_BOXED && (OBJ_TYPE(src) == OBJTYPE_BOXED_ARRAY || OBJ_TYPE(src) == OBJTYPE_BOXED_VECTOR))); ASSERT(doff + len <= OBJ_SIZE(dst)); ASSERT(soff + len <= OBJ_SIZE(src)); if (tag == TAG_UNBOXED) { memmove((char*)dst + doff, (char*)src + soff, len); } else if (src != dst || doff < soff) { writeaddr = (void**)((char*)dst + doff); srcaddr = (void**)((char*)src + soff); for (i = 0; i < len / sizeof(void*); i++) sml_write(dst, writeaddr++, *(srcaddr++)); } else { writeaddr = (void**)((char*)dst + doff + len); srcaddr = (void**)((char*)src + soff + len); for (i = 0; i < len / sizeof(void*); i++) sml_write(dst, --writeaddr, *(--srcaddr)); } }
static void set_stat(struct stat *st, unsigned int *ret) { ASSERT(OBJ_TYPE(ret) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(ret) >= sizeof(unsigned int) * 6); ret[0] = st->st_dev; ret[1] = st->st_ino; ret[3] = st->st_atime; ret[4] = st->st_mtime; ret[5] = st->st_size; #if S_IFIFO == ML_S_IFIFO \ && S_IFCHR == ML_S_IFCHR \ && S_IFDIR == ML_S_IFDIR \ && S_IFBLK == ML_S_IFBLK \ && S_IFREG == ML_S_IFREG \ && S_IFLNK == ML_S_IFLNK \ && S_IFSOCK == ML_S_IFSOCK \ && S_ISUID == ML_S_ISUID \ && S_ISGID == ML_S_ISGID \ && S_ISVTX == ML_S_ISVTX \ && S_IRUSR == ML_S_IRUSR \ && S_IWUSR == ML_S_IWUSR \ && S_IXUSR == ML_S_IXUSR ret[2] = st->st_mode; #else { unsigned int mode = 0; mode |= (st->st_mode & S_IFIFO) ? ML_S_IFIFO : 0; mode |= (st->st_mode & S_IFCHR) ? ML_S_IFCHR : 0; mode |= (st->st_mode & S_IFDIR) ? ML_S_IFDIR : 0; mode |= (st->st_mode & S_IFBLK) ? ML_S_IFBLK : 0; mode |= (st->st_mode & S_IFREG) ? ML_S_IFREG : 0; mode |= (st->st_mode & S_IFLNK) ? ML_S_IFLNK : 0; mode |= (st->st_mode & S_IFSOCK) ? ML_S_IFSOCK : 0; mode |= (st->st_mode & S_ISUID) ? ML_S_ISUID : 0; mode |= (st->st_mode & S_ISGID) ? ML_S_ISGID : 0; mode |= (st->st_mode & S_ISVTX) ? ML_S_ISVTX : 0; mode |= (st->st_mode & S_IRUSR) ? ML_S_IRUSR : 0; mode |= (st->st_mode & S_IWUSR) ? ML_S_IWUSR : 0; mode |= (st->st_mode & S_IXUSR) ? ML_S_IXUSR : 0; ret[2] = mode; } #endif }
void * sml_obj_alloc(unsigned int objtype, size_t payload_size) { void *obj; ASSERT(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); obj = sml_alloc(payload_size, sml_load_frame_pointer()); OBJ_HEADER(obj) = OBJ_HEADER_WORD(objtype, payload_size); ASSERT(OBJ_SIZE(obj) == payload_size); ASSERT(OBJ_TYPE(obj) == OBJTYPE_UNBOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_BOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY); ASSERT(OBJ_GC1(obj) == 0 && OBJ_GC2(obj) == 0); return obj; }
void * sml_record_alloc(size_t payload_size) { void *obj; size_t bitmap_size; ASSERT(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); payload_size = ALIGNSIZE(payload_size, sizeof(void*)); bitmap_size = OBJ_BITMAPS_LEN(payload_size) * SIZEOF_BITMAP; obj = sml_alloc(payload_size + bitmap_size, sml_load_frame_pointer()); OBJ_HEADER(obj) = OBJ_HEADER_WORD(OBJTYPE_RECORD, payload_size); ASSERT(OBJ_SIZE(obj) == payload_size); ASSERT(OBJ_TYPE(obj) == OBJTYPE_RECORD); ASSERT(OBJ_GC1(obj) == 0 && OBJ_GC2(obj) == 0); return obj; }
/* for debug */ void sml_heap_dump() { char *cur; unsigned int size, allocsize; sml_debug("from space : %p - %p\n", HEAP_START(sml_heap_from_space), sml_heap_from_space.limit); cur = HEAP_START(sml_heap_from_space); while (cur < sml_heap_from_space.free) { size = OBJ_TOTAL_SIZE(cur); allocsize = HEAP_ROUND_SIZE(size); sml_debug("%p : type=%08x, size=%u, total=%u, alloc=%u\n", cur, OBJ_TYPE(cur), OBJ_SIZE(cur), size, allocsize); cur += allocsize; } }
void * sml_obj_alloc(unsigned int objtype, size_t payload_size) { void *obj; assert(sml_saved()); assert(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); obj = sml_alloc(payload_size); OBJ_HEADER(obj) = OBJ_HEADER_WORD(objtype, payload_size); assert(OBJ_SIZE(obj) == payload_size); assert(OBJ_TYPE(obj) == OBJTYPE_UNBOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_BOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_INTINF); return obj; }
static int finalizer_cmp(void *, void *); static sml_tree_t finalizer_set = SML_TREE_INITIALIZER(finalizer_cmp, xmalloc, free); static struct finalizer *active_finalizers; static void * persistent_node_alloc(size_t size) { return sml_obstack_alloc(&persistent_node_obstack, size); } static void dump_malloc(void *item, void *data ATTR_UNUSED) { sml_notice("%p (flags=%08x, size=%lu)", item, MALLOC_HEAD(item)->flags, (unsigned long)OBJ_SIZE(item)); } static void dump_finalizer(void *item, void *data ATTR_UNUSED) { struct finalizer *final = item; sml_notice("active=%d, obj=%p, fn=%p", final->active, final->obj, final->finalizer); } static void dump_callback(void *item, void *data ATTR_UNUSED) { struct callback_item *cls = item; while (cls) {
int prim_GenericOS_poll(int *fdary, unsigned int *evary, int timeout_sec, int timeout_usec) { #if (defined(HAVE_CONFIG_H) && defined(HAVE_SELECT)) || !defined(MINGW32) || !defined(HAVE_CONFIG_H) fd_set infds, outfds, prifds; struct timeval timeout; unsigned int i; int nfds, err; /* FIXME: untested */ ASSERT(OBJ_TYPE(fdary) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_TYPE(evary) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(fdary) == OBJ_SIZE(evary)); FD_ZERO(&infds); FD_ZERO(&outfds); FD_ZERO(&prifds); nfds = 0; for (i = 0; i < OBJ_SIZE(fdary) / sizeof(int); i++) { int fd = ((int*)fdary)[i], setfd = 0; unsigned int ev = ((unsigned int*)evary)[i]; if (ev & SML_POLLIN) { setfd = fd; FD_SET(fd, &infds); } if (ev & SML_POLLOUT) { setfd = fd; FD_SET(fd, &outfds); } if (ev & SML_POLLPRI) { setfd = fd; FD_SET(fd, &prifds); } nfds = (nfds > setfd) ? nfds : setfd; } nfds++; if (timeout_sec < 0 || timeout_usec < 0) { err = select(nfds, &infds, &outfds, &prifds, NULL); } else { timeout.tv_sec = timeout_sec; timeout.tv_usec = timeout_usec; err = select(nfds, &infds, &outfds, &prifds, &timeout); } if (err < 0) return err; for (i = 0; i < OBJ_SIZE(evary) / sizeof(unsigned int); i++) { unsigned int ev = 0; if (!FD_ISSET(((int*)fdary)[i], &infds)) ev |= SML_POLLIN; if (!FD_ISSET(((int*)fdary)[i], &outfds)) ev |= SML_POLLOUT; if (!FD_ISSET(((int*)fdary)[i], &prifds)) ev |= SML_POLLPRI; ((unsigned int*)evary)[i] = ev; } return err; #elif defined(HAVE_POLL) struct pollfd *fds; nfds_t nfds, i; int err; /* FIXME: untested */ ASSERT(OBJ_TYPE(fdary) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_TYPE(evary) == OBJTYPE_UNBOXED_ARRAY); ASSERT(OBJ_SIZE(fdary) == OBJ_SIZE(evary)); nfds = OBJ_SIZE(fdary) / sizeof(int); fds = xmalloc(nfds * sizeof(struct pollfd)); for (i = 0; i < nfds; i++) { unsigned int ev = ((unsigned int*)evary)[i]; fds[i].fd = ((int*)fdary)[i]; fds[i].events = 0; if (ev & SML_POLLIN) fds[i].events |= POLLIN; if (ev & SML_POLLOUT) fds[i].events |= POLLOUT; if (ev & SML_POLLPRI) fds[i].events |= POLLPRI; } if (timeout_sec < 0 || timeout_usec < 0) { err = poll(fds, nfds, -1); } else { /* ToDo: overflow check is needed? */ int timeout = timeout_sec * 1000 + timeout_usec / 1000; err = poll(fds, nfds, timeout); } if (err < 0) return err; for (i = 0; i < nfds; i++) { unsigned int ev = 0; if (fds[i].revents & POLLIN) ev |= SML_POLLIN; if (fds[i].revents & POLLOUT) ev |= SML_POLLOUT; if (fds[i].revents & POLLPRI) ev |= SML_POLLPRI; ((unsigned int*)evary)[i] = ev; } return err; #else errno = EIO; return -1; #endif /* HAVE_SELECT | HAVE_POLL */ }
SML_PRIMITIVE int sml_obj_equal(void *obj1, void *obj2) { unsigned int i, tag; unsigned int *bitmap1, *bitmap2; void **p1, **p2; if (obj1 == obj2) return 1; if (obj1 == NULL || obj2 == NULL) return 0; if (OBJ_SIZE(obj1) != OBJ_SIZE(obj2)) return 0; if (OBJ_TYPE(obj1) != OBJ_TYPE(obj2)) { if (OBJ_TYPE(obj1) == OBJTYPE_RECORD) { void *tmp = obj1; obj1 = obj2, obj2 = tmp; } else if (OBJ_TYPE(obj2) != OBJTYPE_RECORD) return 0; if (OBJ_TYPE(obj1) == OBJTYPE_UNBOXED_VECTOR) tag = TAG_UNBOXED; else if (OBJ_TYPE(obj1) == OBJTYPE_BOXED_VECTOR) tag = TAG_BOXED; else return 0; assert(OBJ_SIZE(obj2) % sizeof(void*) == 0); bitmap2 = OBJ_BITMAP(obj2); for (i = 0; i < OBJ_SIZE(obj2) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap2, i) != tag) return 0; } } switch (OBJ_TYPE(obj1)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_BOXED_ARRAY: return 0; case OBJTYPE_UNBOXED_VECTOR: return memcmp(obj1, obj2, OBJ_SIZE(obj1)) == 0; case OBJTYPE_BOXED_VECTOR: p1 = obj1; p2 = obj2; assert(OBJ_SIZE(obj1) % sizeof(void*) == 0); for (i = 0; i < OBJ_SIZE(obj1) / sizeof(void*); i++) { if (!sml_obj_equal(p1[i], p2[i])) return 0; } return 1; case OBJTYPE_INTINF: return sml_intinf_cmp((sml_intinf_t*)obj1, (sml_intinf_t*)obj2) == 0; case OBJTYPE_RECORD: bitmap1 = OBJ_BITMAP(obj1); bitmap2 = OBJ_BITMAP(obj2); p1 = obj1; p2 = obj2; assert(OBJ_NUM_BITMAPS(obj1) == OBJ_NUM_BITMAPS(obj2)); assert(OBJ_SIZE(obj1) % sizeof(void*) == 0); for (i = 0; i < OBJ_NUM_BITMAPS(obj1); i++) { if (bitmap1[i] != bitmap2[i]) return 0; } for (i = 0; i < OBJ_SIZE(obj1) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap1, i) == TAG_UNBOXED) { if (p1[i] != p2[i]) return 0; } else { if (!sml_obj_equal(p1[i], p2[i])) return 0; } } return 1; default: sml_fatal(0, "BUG: invalid object type : %d", OBJ_TYPE(obj1)); } }
int main() { irqInit(); SetMode((LCDC_BITS)(MODE_1 | BG0_ON | BG2_ON | OBJ_ENABLE)); irqSet(IRQ_VBLANK, vblank); irqEnable(IRQ_VBLANK); float xpos = 0; float ypos = 0; float xdir = 0; float ydir = 0; int dir = 0; BG_COLORS[0] = RGB5(31, 0, 31); CpuFastSet(tileset_img, OBJ_BASE_ADR, COPY32 | (256 * 16) / 4); CpuFastSet(tileset_pal, OBJ_COLORS, COPY32 | (256 / 4)); CpuFastSet(tileset_img, PATRAM4(0, 0), COPY32 | (256 * 16) / 4); CpuFastSet(tileset_pal, BG_COLORS, COPY32 | (256 / 4)); // mock up a map /* ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[0] = 0; ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[1] = 1; ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[32] = 32; ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[33] = 33; ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[64] = 64; ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK))[65] = 65; */ for (int y = 0; y < 32; ++y) { for (int x = 0; x < 32; ++x) { ((vu16*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[x + y * 32] = 5; } } for (int x = 0; x < 32; ++x) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[x] = 16; for (int x = 0; x < 32; ++x) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[31 * 32 + x] = 16; for (int y = 0; y < 32; ++y) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[y * 32] = 16; for (int y = 0; y < 32; ++y) ((vu8*)MAP_BASE_ADR(MAP_BASE_BLOCK + 1))[y * 32 + 31] = 16; BGCTRL[0] = SCREEN_BASE(MAP_BASE_BLOCK + 0) | CHAR_BASE(0) | BG_SIZE_0 | BG_16_COLOR | BG_PRIORITY(1); // | CHAR_PALETTE(1); BGCTRL[2] = SCREEN_BASE(MAP_BASE_BLOCK + 1) | CHAR_BASE(0) | BG_SIZE_1 | BG_16_COLOR | BG_PRIORITY(0); // | CHAR_PALETTE(1); float rot = 0.0f; float last_rot = rot; float bg_scroll = 0; int frame = 0; while (1) { int sprite_frame = (int(floor(bg_scroll)) >> 3) & 1; if (fabs(xdir) < 1e-1) sprite_frame = 0; // if (ypos > 0) sprite_frame = 2; int tile_start = sprite_frame * 2; int pal = 0; for (int i = 0; i < 128; ++i) { sprites[i].attr0 = ATTR0_DISABLED; } int sprite = 0; // sprites[sprite].attr0 = OBJ_Y(int(ypos) + 80 - 8) | ATTR0_COLOR_16 | ATTR0_WIDE; // sprites[sprite].attr1 = OBJ_X(int(xpos) + 120) | OBJ_SIZE(Sprite_16x8) | (dir ? ATTR1_FLIP_X : 0); sprites[sprite].attr0 = OBJ_Y(int(0) + 80 - 16) | ATTR0_COLOR_16 | ATTR0_WIDE; sprites[sprite].attr1 = OBJ_X(int(0) + 120 - 8) | OBJ_SIZE(Sprite_16x8) | (dir ? ATTR1_FLIP_X : 0); sprites[sprite].attr2 = OBJ_CHAR(tile_start) | ATTR2_PALETTE(pal); // | OBJ_TRANSLUCENT; sprite++; // sprites[sprite].attr0 = OBJ_Y(int(ypos) + 80) | ATTR0_COLOR_16 | ATTR0_SQUARE; // sprites[sprite].attr1 = OBJ_X(int(xpos) + 120) | OBJ_SIZE(Sprite_16x16) | (dir ? ATTR1_FLIP_X : 0); sprites[sprite].attr0 = OBJ_Y(int(0) + 80 - 8) | ATTR0_COLOR_16 | ATTR0_SQUARE; sprites[sprite].attr1 = OBJ_X(int(0) + 120 - 8) | OBJ_SIZE(Sprite_16x16) | (dir ? ATTR1_FLIP_X : 0); sprites[sprite].attr2 = OBJ_CHAR(tile_start + 32) | ATTR2_PALETTE(pal); // | OBJ_TRANSLUCENT; sprite++; float st = sin(last_rot); float ct = cos(last_rot); last_rot = last_rot + (rot - last_rot) * 0.1; int pa = int(0x100 * ct); int pb =-int(0x100 * st); int pc = int(0x100 * st); int pd = int(0x100 * ct); // don't setup any hw-regs until vblank VBlankIntrWait(); // setup bg0 scroll REG_BG0HOFS = int(bg_scroll) & 0xFFFF; // setup bg2 transform REG_BG2PA = pa; REG_BG2PB = pb; REG_BG2PC = pc; REG_BG2PD = pd; REG_BG2X = (int(xpos) << 8) - (pa * 120 + pb * 80); REG_BG2Y = (int(ypos) << 8) - (pc * 120 + pd * 80); ++frame; CpuSet(sprites, OAM, (128 * sizeof(OAM[0])) / 2); scanKeys(); u32 held = keysHeld(); u32 down = keysDown(); u32 up = keysUp(); float upx = sin(rot); float upy = -cos(rot); float leftx = upy; float lefty = -upx; if (KEY_UP & down) { xdir = upx * 5; ydir = upy * 5; } if (KEY_L & down) { rot += M_PI / 2; } if (KEY_R & down) { rot -= M_PI / 2; } /* if (KEY_L & up) { rot += M_PI / 4; } if (KEY_R & up) { rot -= M_PI / 4; } */ // external forces #if 0 xdir *= 0.95; // friction ydir *= 0.95; // friction #else float a = leftx * xdir + lefty * ydir; // dot(dir, left) float b = upx * xdir + upy * ydir; // dot(dir, up) float new_xdir = upx * b + 0.85 * leftx * a; float new_ydir = upy * b + 0.85 * lefty * a; xdir = new_xdir; ydir = new_ydir; #endif if (fabs(xdir) < 1e-1) xdir = 0; if (fabs(ydir) < 1e-1) ydir = 0; if (KEY_RIGHT & held) { xdir -= leftx * 0.5f; ydir -= lefty * 0.5f; dir = 0; } if (KEY_LEFT & held) { xdir += leftx * 0.5f; ydir += lefty * 0.5f; dir = 1; } xdir -= upx * 0.25; // gravity ydir -= upy * 0.25; // gravity float last_xpos = xpos; float last_ypos = ypos; // apply forces xpos += xdir; ypos += ydir; // resolve constraints if (xpos < 0) xpos = 0; if (xpos > 255) xpos = 255; if (ypos < 0) ypos = 0; if (ypos > 255) ypos = 255; float delta_xpos = last_xpos - xpos; float delta_ypos = last_ypos - ypos; bg_scroll += (delta_xpos * leftx + delta_ypos * lefty) * 0.5f; } return 0; }