diff --git a/Makefile b/Makefile index 5dee44b..caf2463 100644 --- a/Makefile +++ b/Makefile @@ -39,13 +39,13 @@ winexe: $(BUILD)$(OUTNAME) cp $(BUILD)$(OUTNAME) $(BUILD)$(OUTNAME).exe -win: LIBS+= -lws2_32 +win: LIBS+= -lws2_32 -lgdi32 win: all winexe -win-build: LIBS+= -lws2_32 +win-build: LIBS+= -lws2_32 -lgdi32 win-build: build winexe -win-debug: LIBS+= -lws2_32 +win-debug: LIBS+= -lws2_32 -lgdi32 win-debug: debug winexe $(BUILDDIRECTORIES): diff --git a/src/c/winapigpu.c b/src/c/winapigpu.c index b599cd5..79c91d6 100644 --- a/src/c/winapigpu.c +++ b/src/c/winapigpu.c @@ -6,11 +6,100 @@ #include #include +#define BYPP 4 +#define RES_X 800 +#define RES_Y 600 +#define CHARSW (RES_X / 8) +#define CHARSH (RES_Y / 16) + +#define XY_TO_WIN(x, y) (((y) * RES_X * BYPP) + ((x) * BYPP)) +#define XY_TO_COLBUF(x, y, z) (((((y) * CHARSW) + (x)) * 2) + (z)) +#define XY_TO_CHRBUF(x, y) (((y) * CHARSW) + (x)) + #define WINDOW_CLASS "LuPi2 GPU" #define WINDOW_TITLE "LuPi2" +#define uchar unsigned char + +uchar *screenbb = NULL; +HBITMAP screenbmap = NULL; +char *colbuf = 0; +ushort *chrbuf = 0; +int palette[256]; +float pal_yuv[768]; + +static inline float yuv_y(int r, int g, int b) { + float rf = r/255.0f; + float gf = g/255.0f; + float bf = b/255.0f; + return 0.299f * r + 0.587f * g + 0.114f * b; +} +static inline float yuv_u(int r, int g, int b) { + float rf = r/255.0f; + float gf = g/255.0f; + float bf = b/255.0f; + return -0.147f * r - 0.289f * g + 0.436f * b; +} +static inline float yuv_v(int r, int g, int b) { + float rf = r/255.0f; + float gf = g/255.0f; + float bf = b/255.0f; + return 0.615f * r - 0.515f * g - 0.100f * b; +} + +/**************************************/ + +static inline int win_draw_32(int x, int y, int bg, int fg, int chr, int cwd) { + int px, py; + int c = 0; + int* ptr; + + ptr = (int*) (&screenbb[XY_TO_WIN((x * 8), ((y * 16) + py))]); + for (py = 0; py < 16; py++) { + if (cwd == 2) { + c = (res_unifont[chr * 33 + 2 + (py * 2)] << 8) | res_unifont[chr * 33 + 1 + (py * 2)]; + } else if (cwd == 1) { + c = res_unifont[chr * 33 + 1 + py]; + } + for (px = (cwd == 2 ? 15 : 7); px >= 0; px--) { + ptr[px] = (c & 1) ? fg : bg; + c >>= 1; + } + ptr += (RES_X * BYPP) >> 2; + } +} + + + LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { + case WM_PAINT: { + logn("win: PAINT"); + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + screenbmap = CreateBitmap(RES_X, RES_Y, 1, BYPP * 8, (void*) screenbb); + + HDC src = CreateCompatibleDC(hdc); + SelectObject(src, screenbmap); + BitBlt(hdc, 0, 0, RES_X, RES_Y, src, 0, 0, SRCCOPY); + DeleteDC(src); + EndPaint(hwnd, &ps); + } + break; + case WM_CREATE: + logn("win: Create"); + screenbb = (uchar*) calloc(RES_X * RES_Y, BYPP); + //for(int i = 0; i < RES_X * RES_Y * BYPP; i++) screenbb[i] = (uchar) rand(); + win_draw_32(0, 0, 0, 0xFFFFFF, 'H', 1); + win_draw_32(1, 0, 0, 0xFFFFFF, 'e', 1); + win_draw_32(2, 0, 0, 0xFFFFFF, 'l', 1); + win_draw_32(3, 0, 0, 0xFFFFFF, 'l', 1); + win_draw_32(4 , 0, 0, 0xFFFFFF, 'o', 1); + + colbuf = (char *)malloc(2 * CHARSW * CHARSH); + chrbuf = (ushort *)malloc(2 * CHARSW * CHARSH); + + break; case WM_CLOSE: DestroyWindow(hwnd); exit(0); /* TODO: Push exit event? Or just remove gpu component?? */ @@ -24,7 +113,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return 0; } + + + static int l_open(lua_State *L) { + logn("win: INIT"); WNDCLASSEX wc; HWND hwnd; @@ -52,7 +145,7 @@ static int l_open(lua_State *L) { WINDOW_CLASS, WINDOW_TITLE, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, + CW_USEDEFAULT, CW_USEDEFAULT, RES_X, RES_Y, NULL, NULL, GetModuleHandle(NULL), NULL); if(hwnd == NULL) { @@ -64,13 +157,225 @@ static int l_open(lua_State *L) { ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); + InvalidateRect(hwnd, NULL, TRUE); + lua_pushboolean(L, 1); return 1; } +/**************************************/ + +static int win_draw(int x, int y, int bg, int fg, int chr) { + if (x < 0 || x >= CHARSW || y < 0 || y >= CHARSH || bg < 0 || bg >= 256 || fg < 0 || fg >= 256 + || chr < 0 || chr >= 65536) { + return 0; + } + + colbuf[XY_TO_COLBUF(x, y, 0)] = (char) bg; + colbuf[XY_TO_COLBUF(x, y, 1)] = (char) fg; + chrbuf[XY_TO_CHRBUF(x, y)] = (ushort) chr; + + int cwd = res_unifont[chr * 33]; + if (cwd == 2 && x < (CHARSW - 1)) { + chrbuf[XY_TO_CHRBUF(x + 1, y)] = (ushort) 0; + } + win_draw_32(x,y,palette[bg],palette[fg],chr,cwd); + return 0; +} + +static int win_copy(int x, int y, int w, int h, int x2, int y2) { + int i, j; + char* tmp = (char*) malloc(w*h*BYPP); + + for (j = 0; j < h; j++) { + char* ptr = &screenbb[XY_TO_WIN((x), ((y) + (j)))]; + memcpy(&tmp[w*j*BYPP], ptr, w*BYPP); + } + for (j = 0; j < h; j++) { + char* ptr = &screenbb[XY_TO_WIN((x2), (y2 + (j)))]; + memcpy(ptr, &tmp[w*j*BYPP], w*BYPP); + } + + free(tmp); +} + +static int l_set_palette (lua_State *L) { + int i = lua_tonumber(L, 1); + int pal = lua_tonumber(L, 2); + if(i >= 0 && i < 256) { + // calculate yuv + int r = (pal >> 16) & 0xFF; + int g = (pal >> 8) & 0xFF; + int b = pal & 0xFF; + pal_yuv[i*3] = yuv_y(r, g, b); + pal_yuv[i*3+1] = yuv_u(r, g, b); + pal_yuv[i*3+2] = yuv_v(r, g, b); + // set palette color + + palette[i] = pal; + } + return 0; +} + +static int l_put (lua_State *L) { + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + int bg = lua_tonumber(L, 3); + int fg = lua_tonumber(L, 4); + int chr = lua_tonumber(L, 5); + return win_draw(x, y, bg, fg, chr); +} + +static int l_get_nearest (lua_State *L) { + int nck = 0; + float ncv = 1000000; + int i; + int col = lua_tonumber(L, 1); + int r = (col >> 16) & 0xFF; + int g = (col >> 8) & 0xFF; + int b = (col) & 0xFF; + float coly = yuv_y(r, g, b); + float colu = yuv_u(r, g, b); + float colv = yuv_v(r, g, b); + float dist,dy,du,dv; + for (i = 0; i < 256; i++) { + if (palette[i] == col) { + lua_pushnumber(L, i); + return 1; + } + dy = coly - pal_yuv[i*3]; + du = colu - pal_yuv[i*3+1]; + dv = colv - pal_yuv[i*3+2]; + dist = dy*dy + du*du + dv*dv; + if (dist < ncv) { + nck = i; + ncv = dist; + } + } + lua_pushnumber(L, nck); + return 1; +} + +static int l_copy (lua_State *L) { + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + int w = lua_tonumber(L, 3); + int h = lua_tonumber(L, 4); + int tx = x+lua_tonumber(L, 5); + int ty = y+lua_tonumber(L, 6); + int j, px = x<<3, py = y<<4, pw = w<<3, ph = h<<4, ptx = tx<<3, pty = ty<<4; + + char* tmpcol = (char*) malloc(w*h*2); + char* tmpchr = (char*) malloc(w*h*2); + + for (j = 0; j < h; j++) { + memcpy(&tmpcol[j*w*2], &colbuf[XY_TO_COLBUF(x, y+j, 0)], w * 2); + memcpy(&tmpchr[j*w*2], &chrbuf[XY_TO_CHRBUF(x, y+j)], w * 2); + } + + win_copy(px, py, pw, ph, ptx, pty); + + for (j = 0; j < h; j++) { + memcpy(&colbuf[XY_TO_COLBUF(tx, ty+j, 0)], &tmpcol[j*w*2], w * 2); + memcpy(&chrbuf[XY_TO_CHRBUF(tx, ty+j)], &tmpchr[j*w*2], w * 2); + } + + free(tmpcol); + free(tmpchr); +} + +static int l_fill (lua_State *L) { + int x1 = lua_tonumber(L, 1); + int y1 = lua_tonumber(L, 2); + int x2 = lua_tonumber(L, 3); + int y2 = lua_tonumber(L, 4); + int bg = lua_tonumber(L, 5); + int fg = lua_tonumber(L, 6); + int chr = lua_tonumber(L, 7); + int i, j; + for (i = y1; i <= y2; i++) { + for (j = x1; j <= x2; j++) { + win_draw(j, i, bg, fg, chr); + } + } + return 0; +} + +static int l_winfill (lua_State *L) { + int x1 = lua_tonumber(L, 1); + int y1 = lua_tonumber(L, 2); + int x2 = lua_tonumber(L, 3); + int y2 = lua_tonumber(L, 4); + int bg = lua_tonumber(L, 5); + int fg = lua_tonumber(L, 6); + int chr = lua_tonumber(L, 7); + int i, j; + for (i = y1; i <= y2; i++) { + for (j = x1; j <= x2; j++) { + win_draw(j, i, bg, fg, chr); + } + } + return 0; +} + +static int l_get_width (lua_State *L) { + lua_pushnumber(L, CHARSW); + return 1; +} + +static int l_get_height (lua_State *L) { + lua_pushnumber(L, CHARSH); + return 1; +} + +static int l_getbg (lua_State *L) { + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) { + lua_pushnumber(L, colbuf[XY_TO_COLBUF(x, y, 0)]); + } else { + lua_pushnumber(L, 0); + } + return 1; +} + +static int l_getfg (lua_State *L) { + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) { + lua_pushnumber(L, colbuf[XY_TO_COLBUF(x, y, 1)]); + } else { + lua_pushnumber(L, 0); + } + return 1; +} + +static int l_get (lua_State *L) { + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + if (x >= 0 && y >= 0 && x < CHARSW && y < CHARSH) { + lua_pushnumber(L, chrbuf[XY_TO_CHRBUF(x, y)]); + } else { + lua_pushnumber(L, 0); + } + return 1; +} + void winapigpu_init(lua_State* L) { struct luaL_Reg winlib[] = { {"open", l_open}, + + {"setPalette", l_set_palette}, + {"getWidth", l_get_width}, + {"getHeight", l_get_height}, + {"put", l_put}, + {"copy", l_copy}, + {"fill", l_fill}, + {"getBackground", l_getbg}, + {"getForeground", l_getfg}, + {"get", l_get}, + {"getNearest", l_get_nearest}, + {NULL, NULL} }; diff --git a/src/lua/core/fbgpu.lua b/src/lua/core/fbgpu.lua index b95137a..fcffddb 100644 --- a/src/lua/core/fbgpu.lua +++ b/src/lua/core/fbgpu.lua @@ -91,7 +91,7 @@ function fbgpu.start() return fb.getWidth(), fb.getHeight() end function gpu.getViewport() - return termutils.getSize() + return fb.getWidth(), fb.getHeight() end function gpu.setViewport(w, h) checkArg(1, w, "number") diff --git a/src/lua/core/winapigpu.lua b/src/lua/core/winapigpu.lua index b3651b1..506fec5 100644 --- a/src/lua/core/winapigpu.lua +++ b/src/lua/core/winapigpu.lua @@ -1,11 +1,162 @@ local wingpu = {} +local mapping = {} + +for i=0,15 do + mapping[i] = (i * 15) << 16 | (i * 15) << 8 | (i * 15) +end + +for i=0,239 do + local b = math.floor((i % 5) * 255 / 4.0) + local g = math.floor((math.floor(i / 5.0) % 8) * 255 / 7.0) + local r = math.floor((math.floor(i / 40.0) % 6) * 255 / 5.0) + mapping[16+i] = r << 16 | g << 8 | b +end + +local win = winapigpu + +for k,v in pairs(mapping) do + win.setPalette(k, v) +end + +local background = 0 +local foreground = 0 + function wingpu.start() - local s, reason = winapigpu.open() + local gpu = {} + + function gpu.bind() return false, "This is static bound gpu" end + function gpu.getScreen() return "n/a" end + function gpu.setBackground(color, isPaletteIndex) + checkArg(1, color, "number") + checkArg(2, isPaletteIndex, "boolean", "nil") + if isPaletteIndex and color >= 0 and color < 256 then + background = color + return mapping[color] + end + local old = background + background = win.getNearest(color) + return mapping[old] + end + function gpu.setForeground(color, isPaletteIndex) + checkArg(1, color, "number") + checkArg(2, isPaletteIndex, "boolean", "nil") + if isPaletteIndex and color >= 0 and color < 256 then + foreground = color + return mapping[color] + end + local old = foreground + foreground = win.getNearest(color) + return mapping[old] + end + function gpu.getBackground() + return mapping[background], false + end + function gpu.getForeground() + return mapping[foreground], false + end + function gpu.getPaletteColor() + return nil + end + function gpu.setPaletteColor(index, value) + checkArg(1, index, "number") + checkArg(2, value, "number") + win.setPalette(index, value) + return value + end + function gpu.maxDepth() + return 8 + end + function gpu.setDepth() + return false + end + function gpu.getDepth() + return 8 + end + function gpu.maxResolution() + return win.getWidth(), win.getHeight() + end + function gpu.getResolution() + return win.getWidth(), win.getHeight() + end + function gpu.getViewport() + return win.getWidth(), win.getHeight() + end + function gpu.setViewport(w, h) + checkArg(1, w, "number") + checkArg(2, h, "number") + return false, "Viewport not supported for this gpu" + end + function gpu.setResolution(w, h) + checkArg(1, w, "number") + checkArg(2, h, "number") + return false, "Non resizeable gpu" + end + function gpu.get(x, y) + checkArg(1, x, "number") + checkArg(2, y, "number") + return utf8.char(win.get(x-1, y-1)) + end + function gpu.set(x, y, value, vertical) + checkArg(1, x, "number") + checkArg(2, y, "number") + checkArg(3, value, "string") + checkArg(4, vertical, "boolean", "nil") + x = math.floor(x) + y = math.floor(y) + if not vertical then + local i = 0 + value:gsub(".", function(c) + win.put(x+i-1, y-1, background, foreground, utf8.codepoint(c)) + i = i+1 + end) + else + local i = 0 + value:gsub(".", function(c) + win.put(x-1, y+i-1, background, foreground, utf8.codepoint(c)) + i = i+1 + end) + end + return true + end + function gpu.copy(x, y, w, h, tx, ty) --TODO: Check(check X multiple times) + checkArg(1, x, "number") + checkArg(2, y, "number") + checkArg(3, w, "number") + checkArg(4, h, "number") + checkArg(5, tx, "number") + checkArg(6, ty, "number") + win.copy(x-1, y-1, w, h, tx, ty); + return true + end + function gpu.fill(x, y, w, h, ch) + checkArg(1, x, "number") + checkArg(2, y, "number") + checkArg(3, w, "number") + checkArg(4, h, "number") + checkArg(5, ch, "string") + ch = ch:sub(1, 1) + win.fill(x-1, y-1, x+w-2, y+h-2, background, foreground, utf8.codepoint(ch)) + return true + end + + local w, h = gpu.getResolution() + gpu.setForeground(0xFFFFFF) + gpu.setBackground(0x000000) + + + local s, reason = win.open() if not s then lprint("Couldn't open window: " .. tostring(reason)) end + + modules.component.api.register(nil, "gpu", gpu) + modules.component.api.register(nil, "screen", {getKeyboards = function() return {"TODO:SetThisUuid"} end}) --verry dummy screen, TODO: make it better, kbd uuid also in epoll.c + modules.component.api.register("TODO:SetThisUuid", "keyboard", {}) + return s end + + return wingpu