graphics.c (19884B)
1 #include "graphics.h" 2 #include <lauxlib.h> 3 4 /* VGA memory */ 5 uint8_t* vga_memory = (uint8_t*)0xA0000; 6 7 /* Helper function to write VGA registers */ 8 static void write_vga_regs(uint8_t *regs, int count, uint16_t port_index, uint16_t port_data) { 9 for (int i = 0; i < count; i++) { 10 outb(port_index, i); 11 outb(port_data, regs[i]); 12 } 13 } 14 15 /* Enter VGA Mode 13h (320x200 256 colors) - Direct hardware programming */ 16 int lua_enter_graphics_mode(lua_State* L) { 17 (void)L; /* Unused parameter */ 18 /* VGA Mode 13h register values */ 19 uint8_t misc = 0x63; 20 uint8_t seq[5] = {0x03, 0x01, 0x0F, 0x00, 0x0E}; 21 uint8_t crtc[25] = { 22 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 23 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, 0xFF 25 }; 26 uint8_t gc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF}; 27 uint8_t ac[21] = { 28 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 29 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 30 0x41, 0x00, 0x0F, 0x00, 0x00 31 }; 32 33 /* Write misc register */ 34 outb(VGA_MISC_WRITE, misc); 35 36 /* Write sequencer registers */ 37 write_vga_regs(seq, 5, VGA_SEQ_INDEX, VGA_SEQ_DATA); 38 39 /* Unlock CRTC registers */ 40 outb(VGA_CRTC_INDEX, 0x03); 41 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80); 42 outb(VGA_CRTC_INDEX, 0x11); 43 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80); 44 45 /* Write CRTC registers */ 46 write_vga_regs(crtc, 25, VGA_CRTC_INDEX, VGA_CRTC_DATA); 47 48 /* Write graphics controller registers */ 49 write_vga_regs(gc, 9, VGA_GC_INDEX, VGA_GC_DATA); 50 51 /* Write attribute controller registers */ 52 inb(VGA_INSTAT_READ); /* Reset flip-flop */ 53 for (int i = 0; i < 21; i++) { 54 outb(VGA_AC_INDEX, i); 55 outb(VGA_AC_WRITE, ac[i]); 56 } 57 outb(VGA_AC_INDEX, 0x20); /* Enable video output */ 58 59 return 0; 60 } 61 62 /* Exit graphics mode back to text mode */ 63 int lua_exit_graphics_mode(lua_State* L) { 64 (void)L; /* Unused parameter */ 65 /* VGA Text Mode 3 (80x25) register values */ 66 uint8_t misc = 0x67; 67 uint8_t seq[5] = {0x03, 0x00, 0x03, 0x00, 0x02}; 68 uint8_t crtc[25] = { 69 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 70 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50, 71 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3, 0xFF 72 }; 73 uint8_t gc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF}; 74 uint8_t ac[21] = { 75 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 76 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 77 0x0C, 0x00, 0x0F, 0x08, 0x00 78 }; 79 80 /* Write misc register */ 81 outb(VGA_MISC_WRITE, misc); 82 83 /* Write sequencer registers */ 84 write_vga_regs(seq, 5, VGA_SEQ_INDEX, VGA_SEQ_DATA); 85 86 /* Unlock CRTC registers */ 87 outb(VGA_CRTC_INDEX, 0x03); 88 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80); 89 outb(VGA_CRTC_INDEX, 0x11); 90 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80); 91 92 /* Write CRTC registers */ 93 write_vga_regs(crtc, 25, VGA_CRTC_INDEX, VGA_CRTC_DATA); 94 95 /* Write graphics controller registers */ 96 write_vga_regs(gc, 9, VGA_GC_INDEX, VGA_GC_DATA); 97 98 /* Write attribute controller registers */ 99 inb(VGA_INSTAT_READ); /* Reset flip-flop */ 100 for (int i = 0; i < 21; i++) { 101 outb(VGA_AC_INDEX, i); 102 outb(VGA_AC_WRITE, ac[i]); 103 } 104 outb(VGA_AC_INDEX, 0x20); /* Enable video output */ 105 106 return 0; 107 } 108 109 /* Set a pixel at (x, y) with color */ 110 int lua_set_pixel(lua_State* L) { 111 int x = luaL_checkinteger(L, 1); 112 int y = luaL_checkinteger(L, 2); 113 int color = luaL_checkinteger(L, 3); 114 115 if (x >= 0 && x < VGA_WIDTH && y >= 0 && y < VGA_HEIGHT) { 116 vga_memory[y * VGA_WIDTH + x] = (uint8_t)color; 117 } 118 119 return 0; 120 } 121 122 /* Draw a filled rectangle */ 123 int lua_draw_rect(lua_State* L) { 124 int x = luaL_checkinteger(L, 1); 125 int y = luaL_checkinteger(L, 2); 126 int width = luaL_checkinteger(L, 3); 127 int height = luaL_checkinteger(L, 4); 128 int color = luaL_checkinteger(L, 5); 129 130 for (int dy = 0; dy < height; dy++) { 131 for (int dx = 0; dx < width; dx++) { 132 int px = x + dx; 133 int py = y + dy; 134 if (px >= 0 && px < VGA_WIDTH && py >= 0 && py < VGA_HEIGHT) { 135 vga_memory[py * VGA_WIDTH + px] = (uint8_t)color; 136 } 137 } 138 } 139 140 return 0; 141 } 142 143 /* Clear screen with a color */ 144 int lua_clear_screen(lua_State* L) { 145 int color = luaL_optinteger(L, 1, 0); /* Default to black */ 146 147 for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { 148 vga_memory[i] = (uint8_t)color; 149 } 150 151 return 0; 152 } 153 154 /* Helper function to draw outlined rect in C */ 155 void draw_rect_outline(int x, int y, int width, int height, int color, int thickness) { 156 /* Top and bottom edges */ 157 for (int i = 0; i < thickness; i++) { 158 for (int dx = 0; dx < width; dx++) { 159 int px = x + dx; 160 int py1 = y + i; 161 int py2 = y + height - 1 - i; 162 if (px >= 0 && px < VGA_WIDTH) { 163 if (py1 >= 0 && py1 < VGA_HEIGHT) { 164 vga_memory[py1 * VGA_WIDTH + px] = (uint8_t)color; 165 } 166 if (py2 >= 0 && py2 < VGA_HEIGHT) { 167 vga_memory[py2 * VGA_WIDTH + px] = (uint8_t)color; 168 } 169 } 170 } 171 } 172 173 /* Left and right edges */ 174 for (int i = 0; i < thickness; i++) { 175 for (int dy = 0; dy < height; dy++) { 176 int px1 = x + i; 177 int px2 = x + width - 1 - i; 178 int py = y + dy; 179 if (py >= 0 && py < VGA_HEIGHT) { 180 if (px1 >= 0 && px1 < VGA_WIDTH) { 181 vga_memory[py * VGA_WIDTH + px1] = (uint8_t)color; 182 } 183 if (px2 >= 0 && px2 < VGA_WIDTH) { 184 vga_memory[py * VGA_WIDTH + px2] = (uint8_t)color; 185 } 186 } 187 } 188 } 189 } 190 191 /* Helper function to draw filled circle in C */ 192 void draw_circle_fill(int cx, int cy, int radius, int color) { 193 int x = radius; 194 int y = 0; 195 int err = 0; 196 197 while (x >= y) { 198 /* Draw horizontal lines for each octant */ 199 for (int dx = -x; dx <= x; dx++) { 200 int px = cx + dx; 201 if (px >= 0 && px < VGA_WIDTH) { 202 int py1 = cy + y; 203 int py2 = cy - y; 204 if (py1 >= 0 && py1 < VGA_HEIGHT) { 205 vga_memory[py1 * VGA_WIDTH + px] = (uint8_t)color; 206 } 207 if (py2 >= 0 && py2 < VGA_HEIGHT) { 208 vga_memory[py2 * VGA_WIDTH + px] = (uint8_t)color; 209 } 210 } 211 } 212 for (int dx = -y; dx <= y; dx++) { 213 int px = cx + dx; 214 if (px >= 0 && px < VGA_WIDTH) { 215 int py1 = cy + x; 216 int py2 = cy - x; 217 if (py1 >= 0 && py1 < VGA_HEIGHT) { 218 vga_memory[py1 * VGA_WIDTH + px] = (uint8_t)color; 219 } 220 if (py2 >= 0 && py2 < VGA_HEIGHT) { 221 vga_memory[py2 * VGA_WIDTH + px] = (uint8_t)color; 222 } 223 } 224 } 225 226 y++; 227 err = err + 1 + 2 * y; 228 if (2 * (err - x) + 1 > 0) { 229 x--; 230 err = err + 1 - 2 * x; 231 } 232 } 233 } 234 235 /* Helper function to draw outlined circle in C */ 236 void draw_circle_outline(int cx, int cy, int radius, int color, int thickness) { 237 for (int t = 0; t < thickness; t++) { 238 int r = radius - t; 239 if (r < 0) break; 240 241 int x = r; 242 int y = 0; 243 int err = 0; 244 245 while (x >= y) { 246 /* Draw 8 symmetric points */ 247 int points[8][2] = { 248 {cx + x, cy + y}, {cx + y, cy + x}, {cx - y, cy + x}, {cx - x, cy + y}, 249 {cx - x, cy - y}, {cx - y, cy - x}, {cx + y, cy - x}, {cx + x, cy - y} 250 }; 251 252 for (int i = 0; i < 8; i++) { 253 int px = points[i][0]; 254 int py = points[i][1]; 255 if (px >= 0 && px < VGA_WIDTH && py >= 0 && py < VGA_HEIGHT) { 256 vga_memory[py * VGA_WIDTH + px] = (uint8_t)color; 257 } 258 } 259 260 y++; 261 err = err + 1 + 2 * y; 262 if (2 * (err - x) + 1 > 0) { 263 x--; 264 err = err + 1 - 2 * x; 265 } 266 } 267 } 268 } 269 270 /* Helper function to draw filled triangle in C */ 271 void draw_triangle_fill(int x0, int y0, int x1, int y1, int x2, int y2, int color) { 272 /* Sort vertices by y-coordinate (y0 <= y1 <= y2) */ 273 if (y0 > y1) { 274 int tmp; 275 tmp = x0; x0 = x1; x1 = tmp; 276 tmp = y0; y0 = y1; y1 = tmp; 277 } 278 if (y0 > y2) { 279 int tmp; 280 tmp = x0; x0 = x2; x2 = tmp; 281 tmp = y0; y0 = y2; y2 = tmp; 282 } 283 if (y1 > y2) { 284 int tmp; 285 tmp = x1; x1 = x2; x2 = tmp; 286 tmp = y1; y1 = y2; y2 = tmp; 287 } 288 289 /* Draw flat-bottom triangle (y0 to y1) */ 290 if (y1 - y0 > 0) { 291 float invslope1 = (float)(x1 - x0) / (y1 - y0); 292 float invslope2 = (float)(x2 - x0) / (y2 - y0); 293 float curx1 = (float)x0; 294 float curx2 = (float)x0; 295 296 for (int scanlineY = y0; scanlineY <= y1; scanlineY++) { 297 int startX = (int)(curx1 < curx2 ? curx1 : curx2); 298 int endX = (int)(curx1 < curx2 ? curx2 : curx1); 299 300 for (int dx = 0; dx <= endX - startX; dx++) { 301 int px = startX + dx; 302 if (px >= 0 && px < VGA_WIDTH && scanlineY >= 0 && scanlineY < VGA_HEIGHT) { 303 vga_memory[scanlineY * VGA_WIDTH + px] = (uint8_t)color; 304 } 305 } 306 curx1 += invslope1; 307 curx2 += invslope2; 308 } 309 } 310 311 /* Draw flat-top triangle (y1 to y2) */ 312 if (y2 - y1 > 0) { 313 float invslope1 = (float)(x2 - x1) / (y2 - y1); 314 float invslope2 = (float)(x2 - x0) / (y2 - y0); 315 float curx1 = (float)x1; 316 float curx2 = (float)x0 + (y1 - y0) * ((float)(x2 - x0) / (y2 - y0)); 317 318 for (int scanlineY = y1; scanlineY <= y2; scanlineY++) { 319 int startX = (int)(curx1 < curx2 ? curx1 : curx2); 320 int endX = (int)(curx1 < curx2 ? curx2 : curx1); 321 322 for (int dx = 0; dx <= endX - startX; dx++) { 323 int px = startX + dx; 324 if (px >= 0 && px < VGA_WIDTH && scanlineY >= 0 && scanlineY < VGA_HEIGHT) { 325 vga_memory[scanlineY * VGA_WIDTH + px] = (uint8_t)color; 326 } 327 } 328 curx1 += invslope1; 329 curx2 += invslope2; 330 } 331 } 332 } 333 334 /* Helper function to draw line using Bresenham's algorithm */ 335 void draw_line(int x0, int y0, int x1, int y1, int color, int thickness) { 336 int dx = x1 - x0; 337 int dy = y1 - y0; 338 339 /* Handle vertical and horizontal lines specially for thickness */ 340 if (dx == 0) { 341 /* Vertical line */ 342 int startY = y0 < y1 ? y0 : y1; 343 int endY = y0 < y1 ? y1 : y0; 344 for (int ty = startY; ty <= endY; ty++) { 345 for (int tx = 0; tx < thickness; tx++) { 346 int px = x0 + tx; 347 if (px >= 0 && px < VGA_WIDTH && ty >= 0 && ty < VGA_HEIGHT) { 348 vga_memory[ty * VGA_WIDTH + px] = (uint8_t)color; 349 } 350 } 351 } 352 return; 353 } 354 355 if (dy == 0) { 356 /* Horizontal line */ 357 int startX = x0 < x1 ? x0 : x1; 358 int endX = x0 < x1 ? x1 : x0; 359 for (int tx = startX; tx <= endX; tx++) { 360 for (int ty = 0; ty < thickness; ty++) { 361 int py = y0 + ty; 362 if (tx >= 0 && tx < VGA_WIDTH && py >= 0 && py < VGA_HEIGHT) { 363 vga_memory[py * VGA_WIDTH + tx] = (uint8_t)color; 364 } 365 } 366 } 367 return; 368 } 369 370 /* Bresenham's line algorithm */ 371 int dx_abs = dx < 0 ? -dx : dx; 372 int dy_abs = dy < 0 ? -dy : dy; 373 int sx = dx > 0 ? 1 : -1; 374 int sy = dy > 0 ? 1 : -1; 375 int err = dx_abs - dy_abs; 376 377 int x = x0; 378 int y = y0; 379 380 while (1) { 381 /* Draw with thickness */ 382 for (int ty = 0; ty < thickness; ty++) { 383 for (int tx = 0; tx < thickness; tx++) { 384 int px = x + tx; 385 int py = y + ty; 386 if (px >= 0 && px < VGA_WIDTH && py >= 0 && py < VGA_HEIGHT) { 387 vga_memory[py * VGA_WIDTH + px] = (uint8_t)color; 388 } 389 } 390 } 391 392 if (x == x1 && y == y1) break; 393 394 int e2 = 2 * err; 395 if (e2 > -dy_abs) { 396 err = err - dy_abs; 397 x = x + sx; 398 } 399 if (e2 < dx_abs) { 400 err = err + dx_abs; 401 y = y + sy; 402 } 403 } 404 } 405 406 /* Process buffered draw operations */ 407 int lua_process_buffered_draw_ops(lua_State* L) { 408 /* Expect a table of operations as the first argument */ 409 luaL_checktype(L, 1, LUA_TTABLE); 410 411 /* Get the number of operations */ 412 int num_ops = lua_objlen(L, 1); 413 414 /* Process each operation */ 415 for (int i = 1; i <= num_ops; i++) { 416 lua_rawgeti(L, 1, i); /* Get operation table */ 417 418 if (!lua_istable(L, -1)) { 419 lua_pop(L, 1); 420 continue; 421 } 422 423 /* Get operation type */ 424 lua_rawgeti(L, -1, 1); 425 int op_type = lua_tointeger(L, -1); 426 lua_pop(L, 1); 427 428 /* Process based on operation type */ 429 switch (op_type) { 430 case OP_PIXEL: { 431 /* {PIXEL, x, y, color} */ 432 lua_rawgeti(L, -1, 2); int x = lua_tointeger(L, -1); lua_pop(L, 1); 433 lua_rawgeti(L, -1, 3); int y = lua_tointeger(L, -1); lua_pop(L, 1); 434 lua_rawgeti(L, -1, 4); int color = lua_tointeger(L, -1); lua_pop(L, 1); 435 436 if (x >= 0 && x < VGA_WIDTH && y >= 0 && y < VGA_HEIGHT) { 437 vga_memory[y * VGA_WIDTH + x] = (uint8_t)color; 438 } 439 break; 440 } 441 442 case OP_LINE: { 443 /* {LINE, x0, y0, x1, y1, color, thickness} */ 444 lua_rawgeti(L, -1, 2); int x0 = lua_tointeger(L, -1); lua_pop(L, 1); 445 lua_rawgeti(L, -1, 3); int y0 = lua_tointeger(L, -1); lua_pop(L, 1); 446 lua_rawgeti(L, -1, 4); int x1 = lua_tointeger(L, -1); lua_pop(L, 1); 447 lua_rawgeti(L, -1, 5); int y1 = lua_tointeger(L, -1); lua_pop(L, 1); 448 lua_rawgeti(L, -1, 6); int color = lua_tointeger(L, -1); lua_pop(L, 1); 449 lua_rawgeti(L, -1, 7); int thickness = lua_tointeger(L, -1); lua_pop(L, 1); 450 451 draw_line(x0, y0, x1, y1, color, thickness); 452 break; 453 } 454 455 case OP_RECT: { 456 /* {RECT, x, y, width, height, color, thickness} */ 457 lua_rawgeti(L, -1, 2); int x = lua_tointeger(L, -1); lua_pop(L, 1); 458 lua_rawgeti(L, -1, 3); int y = lua_tointeger(L, -1); lua_pop(L, 1); 459 lua_rawgeti(L, -1, 4); int width = lua_tointeger(L, -1); lua_pop(L, 1); 460 lua_rawgeti(L, -1, 5); int height = lua_tointeger(L, -1); lua_pop(L, 1); 461 lua_rawgeti(L, -1, 6); int color = lua_tointeger(L, -1); lua_pop(L, 1); 462 lua_rawgeti(L, -1, 7); int thickness = lua_tointeger(L, -1); lua_pop(L, 1); 463 464 draw_rect_outline(x, y, width, height, color, thickness); 465 break; 466 } 467 468 case OP_RECT_FILL: { 469 /* {RECT_FILL, x, y, width, height, color} */ 470 lua_rawgeti(L, -1, 2); int x = lua_tointeger(L, -1); lua_pop(L, 1); 471 lua_rawgeti(L, -1, 3); int y = lua_tointeger(L, -1); lua_pop(L, 1); 472 lua_rawgeti(L, -1, 4); int width = lua_tointeger(L, -1); lua_pop(L, 1); 473 lua_rawgeti(L, -1, 5); int height = lua_tointeger(L, -1); lua_pop(L, 1); 474 lua_rawgeti(L, -1, 6); int color = lua_tointeger(L, -1); lua_pop(L, 1); 475 476 for (int dy = 0; dy < height; dy++) { 477 for (int dx = 0; dx < width; dx++) { 478 int px = x + dx; 479 int py = y + dy; 480 if (px >= 0 && px < VGA_WIDTH && py >= 0 && py < VGA_HEIGHT) { 481 vga_memory[py * VGA_WIDTH + px] = (uint8_t)color; 482 } 483 } 484 } 485 break; 486 } 487 488 case OP_CIRCLE: { 489 /* {CIRCLE, cx, cy, radius, color, thickness} */ 490 lua_rawgeti(L, -1, 2); int cx = lua_tointeger(L, -1); lua_pop(L, 1); 491 lua_rawgeti(L, -1, 3); int cy = lua_tointeger(L, -1); lua_pop(L, 1); 492 lua_rawgeti(L, -1, 4); int radius = lua_tointeger(L, -1); lua_pop(L, 1); 493 lua_rawgeti(L, -1, 5); int color = lua_tointeger(L, -1); lua_pop(L, 1); 494 lua_rawgeti(L, -1, 6); int thickness = lua_tointeger(L, -1); lua_pop(L, 1); 495 496 draw_circle_outline(cx, cy, radius, color, thickness); 497 break; 498 } 499 500 case OP_CIRCLE_FILL: { 501 /* {CIRCLE_FILL, cx, cy, radius, color} */ 502 lua_rawgeti(L, -1, 2); int cx = lua_tointeger(L, -1); lua_pop(L, 1); 503 lua_rawgeti(L, -1, 3); int cy = lua_tointeger(L, -1); lua_pop(L, 1); 504 lua_rawgeti(L, -1, 4); int radius = lua_tointeger(L, -1); lua_pop(L, 1); 505 lua_rawgeti(L, -1, 5); int color = lua_tointeger(L, -1); lua_pop(L, 1); 506 507 draw_circle_fill(cx, cy, radius, color); 508 break; 509 } 510 511 case OP_TRIANGLE: { 512 /* {TRIANGLE, x0, y0, x1, y1, x2, y2, color, thickness} */ 513 lua_rawgeti(L, -1, 2); int x0 = lua_tointeger(L, -1); lua_pop(L, 1); 514 lua_rawgeti(L, -1, 3); int y0 = lua_tointeger(L, -1); lua_pop(L, 1); 515 lua_rawgeti(L, -1, 4); int x1 = lua_tointeger(L, -1); lua_pop(L, 1); 516 lua_rawgeti(L, -1, 5); int y1 = lua_tointeger(L, -1); lua_pop(L, 1); 517 lua_rawgeti(L, -1, 6); int x2 = lua_tointeger(L, -1); lua_pop(L, 1); 518 lua_rawgeti(L, -1, 7); int y2 = lua_tointeger(L, -1); lua_pop(L, 1); 519 lua_rawgeti(L, -1, 8); int color = lua_tointeger(L, -1); lua_pop(L, 1); 520 lua_rawgeti(L, -1, 9); int thickness = lua_tointeger(L, -1); lua_pop(L, 1); 521 522 /* Draw triangle outline using lines */ 523 draw_line(x0, y0, x1, y1, color, thickness); 524 draw_line(x1, y1, x2, y2, color, thickness); 525 draw_line(x2, y2, x0, y0, color, thickness); 526 break; 527 } 528 529 case OP_TRIANGLE_FILL: { 530 /* {TRIANGLE_FILL, x0, y0, x1, y1, x2, y2, color} */ 531 lua_rawgeti(L, -1, 2); int x0 = lua_tointeger(L, -1); lua_pop(L, 1); 532 lua_rawgeti(L, -1, 3); int y0 = lua_tointeger(L, -1); lua_pop(L, 1); 533 lua_rawgeti(L, -1, 4); int x1 = lua_tointeger(L, -1); lua_pop(L, 1); 534 lua_rawgeti(L, -1, 5); int y1 = lua_tointeger(L, -1); lua_pop(L, 1); 535 lua_rawgeti(L, -1, 6); int x2 = lua_tointeger(L, -1); lua_pop(L, 1); 536 lua_rawgeti(L, -1, 7); int y2 = lua_tointeger(L, -1); lua_pop(L, 1); 537 lua_rawgeti(L, -1, 8); int color = lua_tointeger(L, -1); lua_pop(L, 1); 538 539 draw_triangle_fill(x0, y0, x1, y1, x2, y2, color); 540 break; 541 } 542 543 case OP_POLYGON: 544 case OP_POLYGON_FILL: { 545 /* {POLYGON[_FILL], numVertices, x1, y1, x2, y2, ..., color[, thickness]} */ 546 /* Polygon drawing is complex, skip for now or implement simple version */ 547 /* TODO: Implement polygon rendering in C if needed */ 548 break; 549 } 550 } 551 552 lua_pop(L, 1); /* Pop operation table */ 553 } 554 555 return 0; 556 }