Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* private object for gameboy
- *
- * Copyright (C) 2018 moecmks
- * This file is part of KS3578.
- *
- * do What The Fuck you want to Public License
- *
- * Version 1.0, March 2000
- * Copyright (C) 2000 Banlu Kemiyatorn (]d).
- * 136 Nives 7 Jangwattana 14 Laksi Bangkok
- * Everyone is permitted to copy and distribute verbatim copies
- * of this license document, but changing it is not allowed.
- *
- * Ok, the purpose of this license is simple
- * and you just
- *
- * DO WHAT THE FUCK YOU WANT TO.
- */
- #ifndef _INTERNAL_H
- #define _INTERNAL_H 1
- #include "conf.h"
- #include "controller.h"
- struct gameboy;
- struct controller;
- struct cpu;
- struct ppu;
- struct cartidge;
- struct apu;
- struct elev;
- struct machine_setup;
- struct elev {
- ks_uint8 old;
- ks_uint8 cur;
- };
- #define CHECK_ELEV_CUR(/*struct elev **/ E)\
- (!!((struct elev *)E)->cur)
- #define CHECK_ELEV_OLD(/*struct elev **/ E)\
- (!!((struct elev *)E)->old)
- #define UPDATE_ELEV_(/*struct elev **/ E, /* ks_uint8*/state)\
- do \
- { \
- struct elev *T = (struct elev *)E;\
- T->old = !!T->cur;\
- T->cur = !!state;\
- } while (0)
- #define CHECK_ELEV_LOW_TO_HIGH(/*struct elev **/ E)\
- if ( !CHECK_ELEV_OLD(E) && CHECK_ELEV_CUR(E))
- #define CHECK_ELEV_HIGH_TO_LOW(/*struct elev **/ E)\
- if ( CHECK_ELEV_OLD(E) && !CHECK_ELEV_CUR(E))
- static const
- struct machine_setup {
- ks_double cpu_freq;
- ks_double vsync_freq;
- ks_double hsync_freq;
- ks_double clk_ms;
- ks_double clk_ns;
- ks_double frame_cycles;
- ks_double line_cycles;
- ks_double oam_cycles;
- ks_double oambg_b_cycles;
- ks_double oambg_hbl_cycles;
- ks_int32 line_total;
- ks_int32 line_vbl_st;
- ks_double vbl_clk_last;
- ks_double oam_clk_st;
- ks_double oambg_clk_st;
- ks_double hbl_clk_st_b;
- ks_double vbl_clk_st;
- ks_double oam_clk_pick_per;
- ks_double oam_clk_add_hbl_per;
- ks_double tim0507_vclk;
- ks_double cgb_gbp_p;
- ks_double gbp_cgb_p;
- ks_double div04_clks256;
- ks_double oamdma_clks;
- ks_double gdma_clks_b;
- ks_double gdma_clks_per16; // always 7.63 us (DMG/CGB)
- } std_machine = {
- 4194304.0, /* machine_setup::cpu_freq*/
- 59.73, /* machine_setup::vsync_freq */
- 9198.42, /* machine_setup::hsync_freq, per line, vsync_freq * 154(*machine_setup::scanline_total)*/
- 4194304.0/1000.0, /* machine_setup::clk_ms */
- 4194304.0/1000000.0, /* machine_setup::clk_ns*/
- 70221.061443161, /* machine_setup::frame_cycles, cpu_freq/ vsync_freq */
- 455.98091846208, /* machine_setup::line_cycles, frame_cycles / * 154(*machine_setup::scanline_total)*/
- 80.992010239999985, /* machine_setup::oam_cycles, 19.31 黶ec see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W)*/
- 173.51835647999999, /* machine_setup::oambg_basecycles, 41.37 黶ec see http://www.devrs.com/gb/files/faqs.html#VideoTiming*/
- 455.98091846208 - 80.992010239999985, /* machine_setup::oambg_hbl_cycles */
- 154, /* machine_setup::line_total, see TheNintendoGameboy.pdf ::LCD Position and Scrolling*/
- 144, /* machine_setup::line_vbl_st , see TheNintendoGameboy.pdf ::LCD Interrupts*/
- 4559.809184621, /* machine_setup::vbl_clk_last, see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W) */
- 0.0, /* machine_setup::oam_clk_st*/
- 80.992010239999985, /* machine_setup::oambg_clk_st*/
- 173.51835647999999 + 80.992010239999985, /* machine_setup::hbl_clk_st_b*/
- 70221.061443161 - 4559.809184621, /* machine_setup::vbl_clk_st*/
- 80.992010239999985 / 10.0, /* machine_setup::oam_clk_pick_per*/
- 12.549357568000001, /* machine_setup::oam_clk_add_hbl_per*/
- 0.00097656250000000000, /* machine_setup::tim0507_vclk*/
- 8400000.0/ 4194304.0, /* machine_setup::cgb_gbp_p*/
- 4194304.0/ 8400000.0, /* machine_setup::gbp_cgb_p*/
- 4194304.0/ 256.0, /* machine_setup::div04_clks256*/
- 671.08864000000005, /* machine_setup::oamdma_clks*/
- (4194304.0*220.0)/1000000.0, /* machine_setup::gdma_clks_b*/
- (4194304.0*7.63)/1000000.0 /* machine_setup::gdma_clks_per16*/
- }, adv_machine = {
- 8400000.0, /* machine_setup::cpu_freq*/
- 59.73, /* machine_setup::vsync_freq */
- 9198.42, /* machine_setup::hsync_freq, per line, vsync_freq * 154(*machine_setup::scanline_total)*/
- 8400000.0/1000.0, /* machine_setup::clk_ms*/
- 8400000.0/1000000.0, /* machine_setup::clk_ns*/
- 140632.84781516826, /* machine_setup::frame_cycles, cpu_freq/ vsync_freq */
- 913.20031048810563, /* machine_setup::line_cycles, frame_cycles / * 154(*machine_setup::scanline_total)*/
- 162.20400000000001, /* machine_setup::oam_cycles, 19.31 黶ec see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W)*/
- 347.50799999999998, /* machine_setup::oambg_basecycles, 41.37 黶ec see http://www.devrs.com/gb/files/faqs.html#VideoTiming */
- 913.20031048810563 - 162.20400000000001, /* machine_setup::oambg_hbl_cycles */
- 154, /* machine_setup::line_total, see TheNintendoGameboy.pdf ::LCD Position and Scrolling*/
- 144, /* machine_setup::line_vbl_st , see TheNintendoGameboy.pdf ::LCD Interrupts*/
- 9132.0031048810633, /* machine_setup::vbl_clk_last, see TheNintendoGameboy.pdf :: FF41 - STAT - LCDC Status (R/W) */
- 0.0, /* machine_setup::oam_clk_st*/
- 162.20400000000001, /* machine_setup::oambg_clk_st*/
- 347.50799999999998 + 162.20400000000001, /* machine_setup::hbl_clk_st_b*/
- 140632.84781516826 - 9132.0031048810633, /* machine_setup::vbl_clk_st*/
- 162.20400000000001 / 10.0, /* machine_setup::oam_clk_pick_per*/
- 25.132800000000003, /* machine_setup::oam_clk_add_hbl_per*/
- 0.00048761904761904760, /* machine_setup::tim0507_vclk*/
- 8400000.0/ 4194304.0, /* machine_setup::cgb_gbp_p*/
- 4194304.0/ 8400000.0, /* machine_setup::gbp_cgb_p*/
- 671.08864000000005, /* machine_setup::oamdma_clks*/
- (4194304.0*220.0)/1000000.0, /* machine_setup::gdma_clks_b*/
- (8400000.0*7.63)/1000000.0 /* machine_setup::gdma_clks_per16*/
- };
- struct controller {
- ks_uint8 reg;
- /* for gamebot update host keybuf and IRQ */
- void (*hostdrv_checkIRQ) (struct controller *);
- void *obj;
- void *ubdata_user;
- /* pad infos for gameboy*.*/
- struct controller_pad gb_pad;
- struct gameboy *gb;
- };
- struct cpu {
- /* XXX:memory order dep. */
- union { struct { ks_uint8 F; ks_uint8 A; }; ks_uint16 AF; };
- union { struct { ks_uint8 C; ks_uint8 B; }; ks_uint16 CB; };
- union { struct { ks_uint8 E; ks_uint8 D; }; ks_uint16 DE; };
- union { struct { ks_uint8 L; ks_uint8 H; }; ks_uint16 HL; };
- union { struct { ks_uint8 SL; ks_uint8 SH; }; ks_uint16 SP; };
- union { struct { ks_uint8 PL; ks_uint8 PH; }; ks_uint16 PC; };
- /* Interrupt Master Enable*/
- ks_uint8 IME;
- /* for Halt */
- ks_bool halt;
- /* for stop */
- ks_bool stop;
- /* for speed mode */
- ks_uint8 reg4D_key1;
- /* gameboy object */
- struct gameboy *gb;
- };
- struct oam {
- union {
- struct {
- ks_uint8 y;
- ks_uint8 x;
- ks_uint8 id;
- ks_uint8 attr;
- };
- ks_uint8 blk[4];
- };
- };
- struct pal {
- union {
- struct {
- ks_uint8 _lo;
- ks_uint8 _hi;
- };
- ks_uint16 rgb15;
- ks_uint8 blk[2];
- };
- };
- /* for ppu:: spi_ca */
- #define PIXEL_SPRITE_NOTRANS 1
- #define PIXEL_SPRITE_BACK 2
- /* for ppu:: wmi_cac */
- #define PIXEL_WINDOW_NOTRANS 1
- #define PIXEL_WINDOW_BACK 2
- #define PIXEL_WINDOW_UNINIT 4
- struct ppu {
- ks_uint16 *buf;
- ks_uint16 *bufb; /* for alignmem */
- ks_uint16 *bufline; /* startpos */
- ks_uint16 bufp; /* buffer pitch */
- ks_uint8 ram[0x4000]; /* 8K for DMG, 16 for CGB */
- ks_uint16 spb_cac[176]; /* sprite buffer cache *.*/
- ks_uint16 spi_cac[176];
- ks_uint16 *spbline;
- ks_uint16 *spiline;
- struct gameboy *gb;
- struct oam sp[40];
- struct pal bg_pal[8][4]; /* pal for gameboycolor */
- struct pal sp_pal[8][4]; /* pal for gameboycolor */
- ks_uint16 spl_dmg[40];
- ks_uint16 bg_pal_dmg[4]; /* pal for gameboy */
- ks_uint16 sp_pal_dmg[2][4]; /* pal for gameboy */
- ks_uint16 bg_pal_dmgT[4]; /* pal for gameboy */
- ks_uint16 sp_pal_dmgT[2][4]; /* pal for gameboy */
- ks_bool gameboy_mode;
- ks_bool s890623_mode; /* TODO: see http://fms.komkon.org/GameBoy/Tech/LCD.gif*/
- /* register cache for scanline */
- ks_uint8 reg43_SCX_cac;
- ks_uint8 reg42_SCY_cac;
- ks_uint8 reg4A_WY_cac;
- ks_uint8 reg4B_WX_cac;
- ks_uint8 reg40_LCDC;
- ks_uint8 reg41_LCDS;
- ks_uint8 reg42_SCY;
- ks_uint8 reg43_SCX;
- ks_uint8 reg44_LY;
- ks_uint8 reg45_LYC;
- ks_uint8 reg46_DMA;
- ks_uint8 reg47_BGP;
- ks_uint8 reg48_OBP0;
- ks_uint8 reg49_OBP1;
- ks_uint8 reg4A_WY;
- ks_uint8 reg4B_WX;
- ks_uint8 reg4F_VBK;
- ks_uint8 reg51_HDMA1;
- ks_uint8 reg52_HDMA2;
- ks_uint8 reg53_HDMA3;
- ks_uint8 reg54_HDMA4;
- ks_uint8 reg55_HDMA5;
- ks_uint8 reg68_BCPS;
- ks_uint8 reg69_BCPD;
- ks_uint8 reg6A_OCPS;
- ks_uint8 reg6B_OCPD;
- ks_int32 vscan;
- ks_int32 vscanR;
- ks_int32 vscan10;
- ks_int32 vscan40;
- ks_int32 xscan;
- ks_int32 xscanR;
- ks_int32 uscan;
- ks_int32 uscanR;
- ks_int32 uscan168;
- ks_int32 vscan_cac;
- ks_bool oam_flop;
- ks_bool vbl_flop;
- ks_bool hbl_flop;
- ks_bool interrupt45_strike;
- ks_bool interrupt45_flop;
- ks_int32 line_cac; /* old scanline*/
- ks_int32 lcdm_cac; /* old lcd mode*/
- ks_bool win_stuff; /* window done assert */
- ks_bool hdma_gen;
- ks_uint16 hdma_src;
- ks_uint16 hdma_dst;
- ks_uint16 hdma_r16;
- ks_double hdma_clk;
- ks_double hbl_clks_st;
- ks_double oambg_clks_divider21;
- ks_double oambg_clks_total;
- void (*bgwin_render) (struct ppu *_5028, ks_int16 scanline);
- void (*sprite_render) (struct ppu *_5028, ks_int16 scanline);
- void (*device_blit) (struct ppu *_5028, void * obj); /*blit, and sync */
- void *obj;
- };
- struct gameboy {
- struct controller *joypad;
- struct cpu *lr35902;
- struct ppu *lh5028;
- struct cartidge *cart;
- struct apu *apu_;
- struct machine_setup *mach_tools;
- double cpu_clks;
- double cpu_clks_cl; // old full - block
- double cpu_clks_el; // cur full - block
- double cpu_clks_timer; // cur full - block
- double cpu_clks_divider; // cur full - block
- double cpu_clks_ppu; // cur full - block
- double cpu_clks_dma;
- double divider_04;
- double divider_0507;
- double divider_apu;
- double divider_controller;
- double fire0507;
- double fire04;
- double cur0507;
- double calc0507;
- ks_uint8 reg01_SB;
- ks_uint8 reg02_SC;
- ks_uint8 reg04_DIV;
- ks_uint8 reg05_TIMA;
- ks_uint8 reg06_TMA;
- ks_uint8 reg06_TMA_cac;
- ks_uint16 reg06_TMA_count;
- ks_uint8 reg07_TAC;
- ks_uint8 reg0F_IF; /* interrupt flags register */
- /* TODO: sound register */
- ks_uint8 reg56_IC;
- ks_uint8 reg70_SVBK;
- ks_uint8 regFF_IE; /* Interrupt enable register */
- ks_bool crazy_mode;
- ks_bool clk_stride;
- ks_bool dma_gen;
- // ks_double cpu_clks_oamdma;
- // ks_double cpu_clks_gdma;
- // ks_double cpu_clks_hdma;
- };
- # define GB_VRAM_ADDRESS_START 0x8000
- # define GB_VRAM_LENGTH 8096
- #endif
- /* Game boy's GPU and LCD Screen
- * LCD is Sharp LH5028 http://www.datasheetarchive.com/pdf/download.php?id=c615e5d8551c6b559c3db61b709b3234af856c&type=O&term=LH5028
- *
- * This part of the source code is actually not very good.
- * It looks terrible.
- *
- * Copyright (C) 2018 moecmks
- * This file is part of KS3578.
- *
- * do What The Fuck you want to Public License
- *
- * Version 1.0, March 2000
- * Copyright (C) 2000 Banlu Kemiyatorn (]d).
- * 136 Nives 7 Jangwattana 14 Laksi Bangkok
- * Everyone is permitted to copy and distribute verbatim copies
- * of this license document, but changing it is not allowed.
- *
- * Ok, the purpose of this license is simple
- * and you just
- *
- * DO WHAT THE FUCK YOU WANT TO.
- */
- #include "ppu.h"
- #include "gameboy.h"
- #include "internal.h"
- int ppu_init (struct ppu **X5028) {
- struct ppu *sys = ks_null;
- assert (X5028 != ks_null);
- sys = (struct ppu *)calloc (sizeof (struct ppu), 1);
- assert (sys != ks_null);
- *X5028 = sys;
- return 0;
- }
- int ppu_reset (struct ppu *X5028) {
- /* init register http://gbdev.gg8.se/files/docs/mirrors/pandocs.html#powerupsequence */
- X5028->reg40_LCDC = 0x91;
- X5028->reg42_SCY = 0x00;
- X5028->reg43_SCX = 0x00;
- X5028->reg45_LYC = 0x00;
- X5028->reg47_BGP = 0xFC;
- X5028->reg48_OBP0 = 0xFF;
- X5028->reg49_OBP1 = 0xFF;
- X5028->reg4A_WY = 0x00;
- X5028->reg4B_WX = 0x00;
- /* reset cache */
- X5028->reg42_SCY_cac= X5028->reg42_SCY;
- X5028->reg43_SCX_cac= X5028->reg43_SCX;
- X5028->reg4A_WY_cac= X5028->reg4A_WY;
- X5028->reg4B_WX_cac= X5028->reg4B_WX;
- }
- void ppu_uninit (struct ppu **X5028);
- int ppu_getbuf_ (struct ppu *X5028, ks_uint16 **bufrv, ks_uint16 *pitch);
- void ppu_setupdate (struct ppu *X5028, void (*update) (struct ppu *X5028));
- void ppu_update (struct ppu *X5028);
- int ppu_reset_cycles (struct ppu *X5028);
- int ppu_attach (struct ppu *X5028, struct gameboy *gb);
- void ppu_write_io (struct ppu *X5028, ks_uint16 address, ks_uint8 value) {
- ks_uint8 c, s;
- switch (address) {
- case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
- /*Bit 7 - LCD Display Enable (0=Off, 1=On)
- Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
- Bit 5 - Window Display Enable (0=Off, 1=On)
- Bit 4 - BG & Window Tile Data Select (0=8800-97FF, 1=8000-8FFF)
- Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
- Bit 2 - OBJ (Sprite) Size (0=8x8, 1=8x16)
- Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On)
- Bit 0 - BG/Window Display/Priority (0=Off, 1=On)
- */
- X5028->reg40_LCDC = value;
- break;
- case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
- /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
- Bit 5 - Mode 2 OAM Interrupt (1=Enable) (Read/Write)
- Bit 4 - Mode 1 V-Blank Interrupt (1=Enable) (Read/Write)
- Bit 3 - Mode 0 H-Blank Interrupt (1=Enable) (Read/Write)
- Bit 2 - Coincidence Flag (0:LYC<>LY, 1:LYC=LY) (Read Only)
- Bit 1-0 - Mode Flag (Mode 0-3, see below) (Read Only)
- 0: During H-Blank
- 1: During V-Blank
- 2: During Searching OAM
- 3: During Transferring Data to LCD Driver
- */
- X5028->reg41_LCDS = value;
- break;
- case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
- X5028->reg42_SCY = value;
- break;
- case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
- X5028->reg43_SCX = value;
- break;
- case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
- _DEBUG_BREAK();
- break;
- case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
- X5028->reg45_LYC = value;
- break;
- case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
- X5028->reg4A_WY = value;
- break;
- case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
- X5028->reg4B_WX = value;
- break;
- case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
- X5028->bg_pal_dmg[0] = X5028->bg_pal_dmgT[(value & 0x03) >> 0];
- X5028->bg_pal_dmg[1] = X5028->bg_pal_dmgT[(value & 0x0C) >> 2];
- X5028->bg_pal_dmg[2] = X5028->bg_pal_dmgT[(value & 0x30) >> 4];
- X5028->bg_pal_dmg[3] = X5028->bg_pal_dmgT[(value & 0xC0) >> 6];
- X5028->reg47_BGP = value;
- break ;
- case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
- X5028->sp_pal_dmg[0][0] = X5028->sp_pal_dmgT[0][(value & 0x03) >> 0];
- X5028->sp_pal_dmg[0][1] = X5028->sp_pal_dmgT[0][(value & 0x0C) >> 2];
- X5028->sp_pal_dmg[0][2] = X5028->sp_pal_dmgT[0][(value & 0x30) >> 4];
- X5028->sp_pal_dmg[0][3] = X5028->sp_pal_dmgT[0][(value & 0xC0) >> 6];
- X5028->reg48_OBP0 = value;
- break ;
- case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
- X5028->sp_pal_dmg[1][0] = X5028->sp_pal_dmgT[1][(value & 0x03) >> 0];
- X5028->sp_pal_dmg[1][1] = X5028->sp_pal_dmgT[1][(value & 0x0C) >> 2];
- X5028->sp_pal_dmg[1][2] = X5028->sp_pal_dmgT[1][(value & 0x30) >> 4];
- X5028->sp_pal_dmg[1][3] = X5028->sp_pal_dmgT[1][(value & 0xC0) >> 6];
- X5028->reg49_OBP1 = value;
- break ;
- case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
- X5028->reg68_BCPS = value;
- break ;
- case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
- s = X5028->reg68_BCPS;
- c = s & 0x3F;
- if (c & 1)
- X5028->bg_pal[c >> 3][(c & 7) >> 1]._hi = value;
- else
- X5028->bg_pal[c >> 3][(c & 7) >> 1]._lo = value;
- if (s & 0x80) {
- c = (c + 1) & 0x3F;
- X5028->reg68_BCPS &= ~0x3F;
- X5028->reg68_BCPS |= c;
- }
- X5028->reg69_BCPD = value;
- break;
- case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
- X5028->reg6A_OCPS = value;
- break;
- case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
- s = X5028->reg6A_OCPS;
- c = s & 0x3F;
- if (c & 1)
- X5028->sp_pal[c >> 3][(c & 7) >> 1]._hi = value;
- else
- X5028->sp_pal[c >> 3][(c & 7) >> 1]._lo = value;
- if (s & 0x80) {
- c = (c + 1) & 0x3F;
- X5028->reg6A_OCPS &= ~0x3F;
- X5028->reg6A_OCPS |= c;
- }
- X5028->reg6B_OCPD = value;
- break;
- case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
- for (c = 0; c != 160; c++) {
- s = gameboy_mmu_read (X5028->gb, value * 256 + c);
- ((ks_int8 *)& X5028->sp[0])[c] = s;
- }
- /* OAMDMA ~ 160 us
- OAMDMA is a parallel DMA */
- /* X5028->gb->cpu_clks_dma += X5028->gb->mach_tools->oamdma_clks; */
- X5028->reg46_DMA = value;
- break ;
- case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
- X5028->reg51_HDMA1 = value;
- break;
- case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
- X5028->reg52_HDMA2 = value;
- break;
- case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
- X5028->reg53_HDMA3 = value;
- break;
- case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
- X5028->reg54_HDMA4 = value;
- break;
- case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
- if (value & 0x80) {
- /* H-Blank DMA. **/
- X5028->hdma_src = X5028->reg51_HDMA1 * 256 + X5028->reg52_HDMA2;
- X5028->hdma_dst = X5028->reg53_HDMA3 * 256 + X5028->reg54_HDMA4;
- X5028->hdma_src &= 0xFFF0;
- X5028->hdma_dst &= 0xFFF0;
- X5028->hdma_r16 = value & 0x7F;
- X5028->hdma_r16 ++;
- X5028->hdma_gen = ks_true;
- /* set HDMA uncompelete/active */
- X5028->reg55_HDMA5 &= 0x7F;
- } else {
- /* GDMA **/
- ks_uint16 src = X5028->reg51_HDMA1 * 256 + X5028->reg52_HDMA2;
- ks_uint16 dst = X5028->reg53_HDMA3 * 256 + X5028->reg54_HDMA4;
- ks_uint16 id;
- ks_uint16 K;
- src &= 0xFFF0;
- dst &= 0xFFF0;
- K = value & 0x7F;
- K+= 1;
- /* copy it*/
- for (; id = K; id++) {
- ks_uint16 c;
- for (c =0; c != 16; c++) {
- s = gameboy_mmu_read (X5028->gb, src + id *16 + c);
- gameboy_mmu_write (X5028->gb, dst + id *16 + c, s);
- }
- }
- /* burning OAM clks */
- /* It takes (220 + (n * 7.63)) microseconds in single speed
- and (110 + (n * 7.63)) microseconds in double speed mode */
- X5028->gb->cpu_clks_dma += (X5028->gb->mach_tools->gdma_clks_b
- + X5028->gb->mach_tools->gdma_clks_per16 * (ks_double) K);
- // X5028->reg55_HDMA5 |= 0x80;/* set GDMA compelete/unactive */
- }
- X5028->reg55_HDMA5 = value;
- break;
- case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
- X5028->reg4F_VBK = value;
- break;
- default:
- return;
- }
- }
- ks_uint8 ppu_read_io (struct ppu *X5028, ks_uint16 address) {
- switch (address) {
- case 0xFF40: /* FF40 - LCDC - LCD Control (R/W) **/
- /*Bit 7 - LCD Display Enable (0=Off, 1=On)
- Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
- Bit 5 - Window Display Enable (0=Off, 1=On)
- Bit 4 - BG & Window Tile Data Select (0=8800-97FF, 1=8000-8FFF)
- Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
- Bit 2 - OBJ (Sprite) Size (0=8x8, 1=8x16)
- Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On)
- Bit 0 - BG/Window Display/Priority (0=Off, 1=On)
- */
- return X5028->reg40_LCDC;
- case 0xFF41: /* FF41 - STAT - LCDC Status (R/W) */
- /*Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
- Bit 5 - Mode 2 OAM Interrupt (1=Enable) (Read/Write)
- Bit 4 - Mode 1 V-Blank Interrupt (1=Enable) (Read/Write)
- Bit 3 - Mode 0 H-Blank Interrupt (1=Enable) (Read/Write)
- Bit 2 - Coincidence Flag (0:LYC<>LY, 1:LYC=LY) (Read Only)
- Bit 1-0 - Mode Flag (Mode 0-3, see below) (Read Only)
- 0: During H-Blank
- 1: During V-Blank
- 2: During Searching OAM
- 3: During Transferring Data to LCD Driver
- */
- return X5028->reg41_LCDS;
- case 0xFF42: /* FF42 - SCY - Scroll Y (R/W) */
- return X5028->reg42_SCY;
- case 0xFF43: /* FF43 - SCX - Scroll X (R/W) */
- return X5028->reg43_SCX;
- case 0xFF44: /* FF44 - LY - LCDC Y-Coordinate (R) */
- return X5028->reg44_LY;
- case 0xFF45: /* FF45 - LYC - LY Compare (R/W) */
- return X5028->reg45_LYC;
- case 0xFF4A: /* FF4A - WY - Window Y Position (R/W) */
- return X5028->reg4A_WY;
- case 0xFF4B: /* FF4B - WX - Window X Position minus 7 (R/W) */
- return X5028->reg4B_WX;
- case 0xFF47: /* FF47 - BGP - BG Palette Data (R/W) - Non CGB Mode Only */
- return X5028->reg47_BGP;
- case 0xFF48: /* FF48 - OBP0 - Object Palette 0 Data (R/W) - Non CGB Mode Only */
- return X5028->reg48_OBP0;
- case 0xFF49: /* FF49 - OBP1 - Object Palette 1 Data (R/W) - Non CGB Mode Only */
- return X5028->reg49_OBP1;
- case 0xFF68: /* FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index */
- return X5028->reg68_BCPS;
- case 0xFF69: /* FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data */
- return X5028->reg69_BCPD;
- case 0xFF6A: /* FF6A - OCPS/OBPI - CGB Mode Only - Sprite Palette Index */
- return X5028->reg6A_OCPS;
- case 0xFF6B: /* FF6B - OCPD/OBPD - CGB Mode Only - Sprite Palette Data */
- return X5028->reg6B_OCPD;
- case 0xFF46: /* FF46 - DMA - DMA Transfer and Start Address (R/W) */
- return X5028->reg46_DMA;
- case 0xFF51: /* FF51 - HDMA1 - CGB Mode Only - New DMA Source, High */
- return X5028->reg51_HDMA1;
- case 0xFF52: /* FF52 - HDMA2 - CGB Mode Only - New DMA Source, Low*/
- return X5028->reg52_HDMA2;
- case 0xFF53: /* FF53 - HDMA3 - CGB Mode Only - New DMA Destination, High */
- return X5028->reg53_HDMA3;
- case 0xFF54: /* FF54 - HDMA4 - CGB Mode Only - New DMA Destination, Low*/
- return X5028->reg54_HDMA4;
- case 0xFF55: /* FF55 - HDMA5 - CGB Mode Only - New DMA Length/Mode/Start */
- return X5028->reg55_HDMA5;
- case 0xFF4F: /* FF4F - VBK - CGB Mode Only - VRAM Bank (R/W) */
- return X5028->reg4F_VBK;
- break;
- default:
- return 0xFF;
- }
- }
- static
- void sprite_render (struct ppu *X5028, ks_uint16 scanline) {}
- static
- void background_render (struct ppu *X5028, ks_uint16 scanline) {}
- static /* this method for gameboy color */
- void bgwin_render_cgb (struct ppu *X5028, ks_int16 scanline) {
- struct {
- union { ks_uint16 blk;
- struct { ks_uint8 lo; ks_uint8 hi; }; };
- } chrdat, chrcac;
- /* always scan 168 pixel in every line (21 tiles),
- evenif omfx is ZERO .
- fit buffer offset, so that every time we can scan a complete tile,
- no matter how much omfx is.
- */
- ks_int32 omfx;
- ks_int32 ofx;
- ks_int32 obx;
- ks_int32 omfy;
- ks_int32 ofy;
- ks_int32 vsc;
- ks_uint8 tid;
- ks_int8 tat;
- ks_int32 tidaddr;
- ks_uint16 pixcac;
- ks_uint8 *tdat;
- ks_int32 rxpos;
- ks_uint32 c, q, c2, s;
- ks_int32 c3;
- ks_uint16 *vptrWinDrawStart;
- ks_uint16 *vptrScrollStart;
- /* check current scan region in BG or WINDOW (if WINDOW enable)*/
- if ( X5028->win_stuff != ks_false && (X5028->reg40_LCDC & 0x20)) {
- /* draw window */
- goto windraw;
- } else {
- /* draw background */
- vsc = X5028->uscanR;
- omfx = X5028->reg43_SCX_cac & 7;
- ofx = X5028->reg43_SCX_cac >> 3;
- omfy = X5028->reg42_SCY_cac & 7;
- ofy = X5028->reg42_SCY_cac >> 3;
- ofx = ofx + vsc;
- ofy = ofy + scanline;
- omfy = ofy & 7;
- ofy = ofy >> 3;
- ofx = ofx - (ofx & 32);
- ofy = ofy - (ofy & 32);
- obx = vsc << 3;
- vptrScrollStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-omfx)];
- /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
- tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x08) >> 3) << 10);
- tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
- tid = X5028->ram[tidaddr]; // fetch tileid
- tat = X5028->ram[tidaddr+GB_VRAM_LENGTH]; // fetch tileattr.
- tdat = & X5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
- # if 1
- if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
- tdat = & tdat[tid<<4];
- else //
- tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
- # else
- cti16 = (X5028->reg40_LCDC & 0x10) << 8;
- cti16^= 0x1000;
- tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
- # endif
- # if 1
- if (tat & 0x40) // check vflip ?
- tdat = & tdat[(7-omfy)*2];
- else
- tdat = & tdat[omfy*2];
- # else
- ctu8 = (tat & 0x40) >> 3; // 8
- ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
- tdat = & tdat[(ctu8^omfy)<<1];
- # endif
- chrdat.blk = *(ks_uint16 *)tdat;
- /* check x flip */
- if (tat & 0x20) {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);
- } else {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- }
- rxpos = obx - omfx;
- q = tat&7;
- if (!(X5028->reg40_LCDC & 0x01)) {
- vptrScrollStart = & vptrScrollStart[obx];
- /* When Bit 0 is cleared, the background and window lose their priority,
- the sprites will be always displayed on top of background and window,
- independently of the priority flags in OAM and BG Map attributes.
- */
- for (c = 0; c != 8; c++) {
- s = rxpos+c;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
- vptrScrollStart[c] = X5028->spbline[s];
- else
- vptrScrollStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
- pixcac >>= 2;
- }
- } else if (tat & 0x80) { // BG pri.
- vptrScrollStart = & vptrScrollStart[obx];
- for (c = 0; c != 8; c++) {
- vptrScrollStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
- pixcac >>= 2;
- }
- } else {
- for (c = 0; c != 8; c++) {
- s = rxpos+c;
- c2 = pixcac & 3;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
- if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
- vptrScrollStart[c] = X5028->spbline[s];
- else if ( c2 == 0)
- vptrScrollStart[c] = X5028->spbline[s];
- else
- vptrScrollStart[c] = X5028->bg_pal[q][c2].rgb15;
- else
- vptrScrollStart[c] = X5028->bg_pal[q][c2].rgb15;
- pixcac >>= 2;
- }
- }
- rxpos = obx - omfx; // -7 | 25
- rxpos+= 8; // 1 | 33
- rxpos+= 7; // 8 | 40
- if ( X5028->win_stuff == ks_false && (X5028->reg40_LCDC & 0x20)
- && (X5028->reg4B_WX_cac <= 166 && X5028->reg4B_WX_cac < rxpos) /* check X**/
- && (X5028->reg4A_WY_cac <= scanline && (X5028->reg4A_WY_cac <= 143)))
- {
- X5028->win_stuff = ks_true;
- X5028->xscanR = 0;
- q = 15 - omfx; // 8 | 16-> 9
- // 7->0
- // 8->1
- while (X5028->reg4B_WX_cac >= q) // 15 >= q / 16
- {
- X5028->xscanR ++; // 1 or 2
- q += 8;
- }
- goto windraw;
- }
- }
- return ;
- windraw:
- ofx = X5028->uscanR - X5028->xscanR; // espl x
- c = scanline - X5028->reg4A_WY_cac; // total - y
- omfx = 0;
- omfy = c & 7;
- ofy = c >> 3;
- c3 = ((ks_int8)X5028->reg4B_WX_cac)-7;
- c3 = c3 + (ofx<<3);
- vptrWinDrawStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-0)+c3];
- /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
- tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x40) >> 6) << 10);
- tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
- tid = X5028->ram[tidaddr]; // fetch tileid
- tat = X5028->ram[tidaddr+GB_VRAM_LENGTH]; // fetch tileattr.
- tdat = & X5028->ram[((tat & 0x08)>>3)<<13]; // bank select.
- # if 1
- if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
- tdat = & tdat[tid<<4];
- else //
- tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
- # else
- cti16 = (X5028->reg40_LCDC & 0x10) << 8;
- cti16^= 0x1000;
- tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
- # endif
- # if 1
- if (tat & 0x40) // check vflip ?
- tdat = & tdat[(7-omfy)*2];
- else
- tdat = & tdat[omfy*2];
- # else
- ctu8 = (tat & 0x40) >> 3; // 8
- ctu8 = ctu8 - (ctu8 >> 3);// 0 or 7
- tdat = & tdat[(ctu8^omfy)<<1];
- # endif
- chrdat.blk = *(ks_uint16 *)tdat;
- /* check x flip */
- if (tat & 0x20) {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);
- } else {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- }
- q = tat&7;
- if (!(X5028->reg40_LCDC & 0x01)) {
- for (c = 0; c != 8; c++) {
- s = c3+c;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
- vptrWinDrawStart[c] = X5028->spbline[s];
- else
- vptrWinDrawStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
- pixcac >>= 2;
- }
- } else if (tat & 0x80) { // BG pri.
- for (c = 0; c != 8; c++) {
- vptrWinDrawStart[c] = X5028->bg_pal[q][pixcac & 3].rgb15;
- pixcac >>= 2;
- }
- } else {
- for (c = 0; c != 8; c++) {
- s = c3+c;
- c2 = pixcac & 3;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
- if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
- vptrWinDrawStart[c] = X5028->spbline[s];
- else if ( c2 == 0)
- vptrWinDrawStart[c] = X5028->spbline[s];
- else
- vptrWinDrawStart[c] = X5028->bg_pal[q][c2].rgb15;
- else
- vptrWinDrawStart[c] = X5028->bg_pal[q][c2].rgb15;
- pixcac >>= 2;
- }
- }
- }
- static /* this method for gameboy */
- void bgwin_render_dmg (struct ppu *X5028, ks_int16 scanline) {
- struct {
- union { ks_uint16 blk;
- struct { ks_uint8 lo; ks_uint8 hi; }; };
- } chrdat, chrcac;
- /* always scan 168 pixel in every line (21 tiles),
- evenif omfx is ZERO .
- fit buffer offset, so that every time we can scan a complete tile,
- no matter how much omfx is.
- */
- ks_int32 omfx;
- ks_int32 ofx;
- ks_int32 obx;
- ks_int32 omfy;
- ks_int32 ofy;
- ks_int32 vsc;
- ks_uint8 tid;
- ks_int32 tidaddr;
- ks_uint16 pixcac;
- ks_uint8 *tdat;
- ks_int32 rxpos;
- ks_uint32 c, q, c2, s;
- ks_int32 c3;
- ks_uint16 *vptrWinDrawStart;
- ks_uint16 *vptrScrollStart;
- /* check current scan region in BG or WINDOW (if WINDOW enable)*/
- if ( X5028->win_stuff != ks_false && (X5028->reg40_LCDC & 0x20)) {
- /* draw window */
- goto windraw;
- } else {
- /* draw background */
- vsc = X5028->uscanR;
- omfx = X5028->reg43_SCX_cac & 7;
- ofx = X5028->reg43_SCX_cac >> 3;
- omfy = X5028->reg42_SCY_cac & 7;
- ofy = X5028->reg42_SCY_cac >> 3;
- ofx = ofx + vsc;
- ofy = ofy + scanline;
- omfy = ofy & 7;
- ofy = ofy >> 3;
- ofx = ofx - (ofx & 32);
- ofy = ofy - (ofy & 32);
- obx = vsc << 3;
- vptrScrollStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-omfx)];
- /* pick tileid and attr from ::Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
- tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x08) >> 3) << 10);
- tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
- tid = X5028->ram[tidaddr]; // fetch tileid
- tdat = & X5028->ram[0];
- # if 1
- if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
- tdat = & tdat[tid<<4];
- else //
- tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
- # else
- cti16 = (X5028->reg40_LCDC & 0x10) << 8;
- cti16^= 0x1000;
- tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
- # endif
- tdat = & tdat[omfy*2];
- chrdat.blk = *(ks_uint16 *)tdat;
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- rxpos = obx - omfx;
- if (!(X5028->reg40_LCDC & 0x01)) {
- vptrScrollStart = & vptrScrollStart[obx];
- /* When Bit 0 is cleared, both background and window become blank (white),
- ie. the Window Display Bit (Bit 5) is ignored in that case.
- Only Sprites may still be displayed (if enabled in Bit 1).
- */
- for (c = 0; c != 8; c++) {
- s = rxpos+c;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
- vptrScrollStart[c] = X5028->spbline[s];
- else
- vptrScrollStart[c] = X5028->bg_pal_dmg[0];
- pixcac >>= 2;
- }
- } else {
- for (c = 0; c != 8; c++) {
- s = rxpos+c;
- c2 = pixcac & 3;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
- if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
- vptrScrollStart[c] = X5028->spbline[s];
- else if ( c2 == 0)
- vptrScrollStart[c] = X5028->spbline[s];
- else
- vptrScrollStart[c] = X5028->bg_pal_dmg[pixcac & 3];
- else
- vptrScrollStart[c] = X5028->bg_pal_dmg[pixcac & 3];
- pixcac >>= 2;
- }
- }
- rxpos = obx - omfx; // -7 | 25
- rxpos+= 8; // 1 | 33
- rxpos+= 7; // 8 | 40
- if ( X5028->win_stuff == ks_false && (X5028->reg40_LCDC & 0x20)
- && (X5028->reg4B_WX_cac <= 166 && X5028->reg4B_WX_cac < rxpos) /* check X**/
- && (X5028->reg4A_WY_cac <= scanline && (X5028->reg4A_WY_cac <= 143)))
- {
- X5028->win_stuff = ks_true;
- X5028->xscanR = 0;
- q = 15 - omfx; // 8 | 16-> 9
- // 7->0
- // 8->1
- while (X5028->reg4B_WX_cac >= q) // 15 >= q / 16
- {
- X5028->xscanR ++; // 1 or 2
- q += 8;
- }
- goto windraw;
- }
- }
- return ;
- windraw:
- ofx = X5028->uscanR - X5028->xscanR; // espl x
- c = scanline - X5028->reg4A_WY_cac; // total - y
- omfx = 0;
- omfy = c & 7;
- ofy = c >> 3;
- c3 = ((ks_int8)X5028->reg4B_WX_cac)-7;
- c3 = c3 + (ofx<<3);
- vptrWinDrawStart = & X5028->buf[scanline *(X5028->bufp/sizeof (X5028->buf[0]))+(8-0)+c3];
- /* pick tileid and attr from ::Bit 6 - Tile Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) */
- tidaddr = 0x9C00 - (((X5028->reg40_LCDC & 0x40) >> 6) << 10);
- tidaddr = (tidaddr-GB_VRAM_ADDRESS_START)+(ofy<< 5)+ofx;
- tid = X5028->ram[tidaddr]; // fetch tileid
- tdat = & X5028->ram[0]; // bank select.
- # if 1
- if (X5028->reg40_LCDC & 0x10) // 0x8000 unsigned address
- tdat = & tdat[tid<<4];
- else //
- tdat = & tdat[0x1000+(((ks_int8)tid)<<4)]; // TODO: done.
- # else
- cti16 = (X5028->reg40_LCDC & 0x10) << 8;
- cti16^= 0x1000;
- tdat = & tdat[cti16+((ks_int8)(cti16 >>5)) & (((ks_int8)tid) << 4)];
- # endif
- tdat = & tdat[omfy*2];
- chrdat.blk = *(ks_uint16 *)tdat;
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- if (!(X5028->reg40_LCDC & 0x01)) {
- for (c = 0; c != 8; c++) {
- s = c3+c;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS) // spline ptr to +8
- vptrWinDrawStart[c] = X5028->spbline[s];
- else
- vptrWinDrawStart[c] = X5028->bg_pal_dmg[0];
- }
- } else {
- for (c = 0; c != 8; c++) {
- s = c3+c;
- c2 = pixcac & 3;
- if (X5028->spiline[s] & PIXEL_SPRITE_NOTRANS)
- if (!(X5028->spiline[s] & PIXEL_SPRITE_BACK))
- vptrWinDrawStart[c] = X5028->spbline[s];
- else if ( c2 == 0)
- vptrWinDrawStart[c] = X5028->spbline[s];
- else
- vptrWinDrawStart[c] = X5028->bg_pal_dmg[pixcac & 3];
- else
- vptrWinDrawStart[c] = X5028->bg_pal_dmg[pixcac & 3];
- pixcac >>= 2;
- }
- }
- }
- static /* this method for gameboy color */
- void sprite_render_cgb (struct ppu *X5028, ks_int16 scanline) {
- ks_int16 size_y; /* ?8*16:8*8 */
- /* ks_bool touch;*/
- size_y = (X5028->reg40_LCDC & 0x04)? 16 : 8;
- /* touch = ks_false; */
- /* check sprite in visual scanline */
- for (; X5028->vscan40 < 40; X5028->vscan40++) {
- ks_int16 x;
- ks_int16 y;
- ks_int16 id;
- struct oam *ptr = & X5028->sp[X5028->vscan40];
- y = ptr->y;
- x = ptr->x;
- if (ptr->y == 0 || ptr->y >= 160)
- continue ;
- y -= 16;
- if (scanline >= y && (scanline < (y + size_y))
- && (x != 0 && x < 168)) {
- struct nca {
- union {
- ks_uint16 blk;
- struct {
- ks_uint8 lo;
- ks_uint8 hi;
- };
- };
- } chrdat, chrcac;
- ks_uint16 pixcac ;
- ks_uint8 *chrb;
- /* sprite inc */
- X5028->vscanR++;
- /* pick tile data by tile id and atrr's D3*/
- chrb = & X5028->ram[ptr->attr & 0x08 ? 0x2000 : 0x0000];
- if (size_y != 16)
- chrb = & chrb[ptr->id *16]; // a tile data include 16 bytes
- else
- chrb = & chrb[(ptr->id & 0xFE) *16]; // always pointer tile16's high part in init state .
- /* check Y mapper */
- if (ptr->attr & 0x40) {
- if (size_y == 16) {
- /* sprite16 flip */
- /* get rev offset */
- int calct = scanline - y;
- calct = 7 -calct; /* flip Y in one tile */
- calct *= 2;
- /* get oppo base tile byte8 (^source pos[high or low])*/
- if (calct <= 7) /* high, switch to low */ {
- calct += 16;
- } else { /* low switch to high, nodone, already in high (see line 114).*/
- }
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- } else {
- /* sprite8 flip */
- int calct = scanline - y;
- calct = 7 -calct; /* flip Y */
- calct *= 2;
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- }
- } else {
- int calct = scanline - y;
- calct *= 2;
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- }
- /* mix gbc's pixel (d1d0) */
- /* see GBCPUman.pdf:: 2.8.1. Tiles */
- pixcac = 0; // reset all
- /* check x flip */
- if (ptr->attr & 0x20) {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);
- } else {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- }
- x -= 8;
- for (id = 0; id != 8; id++) {
- ks_uint8 idxpal; /* palette group index, max is8, see OAM struct */
- idxpal = pixcac & 3;
- if (x >= 0 && x <= 159) {
- /* check trans or */
- if (X5028->spi_cac[x+8] & PIXEL_SPRITE_NOTRANS) {
- /* notrans */
- if (X5028->spi_cac[x+8] & PIXEL_SPRITE_BACK) {
- if (!(ptr->attr & 0x80) && idxpal != 0) {
- # if 1 /* maybe error, it's not a big problem. */
- /* cur pick oam is foreground sprite */
- ks_uint16 idxpg = ptr->attr & 7;
- X5028->spb_cac[x+8] = X5028->sp_pal[idxpg][idxpal].rgb15;
- X5028->spi_cac[x+8] = PIXEL_SPRITE_NOTRANS;
- # endif
- }
- } else {
- /* nodone in foreground sprite */
- }
- } else {
- /* trans, write directly */
- ks_uint16 idxpg = ptr->attr & 7;
- X5028->spb_cac[x+8] = X5028->sp_pal[idxpg][idxpal].rgb15;
- X5028->spi_cac[x+8] = 0;
- if (ptr->attr & 0x80) {
- /* background sprite */
- X5028->spi_cac[x+8] |= PIXEL_SPRITE_BACK;
- }
- if (idxpal != 0) {
- /* idxpal is trans color */
- X5028->spi_cac[x+8] |= PIXEL_SPRITE_NOTRANS;
- }
- }
- }
- x ++;
- pixcac >>= 2;
- }
- /* scan one sprite tile compete */
- return ;
- }
- }
- }
- static /* this method for gameboy */
- void sprite_render_dmg (struct ppu *X5028, ks_int16 scanline) {
- ks_int16 size_y; /* ?8*16:8*8 */
- /* ks_bool touch;*/
- size_y = (X5028->reg40_LCDC & 0x04)? 16 : 8;
- /* touch = ks_false; */
- /* check sprite in visual scanline */
- for (; X5028->vscan40 < 40; X5028->vscan40++) {
- ks_int16 x;
- ks_int16 y;
- ks_int16 id;
- struct oam *ptr = & X5028->sp[X5028->vscan40];
- y = ptr->y;
- x = ptr->x;
- if (ptr->y == 0 || ptr->y >= 160)
- continue ;
- y -= 16;
- if (scanline >= y && (scanline < (y + size_y))
- && (x != 0 && x < 168)) {
- struct nca {
- union {
- ks_uint16 blk;
- struct {
- ks_uint8 lo;
- ks_uint8 hi;
- };
- };
- } chrdat, chrcac;
- ks_uint16 pixcac ;
- ks_uint8 *chrb;
- /* sprite inc */
- X5028->vscanR++;
- /* pick tile data by tile id and atrr's D3*/
- chrb = & X5028->ram[ptr->attr & 0x08 ? 0x2000 : 0x0000];
- if (size_y != 16)
- chrb = & chrb[ptr->id *16]; // a tile data include 16 bytes
- else
- chrb = & chrb[(ptr->id & 0xFE) *16]; // always pointer tile16's high part in init state .
- /* check Y mapper */
- if (ptr->attr & 0x40) {
- if (size_y == 16) {
- /* sprite16 flip */
- /* get rev offset */
- int calct = scanline - y;
- calct = 7 -calct; /* flip Y in one tile */
- calct *= 2;
- /* get oppo base tile byte8 (^source pos[high or low])*/
- if (calct <= 7) /* high, switch to low */ {
- calct += 16;
- } else { /* low switch to high, nodone, already in high (see line 114).*/
- }
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- } else {
- /* sprite8 flip */
- int calct = scanline - y;
- calct = 7 -calct; /* flip Y */
- calct *= 2;
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- }
- } else {
- int calct = scanline - y;
- calct *= 2;
- chrdat.blk = *(ks_int16 *)& chrb[calct];
- }
- /* mix gbc's pixel (d1d0) */
- /* see GBCPUman.pdf:: 2.8.1. Tiles */
- pixcac = 0; // reset all
- /* check x flip */
- if (ptr->attr & 0x20) {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo << 7) | (chrcac.hi << 8);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo << 6) | (chrcac.hi << 7);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 4) | (chrcac.hi << 5);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 3) | (chrcac.hi << 4);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo << 1) | (chrcac.hi << 2);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo << 0) | (chrcac.hi << 1);
- } else {
- chrcac.blk = chrdat.blk & 0x8080;
- pixcac = pixcac | (chrcac.lo >> 7) | (chrcac.hi >> 6);
- chrcac.blk = chrdat.blk & 0x4040;
- pixcac = pixcac | (chrcac.lo >> 4) | (chrcac.hi >> 3);
- chrcac.blk = chrdat.blk & 0x2020;
- pixcac = pixcac | (chrcac.lo >> 1) | (chrcac.hi >> 0);
- chrcac.blk = chrdat.blk & 0x1010;
- pixcac = pixcac | (chrcac.lo << 2) | (chrcac.hi << 3);
- chrcac.blk = chrdat.blk & 0x0808;
- pixcac = pixcac | (chrcac.lo << 5) | (chrcac.hi << 6);
- chrcac.blk = chrdat.blk & 0x0404;
- pixcac = pixcac | (chrcac.lo << 8) | (chrcac.hi << 9);
- chrcac.blk = chrdat.blk & 0x0202;
- pixcac = pixcac | (chrcac.lo <<11) | (chrcac.hi <<12);
- chrcac.blk = chrdat.blk & 0x0101;
- pixcac = pixcac | (chrcac.lo <<14) | (chrcac.hi <<15);
- }
- x -= 8;
- for (id = 0; id != 8; id++) {
- ks_uint8 idxpal; /* palette group index, max is8, see OAM struct */
- idxpal = pixcac & 3;
- if (x >= 0 && x <= 159) {
- /* check trans or */
- if (X5028->spi_cac[x+8] & PIXEL_SPRITE_NOTRANS) {
- /* notrans */
- if (X5028->spi_cac[x+8] & PIXEL_SPRITE_BACK) {
- if (!(ptr->attr & 0x80) && idxpal != 0) {
- # if 1 /* maybe error, it's not a big problem. */
- /* cur pick oam is foreground sprite */
- ks_uint16 idxpg = (ptr->attr & 0x10) >> 4;
- X5028->spb_cac[x+8] = X5028->sp_pal_dmg[idxpg][idxpal];
- X5028->spi_cac[x+8] = PIXEL_SPRITE_NOTRANS;
- # endif
- }
- } else {
- /* nodone in foreground sprite */
- }
- } else {
- /* trans, write directly */
- ks_uint16 idxpg = (ptr->attr & 0x10) >> 4;
- X5028->spb_cac[x+8] = X5028->sp_pal_dmg[idxpg][idxpal];
- X5028->spi_cac[x+8] = 0;
- if (ptr->attr & 0x80) {
- /* background sprite */
- X5028->spi_cac[x+8] |= PIXEL_SPRITE_BACK;
- }
- if (idxpal != 0) {
- /* idxpal is trans color */
- X5028->spi_cac[x+8] |= PIXEL_SPRITE_NOTRANS;
- }
- }
- }
- x ++;
- pixcac >>= 2;
- }
- /* scan one sprite tile compete */
- return ; // TODO: gb sprite priority.
- }
- }
- }
- /* XXX:so bad */
- int ppu_run (struct ppu *X5028) {
- ks_int32 scanline;
- ks_int16 interv;
- ks_int16 _nums;
- ks_double clkline;
- if (X5028->gb->cpu_clks_ppu > X5028->gb->mach_tools->frame_cycles) {
- X5028->gb->cpu_clks_ppu -= X5028->gb->mach_tools->frame_cycles; // sub a frame block
- /* at this time and in the scanning of the next frame of the device.
- reset ppu device context */
- /* vblank Interrupt, check touch */
- if (X5028->vbl_flop == ks_false)
- if (X5028->reg41_LCDS & 0x10)
- X5028->gb->reg0F_IF |= IRQ_1;
- else {}
- else {}
- /* reset context */
- X5028->vbl_flop = ks_false;
- X5028->oam_flop = ks_false;
- X5028->hbl_flop = ks_false;
- X5028->interrupt45_flop = ks_false;
- X5028->interrupt45_strike = ks_false;
- X5028->vscan = -1;
- X5028->vscanR = 0;
- X5028->vscan40 = 0;
- X5028->uscan = -1;
- X5028->uscanR = 0;
- X5028->uscan168 = 0;
- X5028->win_stuff = ks_false;
- }
- scanline = (ks_int32) (X5028->gb->cpu_clks_ppu/ X5028->gb->mach_tools->line_cycles);
- clkline = fmod (X5028->gb->cpu_clks_ppu, X5028->gb->mach_tools->line_cycles);
- /* clear mask */
- X5028->reg40_LCDC &= ~LCDCS_MODE_FLAG_ALL_MASK;
- X5028->reg44_LY = scanline;
- /*
- PPU time series
- Mode 0: The LCD controller is in the H-Blank period and
- the CPU can access both the display RAM (8000h-9FFFh)
- and OAM (FE00h-FE9Fh)
- Mode 1: The LCD controller is in the V-Blank period (or the
- display is disabled) and the CPU can access both the
- display RAM (8000h-9FFFh) and OAM (FE00h-FE9Fh)
- Mode 2: The LCD controller is reading from OAM memory.
- The CPU <cannot> access OAM memory (FE00h-FE9Fh)
- during this period.
- Mode 3: The LCD controller is reading from both OAM and VRAM,
- The CPU <cannot> access OAM and VRAM during this period.
- CGB Mode: Cannot access Palette Data (FF69,FF6B) either.
- The following are typical when the display is enabled:
- Mode 2 2_____2_____2_____2_____2_____2___________________2____
- Mode 3 _33____33____33____33____33____33__________________3___
- Mode 0 ___000___000___000___000___000___000________________000
- Mode 1 ____________________________________11111111111111_____
- The Mode Flag goes through the values 0, 2, and 3 at a cycle of about 109uS.
- 0 is present about 48.6uS, 2 about 19uS,
- and 3 about 41uS. This is interrupted every 16.6ms by the VBlank (1).
- The mode flag stays set at 1 for about 1.08 ms.
- Mode 0 is present between 201-207 clks, 2 about 77-83 clks, and 3 about 169-175 clks.
- A complete cycle through these states takes 456 clks.
- VBlank lasts 4560 clks. A complete screen refresh occurs every 70224 clks.)
- */
- /* check scanline and LCDY interrupt */
- if (X5028->line_cac != scanline
- || (X5028->interrupt45_strike != ks_false)) {
- /* setting onrush effective */
- if (X5028->line_cac != scanline) {
- X5028->interrupt45_flop = ks_false; /* reset gate */
- X5028->interrupt45_strike = ks_false; /* close strike function*/
- } /* scanline next, (low to high) for each scanline,
- multiple LCDY interruptions can not be triggered at the same time
- during each vertical synchronization */
- if (X5028->reg45_LYC == scanline) /* check enable ?*/
- /* Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write) */
- if (X5028->reg41_LCDS & 0x40 && !X5028->interrupt45_flop) {
- X5028->interrupt45_strike = ks_false; /* close strike function*/
- X5028->interrupt45_flop = ks_true;
- X5028->gb->reg0F_IF |= IRQ_2;
- } else {}
- else {}
- }
- /* check FF41::Bit 2 Coincidence Flag (0:LYC<>LY, 1:LYC=LY) (Read Only)*/
- if (scanline == X5028->reg45_LYC)
- X5028->reg41_LCDS |= 0x04;
- else X5028->reg41_LCDS &= ~0x04;
- /* check mode */
- if (clkline < X5028->gb->mach_tools->vbl_clk_st) {
- if (clkline > X5028->hbl_clks_st) {
- /* LCD MODE0 - hblank period */
- X5028->reg41_LCDS |= LCDCS_MODE_FLAG_HBLANK;
- /* check edge */
- if (X5028->lcdm_cac != LCDCS_MODE_FLAG_HBLANK) {
- /* oamvram to current, (low to high) */
- while (X5028->uscanR < 21) {
- X5028->bgwin_render (X5028, scanline);
- X5028->uscanR ++;
- }
- /* reset next mode-2 | mode- 3*/
- X5028->oam_flop = ks_false;
- X5028->vscan = -1;
- X5028->vscan40 = 0;
- X5028->uscan = -1;
- X5028->vscanR = 0;
- X5028->uscanR = 0;
- /* check HDMA. **/
- if (scanline >= 0 && scanline <= 143 && X5028->gb->dma_gen) {
- /* copy 16 bytes */
- if (gameboy_hdma_copy (X5028->gb) == 0)
- X5028->gb->dma_gen = ks_false;
- /* add hdma cycles, ~ 8us */
- X5028->hdma_clk += (X5028->gb->mach_tools->clk_ns * 8.0);
- }
- /* in HDMA, no hblank perido */
- X5028->hbl_flop = ks_true;
- }
- /* check hblank interrupt */
- if ((X5028->reg41_LCDS & 0x08) && X5028->hbl_flop == ks_false) {
- X5028->hbl_flop = ks_true;
- X5028->gb->reg0F_IF |= IRQ_2;
- }
- } else if (clkline > X5028->gb->mach_tools->oambg_clk_st) {
- /* LCD MODE3 - oamvram */
- clkline -= X5028->gb->mach_tools->oambg_clk_st; // sub, get start clcks epls.
- X5028->reg41_LCDS |= LCDCS_MODE_FLAG_SERACH_OAMVRAM;
- /* check edge */
- if (X5028->lcdm_cac != LCDCS_MODE_FLAG_SERACH_OAMVRAM) {
- /* check stride sprite render */
- /* get render pos */
- interv = 9;
- /* check render oam *.*/
- if ( X5028->vscan != interv
- && X5028->vscanR < 10
- && X5028->vscan40 < 40) {
- _nums = interv - X5028->vscan;
- X5028->vscan += _nums;
- /* render sprite */
- do
- {
- X5028->sprite_render (X5028, scanline); }
- while (--_nums);
- }
- /* check sprite interrupt */
- if ((X5028->reg41_LCDS & 0x20) && !X5028->oam_flop) {
- X5028->oam_flop = ks_true;
- X5028->gb->reg0F_IF |= IRQ_2;
- }
- X5028->oam_flop = ks_false;
- /* adjust BGOAM clk */
- X5028->hbl_clks_st = (X5028->gb->mach_tools->oambg_b_cycles +
- X5028->vscanR * X5028->gb->mach_tools->oam_clk_add_hbl_per);
- X5028->oambg_clks_divider21 =
- X5028->hbl_clks_st / 21.0;
- X5028->hbl_clks_st += X5028->gb->mach_tools->oam_cycles;
- }
- /* get render pos */
- interv = KS_INT16_CAST (clkline/ X5028->oambg_clks_divider21);
- /* check render bg *.*/
- if (interv != X5028->uscan) {
- _nums = interv - X5028->uscan;
- X5028->uscan += _nums;
- do {
- X5028->bgwin_render (X5028, scanline);
- X5028->uscanR ++;
- } while (--_nums);
- }
- } else {
- /* LCD MODE2 - oam */
- X5028->reg41_LCDS |= LCDCS_MODE_FLAG_SERACH_OAM;
- /* check edge */
- if (X5028->lcdm_cac == LCDCS_MODE_FLAG_HBLANK) {
- /* hblank to current, (low to high), check stride interrupt */
- if (X5028->hbl_flop == ks_false)
- if (X5028->reg41_LCDS & 0x08)
- X5028->gb->reg0F_IF |= IRQ_2;
- else {}
- else {}
- X5028->hbl_flop = ks_false;
- }
- /* get render pos */
- interv = KS_INT16_CAST (clkline/ X5028->gb->mach_tools->oam_clk_pick_per);
- /* check render oam *.*/
- if ( X5028->vscan != interv
- && X5028->vscanR < 10
- && X5028->vscan40 < 40) {
- _nums = interv - X5028->vscan;
- X5028->vscan += _nums;
- /* render sprite */
- do
- {
- X5028->sprite_render (X5028, scanline); }
- while (--_nums);
- }
- /* check sprite interrupt */
- if ((X5028->reg41_LCDS & 0x20) && !X5028->oam_flop) {
- X5028->oam_flop = ks_true;
- X5028->gb->reg0F_IF |= IRQ_2;
- }
- }
- } else {
- /* LCD MODE1 - vblank */
- X5028->reg41_LCDS |= LCDCS_MODE_FLAG_VLANK;
- /* check edge */
- if (X5028->lcdm_cac != LCDCS_MODE_FLAG_VLANK) {
- /* post device render */
- X5028->device_blit (X5028, X5028->obj);
- /* check hblank lack */
- }
- /* check vblank interrupt */
- if ((X5028->reg41_LCDS & 0x10) && !X5028->vbl_flop) {
- X5028->vbl_flop = ks_true;
- X5028->gb->reg0F_IF |= IRQ_1;
- }
- }
- X5028->line_cac = scanline;
- X5028->lcdm_cac = X5028->reg41_LCDS & LCDCS_MODE_FLAG_ALL_MASK;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement