memset(gbLineMix, 0xff, 160*2);
for(int i = 0; i < 160; i++) { gbLineMix[i] = gbPalette[0]; gbLineBuffer[i] = 0; }
void gbRenderLine(){  u8 * bank0;  u8 * bank1;  if(gbCgbMode) {    bank0 = &gbVram[0x0000];    bank1 = &gbVram[0x2000];  } else {    bank0 = &gbMemory[0x8000];    bank1 = NULL;  }    int tile_map = 0x1800;  if((register_LCDC & 8) != 0)    tile_map = 0x1c00;  int tile_pattern = 0x0800;  if((register_LCDC & 16) != 0)    tile_pattern = 0x0000;      int x = 0;  int y = register_LY;  if(y >= 144)    return;  //  int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip;  int sx = register_SCX;  int sy = register_SCY;  sy+=y;  sy &= 255;      int tx = sx >> 3;  int ty = sy >> 3;  int bx = 1 << (7 - (sx & 7));  int by = sy & 7;  int tile_map_line_y = tile_map + ty * 32;    int tile_map_address = tile_map_line_y + tx;  u8 attrs = 0;  if(bank1 != NULL)    attrs = bank1[tile_map_address];    u8 tile = bank0[tile_map_address];    tile_map_address++;    if((register_LCDC & 16) == 0) {    if(tile < 128) tile += 128;    else tile -= 128;  }  int tile_pattern_address = tile_pattern + tile * 16 + by*2;  if(register_LCDC & 0x80) {    if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) {      while(x < 160) {        u8 tile_a = 0;        u8 tile_b = 0;                if(attrs & 0x40) {          tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;        }                if(attrs & 0x08) {          tile_a = bank1[tile_pattern_address++];          tile_b = bank1[tile_pattern_address];        } else {          tile_a = bank0[tile_pattern_address++];          tile_b = bank0[tile_pattern_address];        }                if(attrs & 0x20) {          tile_a = gbInvertTab[tile_a];          tile_b = gbInvertTab[tile_b];        }                while(bx > 0) {          u8 c = (tile_a & bx) ? 1 : 0;          c += ((tile_b & bx) ? 2 : 0);                    gbLineBuffer[x] = c; // mark the gbLineBuffer color                    if(attrs & 0x80)            gbLineBuffer[x] |= 0x300;                    if(gbCgbMode) {            c = c + (attrs & 7)*4;          } else {            c = gbBgp[c];                     if(gbSgbMode && !gbCgbMode) {              int dx = x >> 3;              int dy = y >> 3;                            int palette = gbSgbATF[dy * 20 + dx];                            if(c == 0)                palette = 0;                            c = c + 4*palette;            }          }          gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :            gbPalette[c];          x++;          if(x >= 160)            break;          bx >>= 1;        }        tx++;        if(tx == 32)          tx = 0;        bx = 128;                if(bank1)          attrs = bank1[tile_map_line_y + tx];                tile = bank0[tile_map_line_y + tx];                if((register_LCDC & 16) == 0) {          if(tile < 128) tile += 128;          else tile -= 128;        }        tile_pattern_address = tile_pattern + tile * 16 + by * 2;      }    } else {      memset(gbLineMix, 0, 160*2);    }        // do the window display    if((register_LCDC & 0x20) && (layerSettings & 0x2000)) {      int wy = register_WY;            if(y >= wy) {        int wx = register_WX;        wx -= 7;                if( wx <= 159 && gbWindowLine <= 143) {                    tile_map = 0x1800;                    if((register_LCDC & 0x40) != 0)            tile_map = 0x1c00;                    if(gbWindowLine == -1) {            gbWindowLine = 0;          }                    tx = 0;          ty = gbWindowLine >> 3;                    bx = 128;          by = gbWindowLine & 7;                    if(wx < 0) {            bx >>= (-wx);            wx = 0;          }                    tile_map_line_y = tile_map + ty * 32;                    tile_map_address = tile_map_line_y + tx;                    x = wx;                    tile = bank0[tile_map_address];          u8 attrs = 0;          if(bank1)            attrs = bank1[tile_map_address];          tile_map_address++;                    if((register_LCDC & 16) == 0) {                if(tile < 128) tile += 128;            else tile -= 128;          }                    tile_pattern_address = tile_pattern + tile * 16 + by*2;          while(x < 160) {            u8 tile_a = 0;            u8 tile_b = 0;                        if(attrs & 0x40) {              tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;            }                        if(attrs & 0x08) {              tile_a = bank1[tile_pattern_address++];              tile_b = bank1[tile_pattern_address];            } else {              tile_a = bank0[tile_pattern_address++];              tile_b = bank0[tile_pattern_address];            }                        if(attrs & 0x20) {              tile_a = gbInvertTab[tile_a];              tile_b = gbInvertTab[tile_b];            }                        while(bx > 0) {              u8 c = (tile_a & bx) != 0 ? 1 : 0;              c += ((tile_b & bx) != 0 ? 2 : 0);              if(attrs & 0x80)                gbLineBuffer[x] = 0x300 + c;              else                gbLineBuffer[x] = 0x100 + c;                            if(gbCgbMode) {                c = c + (attrs & 7) * 4;              } else {                c = gbBgp[c];                         if(gbSgbMode && ! gbCgbMode) {                  int dx = x >> 3;                  int dy = y >> 3;                                    int palette = gbSgbATF[dy * 20 + dx];                                    if(c == 0)                    palette = 0;                                    c = c + 4*palette;                            }              }              gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :                gbPalette[c];              x++;              if(x >= 160)                break;              bx >>= 1;            }            tx++;            if(tx == 32)              tx = 0;            bx = 128;            tile = bank0[tile_map_line_y + tx];            if(bank1)              attrs = bank1[tile_map_line_y + tx];                        if((register_LCDC & 16) == 0) {                       if(tile < 128) tile += 128;              else tile -= 128;            }            tile_pattern_address = tile_pattern + tile * 16 + by * 2;          }          gbWindowLine++;        }      }    }  } else {    memset(gbLineMix, 0xff, 160*2);  }}