\r
signal reg_p_oam_cpy_cnt : integer range 0 to 255;\r
signal reg_s_oam_cpy_cnt : integer range 0 to 32;\r
-signal spr_eval_cnt : integer range 0 to 3;\r
-\r
+signal reg_spr_eval_cnt : integer range 0 to 3;\r
\r
signal reg_p_oam_ce_n : std_logic;\r
signal reg_p_oam_rd_n : std_logic;\r
signal reg_spr_ptn_sft_start : std_logic_vector (7 downto 0);\r
signal reg_spr_ptn_l : oam_reg_array;\r
signal reg_spr_ptn_h : oam_reg_array;\r
+signal reg_spr_hit : integer range 0 to 1;\r
\r
begin\r
\r
po_v_wr_n <= reg_v_wr_n;\r
po_v_addr <= reg_v_addr;\r
\r
- po_plt_ce_n <= reg_plt_ce_n;\r
- po_plt_rd_n <= reg_plt_rd_n;\r
- po_plt_wr_n <= reg_plt_wr_n;\r
- po_plt_addr <= reg_plt_addr;\r
-\r
--vram r/w selector state machine...\r
- vac_main_stat_p : process (reg_v_cur_state)\r
+ vram_ac_select_p : process (reg_v_cur_state)\r
begin\r
case reg_v_cur_state is\r
when IDLE =>\r
+ reg_v_ce_n <= 'Z';\r
reg_v_rd_n <= 'Z';\r
reg_v_wr_n <= 'Z';\r
when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 =>\r
+ reg_v_ce_n <= '0';\r
reg_v_rd_n <= '1';\r
reg_v_wr_n <= '1';\r
when AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>\r
+ reg_v_ce_n <= '0';\r
reg_v_rd_n <= '0';\r
reg_v_wr_n <= '1';\r
end case;\r
-\r
- case reg_v_cur_state is\r
- when IDLE =>\r
- reg_v_ce_n <= 'Z';\r
- reg_plt_ce_n <= 'Z';\r
- reg_plt_rd_n <= 'Z';\r
- reg_plt_wr_n <= 'Z'; \r
- when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 | AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>\r
- reg_v_ce_n <= '0';\r
- reg_plt_ce_n <= '0';\r
- reg_plt_rd_n <= '0';\r
- reg_plt_wr_n <= '1'; \r
- end case;\r
end process;\r
\r
--vram address state machine...\r
end if;--if (pi_rst_n = '0') then\r
end process;\r
\r
+ po_plt_ce_n <= reg_plt_ce_n;\r
+ po_plt_rd_n <= reg_plt_rd_n;\r
+ po_plt_wr_n <= reg_plt_wr_n;\r
+ po_plt_addr <= reg_plt_addr;\r
+\r
--palette table state machine...\r
plt_ac_p : process (pi_rst_n, pi_base_clk)\r
+ variable spr_i : integer range -1 to 7;\r
+\r
+function is_disp (\r
+ pm_sbg : in std_logic;\r
+ pm_ssp : in std_logic;\r
+ pm_nes_x : in integer range 0 to VGA_W_MAX - 1;\r
+ pm_nes_y : in integer range 0 to VGA_H_MAX - 1\r
+ ) return integer is\r
+begin\r
+ if ((pm_sbg = '1' or pm_ssp = '1') and pm_nes_x < HSCAN and pm_nes_y < VSCAN) then\r
+ return 1;\r
+ else\r
+ return 0;\r
+ end if;\r
+end;\r
+\r
+procedure get_visible_sprite (\r
+ pm_ssp : in std_logic\r
+ ) is\r
+begin\r
+ if (pm_ssp = '1') then\r
+ for i in 0 to 7 loop\r
+ if (reg_spr_x(i) = "00000000" and\r
+ (reg_spr_ptn_h(i)(0) or reg_spr_ptn_l(i)(0)) = '1' ) then\r
+ spr_i := i;\r
+ exit;\r
+ end if;\r
+ end loop;\r
+ else\r
+ spr_i := -1;\r
+ end if;\r
+end;\r
+\r
begin\r
if (pi_rst_n = '0') then\r
+ reg_plt_ce_n <= 'Z';\r
+ reg_plt_rd_n <= 'Z';\r
+ reg_plt_wr_n <= 'Z'; \r
+\r
reg_plt_addr <= (others => 'Z');\r
reg_plt_data <= (others => 'Z');\r
+ reg_spr_hit <= 0;\r
elsif (rising_edge(pi_base_clk)) then\r
\r
reg_plt_data <= pi_plt_data;\r
--shift pattern propageted 1 cycle later.\r
- if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- (reg_v_cur_state = AD_SET2 or reg_v_cur_state = REG_SET2)) then\r
- if (conv_std_logic_vector(reg_nes_y, 9)(4) = '0'\r
- and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then\r
- reg_plt_addr <=\r
- "0" & reg_disp_attr(1 downto 0) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);\r
- elsif (conv_std_logic_vector(reg_nes_y, 9)(4) = '1'\r
- and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then\r
- reg_plt_addr <=\r
- "0" & reg_disp_attr(5 downto 4) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);\r
- else\r
- ---else: no output color >> universal bg color output.\r
- --0x3f00 is the universal bg palette.\r
- reg_plt_addr <= (others => '0');\r
+ if (is_disp(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
+ reg_plt_ce_n <= '0';\r
+ reg_plt_rd_n <= '0';\r
+ reg_plt_wr_n <= '1'; \r
+\r
+ if (reg_v_cur_state = AD_SET2 or reg_v_cur_state = REG_SET2) then\r
+ --check sprite pattern first.\r
+ get_visible_sprite(pi_ppu_mask(PPUSBG));\r
+ if (spr_i >= 0) then\r
+ --sprite display.\r
+ reg_plt_addr <=\r
+ "1" & reg_spr_attr(spr_i)(1 downto 0) & reg_spr_ptn_h(spr_i)(0) & reg_spr_ptn_l(spr_i)(0);\r
+ elsif (conv_std_logic_vector(reg_nes_y, 9)(4) = '0'\r
+ and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then\r
+ reg_plt_addr <=\r
+ "0" & reg_disp_attr(1 downto 0) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);\r
+ elsif (conv_std_logic_vector(reg_nes_y, 9)(4) = '1'\r
+ and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then\r
+ reg_plt_addr <=\r
+ "0" & reg_disp_attr(5 downto 4) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);\r
+ else\r
+ ---no output color >> universal bg color output.\r
+ --0x3f00 is the universal bg palette.\r
+ reg_plt_addr <= (others => '0');\r
+ end if;\r
end if;\r
+ else\r
+ --reset sprite hit.\r
+ reg_spr_hit <= 0;\r
+ --release plt bus.\r
+ reg_plt_ce_n <= 'Z';\r
+ reg_plt_rd_n <= 'Z';\r
+ reg_plt_wr_n <= 'Z'; \r
+ reg_plt_addr <= (others => 'Z');\r
+ reg_plt_data <= (others => 'Z');\r
end if;\r
end if;--if (pi_rst_n = '0') then\r
end process;\r
po_spr_wr_n <= reg_p_oam_wr_n;\r
po_spr_addr <= reg_p_oam_addr;\r
\r
- sprite_main_p : process (pi_rst_n, pi_base_clk)\r
+ sprite_eval_p : process (pi_rst_n, pi_base_clk)\r
function is_s_oam_clear (\r
pm_ssp : in std_logic;\r
pm_nes_x : in integer range 0 to VGA_W_MAX - 1;\r
reg_p_oam_addr <= (others => '0');\r
reg_s_oam_cpy_cnt <= 0;\r
reg_p_oam_cpy_cnt <= 0;\r
- spr_eval_cnt <= 0;\r
+ reg_spr_eval_cnt <= 0;\r
elsif (is_spr_eval(pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
--copy data from primary oam ram.\r
reg_s_oam_addr <= conv_std_logic_vector(reg_s_oam_cpy_cnt, 5);\r
elsif (reg_s_oam_cur_state = REG_SET1) then\r
reg_s_oam_ce_n <= '1';\r
reg_s_oam_wr_n <= '1';\r
- if (spr_eval_cnt = 0 and\r
+ if (reg_spr_eval_cnt = 0 and\r
(pi_spr_data <= reg_nes_y and reg_nes_y < pi_spr_data + 8)) then\r
--evaluate and found sprite in the range.\r
--increment s-oam.\r
reg_s_oam_cpy_cnt <= reg_s_oam_cpy_cnt + 1;\r
reg_p_oam_cpy_cnt <= reg_p_oam_cpy_cnt + 1;\r
- spr_eval_cnt <= spr_eval_cnt + 1;\r
- elsif (spr_eval_cnt = 0) then\r
+ reg_spr_eval_cnt <= reg_spr_eval_cnt + 1;\r
+ elsif (reg_spr_eval_cnt = 0) then\r
--sprite not hit. next entry.\r
reg_p_oam_cpy_cnt <= reg_p_oam_cpy_cnt + 4;\r
else\r
--sprite copying.\r
reg_s_oam_cpy_cnt <= reg_s_oam_cpy_cnt + 1;\r
reg_p_oam_cpy_cnt <= reg_p_oam_cpy_cnt + 1;\r
- if (spr_eval_cnt = 3) then\r
- spr_eval_cnt <= 0;\r
+ if (reg_spr_eval_cnt = 3) then\r
+ reg_spr_eval_cnt <= 0;\r
else\r
- spr_eval_cnt <= spr_eval_cnt + 1;\r
+ reg_spr_eval_cnt <= reg_spr_eval_cnt + 1;\r
end if;\r
end if;\r
end if;\r