luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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 }