Advertisement
xiahanlu

0分DMG/CGB GPU

Oct 3rd, 2018
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 60.26 KB | None | 0 0
  1. /* private object for gameboy
  2.  *
  3.  * Copyright (C) 2018 moecmks
  4.  * This file is part of KS3578.
  5.  *
  6.  * do What The Fuck you want to Public License
  7.  *
  8.  * Version 1.0, March 2000
  9.  * Copyright (C) 2000 Banlu Kemiyatorn (]d).
  10.  * 136 Nives 7 Jangwattana 14 Laksi Bangkok
  11.  * Everyone is permitted to copy and distribute verbatim copies
  12.  * of this license document, but changing it is not allowed.
  13.  *
  14.  * Ok, the purpose of this license is simple
  15.  * and you just
  16.  *
  17.  * DO WHAT THE FUCK YOU WANT TO.
  18.  */
  19.  
  20. #ifndef _INTERNAL_H
  21. #define _INTERNAL_H 1
  22.  
  23. #include "conf.h"
  24. #include "controller.h"
  25.  
  26. struct gameboy;
  27. struct controller;
  28. struct cpu;
  29. struct ppu;
  30. struct cartidge;
  31. struct apu;
  32. struct elev;
  33. struct machine_setup;
  34.  
  35. struct elev {
  36.   ks_uint8 old;
  37.   ks_uint8 cur;
  38. };
  39.  
  40. #define CHECK_ELEV_CUR(/*struct elev **/ E)\
  41.   (!!((struct elev *)E)->cur)
  42. #define CHECK_ELEV_OLD(/*struct elev **/ E)\
  43.   (!!((struct elev *)E)->old)
  44. #define UPDATE_ELEV_(/*struct elev **/ E, /* ks_uint8*/state)\
  45.   do   \
  46.      { \
  47.        struct elev *T = (struct elev *)E;\
  48.        T->old = !!T->cur;\
  49.        T->cur = !!state;\
  50.      } while (0)
  51. #define CHECK_ELEV_LOW_TO_HIGH(/*struct elev **/ E)\
  52.   if ( !CHECK_ELEV_OLD(E) && CHECK_ELEV_CUR(E))
  53. #define CHECK_ELEV_HIGH_TO_LOW(/*struct elev **/ E)\
  54.   if ( CHECK_ELEV_OLD(E) && !CHECK_ELEV_CUR(E))
  55.  
  56. static const
  57. struct machine_setup {
  58.   ks_double cpu_freq;  
  59.   ks_double vsync_freq;
  60.   ks_double hsync_freq;
  61.   ks_double clk_ms;
  62.   ks_double clk_ns;
  63.   ks_double frame_cycles;
  64.   ks_double line_cycles;
  65.   ks_double oam_cycles;
  66.   ks_double oambg_b_cycles;
  67.   ks_double oambg_hbl_cycles;
  68.   ks_int32 line_total;
  69.   ks_int32 line_vbl_st;
  70.   ks_double vbl_clk_last;
  71.   ks_double oam_clk_st;
  72.   ks_double oambg_clk_st;
  73.   ks_double hbl_clk_st_b;
  74.   ks_double vbl_clk_st;
  75.   ks_double oam_clk_pick_per;
  76.   ks_double oam_clk_add_hbl_per;
  77.   ks_double tim0507_vclk;
  78.   ks_double cgb_gbp_p;
  79.   ks_double gbp_cgb_p;
  80.   ks_double div04_clks256;
  81.   ks_double oamdma_clks;
  82.   ks_double gdma_clks_b;
  83.   ks_double gdma_clks_per16; // always 7.63 us (DMG/CGB)
  84. } std_machine = {
  85.   4194304.0, /* machine_setup::cpu_freq*/
  86.   59.73, /* machine_setup::vsync_freq */
  87.   9198.42, /* machine_setup::hsync_freq, per line, vsync_freq * 154(*machine_setup::scanline_total)*/
  88.   4194304.0/1000.0, /* machine_setup::clk_ms */
  89.   4194304.0/1000000.0, /* machine_setup::clk_ns*/
  90.   70221.061443161, /* machine_setup::frame_cycles, cpu_freq/ vsync_freq */
  91.   455.98091846208, /* machine_setup::line_cycles,  frame_cycles / * 154(*machine_setup::scanline_total)*/
  92.   80.992010239999985, /* machine_setup::oam_cycles, 19.31 黶ec see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W)*/
  93.   173.51835647999999, /* machine_setup::oambg_basecycles, 41.37 黶ec see http://www.devrs.com/gb/files/faqs.html#VideoTiming*/
  94.   455.98091846208 - 80.992010239999985, /* machine_setup::oambg_hbl_cycles */
  95.   154, /* machine_setup::line_total, see TheNintendoGameboy.pdf ::LCD Position and Scrolling*/
  96.   144, /* machine_setup::line_vbl_st , see TheNintendoGameboy.pdf ::LCD Interrupts*/
  97.   4559.809184621, /* machine_setup::vbl_clk_last, see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W) */
  98.   0.0, /* machine_setup::oam_clk_st*/
  99.   80.992010239999985,  /* machine_setup::oambg_clk_st*/
  100.   173.51835647999999 + 80.992010239999985, /* machine_setup::hbl_clk_st_b*/
  101.   70221.061443161 - 4559.809184621, /* machine_setup::vbl_clk_st*/
  102.   80.992010239999985 / 10.0, /* machine_setup::oam_clk_pick_per*/
  103.   12.549357568000001, /* machine_setup::oam_clk_add_hbl_per*/
  104.   0.00097656250000000000, /* machine_setup::tim0507_vclk*/
  105.   8400000.0/ 4194304.0, /* machine_setup::cgb_gbp_p*/
  106.   4194304.0/ 8400000.0, /* machine_setup::gbp_cgb_p*/
  107.   4194304.0/ 256.0, /* machine_setup::div04_clks256*/
  108.   671.08864000000005, /* machine_setup::oamdma_clks*/
  109.   (4194304.0*220.0)/1000000.0, /* machine_setup::gdma_clks_b*/
  110.   (4194304.0*7.63)/1000000.0 /* machine_setup::gdma_clks_per16*/
  111. }, adv_machine = { 
  112.   8400000.0, /* machine_setup::cpu_freq*/
  113.   59.73, /* machine_setup::vsync_freq */
  114.   9198.42, /* machine_setup::hsync_freq, per line, vsync_freq * 154(*machine_setup::scanline_total)*/
  115.   8400000.0/1000.0, /* machine_setup::clk_ms*/
  116.   8400000.0/1000000.0, /* machine_setup::clk_ns*/
  117.   140632.84781516826, /* machine_setup::frame_cycles, cpu_freq/ vsync_freq */
  118.   913.20031048810563, /* machine_setup::line_cycles,  frame_cycles / * 154(*machine_setup::scanline_total)*/
  119.   162.20400000000001, /* machine_setup::oam_cycles, 19.31 黶ec see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W)*/
  120.   347.50799999999998, /* machine_setup::oambg_basecycles, 41.37 黶ec see http://www.devrs.com/gb/files/faqs.html#VideoTiming */
  121.   913.20031048810563 - 162.20400000000001, /* machine_setup::oambg_hbl_cycles */
  122.   154, /* machine_setup::line_total, see TheNintendoGameboy.pdf ::LCD Position and Scrolling*/
  123.   144, /* machine_setup::line_vbl_st , see TheNintendoGameboy.pdf ::LCD Interrupts*/
  124.   9132.0031048810633, /* machine_setup::vbl_clk_last, see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W) */
  125.   0.0, /* machine_setup::oam_clk_st*/
  126.   162.20400000000001,  /* machine_setup::oambg_clk_st*/
  127.   347.50799999999998 + 162.20400000000001, /* machine_setup::hbl_clk_st_b*/
  128.   140632.84781516826 - 9132.0031048810633, /* machine_setup::vbl_clk_st*/
  129.   162.20400000000001 / 10.0, /* machine_setup::oam_clk_pick_per*/
  130.   25.132800000000003, /* machine_setup::oam_clk_add_hbl_per*/
  131.   0.00048761904761904760, /* machine_setup::tim0507_vclk*/
  132.   8400000.0/ 4194304.0, /* machine_setup::cgb_gbp_p*/
  133.   4194304.0/ 8400000.0, /* machine_setup::gbp_cgb_p*/
  134.   671.08864000000005, /* machine_setup::oamdma_clks*/
  135.   (4194304.0*220.0)/1000000.0, /* machine_setup::gdma_clks_b*/
  136.   (8400000.0*7.63)/1000000.0 /* machine_setup::gdma_clks_per16*/
  137. };
  138.  
  139. struct controller  {
  140.   ks_uint8 reg;
  141.  
  142.   /* for gamebot update host keybuf and IRQ */
  143.   void (*hostdrv_checkIRQ) (struct controller *);
  144.  
  145.   void *obj;
  146.   void *ubdata_user;
  147.   /* pad infos for gameboy*.*/
  148.   struct controller_pad gb_pad;
  149.   struct gameboy *gb;
  150. };
  151. struct cpu {
  152.   /*  XXX:memory order dep. */
  153.   union { struct { ks_uint8 F; ks_uint8 A; }; ks_uint16 AF; };
  154.   union { struct { ks_uint8 C; ks_uint8 B; }; ks_uint16 CB; };
  155.   union { struct { ks_uint8 E; ks_uint8 D; }; ks_uint16 DE; };
  156.   union { struct { ks_uint8 L; ks_uint8 H; }; ks_uint16 HL; };
  157.   union { struct { ks_uint8 SL; ks_uint8 SH; }; ks_uint16 SP; };
  158.   union { struct { ks_uint8 PL; ks_uint8 PH; }; ks_uint16 PC; };
  159.  
  160.    /* Interrupt Master Enable*/
  161.   ks_uint8 IME;
  162.  
  163.    /* for Halt */
  164.   ks_bool halt;  
  165.  
  166.    /* for stop */
  167.   ks_bool stop;
  168.  
  169.    /* for speed mode */
  170.   ks_uint8 reg4D_key1;
  171.  
  172.    /* gameboy object  */
  173.   struct gameboy *gb;              
  174. };
  175. struct oam {
  176.   union {
  177.     struct {
  178.       ks_uint8 y;
  179.       ks_uint8 x;
  180.       ks_uint8 id;
  181.       ks_uint8 attr;
  182.     };
  183.     ks_uint8 blk[4];
  184.   };
  185. };
  186. struct pal {
  187.   union {
  188.     struct {
  189.       ks_uint8 _lo;
  190.       ks_uint8 _hi;
  191.     };
  192.     ks_uint16 rgb15;
  193.     ks_uint8 blk[2];
  194.   };
  195. };
  196.  
  197. /* for ppu:: spi_ca */
  198. #define PIXEL_SPRITE_NOTRANS 1
  199. #define PIXEL_SPRITE_BACK 2
  200.  
  201. /* for ppu:: wmi_cac */
  202. #define PIXEL_WINDOW_NOTRANS 1
  203. #define PIXEL_WINDOW_BACK 2
  204. #define PIXEL_WINDOW_UNINIT 4
  205.  
  206. struct ppu {
  207.   ks_uint16 *buf;
  208.   ks_uint16 *bufb; /* for alignmem */
  209.   ks_uint16 *bufline; /* startpos */
  210.   ks_uint16 bufp;          /* buffer pitch */
  211.   ks_uint8 ram[0x4000];  /* 8K for DMG, 16 for CGB */
  212.   ks_uint16 spb_cac[176]; /* sprite buffer cache *.*/
  213.   ks_uint16 spi_cac[176];
  214.   ks_uint16 *spbline;
  215.   ks_uint16 *spiline;
  216.  
  217.   struct gameboy *gb;
  218.   struct oam sp[40];
  219.   struct pal bg_pal[8][4]; /* pal for gameboycolor */
  220.   struct pal sp_pal[8][4]; /* pal for gameboycolor */
  221.  
  222.   ks_uint16 spl_dmg[40];
  223.   ks_uint16 bg_pal_dmg[4]; /* pal for gameboy */
  224.   ks_uint16 sp_pal_dmg[2][4]; /* pal for gameboy */
  225.  
  226.   ks_uint16 bg_pal_dmgT[4]; /* pal for gameboy */
  227.   ks_uint16 sp_pal_dmgT[2][4]; /* pal for gameboy */
  228.  
  229.   ks_bool gameboy_mode;  
  230.   ks_bool s890623_mode; /* TODO: see http://fms.komkon.org/GameBoy/Tech/LCD.gif*/
  231.  
  232.   /* register cache for scanline  */
  233.   ks_uint8 reg43_SCX_cac;
  234.   ks_uint8 reg42_SCY_cac;
  235.   ks_uint8 reg4A_WY_cac;
  236.   ks_uint8 reg4B_WX_cac;
  237.  
  238.   ks_uint8 reg40_LCDC;
  239.   ks_uint8 reg41_LCDS;                              
  240.   ks_uint8 reg42_SCY;
  241.   ks_uint8 reg43_SCX;        
  242.   ks_uint8 reg44_LY;
  243.   ks_uint8 reg45_LYC;
  244.   ks_uint8 reg46_DMA;
  245.   ks_uint8 reg47_BGP;
  246.   ks_uint8 reg48_OBP0;
  247.   ks_uint8 reg49_OBP1;
  248.   ks_uint8 reg4A_WY;
  249.   ks_uint8 reg4B_WX;
  250.   ks_uint8 reg4F_VBK;
  251.   ks_uint8 reg51_HDMA1;
  252.   ks_uint8 reg52_HDMA2;
  253.   ks_uint8 reg53_HDMA3;
  254.   ks_uint8 reg54_HDMA4;
  255.   ks_uint8 reg55_HDMA5;
  256.   ks_uint8 reg68_BCPS;
  257.   ks_uint8 reg69_BCPD;
  258.   ks_uint8 reg6A_OCPS;
  259.   ks_uint8 reg6B_OCPD;
  260.  
  261.   ks_int32 vscan;
  262.   ks_int32 vscanR;
  263.   ks_int32 vscan10;
  264.   ks_int32 vscan40;
  265.   ks_int32 xscan;
  266.   ks_int32 xscanR;
  267.   ks_int32 uscan;
  268.   ks_int32 uscanR;
  269.   ks_int32 uscan168;
  270.   ks_int32 vscan_cac;
  271.  
  272.   ks_bool oam_flop;
  273.   ks_bool vbl_flop;
  274.   ks_bool hbl_flop;
  275.  
  276.   ks_bool interrupt45_strike;
  277.   ks_bool interrupt45_flop;
  278.  
  279.   ks_int32 line_cac; /* old scanline*/
  280.   ks_int32 lcdm_cac; /* old lcd mode*/
  281.  
  282.   ks_bool win_stuff; /* window done assert */
  283.  
  284.   ks_bool hdma_gen;
  285.  
  286.   ks_uint16 hdma_src;
  287.   ks_uint16 hdma_dst;
  288.   ks_uint16 hdma_r16;
  289.  
  290.   ks_double hdma_clk;
  291.   ks_double hbl_clks_st;
  292.   ks_double oambg_clks_divider21;
  293.   ks_double oambg_clks_total;
  294.  
  295.   void (*bgwin_render) (struct ppu *_5028, ks_int16 scanline);
  296.   void (*sprite_render) (struct ppu *_5028, ks_int16 scanline);
  297.   void (*device_blit) (struct ppu *_5028, void * obj); /*blit, and sync */
  298.   void *obj;
  299. };
  300.  
  301. struct gameboy {
  302.   struct controller *joypad;
  303.   struct cpu *lr35902;
  304.   struct ppu *lh5028;
  305.   struct cartidge *cart;
  306.   struct apu *apu_;
  307.   struct machine_setup *mach_tools;
  308.  
  309.   double cpu_clks;
  310.   double cpu_clks_cl; // old full - block
  311.   double cpu_clks_el; // cur full - block
  312.   double cpu_clks_timer; // cur full - block
  313.   double cpu_clks_divider; // cur full - block
  314.   double cpu_clks_ppu; // cur full - block
  315.   double cpu_clks_dma;
  316.  
  317.   double divider_04;
  318.   double divider_0507;
  319.   double divider_apu;
  320.   double divider_controller;
  321.  
  322.   double fire0507;
  323.   double fire04;
  324.   double cur0507;
  325.   double calc0507;
  326.  
  327.   ks_uint8 reg01_SB;
  328.   ks_uint8 reg02_SC;
  329.   ks_uint8 reg04_DIV;
  330.   ks_uint8 reg05_TIMA;
  331.   ks_uint8 reg06_TMA;
  332.   ks_uint8 reg06_TMA_cac;
  333.   ks_uint16 reg06_TMA_count;
  334.   ks_uint8 reg07_TAC;
  335.   ks_uint8 reg0F_IF; /* interrupt flags register */
  336.  
  337.   /* TODO: sound register */
  338.  
  339.   ks_uint8 reg56_IC;
  340.   ks_uint8 reg70_SVBK;
  341.   ks_uint8 regFF_IE; /* Interrupt enable register */
  342.  
  343.   ks_bool crazy_mode;
  344.   ks_bool clk_stride;
  345.   ks_bool dma_gen;
  346.  
  347.   // ks_double cpu_clks_oamdma;
  348.   // ks_double cpu_clks_gdma;
  349.   // ks_double cpu_clks_hdma;
  350. };
  351.  
  352. # define GB_VRAM_ADDRESS_START 0x8000
  353. # define GB_VRAM_LENGTH 8096
  354.  
  355.  
  356. #endif
  357.  
  358. /* Game boy's GPU and LCD Screen
  359.  * LCD is Sharp LH5028 http://www.datasheetarchive.com/pdf/download.php?id=c615e5d8551c6b559c3db61b709b3234af856c&type=O&term=LH5028
  360.  *
  361.  * This part of the source code is actually not very good.
  362.  * It looks terrible.
  363.  *
  364.  * Copyright (C) 2018 moecmks
  365.  * This file is part of KS3578.
  366.  *
  367.  * do What The Fuck you want to Public License
  368.  *
  369.  * Version 1.0, March 2000
  370.  * Copyright (C) 2000 Banlu Kemiyatorn (]d).
  371.  * 136 Nives 7 Jangwattana 14 Laksi Bangkok
  372.  * Everyone is permitted to copy and distribute verbatim copies
  373.  * of this license document, but changing it is not allowed.
  374.  *
  375.  * Ok, the purpose of this license is simple
  376.  * and you just
  377.  *
  378.  * DO WHAT THE FUCK YOU WANT TO.
  379.  */
  380.  
  381. #include "ppu.h"
  382. #include "gameboy.h"
  383. #include "internal.h"
  384.  
  385. int ppu_init (struct ppu **X5028) {
  386.   struct ppu *sys = ks_null;
  387.   assert (X5028 != ks_null);
  388.  
  389.   sys = (struct ppu *)calloc (sizeof (struct ppu), 1);
  390.   assert (sys != ks_null);
  391.   *X5028 = sys;
  392.  
  393.   return 0;
  394. }
  395.  
  396. int ppu_reset (struct ppu *X5028) {
  397.  
  398.   /* init register http://gbdev.gg8.se/files/docs/mirrors/pandocs.html#powerupsequence */
  399.   X5028->reg40_LCDC = 0x91;
  400.   X5028->reg42_SCY = 0x00;
  401.   X5028->reg43_SCX = 0x00;
  402.   X5028->reg45_LYC = 0x00;
  403.   X5028->reg47_BGP = 0xFC;
  404.   X5028->reg48_OBP0 = 0xFF;
  405.   X5028->reg49_OBP1 = 0xFF;
  406.   X5028->reg4A_WY = 0x00;
  407.   X5028->reg4B_WX = 0x00;
  408.   /* reset cache */
  409.   X5028->reg42_SCY_cac= X5028->reg42_SCY;
  410.   X5028->reg43_SCX_cac= X5028->reg43_SCX;
  411.   X5028->reg4A_WY_cac= X5028->reg4A_WY;
  412.   X5028->reg4B_WX_cac= X5028->reg4B_WX;
  413. }
  414.  
  415. void ppu_uninit (struct ppu **X5028);
  416. int ppu_getbuf_ (struct ppu *X5028, ks_uint16 **bufrv, ks_uint16 *pitch);
  417. void ppu_setupdate (struct ppu *X5028, void (*update) (struct ppu *X5028));
  418. void ppu_update (struct ppu *X5028);
  419. int ppu_reset_cycles (struct ppu *X5028);
  420. int ppu_attach (struct ppu *X5028, struct gameboy *gb);
  421.  
  422. void ppu_write_io (struct ppu *X5028, ks_uint16 address, ks_uint8 value) {
  423.  
  424.   ks_uint8 c, s;
  425.   switch (address) {
  426.   case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
  427.     /*Bit 7 - LCD Display Enable             (0=Off, 1=On)
  428.       Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
  429.       Bit 5 - Window Display Enable          (0=Off, 1=On)
  430.       Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
  431.       Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
  432.       Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
  433.       Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
  434.       Bit 0 - BG/Window Display/Priority     (0=Off, 1=On)
  435.      */
  436.     X5028->reg40_LCDC = value;
  437.     break;
  438.   case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
  439.     /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
  440.       Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
  441.       Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
  442.       Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
  443.       Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
  444.       Bit 1-0 - Mode Flag       (Mode 0-3, see below) (Read Only)
  445.               0: During H-Blank
  446.               1: During V-Blank
  447.               2: During Searching OAM
  448.               3: During Transferring Data to LCD Driver
  449.     */
  450.     X5028->reg41_LCDS = value;
  451.     break;
  452.   case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
  453.     X5028->reg42_SCY = value;
  454.     break;
  455.   case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
  456.     X5028->reg43_SCX = value;
  457.     break;
  458.   case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
  459.     _DEBUG_BREAK();
  460.     break;
  461.   case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
  462.     X5028->reg45_LYC = value;
  463.     break;
  464.   case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
  465.     X5028->reg4A_WY = value;
  466.     break;
  467.   case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
  468.     X5028->reg4B_WX = value;
  469.     break;
  470.   case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
  471.     X5028->bg_pal_dmg[0] = X5028->bg_pal_dmgT[(value & 0x03) >> 0];
  472.     X5028->bg_pal_dmg[1] = X5028->bg_pal_dmgT[(value & 0x0C) >> 2];
  473.     X5028->bg_pal_dmg[2] = X5028->bg_pal_dmgT[(value & 0x30) >> 4];
  474.     X5028->bg_pal_dmg[3] = X5028->bg_pal_dmgT[(value & 0xC0) >> 6];
  475.     X5028->reg47_BGP = value;
  476.     break ;
  477.   case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
  478.     X5028->sp_pal_dmg[0][0] = X5028->sp_pal_dmgT[0][(value & 0x03) >> 0];
  479.     X5028->sp_pal_dmg[0][1] = X5028->sp_pal_dmgT[0][(value & 0x0C) >> 2];
  480.     X5028->sp_pal_dmg[0][2] = X5028->sp_pal_dmgT[0][(value & 0x30) >> 4];
  481.     X5028->sp_pal_dmg[0][3] = X5028->sp_pal_dmgT[0][(value & 0xC0) >> 6];
  482.     X5028->reg48_OBP0 = value;
  483.     break ;
  484.   case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
  485.     X5028->sp_pal_dmg[1][0] = X5028->sp_pal_dmgT[1][(value & 0x03) >> 0];
  486.     X5028->sp_pal_dmg[1][1] = X5028->sp_pal_dmgT[1][(value & 0x0C) >> 2];
  487.     X5028->sp_pal_dmg[1][2] = X5028->sp_pal_dmgT[1][(value & 0x30) >> 4];
  488.     X5028->sp_pal_dmg[1][3] = X5028->sp_pal_dmgT[1][(value & 0xC0) >> 6];
  489.     X5028->reg49_OBP1 = value;
  490.     break ;
  491.   case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
  492.     X5028->reg68_BCPS = value;
  493.     break ;
  494.   case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
  495.     s = X5028->reg68_BCPS;
  496.     c = s & 0x3F;
  497.     if (c & 1)
  498.       X5028->bg_pal[c >> 3][(c & 7) >> 1]._hi = value;
  499.     else
  500.       X5028->bg_pal[c >> 3][(c & 7) >> 1]._lo = value;
  501.     if (s & 0x80) {
  502.       c = (c + 1) & 0x3F;
  503.       X5028->reg68_BCPS &= ~0x3F;
  504.       X5028->reg68_BCPS |= c;
  505.     }
  506.     X5028->reg69_BCPD = value;
  507.     break;
  508.   case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
  509.     X5028->reg6A_OCPS = value;
  510.     break;
  511.   case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
  512.     s = X5028->reg6A_OCPS;
  513.     c = s & 0x3F;
  514.     if (c & 1)
  515.       X5028->sp_pal[c >> 3][(c & 7) >> 1]._hi = value;
  516.     else
  517.       X5028->sp_pal[c >> 3][(c & 7) >> 1]._lo = value;
  518.     if (s & 0x80) {
  519.       c = (c + 1) & 0x3F;
  520.       X5028->reg6A_OCPS &= ~0x3F;
  521.       X5028->reg6A_OCPS |= c;
  522.     }
  523.     X5028->reg6B_OCPD = value;
  524.     break;
  525.   case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
  526.     for (c = 0; c != 160; c++) {
  527.       s = gameboy_mmu_read (X5028->gb, value * 256 + c);
  528.       ((ks_int8 *)& X5028->sp[0])[c] = s;
  529.     }
  530.     /* OAMDMA ~ 160 us
  531.        OAMDMA is a parallel DMA */
  532.     /* X5028->gb->cpu_clks_dma += X5028->gb->mach_tools->oamdma_clks; */
  533.     X5028->reg46_DMA = value;
  534.     break ;
  535.   case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
  536.     X5028->reg51_HDMA1 = value;
  537.     break;
  538.   case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
  539.     X5028->reg52_HDMA2 = value;
  540.     break;
  541.   case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
  542.     X5028->reg53_HDMA3 = value;
  543.     break;
  544.   case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
  545.     X5028->reg54_HDMA4 = value;
  546.     break;
  547.   case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
  548.     if (value & 0x80) {
  549.       /* H-Blank DMA. **/
  550.       X5028->hdma_src = X5028->reg51_HDMA1 * 256 + X5028->reg52_HDMA2;
  551.       X5028->hdma_dst = X5028->reg53_HDMA3 * 256 + X5028->reg54_HDMA4;
  552.       X5028->hdma_src &= 0xFFF0;
  553.       X5028->hdma_dst &= 0xFFF0;
  554.       X5028->hdma_r16 = value & 0x7F;
  555.       X5028->hdma_r16 ++;
  556.       X5028->hdma_gen = ks_true;
  557.       /* set HDMA uncompelete/active */
  558.       X5028->reg55_HDMA5 &= 0x7F;
  559.     } else {
  560.       /* GDMA **/
  561.       ks_uint16 src = X5028->reg51_HDMA1 * 256 + X5028->reg52_HDMA2;
  562.       ks_uint16 dst = X5028->reg53_HDMA3 * 256 + X5028->reg54_HDMA4;
  563.       ks_uint16 id;
  564.       ks_uint16 K;
  565.  
  566.       src &= 0xFFF0;
  567.       dst &= 0xFFF0;
  568.       K = value & 0x7F;
  569.       K+= 1;
  570.       /* copy it*/
  571.       for (; id = K; id++) {
  572.         ks_uint16 c;
  573.         for (c =0; c != 16; c++) {
  574.           s = gameboy_mmu_read (X5028->gb, src + id *16 + c);
  575.           gameboy_mmu_write (X5028->gb, dst + id *16 + c, s);
  576.         }
  577.       }
  578.       /* burning OAM clks */
  579.       /* It takes (220 + (n * 7.63)) microseconds in single speed
  580.          and (110 + (n * 7.63)) microseconds in double speed mode */
  581.       X5028->gb->cpu_clks_dma += (X5028->gb->mach_tools->gdma_clks_b
  582.         + X5028->gb->mach_tools->gdma_clks_per16 * (ks_double) K);
  583.       // X5028->reg55_HDMA5 |= 0x80;/* set GDMA compelete/unactive */
  584.     }
  585.     X5028->reg55_HDMA5 = value;
  586.     break;
  587.   case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
  588.     X5028->reg4F_VBK = value;
  589.     break;
  590.   default:
  591.     return;
  592.   }
  593. }
  594.  
  595. ks_uint8 ppu_read_io (struct ppu *X5028, ks_uint16 address) {
  596.  
  597.   switch (address) {
  598.   case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
  599.     /*Bit 7 - LCD Display Enable             (0=Off, 1=On)
  600.       Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
  601.       Bit 5 - Window Display Enable          (0=Off, 1=On)
  602.       Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
  603.       Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
  604.       Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
  605.       Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
  606.       Bit 0 - BG/Window Display/Priority     (0=Off, 1=On)
  607.      */
  608.     return X5028->reg40_LCDC;
  609.   case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
  610.     /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
  611.       Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
  612.       Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
  613.       Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
  614.       Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
  615.       Bit 1-0 - Mode Flag       (Mode 0-3, see below) (Read Only)
  616.               0: During H-Blank
  617.               1: During V-Blank
  618.               2: During Searching OAM
  619.               3: During Transferring Data to LCD Driver
  620.     */
  621.     return X5028->reg41_LCDS;
  622.   case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
  623.     return X5028->reg42_SCY;
  624.   case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
  625.     return X5028->reg43_SCX;
  626.   case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
  627.     return X5028->reg44_LY;
  628.   case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
  629.     return X5028->reg45_LYC;
  630.   case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
  631.     return X5028->reg4A_WY;
  632.   case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
  633.     return X5028->reg4B_WX;
  634.   case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
  635.     return X5028->reg47_BGP;
  636.   case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
  637.     return X5028->reg48_OBP0;
  638.   case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
  639.     return X5028->reg49_OBP1;
  640.   case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
  641.     return X5028->reg68_BCPS;
  642.   case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
  643.     return X5028->reg69_BCPD;
  644.   case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
  645.     return X5028->reg6A_OCPS;
  646.   case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
  647.     return X5028->reg6B_OCPD;
  648.   case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
  649.     return X5028->reg46_DMA;
  650.   case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
  651.     return X5028->reg51_HDMA1;
  652.   case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
  653.     return X5028->reg52_HDMA2;
  654.   case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
  655.     return X5028->reg53_HDMA3;
  656.   case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
  657.     return X5028->reg54_HDMA4;
  658.   case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
  659.     return X5028->reg55_HDMA5;
  660.   case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
  661.     return X5028->reg4F_VBK;
  662.     break;
  663.   default:
  664.     return 0xFF;
  665.   }
  666. }
  667.  
  668. static
  669. void sprite_render (struct ppu *X5028, ks_uint16 scanline) {}
  670. static
  671. void background_render (struct ppu *X5028, ks_uint16 scanline) {}
  672.  
  673.  
  674. static /* this method for gameboy color */
  675. void bgwin_render_cgb (struct ppu *X5028, ks_int16 scanline) {
  676.   struct {
  677.     union { ks_uint16 blk;
  678.       struct { ks_uint8 lo; ks_uint8 hi; }; };
  679.   } chrdat,  chrcac;
  680.   /* always scan 168 pixel in every line (21 tiles),
  681.     evenif omfx is ZERO .
  682.       fit buffer offset, so that every time we can scan a complete tile,
  683.           no matter how much omfx is.
  684.     */
  685.   ks_int32 omfx;
  686.   ks_int32 ofx;
  687.   ks_int32 obx;
  688.   ks_int32 omfy;
  689.   ks_int32 ofy;
  690.   ks_int32 vsc;
  691.   ks_uint8 tid;
  692.   ks_int8 tat;
  693.   ks_int32 tidaddr;
  694.   ks_uint16 pixcac;
  695.   ks_uint8 *tdat;
  696.   ks_int32 rxpos;
  697.   ks_uint32 c, q, c2, s;
  698.   ks_int32 c3;
  699.   ks_uint16 *vptrWinDrawStart;
  700.   ks_uint16 *vptrScrollStart;
  701.   /* check current scan region in BG or WINDOW (if WINDOW enable)*/
  702.   if ( X5028->win_stuff != ks_false && (X5028->reg40_LCDC & 0x20)) {
  703.     /* draw window  */
  704.     goto windraw;
  705.   } else {
  706.     /* draw background */
  707.     vsc = X5028->uscanR;
  708.     omfx = X5028->reg43_SCX_cac & 7;
  709.     ofx = X5028->reg43_SCX_cac >> 3;
  710.     omfy = X5028->reg42_SCY_cac & 7;
  711.     ofy = X5028->reg42_SCY_cac >> 3;
  712.     ofx = ofx + vsc;
  713.     ofy = ofy + scanline;
  714.     omfy = ofy & 7;
  715.     ofy = ofy >> 3;
  716.     ofx = ofx - (ofx & 32);
  717.     ofy = ofy - (ofy & 32);  
  718.     obx = vsc << 3;
  719.     vptrScrollStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-omfx)];
  720.     /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  721.     tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x08) >> 3) << 10);
  722.     tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
  723.     tid = X5028->ram[tidaddr]; // fetch tileid
  724.     tat = X5028->ram[tidaddr+GB_VRAM_LENGTH]; // fetch tileattr.
  725.     tdat = & X5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
  726. #   if  1
  727.     if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  728.       tdat = & tdat[tid<<4];
  729.     else //
  730.       tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  731. #   else
  732.     cti16 = (X5028->reg40_LCDC & 0x10) << 8;
  733.     cti16^= 0x1000;
  734.     tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  735. #   endif
  736. #   if  1
  737.     if (tat & 0x40) // check vflip ?
  738.       tdat = & tdat[(7-omfy)*2];
  739.     else
  740.       tdat = & tdat[omfy*2];
  741. #   else
  742.     ctu8 = (tat & 0x40) >> 3; // 8
  743.     ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
  744.     tdat = & tdat[(ctu8^omfy)<<1];
  745. #   endif
  746.     chrdat.blk = *(ks_uint16 *)tdat;
  747.     /* check x flip  */
  748.     if (tat & 0x20) {
  749.       chrcac.blk = chrdat.blk & 0x8080;
  750.       pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  751.       chrcac.blk = chrdat.blk & 0x4040;
  752.       pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  753.       chrcac.blk = chrdat.blk & 0x2020;
  754.       pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  755.       chrcac.blk = chrdat.blk & 0x1010;
  756.       pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  757.       chrcac.blk = chrdat.blk & 0x0808;
  758.       pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  759.       chrcac.blk = chrdat.blk & 0x0404;
  760.       pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  761.       chrcac.blk = chrdat.blk & 0x0202;
  762.       pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  763.       chrcac.blk = chrdat.blk & 0x0101;
  764.       pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  765.     } else {
  766.       chrcac.blk = chrdat.blk & 0x8080;
  767.       pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  768.       chrcac.blk = chrdat.blk & 0x4040;
  769.       pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  770.       chrcac.blk = chrdat.blk & 0x2020;
  771.       pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  772.       chrcac.blk = chrdat.blk & 0x1010;
  773.       pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  774.       chrcac.blk = chrdat.blk & 0x0808;
  775.       pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  776.       chrcac.blk = chrdat.blk & 0x0404;
  777.       pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  778.       chrcac.blk = chrdat.blk & 0x0202;
  779.       pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  780.       chrcac.blk = chrdat.blk & 0x0101;
  781.       pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  782.     }
  783.     rxpos = obx - omfx;
  784.     q = tat&7;
  785.     if (!(X5028->reg40_LCDC & 0x01)) {
  786.       vptrScrollStart = & vptrScrollStart[obx];
  787.       /* When Bit 0 is cleared, the background and window lose their priority,
  788.         the sprites will be always displayed on top of background and window,
  789.         independently of the priority flags in OAM and BG Map attributes.
  790.         */
  791.       for (c = 0; c != 8; c++) {
  792.         s = rxpos+c;
  793.         if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  794.           vptrScrollStart[c] = X5028->spbline[s];
  795.         else
  796.           vptrScrollStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
  797.         pixcac >>= 2;
  798.       }
  799.     } else if (tat & 0x80) { // BG pri.
  800.       vptrScrollStart = & vptrScrollStart[obx];
  801.       for (c = 0; c != 8; c++) {
  802.         vptrScrollStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
  803.         pixcac >>= 2;
  804.       }
  805.     } else  {
  806.       for (c = 0; c != 8; c++) {
  807.         s = rxpos+c;
  808.         c2 = pixcac & 3;
  809.         if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
  810.           if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
  811.             vptrScrollStart[c] = X5028->spbline[s];
  812.           else if ( c2 == 0)
  813.             vptrScrollStart[c] = X5028->spbline[s];
  814.           else
  815.             vptrScrollStart[c] = X5028->bg_pal[q][c2].rgb15;
  816.         else
  817.           vptrScrollStart[c] = X5028->bg_pal[q][c2].rgb15;
  818.         pixcac >>= 2;
  819.       }
  820.     }
  821.     rxpos = obx - omfx; // -7 | 25
  822.     rxpos+= 8; // 1 | 33
  823.     rxpos+= 7; // 8 | 40
  824.     if ( X5028->win_stuff == ks_false && (X5028->reg40_LCDC & 0x20)
  825.         && (X5028->reg4B_WX_cac <= 166 && X5028->reg4B_WX_cac < rxpos) /* check X**/
  826.         && (X5028->reg4A_WY_cac <= scanline && (X5028->reg4A_WY_cac <= 143)))
  827.     {
  828.       X5028->win_stuff = ks_true;
  829.       X5028->xscanR = 0;
  830.       q = 15 - omfx; // 8 | 16-> 9
  831.       // 7->0
  832.       // 8->1
  833.       while (X5028->reg4B_WX_cac >= q) // 15 >= q / 16
  834.         {
  835.           X5028->xscanR ++; //  1 or 2
  836.           q += 8;
  837.         }
  838.       goto windraw;
  839.     }
  840.   }
  841.   return ;
  842. windraw:
  843.   ofx = X5028->uscanR - X5028->xscanR; // espl x
  844.   c = scanline - X5028->reg4A_WY_cac; // total - y
  845.   omfx = 0;
  846.   omfy = c & 7;
  847.   ofy = c >> 3;
  848.   c3 = ((ks_int8)X5028->reg4B_WX_cac)-7;
  849.   c3 = c3 + (ofx<<3);
  850.   vptrWinDrawStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-0)+c3];
  851.   /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  852.   tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x40) >> 6) << 10);
  853.   tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
  854.   tid = X5028->ram[tidaddr]; // fetch tileid
  855.   tat = X5028->ram[tidaddr+GB_VRAM_LENGTH]; // fetch tileattr.
  856.   tdat = & X5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
  857. #   if  1
  858.   if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  859.     tdat = & tdat[tid<<4];
  860.   else //
  861.     tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  862. #   else
  863.   cti16 = (X5028->reg40_LCDC & 0x10) << 8;
  864.   cti16^= 0x1000;
  865.   tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  866. #   endif
  867. #   if  1
  868.   if (tat & 0x40) // check vflip ?
  869.     tdat = & tdat[(7-omfy)*2];
  870.   else
  871.     tdat = & tdat[omfy*2];
  872. #   else
  873.   ctu8 = (tat & 0x40) >> 3; // 8
  874.   ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
  875.   tdat = & tdat[(ctu8^omfy)<<1];
  876. #   endif
  877.   chrdat.blk = *(ks_uint16 *)tdat;
  878.   /* check x flip  */
  879.   if (tat & 0x20) {
  880.     chrcac.blk = chrdat.blk & 0x8080;
  881.     pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  882.     chrcac.blk = chrdat.blk & 0x4040;
  883.     pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  884.     chrcac.blk = chrdat.blk & 0x2020;
  885.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  886.     chrcac.blk = chrdat.blk & 0x1010;
  887.     pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  888.     chrcac.blk = chrdat.blk & 0x0808;
  889.     pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  890.     chrcac.blk = chrdat.blk & 0x0404;
  891.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  892.     chrcac.blk = chrdat.blk & 0x0202;
  893.     pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  894.     chrcac.blk = chrdat.blk & 0x0101;
  895.     pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  896.   } else {
  897.     chrcac.blk = chrdat.blk & 0x8080;
  898.     pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  899.     chrcac.blk = chrdat.blk & 0x4040;
  900.     pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  901.     chrcac.blk = chrdat.blk & 0x2020;
  902.     pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  903.     chrcac.blk = chrdat.blk & 0x1010;
  904.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  905.     chrcac.blk = chrdat.blk & 0x0808;
  906.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  907.     chrcac.blk = chrdat.blk & 0x0404;
  908.     pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  909.     chrcac.blk = chrdat.blk & 0x0202;
  910.     pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  911.     chrcac.blk = chrdat.blk & 0x0101;
  912.     pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  913.   }
  914.   q = tat&7;
  915.   if (!(X5028->reg40_LCDC & 0x01)) {
  916.     for (c = 0; c != 8; c++) {
  917.       s = c3+c;
  918.       if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  919.         vptrWinDrawStart[c] = X5028->spbline[s];
  920.       else
  921.         vptrWinDrawStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
  922.       pixcac >>= 2;
  923.     }
  924.   } else if (tat & 0x80) { // BG pri.
  925.     for (c = 0; c != 8; c++) {
  926.       vptrWinDrawStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
  927.       pixcac >>= 2;
  928.     }
  929.   } else  {
  930.     for (c = 0; c != 8; c++) {
  931.       s = c3+c;
  932.       c2 = pixcac & 3;
  933.       if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
  934.         if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
  935.           vptrWinDrawStart[c] = X5028->spbline[s];
  936.         else if ( c2 == 0)
  937.           vptrWinDrawStart[c] = X5028->spbline[s];
  938.         else
  939.           vptrWinDrawStart[c] = X5028->bg_pal[q][c2].rgb15;
  940.       else
  941.         vptrWinDrawStart[c] = X5028->bg_pal[q][c2].rgb15;
  942.       pixcac >>= 2;
  943.     }
  944.   }
  945. }
  946. static /* this method for gameboy */
  947. void bgwin_render_dmg (struct ppu *X5028, ks_int16 scanline) {
  948.   struct {
  949.     union { ks_uint16 blk;
  950.       struct { ks_uint8 lo; ks_uint8 hi; }; };
  951.   } chrdat,  chrcac;
  952.   /* always scan 168 pixel in every line (21 tiles),
  953.     evenif omfx is ZERO .
  954.       fit buffer offset, so that every time we can scan a complete tile,
  955.           no matter how much omfx is.
  956.     */
  957.   ks_int32 omfx;
  958.   ks_int32 ofx;
  959.   ks_int32 obx;
  960.   ks_int32 omfy;
  961.   ks_int32 ofy;
  962.   ks_int32 vsc;
  963.   ks_uint8 tid;
  964.   ks_int32 tidaddr;
  965.   ks_uint16 pixcac;
  966.   ks_uint8 *tdat;
  967.   ks_int32 rxpos;
  968.   ks_uint32 c, q, c2, s;
  969.   ks_int32 c3;
  970.   ks_uint16 *vptrWinDrawStart;
  971.   ks_uint16 *vptrScrollStart;
  972.   /* check current scan region in BG or WINDOW (if WINDOW enable)*/
  973.   if ( X5028->win_stuff != ks_false && (X5028->reg40_LCDC & 0x20)) {
  974.     /* draw window  */
  975.     goto windraw;
  976.   } else {
  977.     /* draw background */
  978.     vsc = X5028->uscanR;
  979.     omfx = X5028->reg43_SCX_cac & 7;
  980.     ofx = X5028->reg43_SCX_cac >> 3;
  981.     omfy = X5028->reg42_SCY_cac & 7;
  982.     ofy = X5028->reg42_SCY_cac >> 3;
  983.     ofx = ofx + vsc;
  984.     ofy = ofy + scanline;
  985.     omfy = ofy & 7;
  986.     ofy = ofy >> 3;
  987.     ofx = ofx - (ofx & 32);
  988.     ofy = ofy - (ofy & 32);  
  989.     obx = vsc << 3;
  990.     vptrScrollStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-omfx)];
  991.     /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  992.     tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x08) >> 3) << 10);
  993.     tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
  994.     tid = X5028->ram[tidaddr]; // fetch tileid
  995.     tdat = & X5028->ram[0];
  996. #   if  1
  997.     if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  998.       tdat = & tdat[tid<<4];
  999.     else //
  1000.       tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  1001. #   else
  1002.     cti16 = (X5028->reg40_LCDC & 0x10) << 8;
  1003.     cti16^= 0x1000;
  1004.     tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  1005. #   endif
  1006.     tdat = & tdat[omfy*2];
  1007.     chrdat.blk = *(ks_uint16 *)tdat;
  1008.     chrcac.blk = chrdat.blk & 0x8080;
  1009.     pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  1010.     chrcac.blk = chrdat.blk & 0x4040;
  1011.     pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  1012.     chrcac.blk = chrdat.blk & 0x2020;
  1013.     pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  1014.     chrcac.blk = chrdat.blk & 0x1010;
  1015.     pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1016.     chrcac.blk = chrdat.blk & 0x0808;
  1017.     pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1018.     chrcac.blk = chrdat.blk & 0x0404;
  1019.     pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  1020.     chrcac.blk = chrdat.blk & 0x0202;
  1021.     pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  1022.     chrcac.blk = chrdat.blk & 0x0101;
  1023.     pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  1024.     rxpos = obx - omfx;
  1025.    
  1026.     if (!(X5028->reg40_LCDC & 0x01)) {
  1027.       vptrScrollStart = & vptrScrollStart[obx];
  1028.       /* When Bit 0 is cleared, both background and window become blank (white),
  1029.         ie. the Window Display Bit (Bit 5) is ignored in that case.
  1030.           Only Sprites may still be displayed (if enabled in Bit 1).
  1031.         */
  1032.       for (c = 0; c != 8; c++) {
  1033.         s = rxpos+c;
  1034.         if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  1035.           vptrScrollStart[c] = X5028->spbline[s];
  1036.         else
  1037.           vptrScrollStart[c] = X5028->bg_pal_dmg[0];
  1038.         pixcac >>= 2;
  1039.       }
  1040.     } else  {
  1041.       for (c = 0; c != 8; c++) {
  1042.         s = rxpos+c;
  1043.         c2 = pixcac & 3;
  1044.         if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
  1045.           if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
  1046.             vptrScrollStart[c] = X5028->spbline[s];
  1047.           else if ( c2 == 0)
  1048.             vptrScrollStart[c] = X5028->spbline[s];
  1049.           else
  1050.             vptrScrollStart[c] = X5028->bg_pal_dmg[pixcac & 3];
  1051.         else
  1052.           vptrScrollStart[c] = X5028->bg_pal_dmg[pixcac & 3];
  1053.         pixcac >>= 2;
  1054.       }
  1055.     }
  1056.     rxpos = obx - omfx; // -7 | 25
  1057.     rxpos+= 8; // 1 | 33
  1058.     rxpos+= 7; // 8 | 40
  1059.     if ( X5028->win_stuff == ks_false && (X5028->reg40_LCDC & 0x20)
  1060.         && (X5028->reg4B_WX_cac <= 166 && X5028->reg4B_WX_cac < rxpos) /* check X**/
  1061.         && (X5028->reg4A_WY_cac <= scanline && (X5028->reg4A_WY_cac <= 143)))
  1062.     {
  1063.       X5028->win_stuff = ks_true;
  1064.       X5028->xscanR = 0;
  1065.       q = 15 - omfx; // 8 | 16-> 9
  1066.       // 7->0
  1067.       // 8->1
  1068.       while (X5028->reg4B_WX_cac >= q) // 15 >= q / 16
  1069.         {
  1070.           X5028->xscanR ++; //  1 or 2
  1071.           q += 8;
  1072.         }
  1073.       goto windraw;
  1074.     }
  1075.   }
  1076.   return ;
  1077. windraw:
  1078.   ofx = X5028->uscanR - X5028->xscanR; // espl x
  1079.   c = scanline - X5028->reg4A_WY_cac; // total - y
  1080.   omfx = 0;
  1081.   omfy = c & 7;
  1082.   ofy = c >> 3;
  1083.   c3 = ((ks_int8)X5028->reg4B_WX_cac)-7;
  1084.   c3 = c3 + (ofx<<3);
  1085.   vptrWinDrawStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-0)+c3];
  1086.   /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
  1087.   tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x40) >> 6) << 10);
  1088.   tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
  1089.   tid = X5028->ram[tidaddr]; // fetch tileid
  1090.   tdat = & X5028->ram[0]; // bank select.
  1091. #   if  1
  1092.   if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
  1093.     tdat = & tdat[tid<<4];
  1094.   else //
  1095.     tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
  1096. #   else
  1097.   cti16 = (X5028->reg40_LCDC & 0x10) << 8;
  1098.   cti16^= 0x1000;
  1099.   tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
  1100. #   endif
  1101.   tdat = & tdat[omfy*2];
  1102.   chrdat.blk = *(ks_uint16 *)tdat;
  1103.   chrcac.blk = chrdat.blk & 0x8080;
  1104.   pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  1105.   chrcac.blk = chrdat.blk & 0x4040;
  1106.   pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  1107.   chrcac.blk = chrdat.blk & 0x2020;
  1108.   pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  1109.   chrcac.blk = chrdat.blk & 0x1010;
  1110.   pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1111.   chrcac.blk = chrdat.blk & 0x0808;
  1112.   pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1113.   chrcac.blk = chrdat.blk & 0x0404;
  1114.   pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  1115.   chrcac.blk = chrdat.blk & 0x0202;
  1116.   pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  1117.   chrcac.blk = chrdat.blk & 0x0101;
  1118.   pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  1119.  
  1120.   if (!(X5028->reg40_LCDC & 0x01)) {
  1121.     for (c = 0; c != 8; c++) {
  1122.       s = c3+c;
  1123.       if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
  1124.         vptrWinDrawStart[c] = X5028->spbline[s];
  1125.       else
  1126.         vptrWinDrawStart[c] = X5028->bg_pal_dmg[0];
  1127.     }
  1128.   } else  {
  1129.     for (c = 0; c != 8; c++) {
  1130.       s = c3+c;
  1131.       c2 = pixcac & 3;
  1132.       if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
  1133.         if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
  1134.           vptrWinDrawStart[c] = X5028->spbline[s];
  1135.         else if ( c2 == 0)
  1136.           vptrWinDrawStart[c] = X5028->spbline[s];
  1137.         else
  1138.           vptrWinDrawStart[c] = X5028->bg_pal_dmg[pixcac & 3];
  1139.       else
  1140.         vptrWinDrawStart[c] = X5028->bg_pal_dmg[pixcac & 3];
  1141.       pixcac >>= 2;
  1142.     }
  1143.   }
  1144. }
  1145. static /* this method for gameboy color */
  1146. void sprite_render_cgb (struct ppu *X5028, ks_int16 scanline) {
  1147.  
  1148.   ks_int16 size_y; /* ?8*16:8*8 */
  1149.   /* ks_bool touch;*/
  1150.  
  1151.   size_y = (X5028->reg40_LCDC & 0x04)? 16 : 8;
  1152.   /* touch = ks_false; */
  1153.  
  1154.   /* check sprite in visual scanline */
  1155.   for (; X5028->vscan40 < 40; X5028->vscan40++) {
  1156.     ks_int16 x;
  1157.     ks_int16 y;
  1158.     ks_int16 id;
  1159.     struct oam *ptr = & X5028->sp[X5028->vscan40];
  1160.     y = ptr->y;
  1161.     x = ptr->x;
  1162.  
  1163.     if (ptr->y == 0 || ptr->y >= 160)
  1164.       continue ;
  1165.     y -= 16;
  1166.     if (scanline >= y && (scanline < (y + size_y))
  1167.       && (x != 0 && x < 168)) {
  1168.  
  1169.         struct nca {
  1170.           union {
  1171.             ks_uint16 blk;
  1172.             struct {
  1173.               ks_uint8 lo;
  1174.               ks_uint8 hi;
  1175.             };
  1176.           };
  1177.         } chrdat,  chrcac;
  1178.  
  1179.         ks_uint16 pixcac ;
  1180.         ks_uint8 *chrb;
  1181.         /* sprite inc */
  1182.         X5028->vscanR++;
  1183.         /* pick tile data by tile id and atrr's D3*/
  1184.         chrb = & X5028->ram[ptr->attr & 0x08 ? 0x2000 : 0x0000];
  1185.         if (size_y != 16)
  1186.           chrb = & chrb[ptr->id *16]; // a tile data include 16 bytes
  1187.         else
  1188.           chrb = & chrb[(ptr->id & 0xFE) *16]; // always pointer tile16's high part in init state .
  1189.         /* check Y mapper */
  1190.         if (ptr->attr & 0x40) {
  1191.           if (size_y == 16) {
  1192.             /* sprite16 flip */
  1193.             /* get rev offset */
  1194.             int calct = scanline - y;
  1195.             calct = 7 -calct; /* flip Y in one tile */
  1196.             calct *= 2;
  1197.             /* get oppo base tile byte8 (^source pos[high or low])*/
  1198.             if (calct <= 7) /* high, switch to low */ {
  1199.               calct += 16;
  1200.             } else { /* low switch to high, nodone, already in high (see line 114).*/    
  1201.             }
  1202.             chrdat.blk = *(ks_int16 *)& chrb[calct];
  1203.           } else {
  1204.             /* sprite8 flip */
  1205.             int calct = scanline - y;
  1206.             calct = 7 -calct; /* flip Y */
  1207.             calct *= 2;
  1208.             chrdat.blk = *(ks_int16 *)& chrb[calct];
  1209.           }
  1210.         } else {
  1211.           int calct = scanline - y;
  1212.           calct *= 2;
  1213.           chrdat.blk = *(ks_int16 *)& chrb[calct];
  1214.         }
  1215.         /* mix gbc's pixel (d1d0) */
  1216.         /* see GBCPUman.pdf:: 2.8.1. Tiles */
  1217.         pixcac = 0; // reset all
  1218.         /* check x flip  */
  1219.         if (ptr->attr & 0x20) {
  1220.           chrcac.blk = chrdat.blk & 0x8080;
  1221.           pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  1222.           chrcac.blk = chrdat.blk & 0x4040;
  1223.           pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  1224.           chrcac.blk = chrdat.blk & 0x2020;
  1225.           pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1226.           chrcac.blk = chrdat.blk & 0x1010;
  1227.           pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  1228.           chrcac.blk = chrdat.blk & 0x0808;
  1229.           pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  1230.           chrcac.blk = chrdat.blk & 0x0404;
  1231.           pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1232.           chrcac.blk = chrdat.blk & 0x0202;
  1233.           pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  1234.           chrcac.blk = chrdat.blk & 0x0101;
  1235.           pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  1236.         } else {
  1237.           chrcac.blk = chrdat.blk & 0x8080;
  1238.           pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  1239.           chrcac.blk = chrdat.blk & 0x4040;
  1240.           pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  1241.           chrcac.blk = chrdat.blk & 0x2020;
  1242.           pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  1243.           chrcac.blk = chrdat.blk & 0x1010;
  1244.           pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1245.           chrcac.blk = chrdat.blk & 0x0808;
  1246.           pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1247.           chrcac.blk = chrdat.blk & 0x0404;
  1248.           pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  1249.           chrcac.blk = chrdat.blk & 0x0202;
  1250.           pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  1251.           chrcac.blk = chrdat.blk & 0x0101;
  1252.           pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  1253.         }
  1254.         x -= 8;
  1255.         for (id = 0; id != 8; id++) {
  1256.           ks_uint8 idxpal; /* palette group index, max is8, see OAM struct */
  1257.           idxpal = pixcac & 3;
  1258.           if (x >= 0 && x <= 159) {
  1259.             /* check trans or */
  1260.             if (X5028->spi_cac[x+8] & PIXEL_SPRITE_NOTRANS) {
  1261.               /* notrans */
  1262.               if (X5028->spi_cac[x+8] & PIXEL_SPRITE_BACK) {
  1263.                 if (!(ptr->attr & 0x80) && idxpal != 0) {
  1264. #               if  1 /* maybe error, it's not a big problem. */
  1265.                   /* cur pick oam is foreground sprite */
  1266.                   ks_uint16 idxpg = ptr->attr & 7;
  1267.                   X5028->spb_cac[x+8] = X5028->sp_pal[idxpg][idxpal].rgb15;
  1268.                   X5028->spi_cac[x+8] = PIXEL_SPRITE_NOTRANS;            
  1269. #               endif
  1270.                 }
  1271.               } else {
  1272.                 /* nodone in foreground sprite */
  1273.               }
  1274.             } else {
  1275.               /* trans, write directly */
  1276.               ks_uint16 idxpg = ptr->attr & 7;
  1277.               X5028->spb_cac[x+8] = X5028->sp_pal[idxpg][idxpal].rgb15;
  1278.               X5028->spi_cac[x+8] = 0;
  1279.               if (ptr->attr & 0x80) {
  1280.                 /* background sprite */
  1281.                 X5028->spi_cac[x+8] |= PIXEL_SPRITE_BACK;
  1282.               }
  1283.               if (idxpal != 0) {
  1284.                 /* idxpal is trans color */
  1285.                 X5028->spi_cac[x+8] |= PIXEL_SPRITE_NOTRANS;
  1286.               }
  1287.             }
  1288.           }
  1289.           x ++;
  1290.           pixcac >>= 2;
  1291.         }
  1292.         /* scan one sprite tile compete */
  1293.         return ;
  1294.     }
  1295.   }
  1296. }
  1297. static /* this method for gameboy */
  1298. void sprite_render_dmg (struct ppu *X5028, ks_int16 scanline) {
  1299.  
  1300.   ks_int16 size_y; /* ?8*16:8*8 */
  1301.   /* ks_bool touch;*/
  1302.  
  1303.   size_y = (X5028->reg40_LCDC & 0x04)? 16 : 8;
  1304.   /* touch = ks_false; */
  1305.  
  1306.   /* check sprite in visual scanline */
  1307.   for (; X5028->vscan40 < 40; X5028->vscan40++) {
  1308.     ks_int16 x;
  1309.     ks_int16 y;
  1310.     ks_int16 id;
  1311.     struct oam *ptr = & X5028->sp[X5028->vscan40];
  1312.     y = ptr->y;
  1313.     x = ptr->x;
  1314.  
  1315.     if (ptr->y == 0 || ptr->y >= 160)
  1316.       continue ;
  1317.     y -= 16;
  1318.     if (scanline >= y && (scanline < (y + size_y))
  1319.       && (x != 0 && x < 168)) {
  1320.  
  1321.         struct nca {
  1322.           union {
  1323.             ks_uint16 blk;
  1324.             struct {
  1325.               ks_uint8 lo;
  1326.               ks_uint8 hi;
  1327.             };
  1328.           };
  1329.         } chrdat,  chrcac;
  1330.  
  1331.         ks_uint16 pixcac ;
  1332.         ks_uint8 *chrb;
  1333.         /* sprite inc */
  1334.         X5028->vscanR++;
  1335.         /* pick tile data by tile id and atrr's D3*/
  1336.         chrb = & X5028->ram[ptr->attr & 0x08 ? 0x2000 : 0x0000];
  1337.         if (size_y != 16)
  1338.           chrb = & chrb[ptr->id *16]; // a tile data include 16 bytes
  1339.         else
  1340.           chrb = & chrb[(ptr->id & 0xFE) *16]; // always pointer tile16's high part in init state .
  1341.         /* check Y mapper */
  1342.         if (ptr->attr & 0x40) {
  1343.           if (size_y == 16) {
  1344.             /* sprite16 flip */
  1345.             /* get rev offset */
  1346.             int calct = scanline - y;
  1347.             calct = 7 -calct; /* flip Y in one tile */
  1348.             calct *= 2;
  1349.             /* get oppo base tile byte8 (^source pos[high or low])*/
  1350.             if (calct <= 7) /* high, switch to low */ {
  1351.               calct += 16;
  1352.             } else { /* low switch to high, nodone, already in high (see line 114).*/    
  1353.             }
  1354.             chrdat.blk = *(ks_int16 *)& chrb[calct];
  1355.           } else {
  1356.             /* sprite8 flip */
  1357.             int calct = scanline - y;
  1358.             calct = 7 -calct; /* flip Y */
  1359.             calct *= 2;
  1360.             chrdat.blk = *(ks_int16 *)& chrb[calct];
  1361.           }
  1362.         } else {
  1363.           int calct = scanline - y;
  1364.           calct *= 2;
  1365.           chrdat.blk = *(ks_int16 *)& chrb[calct];
  1366.         }
  1367.         /* mix gbc's pixel (d1d0) */
  1368.         /* see GBCPUman.pdf:: 2.8.1. Tiles */
  1369.         pixcac = 0; // reset all
  1370.         /* check x flip  */
  1371.         if (ptr->attr & 0x20) {
  1372.           chrcac.blk = chrdat.blk & 0x8080;
  1373.           pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
  1374.           chrcac.blk = chrdat.blk & 0x4040;
  1375.           pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
  1376.           chrcac.blk = chrdat.blk & 0x2020;
  1377.           pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1378.           chrcac.blk = chrdat.blk & 0x1010;
  1379.           pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
  1380.           chrcac.blk = chrdat.blk & 0x0808;
  1381.           pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
  1382.           chrcac.blk = chrdat.blk & 0x0404;
  1383.           pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1384.           chrcac.blk = chrdat.blk & 0x0202;
  1385.           pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
  1386.           chrcac.blk = chrdat.blk & 0x0101;
  1387.           pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);        
  1388.         } else {
  1389.           chrcac.blk = chrdat.blk & 0x8080;
  1390.           pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
  1391.           chrcac.blk = chrdat.blk & 0x4040;
  1392.           pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
  1393.           chrcac.blk = chrdat.blk & 0x2020;
  1394.           pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
  1395.           chrcac.blk = chrdat.blk & 0x1010;
  1396.           pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
  1397.           chrcac.blk = chrdat.blk & 0x0808;
  1398.           pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
  1399.           chrcac.blk = chrdat.blk & 0x0404;
  1400.           pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
  1401.           chrcac.blk = chrdat.blk & 0x0202;
  1402.           pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
  1403.           chrcac.blk = chrdat.blk & 0x0101;
  1404.           pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
  1405.         }
  1406.         x -= 8;
  1407.         for (id = 0; id != 8; id++) {
  1408.           ks_uint8 idxpal; /* palette group index, max is8, see OAM struct */
  1409.           idxpal = pixcac & 3;
  1410.           if (x >= 0 && x <= 159) {
  1411.             /* check trans or */
  1412.             if (X5028->spi_cac[x+8] & PIXEL_SPRITE_NOTRANS) {
  1413.               /* notrans */
  1414.               if (X5028->spi_cac[x+8] & PIXEL_SPRITE_BACK) {
  1415.                 if (!(ptr->attr & 0x80) && idxpal != 0) {
  1416. #               if  1 /* maybe error, it's not a big problem. */
  1417.                   /* cur pick oam is foreground sprite */
  1418.                   ks_uint16 idxpg = (ptr->attr & 0x10) >> 4;
  1419.                   X5028->spb_cac[x+8] = X5028->sp_pal_dmg[idxpg][idxpal];
  1420.                   X5028->spi_cac[x+8] = PIXEL_SPRITE_NOTRANS;            
  1421. #               endif
  1422.                 }
  1423.               } else {
  1424.                 /* nodone in foreground sprite */
  1425.               }
  1426.             } else {
  1427.               /* trans, write directly */
  1428.               ks_uint16 idxpg = (ptr->attr & 0x10) >> 4;
  1429.               X5028->spb_cac[x+8] = X5028->sp_pal_dmg[idxpg][idxpal];
  1430.               X5028->spi_cac[x+8] = 0;
  1431.               if (ptr->attr & 0x80) {
  1432.                 /* background sprite */
  1433.                 X5028->spi_cac[x+8] |= PIXEL_SPRITE_BACK;
  1434.               }
  1435.               if (idxpal != 0) {
  1436.                 /* idxpal is trans color */
  1437.                 X5028->spi_cac[x+8] |= PIXEL_SPRITE_NOTRANS;
  1438.               }
  1439.             }
  1440.           }
  1441.           x ++;
  1442.           pixcac >>= 2;
  1443.         }
  1444.         /* scan one sprite tile compete */
  1445.         return ; // TODO: gb sprite priority.
  1446.     }
  1447.   }
  1448. }
  1449. /* XXX:so bad */
  1450. int ppu_run (struct ppu *X5028) {
  1451.  
  1452.   ks_int32 scanline;
  1453.   ks_int16 interv;
  1454.   ks_int16 _nums;
  1455.   ks_double clkline;
  1456.  
  1457.   if (X5028->gb->cpu_clks_ppu > X5028->gb->mach_tools->frame_cycles) {
  1458.     X5028->gb->cpu_clks_ppu -= X5028->gb->mach_tools->frame_cycles; // sub a frame block
  1459.     /* at this time and in the scanning of the next frame of the device.
  1460.               reset ppu device context  */
  1461.    
  1462.     /* vblank Interrupt, check touch */
  1463.     if (X5028->vbl_flop == ks_false)
  1464.       if (X5028->reg41_LCDS & 0x10)
  1465.         X5028->gb->reg0F_IF |= IRQ_1;
  1466.       else {}
  1467.     else {}
  1468.    
  1469.     /* reset context */
  1470.     X5028->vbl_flop = ks_false;
  1471.     X5028->oam_flop = ks_false;
  1472.     X5028->hbl_flop = ks_false;
  1473.     X5028->interrupt45_flop = ks_false;
  1474.     X5028->interrupt45_strike = ks_false;
  1475.     X5028->vscan = -1;
  1476.     X5028->vscanR = 0;
  1477.     X5028->vscan40 = 0;
  1478.     X5028->uscan = -1;
  1479.     X5028->uscanR = 0;
  1480.     X5028->uscan168 = 0;
  1481.     X5028->win_stuff = ks_false;
  1482.   }
  1483.   scanline = (ks_int32) (X5028->gb->cpu_clks_ppu/ X5028->gb->mach_tools->line_cycles);
  1484.   clkline = fmod (X5028->gb->cpu_clks_ppu, X5028->gb->mach_tools->line_cycles);
  1485.   /* clear mask */
  1486.   X5028->reg40_LCDC &= ~LCDCS_MODE_FLAG_ALL_MASK;
  1487.   X5028->reg44_LY = scanline;
  1488.  
  1489.   /*
  1490.     PPU time series
  1491.  
  1492.     Mode 0: The LCD controller is in the H-Blank period and
  1493.          the CPU can access both the display RAM (8000h-9FFFh)
  1494.          and OAM (FE00h-FE9Fh)
  1495.  
  1496.     Mode 1: The LCD controller is in the V-Blank period (or the
  1497.          display is disabled) and the CPU can access both the
  1498.          display RAM (8000h-9FFFh) and OAM (FE00h-FE9Fh)
  1499.  
  1500.     Mode 2: The LCD controller is reading from OAM memory.
  1501.          The CPU <cannot> access OAM memory (FE00h-FE9Fh)
  1502.          during this period.
  1503.  
  1504.     Mode 3: The LCD controller is reading from both OAM and VRAM,
  1505.          The CPU <cannot> access OAM and VRAM during this period.
  1506.          CGB Mode: Cannot access Palette Data (FF69,FF6B) either.
  1507.     The following are typical when the display is enabled:
  1508.  
  1509.     Mode 2  2_____2_____2_____2_____2_____2___________________2____
  1510.     Mode 3  _33____33____33____33____33____33__________________3___
  1511.     Mode 0  ___000___000___000___000___000___000________________000
  1512.     Mode 1  ____________________________________11111111111111_____
  1513.  
  1514.     The Mode Flag goes through the values 0, 2, and 3 at a cycle of about 109uS.
  1515.     0 is present about 48.6uS, 2 about 19uS,
  1516.     and 3 about 41uS. This is interrupted every 16.6ms by the VBlank (1).
  1517.     The mode flag stays set at 1 for about 1.08 ms.
  1518.  
  1519.     Mode 0 is present between 201-207 clks, 2 about 77-83 clks, and 3 about 169-175 clks.
  1520.     A complete cycle through these states takes 456 clks.
  1521.     VBlank lasts 4560 clks. A complete screen refresh occurs every 70224 clks.)
  1522.  */
  1523.  
  1524.   /* check scanline and LCDY interrupt */
  1525.   if (X5028->line_cac != scanline
  1526.        || (X5028->interrupt45_strike != ks_false)) {
  1527.     /* setting onrush effective */
  1528.     if (X5028->line_cac != scanline) {
  1529.       X5028->interrupt45_flop = ks_false; /* reset gate */
  1530.       X5028->interrupt45_strike = ks_false; /* close strike function*/
  1531.     } /*  scanline next, (low to high) for each scanline,
  1532.                    multiple LCDY interruptions can not be triggered at the same time
  1533.            during each vertical synchronization  */
  1534.     if (X5028->reg45_LYC == scanline) /*  check enable ?*/
  1535.          /* Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write) */
  1536.       if (X5028->reg41_LCDS & 0x40 && !X5028->interrupt45_flop) {      
  1537.         X5028->interrupt45_strike = ks_false; /* close strike function*/
  1538.         X5028->interrupt45_flop = ks_true;
  1539.         X5028->gb->reg0F_IF |= IRQ_2;
  1540.       } else {}
  1541.     else {}
  1542.   }
  1543.   /* check FF41::Bit 2 Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)*/
  1544.   if (scanline == X5028->reg45_LYC)
  1545.     X5028->reg41_LCDS |= 0x04;
  1546.   else X5028->reg41_LCDS &= ~0x04;
  1547.  
  1548.   /* check mode */
  1549.   if (clkline < X5028->gb->mach_tools->vbl_clk_st) {
  1550.     if (clkline > X5028->hbl_clks_st) {
  1551.       /*  LCD MODE0 -  hblank period */
  1552.       X5028->reg41_LCDS |= LCDCS_MODE_FLAG_HBLANK;
  1553.       /*  check edge */
  1554.       if (X5028->lcdm_cac != LCDCS_MODE_FLAG_HBLANK) {
  1555.         /* oamvram to current, (low to high) */
  1556.         while (X5028->uscanR < 21) {
  1557.           X5028->bgwin_render (X5028, scanline);
  1558.           X5028->uscanR ++;
  1559.         }
  1560.         /* reset next mode-2 | mode- 3*/
  1561.         X5028->oam_flop = ks_false;
  1562.         X5028->vscan = -1;
  1563.         X5028->vscan40 = 0;
  1564.         X5028->uscan = -1;
  1565.         X5028->vscanR = 0;
  1566.         X5028->uscanR = 0;
  1567.         /* check HDMA. **/
  1568.         if (scanline >= 0 && scanline <= 143 && X5028->gb->dma_gen)  {
  1569.           /* copy 16 bytes  */
  1570.           if (gameboy_hdma_copy (X5028->gb) == 0)
  1571.             X5028->gb->dma_gen = ks_false;
  1572.           /* add hdma cycles, ~ 8us */
  1573.           X5028->hdma_clk += (X5028->gb->mach_tools->clk_ns * 8.0);
  1574.         }
  1575.         /* in HDMA, no hblank perido */
  1576.         X5028->hbl_flop = ks_true;
  1577.       }
  1578.       /* check hblank interrupt  */
  1579.       if ((X5028->reg41_LCDS & 0x08) && X5028->hbl_flop == ks_false) {
  1580.         X5028->hbl_flop = ks_true;
  1581.         X5028->gb->reg0F_IF |= IRQ_2;
  1582.       }
  1583.     } else if (clkline > X5028->gb->mach_tools->oambg_clk_st) {
  1584.       /* LCD MODE3  - oamvram */
  1585.       clkline -= X5028->gb->mach_tools->oambg_clk_st; // sub, get start clcks epls.
  1586.       X5028->reg41_LCDS |= LCDCS_MODE_FLAG_SERACH_OAMVRAM;
  1587.       /* check edge */
  1588.       if (X5028->lcdm_cac != LCDCS_MODE_FLAG_SERACH_OAMVRAM) {
  1589.         /*  check stride sprite render  */
  1590.         /* get render pos */
  1591.         interv = 9;
  1592.  
  1593.         /* check render oam *.*/
  1594.         if ( X5028->vscan != interv
  1595.              &&   X5028->vscanR < 10
  1596.                && X5028->vscan40   < 40) {
  1597.           _nums = interv - X5028->vscan;
  1598.           X5028->vscan += _nums;
  1599.           /* render sprite */
  1600.           do
  1601.           {
  1602.                    X5028->sprite_render (X5028, scanline); }
  1603.              while (--_nums);
  1604.         }
  1605.         /*  check sprite interrupt  */
  1606.         if ((X5028->reg41_LCDS & 0x20) && !X5028->oam_flop) {      
  1607.           X5028->oam_flop = ks_true;
  1608.           X5028->gb->reg0F_IF |= IRQ_2;
  1609.         }
  1610.         X5028->oam_flop = ks_false;
  1611.  
  1612.         /* adjust BGOAM clk */
  1613.  
  1614.         X5028->hbl_clks_st = (X5028->gb->mach_tools->oambg_b_cycles +
  1615.               X5028->vscanR * X5028->gb->mach_tools->oam_clk_add_hbl_per);
  1616.         X5028->oambg_clks_divider21 =
  1617.             X5028->hbl_clks_st / 21.0;
  1618.         X5028->hbl_clks_st += X5028->gb->mach_tools->oam_cycles;
  1619.       }
  1620.       /* get render pos */
  1621.       interv = KS_INT16_CAST (clkline/ X5028->oambg_clks_divider21);
  1622.  
  1623.       /* check render bg *.*/
  1624.       if (interv != X5028->uscan) {
  1625.         _nums = interv - X5028->uscan;
  1626.         X5028->uscan += _nums;
  1627.         do {
  1628.           X5028->bgwin_render (X5028, scanline);
  1629.           X5028->uscanR ++;
  1630.         }  while (--_nums);
  1631.       }
  1632.     } else   {
  1633.       /* LCD MODE2 - oam */
  1634.       X5028->reg41_LCDS |= LCDCS_MODE_FLAG_SERACH_OAM;
  1635.       /* check edge */
  1636.       if (X5028->lcdm_cac == LCDCS_MODE_FLAG_HBLANK) {
  1637.         /* hblank to current, (low to high), check stride interrupt */
  1638.         if (X5028->hbl_flop == ks_false)      
  1639.           if (X5028->reg41_LCDS & 0x08)
  1640.             X5028->gb->reg0F_IF |= IRQ_2;
  1641.           else {}
  1642.         else {}
  1643.         X5028->hbl_flop = ks_false;
  1644.       }
  1645.       /* get render pos */
  1646.       interv = KS_INT16_CAST (clkline/ X5028->gb->mach_tools->oam_clk_pick_per);
  1647.  
  1648.       /* check render oam *.*/
  1649.       if ( X5028->vscan != interv
  1650.            &&   X5028->vscanR < 10
  1651.              && X5028->vscan40   < 40) {
  1652.         _nums = interv - X5028->vscan;
  1653.         X5028->vscan += _nums;
  1654.         /* render sprite */
  1655.         do
  1656.         {
  1657.                  X5028->sprite_render (X5028, scanline); }
  1658.            while (--_nums);
  1659.       }
  1660.       /*  check sprite interrupt  */
  1661.       if ((X5028->reg41_LCDS & 0x20) && !X5028->oam_flop) {      
  1662.         X5028->oam_flop = ks_true;
  1663.         X5028->gb->reg0F_IF |= IRQ_2;
  1664.       }
  1665.     }
  1666.   } else {
  1667.     /* LCD MODE1 - vblank */
  1668.     X5028->reg41_LCDS |= LCDCS_MODE_FLAG_VLANK;
  1669.     /* check edge */
  1670.     if (X5028->lcdm_cac != LCDCS_MODE_FLAG_VLANK) {
  1671.       /* post device render */
  1672.       X5028->device_blit (X5028, X5028->obj);
  1673.       /* check hblank lack */
  1674.     }
  1675.     /*  check vblank interrupt  */
  1676.     if ((X5028->reg41_LCDS & 0x10) && !X5028->vbl_flop) {      
  1677.       X5028->vbl_flop = ks_true;
  1678.       X5028->gb->reg0F_IF |= IRQ_1;
  1679.     }
  1680.   }
  1681.   X5028->line_cac = scanline;
  1682.   X5028->lcdm_cac = X5028->reg41_LCDS & LCDCS_MODE_FLAG_ALL_MASK;
  1683.   return 0;
  1684. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement