From 4ac252adaa5541c6f0997bee20f9fa1771bc8e98 Mon Sep 17 00:00:00 2001 From: "jett@monstersgoboom.com" Date: Thu, 28 Sep 2017 09:15:04 -0400 Subject: [PATCH] textri command added to js & lua supports use_map ( i.e. render like a map ) supports chroma ( i.e. ignore color ) --- src/jsapi.c | 24 ++++++++++ src/luaapi.c | 38 +++++++++++++++- src/tic.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/tic.h | 2 +- src/ticapi.h | 1 + 5 files changed, 187 insertions(+), 2 deletions(-) diff --git a/src/jsapi.c b/src/jsapi.c index 66a26dd..b090deb 100644 --- a/src/jsapi.c +++ b/src/jsapi.c @@ -644,6 +644,29 @@ static duk_ret_t duk_tri(duk_context* duk) return 0; } +static duk_ret_t duk_textri(duk_context* duk) +{ + s32 pt[12]; + + for (s32 i = 0; i < COUNT_OF(pt); i++) + pt[i] = duk_to_int(duk, i); + tic_mem* memory = (tic_mem*)getDukMachine(duk); + bool use_map = duk_is_null_or_undefined(duk, 12) ? false : duk_to_boolean(duk, 12); + u8 chroma = duk_is_null_or_undefined(duk, 13) ? 0xff : duk_to_int(duk, 13); + + memory->api.textri(memory, pt[0], pt[1], // xy 1 + pt[2], pt[3], // xy 2 + pt[4], pt[5], // xy 3 + pt[6], pt[7], // uv 1 + pt[8], pt[9], // uv 2 + pt[10], pt[11],// uv 3 + use_map, // usemap + chroma); // chroma + + return 0; +} + + static duk_ret_t duk_clip(duk_context* duk) { s32 x = duk_to_int(duk, 0); @@ -724,6 +747,7 @@ static const struct{duk_c_function func; s32 params;} ApiFunc[] = {duk_circ, 4}, {duk_circb, 4}, {duk_tri, 7}, + {duk_textri,12}, {duk_clip, 4}, {duk_music, 4}, {duk_sync, 0}, diff --git a/src/luaapi.c b/src/luaapi.c index f95533e..c005e57 100644 --- a/src/luaapi.c +++ b/src/luaapi.c @@ -290,6 +290,42 @@ static s32 lua_tri(lua_State* lua) return 0; } +static s32 lua_textri(lua_State* lua) +{ + s32 top = lua_gettop(lua); + + if (top >= 12) + { + float pt[12]; + + for (s32 i = 0; i < COUNT_OF(pt); i++) + pt[i] = getLuaNumber(lua, i + 1); + + tic_mem* memory = (tic_mem*)getLuaMachine(lua); + u8 chroma = 0xff; + bool use_map = false; + + // check for use map + if (top >= 13) + use_map = lua_toboolean(lua, 13); + // check for chroma + if (top >= 14) + chroma = (u8)getLuaNumber(lua, 14); + + memory->api.textri(memory, pt[0], pt[1], // xy 1 + pt[2], pt[3], // xy 2 + pt[4], pt[5], // xy 3 + pt[6], pt[7], // uv 1 + pt[8], pt[9], // uv 2 + pt[10], pt[11], // uv 3 + use_map, // use map + chroma); // chroma + } + else luaL_error(lua, "invalid parameters, textri(x1,y1,x2,y2,x3,y3,u1,v1,u2,v2,u3,v3,[use_map=false],[chroma=off])\n"); + return 0; +} + + static s32 lua_clip(lua_State* lua) { s32 top = lua_gettop(lua); @@ -1013,7 +1049,7 @@ static const lua_CFunction ApiFunc[] = lua_rectb, lua_spr, lua_btn, lua_btnp, lua_sfx, lua_map, lua_mget, lua_mset, lua_peek, lua_poke, lua_peek4, lua_poke4, lua_memcpy, lua_memset, lua_trace, lua_pmem, lua_time, lua_exit, lua_font, lua_mouse, - lua_circ, lua_circb, lua_tri, lua_clip, lua_music, lua_sync + lua_circ, lua_circb, lua_tri, lua_textri, lua_clip, lua_music, lua_sync }; STATIC_ASSERT(api_func, COUNT_OF(ApiKeywords) == COUNT_OF(ApiFunc)); diff --git a/src/tic.c b/src/tic.c index 9771fe4..fcdf4d4 100644 --- a/src/tic.c +++ b/src/tic.c @@ -711,6 +711,10 @@ static struct { s16 Left[TIC80_HEIGHT]; s16 Right[TIC80_HEIGHT]; + float ULeft[TIC80_HEIGHT]; + float VLeft[TIC80_HEIGHT]; + float URight[TIC80_HEIGHT]; + float VRight[TIC80_HEIGHT]; } SidesBuffer; static void initSidesBuffer() @@ -728,6 +732,26 @@ static void setSidePixel(s32 x, s32 y) } } +static void setSideTexPixel(s32 x, s32 y, float u, float v) +{ + int yy = (int)y; + if (yy >= 0 && yy < TIC80_HEIGHT) + { + if (x < SidesBuffer.Left[yy]) + { + SidesBuffer.Left[yy] = x; + SidesBuffer.ULeft[yy] = u; + SidesBuffer.VLeft[yy] = v; + } + if (x > SidesBuffer.Right[yy]) + { + SidesBuffer.Right[yy] = x; + SidesBuffer.URight[yy] = u; + SidesBuffer.VRight[yy] = v; + } + } +} + static void api_circle(tic_mem* memory, s32 xm, s32 ym, u32 radius, u8 color) { tic_machine* machine = (tic_machine*)memory; @@ -805,6 +829,105 @@ static void api_tri(tic_mem* memory, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3, s32 setPixel(machine, x, y, color); } + +typedef struct +{ + float x, y, u, v; +} TexVert; + + +static void ticTexLine(tic_mem* memory, TexVert *v0, TexVert *v1) +{ + int iy; + TexVert *top = v0; + TexVert *bot = v1; + + if (bot->y < top->y) + { + top = v1; + bot = v0; + } + + float dy = bot->y - top->y; + if ((int)dy == 0) return; + + float step_x = (bot->x - top->x) / dy; + float step_u = (bot->u - top->u) / dy; + float step_v = (bot->v - top->v) / dy; + + float x = top->x; + float y = top->y; + float u = top->u; + float v = top->v; + for (; y < (int)bot->y; y++) + { + setSideTexPixel(x, y, u, v); + x += step_x; + u += step_u; + v += step_v; + } +} + +static void api_textri(tic_mem* memory, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3, s32 y3, s32 u1, s32 v1, s32 u2, s32 v2, s32 u3, s32 v3,bool use_map,u8 chroma) +{ + tic_machine* machine = (tic_machine*)memory; + TexVert V0, V1, V2; + const u8* ptr = memory->ram.gfx.tiles[0].data; + const u8* map = memory->ram.gfx.map.data; + + V0.x = (float)x1; V0.y = (float)y1; V0.u = (float)u1; V0.v = (float)v1; + V1.x = (float)x2; V1.y = (float)y2; V1.u = (float)u2; V1.v = (float)v2; + V2.x = (float)x3; V2.y = (float)y3; V2.u = (float)u3; V2.v = (float)v3; + initSidesBuffer(); + + ticTexLine(memory, &V0, &V1); + ticTexLine(memory, &V1, &V2); + ticTexLine(memory, &V2, &V0); + + { + for (s32 y = 0; y < TIC80_HEIGHT; y++) + { + float width = SidesBuffer.Right[y] - SidesBuffer.Left[y]; + if (width > 0) + { + float du = (SidesBuffer.URight[y] - SidesBuffer.ULeft[y]) / width; + float dv = (SidesBuffer.VRight[y] - SidesBuffer.VLeft[y]) / width; + float u = SidesBuffer.ULeft[y]; + float v = SidesBuffer.VLeft[y]; + + for (s32 x = (int)SidesBuffer.Left[y]; x <= (int)SidesBuffer.Right[y]; ++x) + { + if ((x >= 0) && (x < TIC80_WIDTH)) + { + if (use_map == true) + { + int iu = (int)u % 1920; + int iv = (int)v % 1088; + u8 tile = map[(iv>>3) * TIC_MAP_WIDTH + (iu>>3)]; + u8 *buffer = &ptr[tile << 5]; + u8 color = tic_tool_peek4(buffer, (iu & 7) + ((iv & 7) << 3)); + if (color != chroma) + setPixel(machine, x, y, color); + } + else + { + int iu = (int)(u) & 127; + int iv = (int)(v) & 255; + u8 *buffer = &ptr[((iu >> 3) + ((iv >> 3) << 4)) << 5]; + u8 color = tic_tool_peek4(buffer, (iu & 7) + ((iv & 7) << 3)); + if (color != chroma) + setPixel(machine, x, y, color); + } + } + u += du; + v += dv; + } + } + } + } +} + + static void api_sprite(tic_mem* memory, const tic_gfx* src, s32 index, s32 x, s32 y, u8* colors, s32 count) { drawSprite(memory, src, index, x, y, colors, count, 1, tic_no_flip, tic_no_rotate); @@ -1536,6 +1659,7 @@ static void initApi(tic_api* api) INIT_API(circle); INIT_API(circle_border); INIT_API(tri); + INIT_API(textri); INIT_API(clip); INIT_API(sfx); INIT_API(sfx_stop); diff --git a/src/tic.h b/src/tic.h index 5328409..6a59513 100644 --- a/src/tic.h +++ b/src/tic.h @@ -104,7 +104,7 @@ #define API_KEYWORDS {"TIC", "scanline", "print", "cls", "pix", "line", "rect", "rectb", \ "spr", "btn", "btnp", "sfx", "map", "mget", "mset", "peek", "poke", "peek4", "poke4", \ - "memcpy", "memset", "trace", "pmem", "time", "exit", "font", "mouse", "circ", "circb", "tri", \ + "memcpy", "memset", "trace", "pmem", "time", "exit", "font", "mouse", "circ", "circb", "tri", "textri", \ "clip", "music", "sync"} #define TIC_FONT_CHARS 128 diff --git a/src/ticapi.h b/src/ticapi.h index 340a118..78962a4 100644 --- a/src/ticapi.h +++ b/src/ticapi.h @@ -82,6 +82,7 @@ typedef struct void (*circle) (tic_mem* memory, s32 x, s32 y, u32 radius, u8 color); void (*circle_border) (tic_mem* memory, s32 x, s32 y, u32 radius, u8 color); void (*tri) (tic_mem* memory, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3, s32 y3, u8 color); + void (*textri) (tic_mem* memory, s32 x1, s32 y1, s32 x2, s32 y2, s32 x3, s32 y3, s32 u1, s32 v1, s32 u2, s32 v2, s32 u3, s32 v3 ,bool use_map,u8 chroma); void (*clip) (tic_mem* memory, s32 x, s32 y, s32 width, s32 height); void (*sfx) (tic_mem* memory, s32 index, s32 note, s32 octave, s32 duration, s32 channel); void (*sfx_stop) (tic_mem* memory, s32 channel);