Advertisement
xiahanlu

DMG图形处理器+LCD显示屏

Oct 13th, 2018
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 46.59 KB | None | 0 0
  1. /* Game boy's GPU and LCD Screen
  2.  * LCD is Sharp LH5028 http://www.datasheetarchive.com/pdf/download.php?id=c615e5d8551c6b559c3db61b709b3234af856c&type=O&term=LH5028
  3.  *
  4.  * This part of the source code is actually not very good.
  5.  * It looks terrible.
  6.  *
  7.  * Copyright (C) 2018 moecmks
  8.  * This file is part of KS3578.
  9.  *
  10.  * do What The Fuck you want to Public License
  11.  *
  12.  * Version 1.0, March 2000
  13.  * Copyright (C) 2000 Banlu Kemiyatorn (]d).
  14.  * 136 Nives 7 Jangwattana 14 Laksi Bangkok
  15.  * Everyone is permitted to copy and distribute verbatim copies
  16.  * of this license document, but changing it is not allowed.
  17.  *
  18.  * Ok, the purpose of this license is simple
  19.  * and you just
  20.  *
  21.  * DO WHAT THE FUCK YOU WANT TO.
  22.  */
  23.  
  24. #include "gameboy.h"
  25. #include "internal.h"
  26.  
  27. static
  28. void default_update (struct ppu *_5028, void *obj, struct ppu_framebuffer *fbuf) {
  29.   printf ("%s:%s please set ppu_update callback( controller_setupdate function)\n", __FILE__, __LINE__);
  30.   assert (0);
  31. }
  32.  
  33. void ppu_setupdate_ (struct ppu *lh5028, void (*update)
  34.             (struct ppu *,
  35.             void *,
  36.               struct ppu_framebuffer *), void *obj)
  37. {
  38.   lh5028->device_blit = update;
  39.   lh5028->obj = obj;
  40. }
  41.  
  42. int ppu_reset (struct ppu *lh5028) {
  43.  
  44.   /* init register http://gbdev.gg8.se/files/docs/mirrors/pandocs.html#powerupsequence */
  45.   lh5028->reg40_LCDC = 0x91;
  46.   lh5028->reg42_SCY = 0x00;
  47.   lh5028->reg43_SCX = 0x00;
  48.   lh5028->reg45_LYC = 0x00;
  49.   lh5028->reg47_BGP = 0xFC;
  50.   lh5028->reg48_OBP0 = 0xFF;
  51.   lh5028->reg49_OBP1 = 0xFF;
  52.   lh5028->reg4A_WY = 0x00;
  53.   lh5028->reg4B_WX = 0x00;
  54.   /* reset cache */
  55.   lh5028->reg41_LCDM_T = lh5028->reg41_LCDS;
  56.  
  57.   lh5028->hbl_clks_st = 9999.8;
  58.   return 0;
  59. }
  60.  
  61. void ppu_uninit (struct ppu **lh5028);
  62.  
  63. void ppu_write (struct ppu *lh5028, ks_uint16 address, ks_uint8 value) {
  64.  
  65.   ks_uint8 c, s;
  66.   switch (address) {
  67.   case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
  68.     /*Bit 7 - LCD Display Enable             (0=Off, 1=On)
  69.       Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
  70.       Bit 5 - Window Display Enable          (0=Off, 1=On)
  71.       Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
  72.       Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
  73.       Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
  74.       Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
  75.       Bit 0 - BG/Window Display/Priority     (0=Off, 1=On)
  76.      */
  77.     if (!(lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)&& (value & LCDC_DISPLAY_MASK)) {
  78.       /* re-enable display */
  79. #   if 0
  80.       lh5028->gb->cpu_clks_ppu = 0.0;
  81.       lh5028->reg41_LCDM_T =LCDS_MODE_FLAG_SERACH_OAM;
  82.       lh5028->reg41_IRQf |= LCDS_INTERRUPET_ALL_MASK;
  83.       lh5028->reg41_LCDS &= ~3;
  84.       lh5028->reg41_LCDS |= LCDS_MODE_FLAG_SERACH_OAM;
  85.       lh5028->reg40_NMIf = 1;
  86.       lh5028->vscan = -1;
  87.       lh5028->vscanR = 0;
  88.       lh5028->vscan40 = 0;
  89.       lh5028->uscan = -1;
  90.       lh5028->uscanR = 0;
  91.       lh5028->win_stuff = ks_false;
  92.       lh5028->hbl_clks_st = 9999.8;
  93.       lh5028->reg44_LY = 0;
  94.  
  95. #   endif
  96.       lh5028->reg4A_WYRSC = 0;
  97.     }
  98.     if (!(value & LCDC_DISPLAY_MASK))
  99.       lh5028->reg44_LY = 0;
  100.     else ;
  101.     lh5028->reg40_LCDC = value;
  102.     break;
  103.   case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
  104.     /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
  105.       Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
  106.       Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
  107.       Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
  108.       Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
  109.       Bit 1-0 - Mode Flag                             (Read Only)
  110.               0: During H-Blank
  111.               1: During V-Blank
  112.               2: During Searching OAM
  113.               3: During Transferring Data to LCD Driver
  114.     */
  115.     lh5028->reg41_LCDS &= 7;
  116.     lh5028->reg41_LCDS |= (value & ~7);
  117.     break;
  118.   case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
  119.     lh5028->reg42_SCY = value;
  120.     break;
  121.   case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
  122.     lh5028->reg43_SCX = value;
  123.     break;
  124.   case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
  125.     _DEBUG_BREAK();
  126.     break;
  127.   case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
  128.     lh5028->reg45_LYC = value;
  129.     break;
  130.   case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
  131.     lh5028->reg4A_WY = value;
  132.     break;
  133.   case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
  134.     lh5028->reg4B_WX = value;
  135.     break;
  136.   case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
  137.     // value = 0xE8;
  138.     lh5028->bg_pal_dmg[0] = lh5028->bg_pal_dmgT[(value & 0x03) >> 0];
  139.     lh5028->bg_pal_dmg[1] = lh5028->bg_pal_dmgT[(value & 0x0C) >> 2];
  140.     lh5028->bg_pal_dmg[2] = lh5028->bg_pal_dmgT[(value & 0x30) >> 4];
  141.     lh5028->bg_pal_dmg[3] = lh5028->bg_pal_dmgT[(value & 0xC0) >> 6];
  142.     lh5028->reg47_BGP = value;
  143.     break ;
  144.   case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
  145.     lh5028->sp_pal_dmg[0][0] = lh5028->sp_pal_dmgT[0][(value & 0x03) >> 0];
  146.     lh5028->sp_pal_dmg[0][1] = lh5028->sp_pal_dmgT[0][(value & 0x0C) >> 2];
  147.     lh5028->sp_pal_dmg[0][2] = lh5028->sp_pal_dmgT[0][(value & 0x30) >> 4];
  148.     lh5028->sp_pal_dmg[0][3] = lh5028->sp_pal_dmgT[0][(value & 0xC0) >> 6];
  149.     lh5028->reg48_OBP0 = value;
  150.     break ;
  151.   case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
  152.     lh5028->sp_pal_dmg[1][0] = lh5028->sp_pal_dmgT[1][(value & 0x03) >> 0];
  153.     lh5028->sp_pal_dmg[1][1] = lh5028->sp_pal_dmgT[1][(value & 0x0C) >> 2];
  154.     lh5028->sp_pal_dmg[1][2] = lh5028->sp_pal_dmgT[1][(value & 0x30) >> 4];
  155.     lh5028->sp_pal_dmg[1][3] = lh5028->sp_pal_dmgT[1][(value & 0xC0) >> 6];
  156.     lh5028->reg49_OBP1 = value;
  157.     break ;
  158.   case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
  159.     lh5028->reg68_BCPS = value;
  160.     break ;
  161.   case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
  162.     s = lh5028->reg68_BCPS;
  163.     c = s & 0x3F;
  164.     if (c & 1)
  165.       lh5028->bg_pal[c >> 3][(c & 7) >> 1]._hi = value;
  166.     else
  167.       lh5028->bg_pal[c >> 3][(c & 7) >> 1]._lo = value;
  168.     if (s & 0x80) {
  169.       c = (c + 1) & 0x3F;
  170.       lh5028->reg68_BCPS &= ~0x3F;
  171.       lh5028->reg68_BCPS |= c;
  172.     }
  173.     lh5028->reg69_BCPD = value;
  174.     break;
  175.   case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
  176.     lh5028->reg6A_OCPS = value;
  177.     break;
  178.   case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
  179.     s = lh5028->reg6A_OCPS;
  180.     c = s & 0x3F;
  181.     if (c & 1)
  182.       lh5028->sp_pal[c >> 3][(c & 7) >> 1]._hi = value;
  183.     else
  184.       lh5028->sp_pal[c >> 3][(c & 7) >> 1]._lo = value;
  185.     if (s & 0x80) {
  186.       c = (c + 1) & 0x3F;
  187.       lh5028->reg6A_OCPS &= ~0x3F;
  188.       lh5028->reg6A_OCPS |= c;
  189.     }
  190.     lh5028->reg6B_OCPD = value;
  191.     break;
  192.   case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
  193.     for (c = 0; c != 160; c++) {
  194.       s = gameboy_mmu_read (lh5028->gb, value * 256 + c);
  195.       ((ks_int8 *)& lh5028->sp[0])[c] = s;
  196.     }
  197.     /* OAMDMA ~ 160 us
  198.        OAMDMA is a parallel DMA */
  199.     /* lh5028->gb->cpu_clks_dma += lh5028->gb->mach_tools->oamdma_clks; */
  200.     lh5028->reg46_DMA = value;
  201.     break ;
  202.   case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
  203.     lh5028->reg51_HDMA1 = value;
  204.     break;
  205.   case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
  206.     lh5028->reg52_HDMA2 = value;
  207.     break;
  208.   case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
  209.     lh5028->reg53_HDMA3 = value;
  210.     break;
  211.   case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
  212.     lh5028->reg54_HDMA4 = value;
  213.     break;
  214.   case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
  215.     if (value & 0x80) {
  216.       /* H-Blank DMA. **/
  217.       lh5028->hdma_src = lh5028->reg51_HDMA1 * 256 + lh5028->reg52_HDMA2;
  218.       lh5028->hdma_dst = lh5028->reg53_HDMA3 * 256 + lh5028->reg54_HDMA4;
  219.       lh5028->hdma_src &= 0xFFF0;
  220.       lh5028->hdma_dst &= 0xFFF0;
  221.       lh5028->hdma_r16 = value & 0x7F;
  222.       lh5028->hdma_r16 ++;
  223.       lh5028->hdma_gen = ks_true;
  224.       /* set HDMA uncompelete/active */
  225.       lh5028->reg55_HDMA5 &= 0x7F;
  226.     } else {
  227.       /* GDMA **/
  228.      
  229.       ks_uint16 src = lh5028->reg51_HDMA1 * 256 + lh5028->reg52_HDMA2;
  230.       ks_uint16 dst = lh5028->reg53_HDMA3 * 256 + lh5028->reg54_HDMA4;
  231.       ks_uint16 id = 0;
  232.       ks_uint16 K;
  233.  
  234.       src &= 0xFFF0;
  235.       dst &= 0xFFF0;
  236.       K = value & 0x7F;
  237.       K+= 1;
  238.       /* copy it*/
  239.       for (; id != K; id++) {
  240.         ks_uint16 c;
  241.         for (c =0; c != 16; c++) {
  242.           s = gameboy_mmu_read (lh5028->gb, src + id *16 + c);
  243.           gameboy_mmu_write (lh5028->gb, dst + id *16 + c, s);
  244.         }
  245.       }
  246.       /* burning OAM clks */
  247.       /* It takes (220 + (n * 7.63)) microseconds in single speed
  248.          and (110 + (n * 7.63)) microseconds in double speed mode */
  249.       lh5028->gb->cpu_clks_dma += (lh5028->gb->mach_tools->gdma_clks_b
  250.         + lh5028->gb->mach_tools->gdma_clks_per16 * (ks_double) K);
  251.       /* lh5028->reg55_HDMA5 |= 0x80;/* set GDMA compelete/unactive */
  252.     }
  253.     lh5028->reg55_HDMA5 = value;
  254.     break;
  255.   case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
  256.     lh5028->reg4F_VBK = value;
  257.     break;
  258.   default:
  259.     return;
  260.   }
  261. }
  262.  
  263. ks_uint8 ppu_read (struct ppu *lh5028, ks_uint16 address) {
  264.  
  265.   switch (address) {
  266.   case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
  267.     /*Bit 7 - LCD Display Enable             (0=Off, 1=On)
  268.       Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
  269.       Bit 5 - Window Display Enable          (0=Off, 1=On)
  270.       Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
  271.       Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
  272.       Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
  273.       Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
  274.       Bit 0 - BG/Window Display/Priority     (0=Off, 1=On)
  275.      */
  276.     return lh5028->reg40_LCDC;
  277.   case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
  278.     /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
  279.       Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
  280.       Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
  281.       Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
  282.       Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
  283.       Bit 1-0 - Mode Flag       (Mode 0-3, see below) (Read Only)
  284.               0: During H-Blank
  285.               1: During V-Blank
  286.               2: During Searching OAM
  287.               3: During Transferring Data to LCD Driver
  288.     */
  289.     return lh5028->reg41_LCDS;
  290.   case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
  291.     return lh5028->reg42_SCY;
  292.   case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
  293.     return lh5028->reg43_SCX;
  294.   case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
  295.     return lh5028->reg44_LY;
  296.   case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
  297.     return lh5028->reg45_LYC;
  298.   case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
  299.     return lh5028->reg4A_WY;
  300.   case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
  301.     return lh5028->reg4B_WX;
  302.   case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
  303.     return lh5028->reg47_BGP;
  304.   case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
  305.     return lh5028->reg48_OBP0;
  306.   case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
  307.     return lh5028->reg49_OBP1;
  308.   case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
  309.     return lh5028->reg68_BCPS;
  310.   case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
  311.     return lh5028->reg69_BCPD;
  312.   case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
  313.     return lh5028->reg6A_OCPS;
  314.   case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
  315.     return lh5028->reg6B_OCPD;
  316.   case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
  317.     return lh5028->reg46_DMA;
  318.   case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
  319.     return lh5028->reg51_HDMA1;
  320.   case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
  321.     return lh5028->reg52_HDMA2;
  322.   case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
  323.     return lh5028->reg53_HDMA3;
  324.   case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
  325.     return lh5028->reg54_HDMA4;
  326.   case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
  327.     return lh5028->reg55_HDMA5;
  328.   case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
  329.     return lh5028->reg4F_VBK;
  330.     break;
  331.   default:
  332.     return 0xFF;
  333.   }
  334. }
  335. static /* this method for gameboy color */
  336. void bgwin_render_cgb (struct ppu *lh5028, ks_int16 scanline) {
  337.   struct {
  338.     union { ks_uint16 blk;
  339.       struct { ks_uint8 lo; ks_uint8 hi; }; };
  340.   } chrdat,  chrcac;
  341.   /* always scan 168 pixel in every line (21 tiles),
  342.     evenif omfx is ZERO .
  343.       fit buffer offset, so that every time we can scan a complete tile,
  344.           no matter how much omfx is.
  345.     */
  346.   ks_int32 omfx;
  347.   ks_int32 ofx;
  348.   ks_int32 obx;
  349.   ks_int32 omfy;
  350.   ks_int32 ofy;
  351.   ks_int32 vsc;
  352.   ks_uint8 tid;
  353.   ks_int8 tat;
  354.   ks_int32 tidaddr;
  355.   ks_uint16 pixcac;
  356.   ks_uint8 *tdat;
  357.   ks_int32 rxpos;
  358.   ks_uint32 c, q, c2, s;
  359.   ks_int32 c3;
  360.   ks_uint16 *vptrWinDrawStart;
  361.   ks_uint16 *vptrScrollStart;
  362.   /* check current scan region in BG or WINDOW (if WINDOW enable)*/
  363.   if ( (lh5028->reg40_LCDC & 0x20)) {
  364.     /* draw window  */
  365.     goto windraw;
  366.   } else {
  367.     /* draw background */
  368.     vsc = lh5028->uscanR;
  369.     omfx = lh5028->reg43_SCX & 7;
  370.     ofx = lh5028->reg43_SCX >> 3;
  371.     omfy = lh5028->reg42_SCY & 7;
  372.     ofy = lh5028->reg42_SCY >> 3;
  373.     ofx = ofx + vsc;
  374.     ofy = ofy + scanline;
  375.     omfy = ofy & 7;
  376.     ofy = ofy >> 3;
  377.     ofx = ofx - (ofx & 32);
  378.     ofy = ofy - (ofy & 32);  
  379.     obx = vsc << 3;
  380.     vptrScrollStart = & lh5028->fmebuf.buf[scanline *(lh5028->fmebuf.pitch/sizeof (lh5028->fmebuf.buf[0]))-omfx];
  381.     /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  382.     tidaddr = 0x9800 + (((lh5028->reg40_LCDC & 0x08) >> 3) << 10);
  383.     tidaddr = (tidaddr-0x8000)+(ofy<< 5)+ofx;
  384.     tid = lh5028->ram[tidaddr]; // fetch tileid
  385.     tat = lh5028->ram[tidaddr+0x2000]; // fetch tileattr.
  386.     tdat = & lh5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
  387. #   if  1
  388.     if (lh5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  389.       tdat = & tdat[tid<<4];
  390.     else //
  391.       tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  392. #   else
  393.     cti16 = (lh5028->reg40_LCDC & 0x10) << 8;
  394.     cti16^= 0x1000;
  395.     tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  396. #   endif
  397. #   if  1
  398.     if (tat & 0x40) // check vflip ?
  399.       tdat = & tdat[(7-omfy)*2];
  400.     else
  401.       tdat = & tdat[omfy*2];
  402. #   else
  403.     ctu8 = (tat & 0x40) >> 3; // 8
  404.     ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
  405.     tdat = & tdat[(ctu8^omfy)<<1];
  406. #   endif
  407.     chrdat.blk = *(ks_uint16 *)tdat;
  408.     /* check x flip  */
  409.     if (tat & 0x20) {
  410.       chrcac.blk = chrdat.blk & 0x8080;
  411.       pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  412.       chrcac.blk = chrdat.blk & 0x4040;
  413.       pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  414.       chrcac.blk = chrdat.blk & 0x2020;
  415.       pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  416.       chrcac.blk = chrdat.blk & 0x1010;
  417.       pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  418.       chrcac.blk = chrdat.blk & 0x0808;
  419.       pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  420.       chrcac.blk = chrdat.blk & 0x0404;
  421.       pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  422.       chrcac.blk = chrdat.blk & 0x0202;
  423.       pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  424.       chrcac.blk = chrdat.blk & 0x0101;
  425.       pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  426.     } else {
  427.       chrcac.blk = chrdat.blk & 0x8080;
  428.       pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  429.       chrcac.blk = chrdat.blk & 0x4040;
  430.       pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  431.       chrcac.blk = chrdat.blk & 0x2020;
  432.       pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  433.       chrcac.blk = chrdat.blk & 0x1010;
  434.       pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  435.       chrcac.blk = chrdat.blk & 0x0808;
  436.       pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  437.       chrcac.blk = chrdat.blk & 0x0404;
  438.       pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  439.       chrcac.blk = chrdat.blk & 0x0202;
  440.       pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  441.       chrcac.blk = chrdat.blk & 0x0101;
  442.       pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  443.     }
  444.     rxpos = obx - omfx;
  445.     q = tat&7;
  446.     if (!(lh5028->reg40_LCDC & 0x01)) {
  447.       vptrScrollStart = & vptrScrollStart[obx];
  448.       /* When Bit 0 is cleared, the background and window lose their priority,
  449.         the sprites will be always displayed on top of background and window,
  450.         independently of the priority flags in OAM and BG Map attributes.
  451.         */
  452.       for (c = 0; c != 8; c++) {
  453.         s = rxpos+c;
  454.         if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  455.           vptrScrollStart[c] = lh5028->olf[s].pixel;
  456.         else
  457.           vptrScrollStart[c] = lh5028->bg_pal[q][pixcac & 3].rgb15;
  458.         pixcac >>= 2;
  459.       }
  460.     } else if (tat & 0x80) { // BG pri.
  461.       vptrScrollStart = & vptrScrollStart[obx];
  462.       for (c = 0; c != 8; c++) {
  463.         vptrScrollStart[c] = lh5028->bg_pal[q][pixcac & 3].rgb15;
  464.         pixcac >>= 2;
  465.       }
  466.     } else  {
  467.       for (c = 0; c != 8; c++) {
  468.         s = rxpos+c;
  469.         c2 = pixcac & 3;
  470.         if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS)
  471.           if (!(lh5028->olf[s].attr & PIXEL_SPRITE_BACK))
  472.             vptrScrollStart[c] = lh5028->olf[s].pixel;
  473.           else if ( c2 == 0)
  474.             vptrScrollStart[c] = lh5028->olf[s].pixel;
  475.           else
  476.             vptrScrollStart[c] = lh5028->bg_pal[q][c2].rgb15;
  477.         else
  478.           vptrScrollStart[c] = lh5028->bg_pal[q][c2].rgb15;
  479.         pixcac >>= 2;
  480.       }
  481.     }
  482.     rxpos = obx - omfx; // -7 | 25
  483.     rxpos+= 8; // 1 | 33
  484.     rxpos+= 7; // 8 | 40
  485.     if ( (lh5028->reg40_LCDC & 0x20)
  486.         && (lh5028->reg4B_WX <= 166 && lh5028->reg4B_WX < rxpos) /* check X**/
  487.         && (lh5028->reg4A_WY <= scanline && (lh5028->reg4A_WY <= 143)))
  488.     {
  489.      
  490.       lh5028->xscanR = 0;
  491.       q = 15 - omfx; // 8 | 16-> 9
  492.       // 7->0
  493.       // 8->1
  494.       while (lh5028->reg4B_WX >= q) // 15 >= q / 16
  495.         {
  496.           lh5028->xscanR ++; //  1 or 2
  497.           q += 8;
  498.         }
  499.       goto windraw;
  500.     }
  501.   }
  502.   return ;
  503. windraw:
  504.   ofx = lh5028->uscanR - lh5028->xscanR; // espl x
  505.   c = scanline - lh5028->reg4A_WY; // total - y
  506.   omfx = 0;
  507.   omfy = c & 7;
  508.   ofy = c >> 3;
  509.   c3 = ((ks_int8)lh5028->reg4B_WX)-7;
  510.   c3 = c3 + (ofx<<3);
  511.   vptrWinDrawStart = & lh5028->fmebuf.buf[scanline *(lh5028->fmebuf.pitch/sizeof (lh5028->fmebuf.buf[0]))+c3];
  512.   /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  513.   tidaddr = 0x9800 + (((lh5028->reg40_LCDC & 0x40) >> 6) << 10);
  514.   tidaddr = (tidaddr-0x8000)+(ofy<< 5)+ofx;
  515.   tid = lh5028->ram[tidaddr]; // fetch tileid
  516.   tat = lh5028->ram[tidaddr+0x2000]; // fetch tileattr.
  517.   tdat = & lh5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
  518. #   if  1
  519.   if (lh5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  520.     tdat = & tdat[tid<<4];
  521.   else //
  522.     tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  523. #   else
  524.   cti16 = (lh5028->reg40_LCDC & 0x10) << 8;
  525.   cti16^= 0x1000;
  526.   tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  527. #   endif
  528. #   if  1
  529.   if (tat & 0x40) // check vflip ?
  530.     tdat = & tdat[(7-omfy)*2];
  531.   else
  532.     tdat = & tdat[omfy*2];
  533. #   else
  534.   ctu8 = (tat & 0x40) >> 3; // 8
  535.   ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
  536.   tdat = & tdat[(ctu8^omfy)<<1];
  537. #   endif
  538.   chrdat.blk = *(ks_uint16 *)tdat;
  539.   /* check x flip  */
  540.   if (tat & 0x20) {
  541.     chrcac.blk = chrdat.blk & 0x8080;
  542.     pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  543.     chrcac.blk = chrdat.blk & 0x4040;
  544.     pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  545.     chrcac.blk = chrdat.blk & 0x2020;
  546.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  547.     chrcac.blk = chrdat.blk & 0x1010;
  548.     pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  549.     chrcac.blk = chrdat.blk & 0x0808;
  550.     pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  551.     chrcac.blk = chrdat.blk & 0x0404;
  552.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  553.     chrcac.blk = chrdat.blk & 0x0202;
  554.     pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  555.     chrcac.blk = chrdat.blk & 0x0101;
  556.     pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  557.   } else {
  558.     chrcac.blk = chrdat.blk & 0x8080;
  559.     pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  560.     chrcac.blk = chrdat.blk & 0x4040;
  561.     pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  562.     chrcac.blk = chrdat.blk & 0x2020;
  563.     pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  564.     chrcac.blk = chrdat.blk & 0x1010;
  565.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  566.     chrcac.blk = chrdat.blk & 0x0808;
  567.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  568.     chrcac.blk = chrdat.blk & 0x0404;
  569.     pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  570.     chrcac.blk = chrdat.blk & 0x0202;
  571.     pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  572.     chrcac.blk = chrdat.blk & 0x0101;
  573.     pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  574.   }
  575.   q = tat&7;
  576.   if (!(lh5028->reg40_LCDC & 0x01)) {
  577.     for (c = 0; c != 8; c++) {
  578.       s = c3+c;
  579.       if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  580.         vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  581.       else
  582.         vptrWinDrawStart[c] = lh5028->bg_pal[q][pixcac & 3].rgb15;
  583.       pixcac >>= 2;
  584.     }
  585.   } else if (tat & 0x80) { // BG pri.
  586.     for (c = 0; c != 8; c++) {
  587.       vptrWinDrawStart[c] = lh5028->bg_pal[q][pixcac & 3].rgb15;
  588.       pixcac >>= 2;
  589.     }
  590.   } else  {
  591.     for (c = 0; c != 8; c++) {
  592.       s = c3+c;
  593.       c2 = pixcac & 3;
  594.       if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS)
  595.         if (!(lh5028->olf[s].attr & PIXEL_SPRITE_BACK))
  596.           vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  597.         else if ( c2 == 0)
  598.           vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  599.         else
  600.           vptrWinDrawStart[c] = lh5028->bg_pal[q][c2].rgb15;
  601.       else
  602.         vptrWinDrawStart[c] = lh5028->bg_pal[q][c2].rgb15;
  603.       pixcac >>= 2;
  604.     }
  605.   }
  606. }
  607. static /* this method for gameboy */
  608. void bgwin_render_dmg (struct ppu *lh5028, ks_int16 scanline) {
  609.   struct {
  610.     union { ks_uint16 blk;
  611.       struct { ks_uint8 lo; ks_uint8 hi; }; };
  612.   } chrdat,  chrcac;
  613.   /* always scan 168 pixel in every line (21 tiles),
  614.     evenif omfx is ZERO .
  615.       fit buffer offset, so that every time we can scan a complete tile,
  616.           no matter how much omfx is.
  617.     */
  618.   ks_int32 omfx;
  619.   ks_int32 ofx;
  620.   ks_int32 obx;
  621.   ks_int32 omfy;
  622.   ks_int32 ofy;
  623.   ks_int32 vsc;
  624.   ks_uint8 tid;
  625.   ks_int32 tidaddr;
  626.   ks_uint16 pixcac;
  627.   ks_uint8 *tdat;
  628.   ks_int32 rxpos;
  629.   ks_uint32 c, q, c2, s;
  630.   ks_int32 c3;
  631.   ks_uint16 *vptrWinDrawStart;
  632.   ks_uint16 *vptrScrollStart;
  633.   /* check current scan region in BG or WINDOW (if WINDOW enable)*/
  634.   if ( lh5028->reg4A_WYLineHit != 0 && (lh5028->reg40_LCDC & LCDC_WINDOW_MASK)) {
  635.     /* draw window  */
  636.     goto windraw;
  637.   } else {
  638.     /* draw background */
  639.     vsc = lh5028->uscanR;
  640.     omfx = lh5028->reg43_SCX & 7;
  641.     ofx = lh5028->reg43_SCX >> 3;
  642.     omfy = lh5028->reg42_SCY & 7;
  643.     ofy = lh5028->reg42_SCY >> 0;
  644.     ofx = ofx + vsc;
  645.     ofy = ofy + scanline;
  646.     omfy = ofy & 7;
  647.     ofy = ofy >> 3;
  648.     ofx = ofx - (ofx & 32);
  649.     ofy = ofy - (ofy & 32);  
  650.     obx = vsc << 3;
  651.     vptrScrollStart = & lh5028->fmebuf.buf[scanline *(lh5028->fmebuf.pitch/sizeof (lh5028->fmebuf.buf[0]))-omfx];
  652.     /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  653.     tidaddr = 0x9800 + (((lh5028->reg40_LCDC & 0x08) >> 3) << 10);
  654.     tidaddr = (tidaddr-0x8000)+(ofy<< 5)+ofx;
  655.     tid = lh5028->ram[tidaddr]; // fetch tileid
  656.     tdat = & lh5028->ram[0];
  657. #   if  1
  658.     if (lh5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  659.       tdat = & tdat[tid<<4];
  660.     else //
  661.       tdat = & tdat[0x1000+(((ks_int8)tid)*16)]; // TODO: done.
  662. #   else
  663.     c2 = (lh5028->reg40_LCDC & 0x10) << 8;
  664.     c2^= 0x1000;
  665.     tdat = & tdat[c2+((ks_int8)(c2 >>5)) & (((ks_int8)tid) << 4)];
  666. #   endif
  667.     tdat = & tdat[omfy*2];
  668.     chrdat.blk = *(ks_uint16 *)tdat;
  669.     chrcac.blk = chrdat.blk & 0x8080;
  670.     pixcac =          (chrcac.lo >> 7) | (chrcac.hi >> 6);
  671.     chrcac.blk = chrdat.blk & 0x4040;
  672.     pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  673.     chrcac.blk = chrdat.blk & 0x2020;
  674.     pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  675.     chrcac.blk = chrdat.blk & 0x1010;
  676.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  677.     chrcac.blk = chrdat.blk & 0x0808;
  678.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  679.     chrcac.blk = chrdat.blk & 0x0404;
  680.     pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  681.     chrcac.blk = chrdat.blk & 0x0202;
  682.     pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  683.     chrcac.blk = chrdat.blk & 0x0101;
  684.     pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  685.     rxpos = obx - omfx;
  686.    
  687.     if (!(lh5028->reg40_LCDC & 0x01)) {
  688.       vptrScrollStart = & vptrScrollStart[obx];
  689.       /* When Bit 0 is cleared, both background and window become blank (white),
  690.         ie. the Window Display Bit (Bit 5) is ignored in that case.
  691.           Only Sprites may still be displayed (if enabled in Bit 1).
  692.         */
  693.       for (c = 0; c != 8; c++) {
  694.         s = rxpos+c;
  695.         if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  696.           vptrScrollStart[c] = lh5028->olf[s].pixel;
  697.         else
  698.           // vptrScrollStart[c] = lh5028->bg_pal_dmg[0];
  699.         vptrScrollStart[c] = lh5028->bg_pal_dmgT[0];
  700.         pixcac >>= 2;
  701.       }
  702.     } else  {
  703.       vptrScrollStart = & vptrScrollStart[obx];
  704.       for (c = 0; c != 8; c++) {
  705.         s = rxpos+c;
  706.         c2 = pixcac & 3;
  707.         if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS)
  708.           if (!(lh5028->olf[s].attr & PIXEL_SPRITE_BACK))
  709.             vptrScrollStart[c] = lh5028->olf[s].pixel;
  710.           else if ( c2 == 0)
  711.             vptrScrollStart[c] = lh5028->olf[s].pixel;
  712.           else
  713.             vptrScrollStart[c] = lh5028->bg_pal_dmg[pixcac & 3];
  714.         else
  715.           vptrScrollStart[c] = lh5028->bg_pal_dmg[pixcac & 3];
  716.         pixcac >>= 2;
  717.       }
  718.     }
  719.     rxpos = obx - omfx; // -7 | 25
  720.     rxpos+= 8; // 1 | 33
  721.     rxpos+= 7; // 8 | 40
  722.     if ((lh5028->reg40_LCDC & 0x20)
  723.         && (lh5028->reg4B_WX <= 166 && lh5028->reg4B_WX < rxpos) /* check X**/
  724.         && (lh5028->reg4A_WY <= scanline && (lh5028->reg4A_WY <= 143)))
  725.     {
  726.       lh5028->xscanR = 0;
  727.       q = 15 - omfx; // 8 | 16-> 9
  728.       lh5028->reg4A_WYLineHit = 1;
  729.       // 7->0
  730.       // 8->1
  731.       while (lh5028->reg4B_WX >= q) // 15 >= q / 16
  732.         {
  733.           lh5028->xscanR ++; //  1 or 2
  734.           q += 8;
  735.         }
  736.       goto windraw;
  737.     }
  738.   }
  739.   return ;
  740. windraw:
  741.   // return ;
  742.   ofx = lh5028->uscanR - lh5028->xscanR; // espl x  
  743.   c = lh5028->reg4A_WYRSC;
  744.   omfx = 0;
  745.   omfy = c & 7;
  746.   ofy = c >> 3;
  747.   c3 = lh5028->reg4B_WX - 7;
  748.   c3 = c3 + (ofx<<3);
  749.   vptrWinDrawStart = & lh5028->fmebuf.buf[scanline *(lh5028->fmebuf.pitch/sizeof (lh5028->fmebuf.buf[0]))+c3];
  750.   /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  751.   tidaddr = 0x9800 + (((lh5028->reg40_LCDC & 0x40) >> 6) << 10);
  752.   tidaddr = (tidaddr-0x8000)+(ofy<< 5)+ofx;
  753.   tid = lh5028->ram[tidaddr]; // fetch tileid
  754.   tdat = & lh5028->ram[0]; // bank select.
  755. #   if  1
  756.   if (lh5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  757.     tdat = & tdat[tid<<4];
  758.   else //
  759.     tdat = & tdat[0x1000+(((ks_int8)tid)*16)]; // TODO: done.
  760. #   else
  761.   cti16 = (lh5028->reg40_LCDC & 0x10) << 8;
  762.   cti16^= 0x1000;
  763.   tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  764. #   endif
  765.   tdat = & tdat[omfy*2];
  766.   chrdat.blk = *(ks_uint16 *)tdat;
  767.   chrcac.blk = chrdat.blk & 0x8080;
  768.   pixcac =          (chrcac.lo >> 7) | (chrcac.hi >> 6);
  769.   chrcac.blk = chrdat.blk & 0x4040;
  770.   pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  771.   chrcac.blk = chrdat.blk & 0x2020;
  772.   pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  773.   chrcac.blk = chrdat.blk & 0x1010;
  774.   pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  775.   chrcac.blk = chrdat.blk & 0x0808;
  776.   pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  777.   chrcac.blk = chrdat.blk & 0x0404;
  778.   pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  779.   chrcac.blk = chrdat.blk & 0x0202;
  780.   pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  781.   chrcac.blk = chrdat.blk & 0x0101;
  782.   pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  783.  
  784.   if (!(lh5028->reg40_LCDC & 0x01)) {
  785.     for (c = 0; c != 8; c++) {
  786.       s = c3+c;
  787.       if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  788.         vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  789.       else
  790.         vptrWinDrawStart[c] = lh5028->bg_pal_dmg[0];
  791.     }
  792.   } else  {
  793.     for (c = 0; c != 8; c++) {
  794.       s = c3+c;
  795.       c2 = pixcac & 3;
  796.       if (lh5028->olf[s].attr & PIXEL_SPRITE_NOTRANS)
  797.         if (!(lh5028->olf[s].attr & PIXEL_SPRITE_BACK))
  798.           vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  799.         else if ( c2 == 0)
  800.           vptrWinDrawStart[c] = lh5028->olf[s].pixel;
  801.         else
  802.           vptrWinDrawStart[c] = lh5028->bg_pal_dmg[pixcac & 3];
  803.       else
  804.         vptrWinDrawStart[c] = lh5028->bg_pal_dmg[pixcac & 3];
  805.       pixcac >>= 2;
  806.     }
  807.   }
  808. }
  809. static /* this method for gameboy color */
  810. void sprite_render_cgb (struct ppu *lh5028, ks_int16 scanline) {
  811.  
  812. }
  813.  
  814. static /* this method for gameboy */
  815. void sprite_render_dmg (struct ppu *lh5028, ks_int delta) {
  816.  
  817.   struct {
  818.     union {
  819.       ks_uint16 blk;
  820.       struct {
  821.         ks_uint8 lo;
  822.         ks_uint8 hi;
  823.       };
  824.     };
  825.   } chrdat,  chrcac;
  826.  
  827.   while (delta > 0 && (lh5028->vscan40 < 40) && (lh5028->vscanR < 10)) {
  828.     ks_intptr size16 = (lh5028->reg40_LCDC & LCDC_OAM_SIZE16_MASK) ? 0 : 8;
  829.     struct oam *ops = & lh5028->sp[lh5028->vscan40];
  830.     lh5028->vscan40++;
  831.     if ( !(ops->y == 0  || ops->y >= 160
  832.      || ops->x == 0 || ops->x >= 168)
  833.      && (lh5028->reg44_LY >= (ops->y - 16))
  834.      && (lh5028->reg44_LY < (ops->y - size16)))
  835.     {
  836.       /*draw scanline */
  837.       ks_uint16 pixcac ;
  838.       ks_uint8 *chr;
  839.       ks_uint32 id;
  840.       ks_int x;
  841.  
  842.       lh5028->vscanR++;
  843.       delta--;
  844.       if (size16 == 0)
  845.         chr = & lh5028->ram[(ops->id & 0xFE)<<4]; // always pointer tile16's high part in init state .
  846.       else
  847.         chr = & lh5028->ram[(ops->id & 0xFF)<<4];
  848.  
  849.       if (size16 == 0) {
  850.         if (ops->attr & LCD_OAM_FLIP_Y_MASK) {
  851.           int cc = lh5028->reg44_LY - (ops->y - 16);
  852.           /* get oppo base tile byte8 (^source pos[high or low])*/
  853.           if (cc < 7) /* high, switch to low */ {
  854.             cc = 7 -cc; /* flip Y in one tile */
  855.             cc<<= 1;
  856.             cc += 16;
  857.           } else { /* low switch to high, nodone, already in high.*/    
  858.             cc = 15 -cc; /* flip Y in one tile */
  859.             cc<<= 1;
  860.           }
  861.           chrdat.blk = *(ks_int16 *)& chr[cc];
  862.         } else {
  863.           int cc = lh5028->reg44_LY - (ops->y - 16);
  864.           cc<<= 1;
  865.           chrdat.blk = *(ks_int16 *)& chr[cc];
  866.         }
  867.       } else {
  868.         if (ops->attr & LCD_OAM_FLIP_Y_MASK) {
  869.           int cc = lh5028->reg44_LY - (ops->y - 16);
  870.           cc = 7 -cc; /* flip Y in one tile */
  871.           cc *= 2;
  872.           chrdat.blk = *(ks_int16 *)& chr[cc];
  873.         } else {
  874.           int cc = lh5028->reg44_LY - (ops->y - 16);
  875.           cc *= 2;
  876.           chrdat.blk = *(ks_int16 *)& chr[cc];
  877.         }
  878.       }
  879.       /* mix gbc's pixel (d1d0)
  880.        * see GBCPUman.pdf:: 2.8.1. Tiles
  881.        * check x flip  
  882.        */
  883.       if (ops->attr & LCD_OAM_FLIP_X_MASK) {
  884.         chrcac.blk = chrdat.blk & 0x8080;
  885.         pixcac =          (chrcac.lo << 7) | (chrcac.hi << 8);
  886.         chrcac.blk = chrdat.blk & 0x4040;
  887.         pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  888.         chrcac.blk = chrdat.blk & 0x2020;
  889.         pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  890.         chrcac.blk = chrdat.blk & 0x1010;
  891.         pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  892.         chrcac.blk = chrdat.blk & 0x0808;
  893.         pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  894.         chrcac.blk = chrdat.blk & 0x0404;
  895.         pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  896.         chrcac.blk = chrdat.blk & 0x0202;
  897.         pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  898.         chrcac.blk = chrdat.blk & 0x0101;
  899.         pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  900.       } else {
  901.         chrcac.blk = chrdat.blk & 0x8080;
  902.         pixcac =         (chrcac.lo >> 7) | (chrcac.hi >> 6);
  903.         chrcac.blk = chrdat.blk & 0x4040;
  904.         pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  905.         chrcac.blk = chrdat.blk & 0x2020;
  906.         pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  907.         chrcac.blk = chrdat.blk & 0x1010;
  908.         pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  909.         chrcac.blk = chrdat.blk & 0x0808;
  910.         pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  911.         chrcac.blk = chrdat.blk & 0x0404;
  912.         pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  913.         chrcac.blk = chrdat.blk & 0x0202;
  914.         pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  915.         chrcac.blk = chrdat.blk & 0x0101;
  916.         pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  917.       }
  918.       x = ops->x - 8;
  919.       for (id = 8; id != 0; id--) {
  920.         ks_uint8 idpal = pixcac & 3;
  921.         /* check trans or */
  922.         if (lh5028->olf[x].attr & PIXEL_SPRITE_NOTRANS) {
  923.           /* notrans */
  924.           if (lh5028->olf[x].attr & PIXEL_SPRITE_BACK) {
  925.             if (!(ops->attr & LCD_OAM_BACKGROUND_MASK) && idpal != 0) {
  926. #             if  1 /* maybe error, it's not a big problem. */
  927.               /* cur pick oam is foreground sprite */
  928.               lh5028->olf[x].pixel = lh5028->sp_pal_dmg[(ops->attr & 0x10) >> 4][idpal];
  929.               lh5028->olf[x].attr = PIXEL_SPRITE_NOTRANS;            
  930. #             endif
  931.             }
  932.           } else {
  933.             /* nodone in foreground sprite */
  934.           }
  935.         } else {
  936.           /* trans, write directly */
  937.           lh5028->olf[x].pixel = lh5028->sp_pal_dmg[(ops->attr & 0x10) >> 4][idpal];
  938.           lh5028->olf[x].attr = 0;
  939.  
  940.           if (ops->attr & LCD_OAM_BACKGROUND_MASK)
  941.             lh5028->olf[x].attr |= PIXEL_SPRITE_BACK;
  942.           if (idpal != 0)
  943.             lh5028->olf[x].attr |= PIXEL_SPRITE_NOTRANS;
  944.         }
  945.         x ++;
  946.         pixcac >>= 2;
  947.       }
  948.     }
  949.   }
  950. }
  951. /* XXX:so bad */
  952. static
  953. void ticks (struct ppu *lh5028) {
  954.  
  955.   ks_int32 scanline;
  956.   ks_int16 interv;
  957.   ks_int16 delta;
  958.   ks_double clkline;
  959.  
  960.   if (lh5028->gb->cpu_clks_ppu > lh5028->gb->mach_tools->frame_cycles) {
  961.     lh5028->gb->cpu_clks_ppu -= lh5028->gb->mach_tools->frame_cycles; // sub a frame block
  962.     /* vblank Interrupt, check missing interruption */
  963.     if (lh5028->reg40_NMIf != 0 && (lh5028->reg40_LCDC & LCDC_DISPLAY_MASK))
  964.       lh5028->gb->reg0F_IF |= IRQ_1;
  965.     /* vblank stat Interrupt, check missing interruption */
  966.     if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  967.        && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_VBLANK_MASK))
  968.       lh5028->gb->reg0F_IF |= IRQ_2;
  969.     /* the beginning of a new frame  reset ppu's context */
  970.     lh5028->reg41_IRQf |= LCDS_INTERRUPET_ALL_MASK;
  971.     lh5028->reg40_NMIf = 1;
  972.     lh5028->vscan = -1;
  973.     lh5028->vscanR = 0;
  974.     lh5028->vscan40 = 0;
  975.     lh5028->uscan = -1;
  976.   }
  977.   scanline = (ks_int32) (lh5028->gb->cpu_clks_ppu/ lh5028->gb->mach_tools->line_cycles);
  978.   clkline = lh5028->gb->cpu_clks_ppu - lh5028->gb->mach_tools->line_cycles * (ks_double) scanline;
  979.   /* clear mask */
  980.   lh5028->reg41_LCDS &= ~LCDS_MODE_FLAG_ALL_MASK;
  981.   lh5028->reg44_LY = scanline;
  982.  
  983.   /*
  984.     PPU time series
  985.  
  986.     Mode 0: The LCD controller is in the H-Blank period and
  987.          the CPU can access both the display RAM (8000h-9FFFh)
  988.          and OAM (FE00h-FE9Fh)
  989.  
  990.     Mode 1: The LCD controller is in the V-Blank period (or the
  991.          display is disabled) and the CPU can access both the
  992.          display RAM (8000h-9FFFh) and OAM (FE00h-FE9Fh)
  993.  
  994.     Mode 2: The LCD controller is reading from OAM memory.
  995.          The CPU <cannot> access OAM memory (FE00h-FE9Fh)
  996.          during this period.
  997.  
  998.     Mode 3: The LCD controller is reading from both OAM and VRAM,
  999.          The CPU <cannot> access OAM and VRAM during this period.
  1000.          CGB Mode: Cannot access Palette Data (FF69,FF6B) either.
  1001.     The following are typical when the display is enabled:
  1002.  
  1003.     Mode 2  2_____2_____2_____2_____2_____2___________________2____
  1004.     Mode 3  _33____33____33____33____33____33__________________3___
  1005.     Mode 0  ___000___000___000___000___000___000________________000
  1006.     Mode 1  ____________________________________11111111111111_____
  1007.  
  1008.     The Mode Flag goes through the values 0, 2, and 3 at a cycle of about 109uS.
  1009.     0 is present about 48.6uS, 2 about 19uS,
  1010.     and 3 about 41uS. This is interrupted every 16.6ms by the VBlank (1).
  1011.     The mode flag stays set at 1 for about 1.08 ms.
  1012.  
  1013.     Mode 0 is present between 201-207 clks, 2 about 77-83 clks, and 3 about 169-175 clks.
  1014.     A complete cycle through these states takes 456 clks.
  1015.     VBlank lasts 4560 clks. A complete screen refresh occurs every 70224 clks.)
  1016.  */
  1017.   if (lh5028->reg44_LY_T != lh5028->reg44_LY) {
  1018.     lh5028->reg41_IRQf |= LCDS_INTERRUPET_LINE_MASK;
  1019.     lh5028->reg4A_WYLineHit = 0;
  1020.   }
  1021.   /* check FF41::Bit 2 Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)*/
  1022.   if (lh5028->reg44_LY != lh5028->reg45_LYC)
  1023.     lh5028->reg41_LCDS &= ~0x04;
  1024.   else {
  1025.     if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1026.        && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_LINE_MASK)) {
  1027.        lh5028->reg41_IRQf &= ~LCDS_INTERRUPET_LINE_MASK;
  1028.        lh5028->gb->reg0F_IF |= IRQ_2;
  1029.     }
  1030.     lh5028->reg41_LCDS |= 0x04;
  1031.   }
  1032.  
  1033.   /* check mode */
  1034.   if (lh5028->gb->cpu_clks_ppu < lh5028->gb->mach_tools->vbl_clk_st) {
  1035.     if (clkline > lh5028->hbl_clks_st) {
  1036.       /* ------------------------------ MODE0-HBLANK ------------------------------ */
  1037.       lh5028->reg41_LCDS |= LCDS_MODE_FLAG_HBLANK;
  1038.       /*  check edge */
  1039.       if (lh5028->reg41_LCDM_T != LCDS_MODE_FLAG_HBLANK) {
  1040.         /* oamvram to current, (low to high) */    
  1041.         while (lh5028->uscanR < 21) {
  1042.           lh5028->bgwin_done (lh5028, scanline);
  1043.           lh5028->uscanR ++;
  1044.         }
  1045.         if (lh5028->reg4A_WYLineHit != 0)
  1046.           lh5028->reg4A_WYRSC++;
  1047.         /* reset next mode-2 | mode- 3*/
  1048.         lh5028->reg41_IRQf |= LCDS_INTERRUPET_OAM_MASK | LCDS_INTERRUPET_VBLANK_MASK;
  1049.         lh5028->vscan = -1;
  1050.         lh5028->vscan40 = 0;
  1051.         lh5028->uscan = -1;
  1052.         lh5028->vscanR = 0;
  1053.         lh5028->uscanR = 0;
  1054.         /* check HDMA. **/
  1055.         if (lh5028->reg44_LY >= 0 && lh5028->reg44_LY <= 143 && lh5028->hdma_gen && lh5028->hdma_r16)  {
  1056.           /* copy 16 bytes  */
  1057.           ks_uint16 c;
  1058.           for (c =0; c != 16; c++) {
  1059.             ks_uint8 s;
  1060.             s = gameboy_mmu_read (lh5028->gb, lh5028->hdma_src + c);
  1061.             gameboy_mmu_write (lh5028->gb, lh5028->hdma_dst + c, s);
  1062.           }
  1063.           lh5028->hdma_src += 16;
  1064.           lh5028->hdma_dst += 16;
  1065.           lh5028->hdma_r16 --;
  1066.           /* add hdma cycles, ~ 8us */
  1067.           lh5028->gb->cpu_clks_dma += (lh5028->gb->mach_tools->clk_ns * 8.0);
  1068.         }
  1069.         /* in HDMA, no hblank perido */
  1070.         lh5028->reg41_IRQf &= ~LCDS_INTERRUPET_HBLANK_MASK;
  1071.       }
  1072.       /* check hblank interrupt  */
  1073.       if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1074.          && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_HBLANK_MASK)) {
  1075.          lh5028->reg41_IRQf &= ~LCDS_INTERRUPET_HBLANK_MASK;
  1076.          lh5028->gb->reg0F_IF |= IRQ_2;
  1077.       }
  1078.     } else if (clkline > lh5028->gb->mach_tools->oambg_clk_st) {
  1079.       /* ------------------------------ MODE3-OAMBG ------------------------------ */
  1080.       clkline -= lh5028->gb->mach_tools->oambg_clk_st; // sub, get start clcks epls.
  1081.       lh5028->reg41_LCDS |= LCDS_MODE_FLAG_SERACH_OAMVRAM;
  1082.       /* check edge */
  1083.       if (lh5028->reg41_LCDM_T != LCDS_MODE_FLAG_SERACH_OAMVRAM) {
  1084.         lh5028->sprite_done (lh5028, 10);
  1085.         /*  check sprite interrupt  */    
  1086.         if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1087.            && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_OAM_MASK))
  1088.           lh5028->gb->reg0F_IF |= IRQ_2;
  1089.         /* adjust BGOAM clk */
  1090.         lh5028->hbl_clks_st = (lh5028->gb->mach_tools->oambg_b_cycles +
  1091.               lh5028->vscanR * lh5028->gb->mach_tools->oam_clk_add_hbl_per);
  1092.         lh5028->oambg_clks_divider21 =
  1093.             lh5028->hbl_clks_st / 21.0;
  1094.         lh5028->hbl_clks_st += lh5028->gb->mach_tools->oam_cycles;
  1095.         lh5028->reg41_IRQf |= (LCDS_INTERRUPET_OAM_MASK | LCDS_INTERRUPET_HBLANK_MASK | LCDS_INTERRUPET_VBLANK_MASK);
  1096.       }
  1097.       /* check render bg *.*/
  1098.       if ((interv = KS_INT16_CAST (clkline/ lh5028->oambg_clks_divider21)) != lh5028->uscan
  1099.         && ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK))) {
  1100.         delta = interv - lh5028->uscan;
  1101.         lh5028->uscan += delta;
  1102.         do {
  1103.           lh5028->bgwin_done (lh5028, scanline);
  1104.           lh5028->uscanR ++;
  1105.         }  while (--delta);
  1106.       }
  1107.     } else   {
  1108.       /* ------------------------------ MODE2-OAM ------------------------------ */
  1109.       lh5028->reg41_LCDS |= LCDS_MODE_FLAG_SERACH_OAM;
  1110.       lh5028->hbl_clks_st = 571583.0;
  1111.       lh5028->reg40_NMIf = 1;
  1112.       /* check edge */
  1113.       if (lh5028->reg41_LCDM_T == LCDS_MODE_FLAG_HBLANK) {
  1114.         /* hblank to current, (low to high), check stride interrupt */
  1115.         if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1116.            && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_MODE_FLAG_HBLANK))
  1117.          lh5028->gb->reg0F_IF |= IRQ_2;
  1118.         lh5028->reg41_IRQf |= (LCDS_INTERRUPET_HBLANK_MASK | LCDS_INTERRUPET_VBLANK_MASK);
  1119.         /* clear sprite ctx */
  1120.         memset (& lh5028->olf[0], 0, sizeof (lh5028->olf));
  1121.       }
  1122.       /* check render oam *.*/
  1123.       if ( (lh5028->reg40_LCDC & LCDC_OAM_MASK)
  1124.         && lh5028->vscan != (interv = KS_INT16_CAST (clkline/ lh5028->gb->mach_tools->oam_clk_pick_per))) {
  1125.         delta = interv - lh5028->vscan;
  1126.         lh5028->vscan += delta;
  1127.         /* render sprite */
  1128.         lh5028->sprite_done (lh5028, delta);
  1129.       }
  1130.       /*  check sprite interrupt  */
  1131.       if (  (lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1132.          && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_OAM_MASK)) {
  1133.          lh5028->reg41_IRQf &= ~LCDS_INTERRUPET_OAM_MASK;
  1134.          lh5028->gb->reg0F_IF |= IRQ_2;
  1135.       }  
  1136.     }
  1137.   } else {
  1138.     /* ------------------------------ MODE1-VLANK ------------------------------ */
  1139.     lh5028->reg41_LCDS |= LCDS_MODE_FLAG_VLANK;
  1140.     /* check edge */
  1141.     if (lh5028->reg41_LCDM_T != LCDS_MODE_FLAG_VLANK) {
  1142.       /* post device render */
  1143.       lh5028->device_blit (lh5028, lh5028->obj, & lh5028->fmebuf);
  1144.       /* check stride */
  1145.       if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1146.          && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_HBLANK_MASK))
  1147.        lh5028->gb->reg0F_IF |= IRQ_2;
  1148.       lh5028->reg4A_WYRSC = 0;
  1149.       lh5028->reg41_IRQf |= (LCDS_INTERRUPET_HBLANK_MASK | LCDS_INTERRUPET_OAM_MASK);
  1150.     }
  1151.     if (lh5028->reg40_NMIf != 0 && (lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)) {
  1152.       lh5028->reg40_NMIf = 0;
  1153.       lh5028->gb->reg0F_IF |= IRQ_1;
  1154.     }
  1155.     if ((lh5028->reg40_LCDC & LCDC_DISPLAY_MASK)
  1156.         && (lh5028->reg41_IRQf & lh5028->reg41_LCDS & LCDS_INTERRUPET_VBLANK_MASK)) {
  1157.       lh5028->reg41_IRQf &= ~LCDS_INTERRUPET_VBLANK_MASK;
  1158.       lh5028->gb->reg0F_IF |= IRQ_2;
  1159.     }
  1160.   }
  1161.   lh5028->reg44_LY_T = lh5028->reg44_LY;
  1162.   lh5028->reg41_LCDM_T = lh5028->reg41_LCDS & LCDS_MODE_FLAG_ALL_MASK;
  1163. }
  1164.  
  1165. int ppu_cgb_mode (struct ppu *lh5028) {
  1166.   lh5028->bgwin_done = bgwin_render_cgb;
  1167.   lh5028->sprite_done = sprite_render_dmg;
  1168.   return 0;
  1169. }
  1170. int ppu_dmg_mode (struct ppu *lh5028) {
  1171.   lh5028->bgwin_done = bgwin_render_dmg;
  1172.   lh5028->sprite_done = sprite_render_dmg;
  1173.   return 0;
  1174. }
  1175.  
  1176. int ppu_init (struct ppu **lh5028) {
  1177.  
  1178.   struct ppu *sys = ks_null;
  1179.   assert (lh5028 != ks_null);
  1180.  
  1181.   sys = (struct ppu *)calloc (sizeof (struct ppu), 1);
  1182.   assert (sys != ks_null);
  1183.   *lh5028 = sys;
  1184.  
  1185.   if (1) {
  1186.     /* init dmg palette
  1187.      0  White
  1188.      1  Light gray
  1189.      2  Dark gray
  1190.      3  Black
  1191.      */
  1192.     ks_uint16 color[4] = {
  1193. #   if 0
  1194.       (0x1F << 0) | (0x1F << 5) | (0x1F << 10), /* color index 0*/
  1195.       (0x15 << 0) | (0x15 << 5) | (0x15 << 10),  /* color index 1*/
  1196.       (0x0A << 0) | (0x0A << 5) | (0x0A << 10),  /* color index 2*/
  1197.       (0x00 << 0) | (0x00 << 5) | (0x00 << 10)  /* color index 3*/
  1198. #   else
  1199.       // fce88c:0
  1200.       // dcb45c:1
  1201.       // 987c3c:2
  1202.       // 4c3c1c:0
  1203.       // ((0x) >> 3)
  1204.       (((0x8c) >> 3) << 0) | (((0xe8) >> 3) << 5) | (((0xfc) >> 3) << 10), /* color index 0*/
  1205.       (((0x5c) >> 3) << 0) | (((0xb4) >> 3) << 5) | (((0xdc) >> 3) << 10),  /* color index 1*/
  1206.       (((0x3c) >> 3) << 0) | (((0x7c) >> 3) << 5) | (((0x98) >> 3) << 10),  /* color index 2*/
  1207.       (((0x1c) >> 3) << 0) | (((0x3c) >> 3) << 5) | (((0x4c) >> 3) << 10)  /* color index 3*/
  1208. #   endif
  1209.     };
  1210.     ks_uint16 Q;
  1211.    
  1212.     for (Q = 0; Q != 4; Q++) {
  1213.       sys->bg_pal_dmgT[Q] = color[Q];
  1214.       sys->sp_pal_dmgT[0][Q] = color[Q];  
  1215.       sys->sp_pal_dmgT[1][Q] = color[Q];    
  1216.     }
  1217.   }
  1218.   sys->fmebuf.w = 160;
  1219.   sys->fmebuf.h = 144;
  1220.   sys->fmebuf.pitch = 512;
  1221.   sys->bufb = (ks_uint16 *)malloc ( (sys->fmebuf.w + 96) * (sys->fmebuf.h + 16) * 2 + 128);
  1222.   sys->fmebuf.buf = (ks_uint16 *)(((((intptr_t)& sys->bufb[0]) + 31) & -32) + 16);
  1223.   sys->device_blit = default_update;
  1224.   sys->clks = ticks;
  1225.   sys->reg41_LCDM_T =LCDS_MODE_FLAG_SERACH_OAM;
  1226.  
  1227. // value = 0xE8;
  1228.   sys->bg_pal_dmg[0] = sys->bg_pal_dmgT[(0xFC & 0x03) >> 0];
  1229.   sys->bg_pal_dmg[1] = sys->bg_pal_dmgT[(0xFC & 0x0C) >> 2];
  1230.   sys->bg_pal_dmg[2] = sys->bg_pal_dmgT[(0xFC & 0x30) >> 4];
  1231.   sys->bg_pal_dmg[3] = sys->bg_pal_dmgT[(0xFC & 0xC0) >> 6];
  1232.   return 0;
  1233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement