home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / Gfx.h < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  41.8 KB  |  1,580 lines

  1. // -*- C++ -*-
  2. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  3. // Copyright (C) 1999-2003 Forgotten
  4. // Copyright (C) 2004 Forgotten and the VBA development team
  5.  
  6. // This program is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 2, or(at your option)
  9. // any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  
  20. #ifndef VBA_GFX_H
  21. #define VBA_GFX_H
  22.  
  23. #include "GBA.h"
  24. #include "Gfx.h"
  25. #include "Globals.h"
  26.  
  27. #include "Port.h"
  28.  
  29. //#define SPRITE_DEBUG
  30.  
  31. void gfxDrawTextScreen(u16, u16, u16, u32 *);
  32. void gfxDrawRotScreen(u16,
  33.                       u16, u16,
  34.                       u16, u16,
  35.                       u16, u16,
  36.                       u16, u16,
  37.                       int&, int&,
  38.                       int,
  39.                       u32*);
  40. void gfxDrawRotScreen16Bit(u16,
  41.                            u16, u16,
  42.                            u16, u16,
  43.                            u16, u16,
  44.                            u16, u16,
  45.                            int&, int&,
  46.                            int,
  47.                            u32*);
  48. void gfxDrawRotScreen256(u16,
  49.                          u16, u16,
  50.                          u16, u16,
  51.                          u16, u16,
  52.                          u16, u16,
  53.                          int&, int&,
  54.                          int,
  55.                          u32*);
  56. void gfxDrawRotScreen16Bit160(u16,
  57.                               u16, u16,
  58.                               u16, u16,
  59.                               u16, u16,
  60.                               u16, u16,
  61.                               int&, int&,
  62.                               int,
  63.                               u32*);
  64. void gfxDrawSprites(u32 *);
  65. void gfxIncreaseBrightness(u32 *line, int coeff);
  66. void gfxDecreaseBrightness(u32 *line, int coeff);
  67. void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb);
  68.  
  69. void mode0RenderLine();
  70. void mode0RenderLineNoWindow();
  71. void mode0RenderLineAll();
  72.  
  73. void mode1RenderLine();
  74. void mode1RenderLineNoWindow();
  75. void mode1RenderLineAll();
  76.  
  77. void mode2RenderLine();
  78. void mode2RenderLineNoWindow();
  79. void mode2RenderLineAll();
  80.  
  81. void mode3RenderLine();
  82. void mode3RenderLineNoWindow();
  83. void mode3RenderLineAll();
  84.  
  85. void mode4RenderLine();
  86. void mode4RenderLineNoWindow();
  87. void mode4RenderLineAll();
  88.  
  89. void mode5RenderLine();
  90. void mode5RenderLineNoWindow();
  91. void mode5RenderLineAll();
  92.  
  93. extern int coeff[32];
  94. extern u32 line0[240];
  95. extern u32 line1[240];
  96. extern u32 line2[240];
  97. extern u32 line3[240];
  98. extern u32 lineOBJ[240];
  99. extern u32 lineOBJWin[240];
  100. extern u32 lineMix[240];
  101. extern bool gfxInWin0[240];
  102. extern bool gfxInWin1[240];
  103.  
  104. extern int gfxBG2Changed;
  105. extern int gfxBG3Changed;
  106.  
  107. extern int gfxBG2X;
  108. extern int gfxBG2Y;
  109. extern int gfxBG2LastX;
  110. extern int gfxBG2LastY;
  111. extern int gfxBG3X;
  112. extern int gfxBG3Y;
  113. extern int gfxBG3LastX;
  114. extern int gfxBG3LastY;
  115. extern int gfxLastVCOUNT;
  116.  
  117. inline void gfxClearArray(u32 *array)
  118. {
  119.   for(int i = 0; i < 240; i++) {
  120.     *array++ = 0x80000000;
  121.   }
  122. }
  123.  
  124. inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
  125.                               u32 *line)
  126. {
  127.   u16 *palette = (u16 *)paletteRAM;
  128.   u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
  129.   u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
  130.   u32 prio = ((control & 3)<<25) + 0x1000000;
  131.   int sizeX = 256;
  132.   int sizeY = 256;
  133.   switch((control >> 14) & 3) {
  134.   case 0:
  135.     break;
  136.   case 1:
  137.     sizeX = 512;
  138.     break;
  139.   case 2:
  140.     sizeY = 512;
  141.     break;
  142.   case 3:
  143.     sizeX = 512;
  144.     sizeY = 512;
  145.     break;
  146.   }
  147.  
  148.   int maskX = sizeX-1;
  149.   int maskY = sizeY-1;
  150.   
  151.   bool mosaicOn = (control & 0x40) ? true : false;
  152.  
  153.   int xxx = hofs & maskX;
  154.   int yyy = (vofs + VCOUNT) & maskY;
  155.   int mosaicX = (MOSAIC & 0x000F)+1;
  156.   int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
  157.  
  158.   if(mosaicOn) {
  159.     if((VCOUNT % mosaicY) != 0) {
  160.       mosaicY = (VCOUNT / mosaicY) * mosaicY;
  161.       yyy = (vofs + mosaicY) & maskY;
  162.     }
  163.   }
  164.  
  165.   if(yyy > 255 && sizeY > 256) {
  166.     yyy &= 255;
  167.     screenBase += 0x400;
  168.     if(sizeX > 256)
  169.       screenBase += 0x400;
  170.   }
  171.   
  172.   int yshift = ((yyy>>3)<<5);
  173.   if((control) & 0x80) {
  174.     u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
  175.     for(int x = 0; x < 240; x++) {
  176.       u16 data = READ16LE(screenSource);
  177.       
  178.       int tile = data & 0x3FF;
  179.       int tileX = (xxx & 7);
  180.       int tileY = yyy & 7;
  181.       
  182.       if(data & 0x0400)
  183.         tileX = 7 - tileX;
  184.       if(data & 0x0800)
  185.         tileY = 7 - tileY;
  186.       
  187.       u8 color = charBase[tile * 64 + tileY * 8 + tileX];
  188.       
  189.       line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
  190.       
  191.       if(data & 0x0400) {
  192.         if(tileX == 0)
  193.           screenSource++;
  194.       } else if(tileX == 7)
  195.         screenSource++;
  196.       xxx++;
  197.       if(xxx == 256) {
  198.         if(sizeX > 256)
  199.           screenSource = screenBase + 0x400 + yshift;
  200.         else {
  201.           screenSource = screenBase + yshift;
  202.           xxx = 0;
  203.         }
  204.       } else if(xxx >= sizeX) {
  205.         xxx = 0;
  206.         screenSource = screenBase + yshift;
  207.       }
  208.     }
  209.   } else {
  210.     u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
  211.       yshift;
  212.     for(int x = 0; x < 240; x++) {
  213.       u16 data = READ16LE(screenSource);
  214.         
  215.       int tile = data & 0x3FF;
  216.       int tileX = (xxx & 7);
  217.       int tileY = yyy & 7;
  218.  
  219.       if(data & 0x0400)
  220.         tileX = 7 - tileX;
  221.       if(data & 0x0800)
  222.         tileY = 7 - tileY;
  223.  
  224.       u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
  225.  
  226.       if(tileX & 1) {
  227.         color = (color >> 4);
  228.       } else {
  229.         color &= 0x0F;
  230.       }
  231.       
  232.       int pal = (READ16LE(screenSource)>>8) & 0xF0;
  233.       line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
  234.  
  235.       if(data & 0x0400) {
  236.         if(tileX == 0)
  237.           screenSource++;
  238.       } else if(tileX == 7)
  239.         screenSource++;
  240.       xxx++;
  241.       if(xxx == 256) {
  242.         if(sizeX > 256)
  243.           screenSource = screenBase + 0x400 + yshift;
  244.         else {
  245.           screenSource = screenBase + yshift;
  246.           xxx = 0;
  247.         }
  248.       } else if(xxx >= sizeX) {
  249.         xxx = 0;
  250.         screenSource = screenBase + yshift;
  251.       }
  252.     }
  253.   }
  254.   if(mosaicOn) {
  255.     if(mosaicX > 1) {
  256.       int m = 1;
  257.       for(int i = 0; i < 239; i++) {
  258.         line[i+1] = line[i];
  259.         m++;
  260.         if(m == mosaicX) {
  261.           m = 1;
  262.           i++;
  263.         }
  264.       }
  265.     }
  266.   }
  267. }
  268.  
  269. inline void gfxDrawRotScreen(u16 control, 
  270.                              u16 x_l, u16 x_h,
  271.                              u16 y_l, u16 y_h,
  272.                              u16 pa,  u16 pb,
  273.                              u16 pc,  u16 pd,
  274.                              int& currentX, int& currentY,
  275.                              int changed,
  276.                              u32 *line)
  277. {
  278.   u16 *palette = (u16 *)paletteRAM;
  279.   u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
  280.   u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
  281.   int prio = ((control & 3) << 25) + 0x1000000;
  282.  
  283.   int sizeX = 128;
  284.   int sizeY = 128;
  285.   switch((control >> 14) & 3) {
  286.   case 0:
  287.     break;
  288.   case 1:
  289.     sizeX = sizeY = 256;
  290.     break;
  291.   case 2:
  292.     sizeX = sizeY = 512;
  293.     break;
  294.   case 3:
  295.     sizeX = sizeY = 1024;
  296.     break;
  297.   }
  298.  
  299.   int dx = pa & 0x7FFF;
  300.   if(pa & 0x8000)
  301.     dx |= 0xFFFF8000;
  302.   int dmx = pb & 0x7FFF;
  303.   if(pb & 0x8000)
  304.     dmx |= 0xFFFF8000;
  305.   int dy = pc & 0x7FFF;
  306.   if(pc & 0x8000)
  307.     dy |= 0xFFFF8000;
  308.   int dmy = pd & 0x7FFFF;
  309.   if(pd & 0x8000)
  310.     dmy |= 0xFFFF8000;
  311.  
  312.   if(VCOUNT == 0)
  313.     changed = 3;
  314.  
  315.   if(changed & 1) {
  316.     currentX = (x_l) | ((x_h & 0x07FF)<<16);
  317.     if(x_h & 0x0800)
  318.       currentX |= 0xF8000000;
  319.   } else {
  320.     currentX += dmx;
  321.   }
  322.  
  323.   if(changed & 2) {
  324.     currentY = (y_l) | ((y_h & 0x07FF)<<16);
  325.     if(y_h & 0x0800)
  326.       currentY |= 0xF8000000;
  327.   } else {
  328.     currentY += dmy;
  329.   }  
  330.   
  331.   int realX = currentX;
  332.   int realY = currentY;
  333.  
  334.   if(control & 0x40) {
  335.     int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
  336.     int y = (VCOUNT % mosaicY);
  337.     realX -= y*dmx;
  338.     realY -= y*dmy;
  339.   }
  340.   
  341.   int xxx = (realX >> 8);
  342.   int yyy = (realY >> 8);
  343.   
  344.   if(control & 0x2000) {
  345.     xxx %= sizeX;
  346.     yyy %= sizeY;
  347.     if(xxx < 0)
  348.       xxx += sizeX;
  349.     if(yyy < 0)
  350.       yyy += sizeY;
  351.   }
  352.   
  353.   if(control & 0x80) {
  354.     for(int x = 0; x < 240; x++) {
  355.       if(xxx < 0 ||
  356.          yyy < 0 ||
  357.          xxx >= sizeX ||
  358.          yyy >= sizeY) {
  359.         line[x] = 0x80000000;
  360.       } else {
  361.         int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
  362.         
  363.         int tileX = (xxx & 7);
  364.         int tileY = yyy & 7;
  365.         
  366.         u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
  367.           
  368.         line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
  369.       }
  370.       realX += dx;
  371.       realY += dy;
  372.       
  373.       xxx = (realX >> 8);
  374.       yyy = (realY >> 8);
  375.       
  376.       if(control & 0x2000) {
  377.         xxx %= sizeX;
  378.         yyy %= sizeY;
  379.         if(xxx < 0)
  380.           xxx += sizeX;
  381.         if(yyy < 0)
  382.           yyy += sizeY;
  383.       }
  384.     }
  385.   } else {
  386.     for(int x = 0; x < 240; x++) {
  387.       if(xxx < 0 ||
  388.          yyy < 0 ||
  389.          xxx >= sizeX ||
  390.          yyy >= sizeY) {
  391.         line[x] = 0x80000000;
  392.       } else {
  393.         int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
  394.         
  395.         int tileX = (xxx & 7);
  396.         int tileY = yyy & 7;
  397.         
  398.         u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
  399.           
  400.         line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
  401.       }
  402.       realX += dx;
  403.       realY += dy;
  404.       
  405.       xxx = (realX >> 8);
  406.       yyy = (realY >> 8);
  407.       
  408.       if(control & 0x2000) {
  409.         xxx %= sizeX;
  410.         yyy %= sizeY;
  411.         if(xxx < 0)
  412.           xxx += sizeX;
  413.         if(yyy < 0)
  414.           yyy += sizeY;
  415.       }
  416.     }    
  417.   }
  418.  
  419.   if(control & 0x40) {    
  420.     int mosaicX = (MOSAIC & 0xF) + 1;
  421.     if(mosaicX > 1) {
  422.       int m = 1;
  423.       for(int i = 0; i < 239; i++) {
  424.         line[i+1] = line[i];
  425.         m++;
  426.         if(m == mosaicX) {
  427.           m = 1;
  428.           i++;
  429.         }
  430.       }
  431.     }
  432.   }  
  433. }
  434.  
  435. inline void gfxDrawRotScreen16Bit(u16 control,
  436.                                   u16 x_l, u16 x_h,
  437.                                   u16 y_l, u16 y_h,
  438.                                   u16 pa,  u16 pb,
  439.                                   u16 pc,  u16 pd,
  440.                                   int& currentX, int& currentY,
  441.                                   int changed,
  442.                                   u32 *line)
  443. {
  444.   u16 *screenBase = (u16 *)&vram[0];
  445.   int prio = ((control & 3) << 25) + 0x1000000;
  446.   int sizeX = 240;
  447.   int sizeY = 160;
  448.   
  449.   int startX = (x_l) | ((x_h & 0x07FF)<<16);
  450.   if(x_h & 0x0800)
  451.     startX |= 0xF8000000;
  452.   int startY = (y_l) | ((y_h & 0x07FF)<<16);
  453.   if(y_h & 0x0800)
  454.     startY |= 0xF8000000;
  455.  
  456.   int dx = pa & 0x7FFF;
  457.   if(pa & 0x8000)
  458.     dx |= 0xFFFF8000;
  459.   int dmx = pb & 0x7FFF;
  460.   if(pb & 0x8000)
  461.     dmx |= 0xFFFF8000;
  462.   int dy = pc & 0x7FFF;
  463.   if(pc & 0x8000)
  464.     dy |= 0xFFFF8000;
  465.   int dmy = pd & 0x7FFFF;
  466.   if(pd & 0x8000)
  467.     dmy |= 0xFFFF8000;
  468.  
  469.   if(VCOUNT == 0)
  470.     changed = 3;
  471.   
  472.   if(changed & 1) {
  473.     currentX = (x_l) | ((x_h & 0x07FF)<<16);
  474.     if(x_h & 0x0800)
  475.       currentX |= 0xF8000000;
  476.   } else
  477.     currentX += dmx;
  478.  
  479.   if(changed & 2) {
  480.     currentY = (y_l) | ((y_h & 0x07FF)<<16);
  481.     if(y_h & 0x0800)
  482.       currentY |= 0xF8000000;
  483.   } else {
  484.     currentY += dmy;
  485.   }  
  486.   
  487.   int realX = currentX;
  488.   int realY = currentY;
  489.  
  490.   if(control & 0x40) {
  491.     int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
  492.     int y = (VCOUNT % mosaicY);
  493.     realX -= y*dmx;
  494.     realY -= y*dmy;
  495.   }
  496.   
  497.   int xxx = (realX >> 8);
  498.   int yyy = (realY >> 8);
  499.   
  500.   for(int x = 0; x < 240; x++) {
  501.     if(xxx < 0 ||
  502.        yyy < 0 ||
  503.        xxx >= sizeX ||
  504.        yyy >= sizeY) {
  505.       line[x] = 0x80000000;
  506.     } else {
  507.       line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
  508.     }
  509.     realX += dx;
  510.     realY += dy;
  511.     
  512.     xxx = (realX >> 8);
  513.     yyy = (realY >> 8);
  514.   }
  515.  
  516.   if(control & 0x40) {    
  517.     int mosaicX = (MOSAIC & 0xF) + 1;
  518.     if(mosaicX > 1) {
  519.       int m = 1;
  520.       for(int i = 0; i < 239; i++) {
  521.         line[i+1] = line[i];
  522.         m++;
  523.         if(m == mosaicX) {
  524.           m = 1;
  525.           i++;
  526.         }
  527.       }
  528.     }
  529.   }  
  530. }
  531.  
  532. inline void gfxDrawRotScreen256(u16 control, 
  533.                                 u16 x_l, u16 x_h,
  534.                                 u16 y_l, u16 y_h,
  535.                                 u16 pa,  u16 pb,
  536.                                 u16 pc,  u16 pd,
  537.                                 int ¤tX, int& currentY,
  538.                                 int changed,
  539.                                 u32 *line)
  540. {
  541.   u16 *palette = (u16 *)paletteRAM;
  542.   u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000];
  543.   int prio = ((control & 3) << 25) + 0x1000000;
  544.   int sizeX = 240;
  545.   int sizeY = 160;
  546.   
  547.   int startX = (x_l) | ((x_h & 0x07FF)<<16);
  548.   if(x_h & 0x0800)
  549.     startX |= 0xF8000000;
  550.   int startY = (y_l) | ((y_h & 0x07FF)<<16);
  551.   if(y_h & 0x0800)
  552.     startY |= 0xF8000000;
  553.  
  554.   int dx = pa & 0x7FFF;
  555.   if(pa & 0x8000)
  556.     dx |= 0xFFFF8000;
  557.   int dmx = pb & 0x7FFF;
  558.   if(pb & 0x8000)
  559.     dmx |= 0xFFFF8000;
  560.   int dy = pc & 0x7FFF;
  561.   if(pc & 0x8000)
  562.     dy |= 0xFFFF8000;
  563.   int dmy = pd & 0x7FFFF;
  564.   if(pd & 0x8000)
  565.     dmy |= 0xFFFF8000;
  566.  
  567.   if(VCOUNT == 0)
  568.     changed = 3;
  569.  
  570.   if(changed & 1) {
  571.     currentX = (x_l) | ((x_h & 0x07FF)<<16);
  572.     if(x_h & 0x0800)
  573.       currentX |= 0xF8000000;
  574.   } else {
  575.     currentX += dmx;
  576.   }
  577.  
  578.   if(changed & 2) {
  579.     currentY = (y_l) | ((y_h & 0x07FF)<<16);
  580.     if(y_h & 0x0800)
  581.       currentY |= 0xF8000000;
  582.   } else {
  583.     currentY += dmy;
  584.   }  
  585.   
  586.   int realX = currentX;
  587.   int realY = currentY;
  588.  
  589.   if(control & 0x40) {
  590.     int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
  591.     int y = (VCOUNT / mosaicY) * mosaicY;
  592.     realX = startX + y*dmx;
  593.     realY = startY + y*dmy;
  594.   }
  595.   
  596.   int xxx = (realX >> 8);
  597.   int yyy = (realY >> 8);
  598.   
  599.   for(int x = 0; x < 240; x++) {
  600.     if(xxx < 0 ||
  601.          yyy < 0 ||
  602.        xxx >= sizeX ||
  603.        yyy >= sizeY) {
  604.       line[x] = 0x80000000;
  605.     } else {
  606.       u8 color = screenBase[yyy * 240 + xxx];
  607.       
  608.       line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
  609.     }
  610.     realX += dx;
  611.     realY += dy;
  612.     
  613.     xxx = (realX >> 8);
  614.     yyy = (realY >> 8);
  615.   }
  616.  
  617.   if(control & 0x40) {    
  618.     int mosaicX = (MOSAIC & 0xF) + 1;
  619.     if(mosaicX > 1) {
  620.       int m = 1;
  621.       for(int i = 0; i < 239; i++) {
  622.         line[i+1] = line[i];
  623.         m++;
  624.         if(m == mosaicX) {
  625.           m = 1;
  626.           i++;
  627.         }
  628.       }
  629.     }
  630.   }    
  631. }
  632.  
  633. inline void gfxDrawRotScreen16Bit160(u16 control,
  634.                                      u16 x_l, u16 x_h,
  635.                                      u16 y_l, u16 y_h,
  636.                                      u16 pa,  u16 pb,
  637.                                      u16 pc,  u16 pd,
  638.                                      int& currentX, int& currentY,
  639.                                      int changed,
  640.                                      u32 *line)
  641. {
  642.   u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] :
  643.     (u16 *)&vram[0];
  644.   int prio = ((control & 3) << 25) + 0x1000000;
  645.   int sizeX = 160;
  646.   int sizeY = 128;
  647.   
  648.   int startX = (x_l) | ((x_h & 0x07FF)<<16);
  649.   if(x_h & 0x0800)
  650.     startX |= 0xF8000000;
  651.   int startY = (y_l) | ((y_h & 0x07FF)<<16);
  652.   if(y_h & 0x0800)
  653.     startY |= 0xF8000000;
  654.  
  655.   int dx = pa & 0x7FFF;
  656.   if(pa & 0x8000)
  657.     dx |= 0xFFFF8000;
  658.   int dmx = pb & 0x7FFF;
  659.   if(pb & 0x8000)
  660.     dmx |= 0xFFFF8000;
  661.   int dy = pc & 0x7FFF;
  662.   if(pc & 0x8000)
  663.     dy |= 0xFFFF8000;
  664.   int dmy = pd & 0x7FFFF;
  665.   if(pd & 0x8000)
  666.     dmy |= 0xFFFF8000;
  667.  
  668.   if(VCOUNT == 0)
  669.     changed = 3;
  670.  
  671.   if(changed & 1) {
  672.     currentX = (x_l) | ((x_h & 0x07FF)<<16);
  673.     if(x_h & 0x0800)
  674.       currentX |= 0xF8000000;
  675.   } else {
  676.     currentX += dmx;
  677.   }
  678.  
  679.   if(changed & 2) {
  680.     currentY = (y_l) | ((y_h & 0x07FF)<<16);
  681.     if(y_h & 0x0800)
  682.       currentY |= 0xF8000000;
  683.   } else {
  684.     currentY += dmy;
  685.   }  
  686.   
  687.   int realX = currentX;
  688.   int realY = currentY;
  689.  
  690.   if(control & 0x40) {
  691.     int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
  692.     int y = (VCOUNT / mosaicY) * mosaicY;
  693.     realX = startX + y*dmx;
  694.     realY = startY + y*dmy;
  695.   }
  696.   
  697.   int xxx = (realX >> 8);
  698.   int yyy = (realY >> 8);
  699.   
  700.   for(int x = 0; x < 240; x++) {
  701.     if(xxx < 0 ||
  702.        yyy < 0 ||
  703.        xxx >= sizeX ||
  704.        yyy >= sizeY) {
  705.       line[x] = 0x80000000;
  706.     } else {
  707.       line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
  708.     }
  709.     realX += dx;
  710.     realY += dy;
  711.     
  712.     xxx = (realX >> 8);
  713.     yyy = (realY >> 8);
  714.   }
  715.  
  716.   if(control & 0x40) {    
  717.     int mosaicX = (MOSAIC & 0xF) + 1;
  718.     if(mosaicX > 1) {
  719.       int m = 1;
  720.       for(int i = 0; i < 239; i++) {
  721.         line[i+1] = line[i];
  722.         m++;
  723.         if(m == mosaicX) {
  724.           m = 1;
  725.           i++;
  726.         }
  727.       }
  728.     }
  729.   }      
  730. }
  731.  
  732. inline void gfxDrawSprites(u32 *lineOBJ)
  733. {
  734.   int m=0;
  735.   gfxClearArray(lineOBJ);
  736.   if(layerEnable & 0x1000) {
  737.     u16 *sprites = (u16 *)oam;
  738.     u16 *spritePalette = &((u16 *)paletteRAM)[256];
  739.     int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
  740.     int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;    
  741.     for(int x = 0; x < 128 ; x++) {
  742.       u16 a0 = READ16LE(sprites++);
  743.       u16 a1 = READ16LE(sprites++);
  744.       u16 a2 = READ16LE(sprites++);
  745.       sprites++;
  746.  
  747.       // ignore OBJ-WIN
  748.       if((a0 & 0x0c00) == 0x0800)
  749.          continue;
  750.       
  751.       int sizeY = 8;
  752.       int sizeX = 8;
  753.       
  754.       switch(((a0 >>12) & 0x0c)|(a1>>14)) {
  755.       case 0:
  756.         break;
  757.       case 1:
  758.         sizeX = sizeY = 16;
  759.         break;
  760.       case 2:
  761.         sizeX = sizeY = 32;
  762.         break;
  763.       case 3:
  764.         sizeX = sizeY = 64;
  765.         break;
  766.       case 4:
  767.         sizeX = 16;
  768.         break;
  769.       case 5:
  770.         sizeX = 32;
  771.         break;
  772.       case 6:
  773.         sizeX = 32;
  774.         sizeY = 16;
  775.         break;
  776.       case 7:
  777.         sizeX = 64;
  778.         sizeY = 32;
  779.         break;
  780.       case 8:
  781.         sizeY = 16;
  782.         break;
  783.       case 9:
  784.         sizeY = 32;
  785.         break;
  786.       case 10:
  787.         sizeX = 16;
  788.         sizeY = 32;
  789.         break;
  790.       case 11:
  791.         sizeX = 32;
  792.         sizeY = 64;
  793.         break;
  794.       default:
  795.         continue;
  796.       }
  797.  
  798. #ifdef SPRITE_DEBUG
  799.       int maskX = sizeX-1;
  800.       int maskY = sizeY-1;
  801. #endif
  802.  
  803.       int sy = (a0 & 255);
  804.  
  805.       if(sy > 160)
  806.         sy -= 256;
  807.       
  808.       if(a0 & 0x0100) {
  809.         int fieldX = sizeX;
  810.         int fieldY = sizeY;
  811.         if(a0 & 0x0200) {
  812.           fieldX <<= 1;
  813.           fieldY <<= 1;
  814.         }
  815.         
  816.         int t = VCOUNT - sy;
  817.         if((t >= 0) && (t < fieldY)) {
  818.           int sx = (a1 & 0x1FF);
  819.           if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
  820.             // int t2 = t - (fieldY >> 1);
  821.             int rot = (a1 >> 9) & 0x1F;
  822.             u16 *OAM = (u16 *)oam;
  823.             int dx = READ16LE(&OAM[3 + (rot << 4)]);
  824.             if(dx & 0x8000)
  825.               dx |= 0xFFFF8000;
  826.             int dmx = READ16LE(&OAM[7 + (rot << 4)]);
  827.             if(dmx & 0x8000)
  828.               dmx |= 0xFFFF8000;
  829.             int dy = READ16LE(&OAM[11 + (rot << 4)]);
  830.             if(dy & 0x8000)
  831.               dy |= 0xFFFF8000;
  832.             int dmy = READ16LE(&OAM[15 + (rot << 4)]);
  833.             if(dmy & 0x8000)
  834.               dmy |= 0xFFFF8000;
  835.             
  836.             if(a0 & 0x1000) {
  837.               t -= (t % mosaicY);
  838.             }
  839.  
  840.             int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
  841.               + t * dmx;
  842.             int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
  843.               + t * dmy;
  844.  
  845.             u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  846.             
  847.             if(a0 & 0x2000) {
  848.               int c = (a2 & 0x3FF);
  849.               if((DISPCNT & 7) > 2 && (c < 512))
  850.                 continue;
  851.               int inc = 32;
  852.               if(DISPCNT & 0x40)
  853.                 inc = sizeX >> 2;
  854.               else
  855.                 c &= 0x3FE;
  856.               for(int x = 0; x < fieldX; x++) {
  857.                 int xxx = realX >> 8;
  858.                 int yyy = realY >> 8;
  859.                 
  860.                 if(xxx < 0 || xxx >= sizeX ||
  861.                    yyy < 0 || yyy >= sizeY ||
  862.                    sx >= 240);
  863.                 else {
  864.                   u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
  865.                                     + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
  866.                                     (xxx & 7))&0x7FFF)];
  867.                   if ((color==0) && (((prio >> 25)&3) < 
  868.                                      ((lineOBJ[sx]>>25)&3))) {
  869.                     lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
  870.                     if((a0 & 0x1000) && m)
  871.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  872.                   } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
  873.                     lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
  874.                     if((a0 & 0x1000) && m)
  875.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  876.                   }
  877.  
  878.                   if (a0 & 0x1000) {
  879.                     m++;
  880.                     if (m==mosaicX)
  881.                       m=0;
  882.                   }
  883. #ifdef SPRITE_DEBUG
  884.                   if(t == 0 || t == maskY || x == 0 || x == maskX)
  885.                     lineOBJ[sx] = 0x001F;
  886. #endif
  887.                 }
  888.                 sx = (sx+1)&511;;
  889.                 realX += dx;
  890.                 realY += dy;
  891.               }
  892.             } else {
  893.               int c = (a2 & 0x3FF);
  894.               if((DISPCNT & 7) > 2 && (c < 512))
  895.                 continue;
  896.               
  897.               int inc = 32;
  898.               if(DISPCNT & 0x40)
  899.                 inc = sizeX >> 3;
  900.               int palette = (a2 >> 8) & 0xF0;                 
  901.               for(int x = 0; x < fieldX; x++) {
  902.                 int xxx = realX >> 8;
  903.                 int yyy = realY >> 8;
  904.                 if(xxx < 0 || xxx >= sizeX ||
  905.                    yyy < 0 || yyy >= sizeY ||
  906.                    sx >= 240);
  907.                 else {
  908.                   u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
  909.                                                 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
  910.                                                ((xxx & 7)>>1))&0x7FFF)];
  911.                   if(xxx & 1)
  912.                     color >>= 4;
  913.                   else
  914.                     color &= 0x0F;
  915.                   
  916.                   if ((color==0) && (((prio >> 25)&3) < 
  917.                                      ((lineOBJ[sx]>>25)&3))) {
  918.                     lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
  919.                     if((a0 & 0x1000) && m)
  920.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  921.                   } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
  922.                     lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio;
  923.                     if((a0 & 0x1000) && m)
  924.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  925.                   }
  926.                 }
  927.                 if((a0 & 0x1000) && m) {
  928.                   m++;
  929.                   if (m==mosaicX)
  930.                     m=0;
  931.                 }
  932.  
  933. #ifdef SPRITE_DEBUG
  934.                   if(t == 0 || t == maskY || x == 0 || x == maskX)
  935.                     lineOBJ[sx] = 0x001F;
  936. #endif
  937.                 sx = (sx+1)&511;;
  938.                 realX += dx;
  939.                 realY += dy;
  940.                 
  941.               }       
  942.             }
  943.           }
  944.         }
  945.       } else {
  946.         int t = VCOUNT - sy;
  947.         if((t >= 0) && (t < sizeY)) {
  948.           int sx = (a1 & 0x1FF);
  949.           if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
  950.             if(a0 & 0x2000) {
  951.               if(a1 & 0x2000)
  952.                 t = sizeY - t - 1;
  953.               int c = (a2 & 0x3FF);
  954.               if((DISPCNT & 7) > 2 && (c < 512))
  955.                 continue;
  956.               
  957.               int inc = 32;
  958.               if(DISPCNT & 0x40) {
  959.                 inc = sizeX >> 2;
  960.               } else {
  961.                 c &= 0x3FE;
  962.               }
  963.               int xxx = 0;
  964.               if(a1 & 0x1000)
  965.                 xxx = sizeX-1;
  966.  
  967.               if(a0 & 0x1000) {
  968.                 t -= (t % mosaicY);
  969.               }
  970.  
  971.               int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
  972.                 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
  973.                 
  974.               if(a1 & 0x1000)
  975.                 xxx = 7;
  976.               u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  977.                 
  978.               for(int xx = 0; xx < sizeX; xx++) {
  979.                 if(sx < 240) {
  980.                   u8 color = vram[address];
  981.                   if ((color==0) && (((prio >> 25)&3) < 
  982.                                      ((lineOBJ[sx]>>25)&3))) {
  983.                     lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
  984.                     if((a0 & 0x1000) && m)
  985.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  986.                   } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
  987.                     lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
  988.                     if((a0 & 0x1000) && m)
  989.                       lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  990.                   }
  991.  
  992.                   if (a0 & 0x1000) {
  993.                     m++;
  994.                     if (m==mosaicX)
  995.                       m=0;
  996.                   }
  997.  
  998. #ifdef SPRITE_DEBUG
  999.                   if(t == 0 || t == maskY || xx == 0 || xx == maskX)
  1000.                     lineOBJ[sx] = 0x001F;
  1001. #endif
  1002.                 }
  1003.                   
  1004.                 sx = (sx+1) & 511;
  1005.                 if(a1 & 0x1000) {
  1006.                   xxx--;
  1007.                   address--;
  1008.                   if(xxx == -1) {
  1009.                     address -= 56;
  1010.                     xxx = 7;
  1011.                   }
  1012.                   if(address < 0x10000)
  1013.                     address += 0x8000;
  1014.                 } else {
  1015.                   xxx++;
  1016.                   address++;
  1017.                   if(xxx == 8) {
  1018.                     address += 56;
  1019.                     xxx = 0;
  1020.                   }
  1021.                   if(address > 0x17fff)
  1022.                     address -= 0x8000;
  1023.                 }
  1024.               }
  1025.             } else {
  1026.               if(a1 & 0x2000)
  1027.                 t = sizeY - t - 1;
  1028.               int c = (a2 & 0x3FF);
  1029.               if((DISPCNT & 7) > 2 && (c < 512))
  1030.                 continue;
  1031.               
  1032.               int inc = 32;
  1033.               if(DISPCNT & 0x40) {
  1034.                 inc = sizeX >> 3;
  1035.               }
  1036.               int xxx = 0;
  1037.               if(a1 & 0x1000)
  1038.                 xxx = sizeX - 1;
  1039.                   
  1040.                 if(a0 & 0x1000) {
  1041.                   t -= (t % mosaicY);
  1042.                 }
  1043.  
  1044.               int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
  1045.                 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
  1046.               u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  1047.               int palette = (a2 >> 8) & 0xF0;         
  1048.               if(a1 & 0x1000) {
  1049.                 xxx = 7;
  1050.                 for(int xx = sizeX - 1; xx >= 0; xx--) {
  1051.                   if(sx < 240) {
  1052.                     u8 color = vram[address];
  1053.                     if(xx & 1) {
  1054.                       color = (color >> 4);
  1055.                     } else
  1056.                       color &= 0x0F;
  1057.                     
  1058.                     if ((color==0) && (((prio >> 25)&3) < 
  1059.                                        ((lineOBJ[sx]>>25)&3))) {
  1060.                       lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
  1061.                       if((a0 & 0x1000) && m)
  1062.                         lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  1063.                     } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
  1064.                       lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
  1065.                       if((a0 & 0x1000) && m)
  1066.                         lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  1067.                     }
  1068.                   }
  1069.                   if (a0 & 0x1000) {
  1070.                     m++;
  1071.                     if (m==mosaicX)
  1072.                       m=0;
  1073.                   }
  1074. #ifdef SPRITE_DEBUG
  1075.                   if(t == 0 || t == maskY || xx == 0 || xx == maskX)
  1076.                     lineOBJ[sx] = 0x001F;
  1077. #endif
  1078.                   sx = (sx+1) & 511;
  1079.                   xxx--;
  1080.                   if(!(xx & 1))
  1081.                     address--;
  1082.                   if(xxx == -1) {
  1083.                     xxx = 7;
  1084.                     address -= 28;
  1085.                   }
  1086.                   if(address < 0x10000)
  1087.                     address += 0x8000;
  1088.                 }           
  1089.               } else {        
  1090.                 for(int xx = 0; xx < sizeX; xx++) {
  1091.                   if(sx < 240) {
  1092.                     u8 color = vram[address];
  1093.                     if(xx & 1) {
  1094.                       color = (color >> 4);
  1095.                     } else
  1096.                       color &= 0x0F;
  1097.                     
  1098.                     if ((color==0) && (((prio >> 25)&3) < 
  1099.                                        ((lineOBJ[sx]>>25)&3))) {
  1100.                       lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
  1101.                       if((a0 & 0x1000) && m)
  1102.                         lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  1103.                     } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
  1104.                       lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
  1105.                       if((a0 & 0x1000) && m)
  1106.                         lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
  1107.  
  1108.                     }
  1109.                   }
  1110.                   if (a0 & 0x1000) {
  1111.                     m++;
  1112.                     if (m==mosaicX)
  1113.                       m=0;
  1114.                   }
  1115. #ifdef SPRITE_DEBUG
  1116.                   if(t == 0 || t == maskY || xx == 0 || xx == maskX)
  1117.                     lineOBJ[sx] = 0x001F;
  1118. #endif
  1119.                   sx = (sx+1) & 511;
  1120.                   xxx++;
  1121.                   if(xx & 1)
  1122.                     address++;
  1123.                   if(xxx == 8) {
  1124.                     address += 28;
  1125.                     xxx = 0;
  1126.                   }
  1127.                   if(address > 0x17fff)
  1128.                     address -= 0x8000;
  1129.                 }           
  1130.               }
  1131.             }
  1132.           }
  1133.         }
  1134.       }
  1135.     }
  1136.   }
  1137. }
  1138.  
  1139. inline void gfxDrawOBJWin(u32 *lineOBJWin)
  1140. {
  1141.   gfxClearArray(lineOBJWin);
  1142.   if(layerEnable & 0x8000) {
  1143.     u16 *sprites = (u16 *)oam;
  1144.     // u16 *spritePalette = &((u16 *)paletteRAM)[256];
  1145.     for(int x = 0; x < 128 ; x++) {
  1146.       u16 a0 = READ16LE(sprites++);
  1147.       u16 a1 = READ16LE(sprites++);
  1148.       u16 a2 = READ16LE(sprites++);
  1149.       sprites++;
  1150.  
  1151.       // ignore non OBJ-WIN
  1152.       if((a0 & 0x0c00) != 0x0800)
  1153.         continue;
  1154.       
  1155.       int sizeY = 8;
  1156.       int sizeX = 8;
  1157.       
  1158.       switch(((a0 >>12) & 0x0c)|(a1>>14)) {
  1159.       case 0:
  1160.         break;
  1161.       case 1:
  1162.         sizeX = sizeY = 16;
  1163.         break;
  1164.       case 2:
  1165.         sizeX = sizeY = 32;
  1166.         break;
  1167.       case 3:
  1168.         sizeX = sizeY = 64;
  1169.         break;
  1170.       case 4:
  1171.         sizeX = 16;
  1172.         break;
  1173.       case 5:
  1174.         sizeX = 32;
  1175.         break;
  1176.       case 6:
  1177.         sizeX = 32;
  1178.         sizeY = 16;
  1179.         break;
  1180.       case 7:
  1181.         sizeX = 64;
  1182.         sizeY = 32;
  1183.         break;
  1184.       case 8:
  1185.         sizeY = 16;
  1186.         break;
  1187.       case 9:
  1188.         sizeY = 32;
  1189.         break;
  1190.       case 10:
  1191.         sizeX = 16;
  1192.         sizeY = 32;
  1193.         break;
  1194.       case 11:
  1195.         sizeX = 32;
  1196.         sizeY = 64;
  1197.         break;
  1198.       default:
  1199.         continue;
  1200.       }
  1201.  
  1202.       int sy = (a0 & 255);
  1203.  
  1204.       if(sy > 160)
  1205.         sy -= 256;
  1206.       
  1207.       if(a0 & 0x0100) {
  1208.         int fieldX = sizeX;
  1209.         int fieldY = sizeY;
  1210.         if(a0 & 0x0200) {
  1211.           fieldX <<= 1;
  1212.           fieldY <<= 1;
  1213.         }
  1214.         
  1215.         int t = VCOUNT - sy;
  1216.         if((t >= 0) && (t < fieldY)) {
  1217.           int sx = (a1 & 0x1FF);
  1218.           if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
  1219.             // int t2 = t - (fieldY >> 1);
  1220.             int rot = (a1 >> 9) & 0x1F;
  1221.             u16 *OAM = (u16 *)oam;
  1222.             int dx = READ16LE(&OAM[3 + (rot << 4)]);
  1223.             if(dx & 0x8000)
  1224.               dx |= 0xFFFF8000;
  1225.             int dmx = READ16LE(&OAM[7 + (rot << 4)]);
  1226.             if(dmx & 0x8000)
  1227.               dmx |= 0xFFFF8000;
  1228.             int dy = READ16LE(&OAM[11 + (rot << 4)]);
  1229.             if(dy & 0x8000)
  1230.               dy |= 0xFFFF8000;
  1231.             int dmy = READ16LE(&OAM[15 + (rot << 4)]);
  1232.             if(dmy & 0x8000)
  1233.               dmy |= 0xFFFF8000;
  1234.             
  1235.             int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
  1236.               + t * dmx;
  1237.             int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
  1238.               + t * dmy;
  1239.  
  1240.             // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  1241.             
  1242.             if(a0 & 0x2000) {
  1243.               int c = (a2 & 0x3FF);
  1244.               if((DISPCNT & 7) > 2 && (c < 512))
  1245.                 continue;
  1246.               int inc = 32;
  1247.               if(DISPCNT & 0x40)
  1248.                 inc = sizeX >> 2;
  1249.               else
  1250.                 c &= 0x3FE;
  1251.               for(int x = 0; x < fieldX; x++) {
  1252.                 int xxx = realX >> 8;
  1253.                 int yyy = realY >> 8;
  1254.                 
  1255.                 if(xxx < 0 || xxx >= sizeX ||
  1256.                    yyy < 0 || yyy >= sizeY) {
  1257.                 } else {
  1258.                   u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
  1259.                                     + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
  1260.                                    (xxx & 7))&0x7fff)];
  1261.                   if(color) {
  1262.                     lineOBJWin[sx] = 1;
  1263.                   }
  1264.                 }
  1265.                 sx = (sx+1)&511;;
  1266.                 realX += dx;
  1267.                 realY += dy;
  1268.               }
  1269.             } else {
  1270.               int c = (a2 & 0x3FF);
  1271.               if((DISPCNT & 7) > 2 && (c < 512))
  1272.                 continue;
  1273.               
  1274.               int inc = 32;
  1275.               if(DISPCNT & 0x40)
  1276.                 inc = sizeX >> 3;
  1277.               // int palette = (a2 >> 8) & 0xF0;                      
  1278.               for(int x = 0; x < fieldX; x++) {
  1279.                 int xxx = realX >> 8;
  1280.                 int yyy = realY >> 8;
  1281.  
  1282.                 //              if(x == 0 || x == (sizeX-1) ||
  1283.                 //                 t == 0 || t == (sizeY-1)) {
  1284.                 //                lineOBJ[sx] = 0x001F | prio;
  1285.                 //              } else {
  1286.                   if(xxx < 0 || xxx >= sizeX ||
  1287.                      yyy < 0 || yyy >= sizeY){
  1288.                   } else {
  1289.                     u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
  1290.                                      + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
  1291.                                      ((xxx & 7)>>1))&0x7fff)];
  1292.                     if(xxx & 1)
  1293.                       color >>= 4;
  1294.                     else
  1295.                       color &= 0x0F;
  1296.                     
  1297.                     if(color) {
  1298.                       lineOBJWin[sx] = 1;
  1299.                     }
  1300.                   }
  1301.                   //            }
  1302.                 sx = (sx+1)&511;;
  1303.                 realX += dx;
  1304.                 realY += dy;
  1305.               }       
  1306.             }
  1307.           }
  1308.         }
  1309.       } else {
  1310.         int t = VCOUNT - sy;
  1311.         if((t >= 0) && (t < sizeY)) {
  1312.           int sx = (a1 & 0x1FF);
  1313.           if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
  1314.             if(a0 & 0x2000) {
  1315.               if(a1 & 0x2000)
  1316.                 t = sizeY - t - 1;
  1317.               int c = (a2 & 0x3FF);
  1318.               if((DISPCNT & 7) > 2 && (c < 512))
  1319.                 continue;
  1320.               
  1321.               int inc = 32;
  1322.               if(DISPCNT & 0x40) {
  1323.                 inc = sizeX >> 2;
  1324.               } else {
  1325.                 c &= 0x3FE;
  1326.               }
  1327.               int xxx = 0;
  1328.               if(a1 & 0x1000)
  1329.                 xxx = sizeX-1;
  1330.               int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
  1331.                 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
  1332.               if(a1 & 0x1000)
  1333.                 xxx = 7;
  1334.               // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  1335.               for(int xx = 0; xx < sizeX; xx++) {
  1336.                 if(sx < 240) {
  1337.                   u8 color = vram[address];
  1338.                   if(color) {
  1339.                     lineOBJWin[sx] = 1;
  1340.                   }
  1341.                 }
  1342.                   
  1343.                 sx = (sx+1) & 511;
  1344.                 if(a1 & 0x1000) {
  1345.                   xxx--;
  1346.                   address--;
  1347.                   if(xxx == -1) {
  1348.                     address -= 56;
  1349.                     xxx = 7;
  1350.                   }
  1351.                   if(address < 0x10000)
  1352.                     address += 0x8000;
  1353.                 } else {
  1354.                   xxx++;
  1355.                   address++;
  1356.                   if(xxx == 8) {
  1357.                     address += 56;
  1358.                     xxx = 0;
  1359.                   }
  1360.                   if(address > 0x17fff)
  1361.                     address -= 0x8000;
  1362.                 }
  1363.               }
  1364.             } else {
  1365.               if(a1 & 0x2000)
  1366.                 t = sizeY - t - 1;
  1367.               int c = (a2 & 0x3FF);
  1368.               if((DISPCNT & 7) > 2 && (c < 512))
  1369.                 continue;
  1370.               
  1371.               int inc = 32;
  1372.               if(DISPCNT & 0x40) {
  1373.                 inc = sizeX >> 3;
  1374.               }
  1375.               int xxx = 0;
  1376.               if(a1 & 0x1000)
  1377.                 xxx = sizeX - 1;
  1378.               int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
  1379.                 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
  1380.               // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
  1381.               // int palette = (a2 >> 8) & 0xF0;              
  1382.               if(a1 & 0x1000) {
  1383.                 xxx = 7;
  1384.                 for(int xx = sizeX - 1; xx >= 0; xx--) {
  1385.                   if(sx < 240) {
  1386.                     u8 color = vram[address];
  1387.                     if(xx & 1) {
  1388.                       color = (color >> 4);
  1389.                     } else
  1390.                       color &= 0x0F;
  1391.                     
  1392.                     if(color) {
  1393.                       lineOBJWin[sx] = 1;
  1394.                     }
  1395.                   }
  1396.                   sx = (sx+1) & 511;
  1397.                   xxx--;
  1398.                   if(!(xx & 1))
  1399.                     address--;
  1400.                   if(xxx == -1) {
  1401.                     xxx = 7;
  1402.                     address -= 28;
  1403.                   }
  1404.                   if(address < 0x10000)
  1405.                     address += 0x8000;
  1406.                 }           
  1407.               } else {        
  1408.                 for(int xx = 0; xx < sizeX; xx++) {
  1409.                   if(sx < 240) {
  1410.                     u8 color = vram[address];
  1411.                     if(xx & 1) {
  1412.                       color = (color >> 4);
  1413.                     } else
  1414.                       color &= 0x0F;
  1415.                     
  1416.                     if(color) {
  1417.                       lineOBJWin[sx] = 1;
  1418.                     }
  1419.                   }
  1420.                   sx = (sx+1) & 511;
  1421.                   xxx++;
  1422.                   if(xx & 1)
  1423.                     address++;
  1424.                   if(xxx == 8) {
  1425.                     address += 28;
  1426.                     xxx = 0;
  1427.                   }
  1428.                   if(address > 0x17fff)
  1429.                     address -= 0x8000;
  1430.                 }           
  1431.               }
  1432.             }
  1433.           }
  1434.         }
  1435.       }
  1436.     }
  1437.   }
  1438. }
  1439.  
  1440. inline u32 gfxIncreaseBrightness(u32 color, int coeff)
  1441. {
  1442.   int r = (color & 0x1F);
  1443.   int g = ((color >> 5) & 0x1F);
  1444.   int b = ((color >> 10) & 0x1F);
  1445.   
  1446.   r = r + (((31 - r) * coeff) >> 4);
  1447.   g = g + (((31 - g) * coeff) >> 4);
  1448.   b = b + (((31 - b) * coeff) >> 4);
  1449.   if(r > 31)
  1450.     r = 31;
  1451.   if(g > 31)
  1452.     g = 31;
  1453.   if(b > 31)
  1454.     b = 31;
  1455.   color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1456.   return color;
  1457. }
  1458.  
  1459. inline void gfxIncreaseBrightness(u32 *line, int coeff)
  1460. {
  1461.   for(int x = 0; x < 240; x++) {
  1462.     u32 color = *line;
  1463.     int r = (color & 0x1F);
  1464.     int g = ((color >> 5) & 0x1F);
  1465.     int b = ((color >> 10) & 0x1F);
  1466.     
  1467.     r = r + (((31 - r) * coeff) >> 4);
  1468.     g = g + (((31 - g) * coeff) >> 4);
  1469.     b = b + (((31 - b) * coeff) >> 4);
  1470.     if(r > 31)
  1471.       r = 31;
  1472.     if(g > 31)
  1473.       g = 31;
  1474.     if(b > 31)
  1475.       b = 31;
  1476.     *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1477.   }
  1478. }
  1479.  
  1480. inline u32 gfxDecreaseBrightness(u32 color, int coeff)
  1481. {
  1482.   int r = (color & 0x1F);
  1483.   int g = ((color >> 5) & 0x1F);
  1484.   int b = ((color >> 10) & 0x1F);
  1485.   
  1486.   r = r - ((r * coeff) >> 4);
  1487.   g = g - ((g * coeff) >> 4);
  1488.   b = b - ((b * coeff) >> 4);
  1489.   if(r < 0)
  1490.     r = 0;
  1491.   if(g < 0)
  1492.     g = 0;
  1493.   if(b < 0)
  1494.     b = 0;
  1495.   color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1496.   
  1497.   return color;
  1498. }
  1499.  
  1500. inline void gfxDecreaseBrightness(u32 *line, int coeff)
  1501. {
  1502.   for(int x = 0; x < 240; x++) {
  1503.     u32 color = *line;
  1504.     int r = (color & 0x1F);
  1505.     int g = ((color >> 5) & 0x1F);
  1506.     int b = ((color >> 10) & 0x1F);
  1507.     
  1508.     r = r - ((r * coeff) >> 4);
  1509.     g = g - ((g * coeff) >> 4);
  1510.     b = b - ((b * coeff) >> 4);
  1511.     if(r < 0)
  1512.       r = 0;
  1513.     if(g < 0)
  1514.       g = 0;
  1515.     if(b < 0)
  1516.       b = 0;
  1517.     *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1518.   }
  1519. }
  1520.  
  1521. inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb)
  1522. {
  1523.   if(color < 0x80000000) {
  1524.     int r = (color & 0x1F);
  1525.     int g = ((color >> 5) & 0x1F);
  1526.     int b = ((color >> 10) & 0x1F);
  1527.     int r0 = (color2 & 0x1F);
  1528.     int g0 = ((color2 >> 5) & 0x1F);
  1529.     int b0 = ((color2 >> 10) & 0x1F);
  1530.     
  1531.     r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
  1532.     g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
  1533.     b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
  1534.     
  1535.     if(r > 31)
  1536.       r = 31;
  1537.     if(g > 31)
  1538.       g = 31;
  1539.     if(b > 31)
  1540.       b = 31;
  1541.  
  1542.     return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1543.   }
  1544.   return color;
  1545. }
  1546.  
  1547. inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb)
  1548. {
  1549.   for(int x = 0; x < 240; x++) {
  1550.     u32 color = *ta;
  1551.     if(color < 0x80000000) {
  1552.       int r = (color & 0x1F);
  1553.       int g = ((color >> 5) & 0x1F);
  1554.       int b = ((color >> 10) & 0x1F);
  1555.       u32 color2 = (*tb++);
  1556.       int r0 = (color2 & 0x1F);
  1557.       int g0 = ((color2 >> 5) & 0x1F);
  1558.       int b0 = ((color2 >> 10) & 0x1F);
  1559.       
  1560.       r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
  1561.       g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
  1562.       b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
  1563.       
  1564.       if(r > 31)
  1565.         r = 31;
  1566.       if(g > 31)
  1567.         g = 31;
  1568.       if(b > 31)
  1569.         b = 31;
  1570.       
  1571.       *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
  1572.     } else {
  1573.       ta++;
  1574.       tb++;
  1575.     }
  1576.   }
  1577. }
  1578.  
  1579. #endif // VBA_GFX_H
  1580.