using System; using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { public class PPU { public GBHawk Core { get; set; } public uint[] BG_palette = new uint[32]; public uint[] OBJ_palette = new uint[32]; public bool HDMA_active; // register variables public byte LCDC; public byte STAT; public byte scroll_y; public byte scroll_x; public byte LY; public byte LY_actual; public byte LY_inc; public byte LYC; public byte DMA_addr; public byte BGP; public byte obj_pal_0; public byte obj_pal_1; public byte window_y; public byte window_x; public bool DMA_start; public int DMA_clock; public int DMA_inc; public byte DMA_byte; // state variables public int cycle; public bool LYC_INT; public bool HBL_INT; public bool VBL_INT; public bool OAM_INT; public bool LCD_was_off; public bool stat_line; public bool stat_line_old; public int hbl_countdown; // OAM scan public bool DMA_OAM_access; public bool OAM_access_read; public bool OAM_access_write; public int OAM_scan_index; public int SL_sprites_index; public int[] SL_sprites = new int[40]; public int write_sprite; public bool no_scan; // render public bool VRAM_access_read; public bool VRAM_access_write; public int read_case; public int internal_cycle; public int y_tile; public int y_scroll_offset; public int x_tile; public int x_scroll_offset; public int tile_byte; public int sprite_fetch_cycles; public bool fetch_sprite; public bool fetch_sprite_01; public bool fetch_sprite_4; public bool going_to_fetch; public bool first_fetch; public int sprite_fetch_counter; public byte[] sprite_attr_list = new byte[160]; public byte[] sprite_pixel_list = new byte[160]; public byte[] sprite_present_list = new byte[160]; public int temp_fetch; public int tile_inc; public bool pre_render; public byte[] tile_data = new byte[3]; public byte[] tile_data_latch = new byte[3]; public int latch_counter; public bool latch_new_data; public int render_counter; public int render_offset; public int pixel_counter; public int pixel; public byte[] sprite_data = new byte[2]; public byte[] sprite_sel = new byte[2]; public int sl_use_index; public bool no_sprites; public int[] SL_sprites_ordered = new int[40]; // (x_end, data_low, data_high, attr) public int evaled_sprites; public int sprite_ordered_index; public bool blank_frame; public bool window_latch; // windowing state public int window_counter; public bool window_pre_render; public bool window_started; public bool window_is_reset; public int window_tile_inc; public int window_y_tile; public int window_x_tile; public int window_y_tile_inc; public int window_x_latch; public virtual byte ReadReg(int addr) { return 0; } public virtual void WriteReg(int addr, byte value) { } public virtual void tick() { } // might be needed, not sure yet public virtual void latch_delay() { } public virtual void render(int render_cycle) { } public virtual void process_sprite() { } // normal DMA moves twice as fast in double speed mode on GBC // So give it it's own function so we can seperate it from PPU tick public virtual void DMA_tick() { } public virtual void OAM_scan(int OAM_cycle) { } public virtual void Reset() { } // order sprites according to x coordinate // note that for sprites of equal x coordinate, priority goes to first on the list public virtual void reorder_and_assemble_sprites() { } public virtual void SyncState(Serializer ser) { ser.Sync("BG_palette", ref BG_palette, false); ser.Sync("OBJ_palette", ref OBJ_palette, false); ser.Sync("HDMA_active", ref HDMA_active); ser.Sync("LCDC", ref LCDC); ser.Sync("STAT", ref STAT); ser.Sync("scroll_y", ref scroll_y); ser.Sync("scroll_x", ref scroll_x); ser.Sync("LY", ref LY); ser.Sync("LY_actual", ref LY_actual); ser.Sync("LYinc", ref LY_inc); ser.Sync("LYC", ref LYC); ser.Sync("DMA_addr", ref DMA_addr); ser.Sync("BGP", ref BGP); ser.Sync("obj_pal_0", ref obj_pal_0); ser.Sync("obj_pal_1", ref obj_pal_1); ser.Sync("window_y", ref window_y); ser.Sync("window_x", ref window_x); ser.Sync("DMA_start", ref DMA_start); ser.Sync("DMA_clock", ref DMA_clock); ser.Sync("DMA_inc", ref DMA_inc); ser.Sync("DMA_byte", ref DMA_byte); ser.Sync("cycle", ref cycle); ser.Sync("LYC_INT", ref LYC_INT); ser.Sync("HBL_INT", ref HBL_INT); ser.Sync("VBL_INT", ref VBL_INT); ser.Sync("OAM_INT", ref OAM_INT); ser.Sync("stat_line", ref stat_line); ser.Sync("stat_line_old", ref stat_line_old); ser.Sync("hbl_countdown", ref hbl_countdown); ser.Sync("LCD_was_off", ref LCD_was_off); ser.Sync("OAM_scan_index", ref OAM_scan_index); ser.Sync("SL_sprites_index", ref SL_sprites_index); ser.Sync("SL_sprites", ref SL_sprites, false); ser.Sync("write_sprite", ref write_sprite); ser.Sync("no_scan", ref no_scan); ser.Sync("DMA_OAM_access", ref DMA_OAM_access); ser.Sync("OAM_access_read", ref OAM_access_read); ser.Sync("OAM_access_write", ref OAM_access_write); ser.Sync("VRAM_access_read", ref VRAM_access_read); ser.Sync("VRAM_access_write", ref VRAM_access_write); ser.Sync("read_case", ref read_case); ser.Sync("internal_cycle", ref internal_cycle); ser.Sync("y_tile", ref y_tile); ser.Sync("y_scroll_offset", ref y_scroll_offset); ser.Sync("x_tile", ref x_tile); ser.Sync("x_scroll_offset", ref x_scroll_offset); ser.Sync("tile_byte", ref tile_byte); ser.Sync("sprite_fetch_cycles", ref sprite_fetch_cycles); ser.Sync("fetch_sprite", ref fetch_sprite); ser.Sync("fetch_sprite_01", ref fetch_sprite_01); ser.Sync("fetch_sprite_4", ref fetch_sprite_4); ser.Sync("going_to_fetch", ref going_to_fetch); ser.Sync("first_fetch", ref first_fetch); ser.Sync("sprite_fetch_counter", ref sprite_fetch_counter); ser.Sync("sprite_attr_list", ref sprite_attr_list, false); ser.Sync("sprite_pixel_list", ref sprite_pixel_list, false); ser.Sync("sprite_present_list", ref sprite_present_list, false); ser.Sync("temp_fetch", ref temp_fetch); ser.Sync("tile_inc", ref tile_inc); ser.Sync("pre_render", ref pre_render); ser.Sync("tile_data", ref tile_data, false); ser.Sync("tile_data_latch", ref tile_data_latch, false); ser.Sync("latch_counter", ref latch_counter); ser.Sync("latch_new_data", ref latch_new_data); ser.Sync("render_counter", ref render_counter); ser.Sync("render_offset", ref render_offset); ser.Sync("pixel_counter", ref pixel_counter); ser.Sync("pixel", ref pixel); ser.Sync("sprite_data", ref sprite_data, false); ser.Sync("sl_use_index", ref sl_use_index); ser.Sync("sprite_sel", ref sprite_sel, false); ser.Sync("no_sprites", ref no_sprites); ser.Sync("evaled_sprites", ref evaled_sprites); ser.Sync("SL_sprites_ordered", ref SL_sprites_ordered, false); ser.Sync("sprite_ordered_index", ref sprite_ordered_index); ser.Sync("blank_frame", ref blank_frame); ser.Sync("window_latch", ref window_latch); ser.Sync("window_counter", ref window_counter); ser.Sync("window_pre_render", ref window_pre_render); ser.Sync("window_started", ref window_started); ser.Sync("window_is_reset", ref window_is_reset); ser.Sync("window_tile_inc", ref window_tile_inc); ser.Sync("window_y_tile", ref window_y_tile); ser.Sync("window_x_tile", ref window_x_tile); ser.Sync("window_y_tile_inc", ref window_y_tile_inc); ser.Sync("window_x_latch", ref window_x_latch); } } }