end if;\r
end;\r
\r
+function is_spr_pfetch (\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_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
signal reg_vga_x : integer range 0 to VGA_W_MAX - 1;\r
signal reg_vga_y : integer range 0 to VGA_H_MAX - 1;\r
\r
\r
--state change to next.\r
vac_next_stat_p : process (reg_v_cur_state, pi_rnd_en, pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y)\r
-function bg_process (\r
+function is_v_access (\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'and\r
- (pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START) and\r
- (pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then\r
- return 1;\r
+ if ((pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then\r
+ if ((pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START)) then\r
+ if (pm_sbg = '1') then\r
+ return 1;\r
+ else\r
+ return 0;\r
+ end if;\r
+ elsif ((pm_nes_x > HSCAN and pm_nes_x < HSCAN_SPR_MAX)) then\r
+ if (pm_ssp = '1') then\r
+ return 1;\r
+ else\r
+ return 0;\r
+ end if;\r
+ else\r
+ return 0;\r
+ end if;\r
else\r
return 0;\r
end if;\r
end;\r
\r
-function is_idle (\r
- pm_sbg : 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 = '0' or\r
- (pm_nes_x > HSCAN and pm_nes_x < HSCAN_NEXT_START) or\r
- (pm_nes_y >= VSCAN and pm_nes_y < VSCAN_NEXT_START)) then\r
- return 1;\r
- else\r
- return 0;\r
- end if;\r
-end;\r
begin\r
case reg_v_cur_state is\r
when IDLE =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1 and\r
pi_rnd_en(2) = '1' and\r
reg_nes_x mod 8 = 0) then\r
--start vram access process.\r
reg_v_next_state <= reg_v_cur_state;\r
end if;\r
when AD_SET0 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(3) = '1'\r
- ) then\r
- reg_v_next_state <= AD_SET1;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(3) = '1') then\r
+ reg_v_next_state <= AD_SET1;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when AD_SET1 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(0) = '1'\r
- ) then\r
- reg_v_next_state <= AD_SET2;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(0) = '1') then\r
+ reg_v_next_state <= AD_SET2;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when AD_SET2 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(1) = '1'\r
- ) then\r
- reg_v_next_state <= AD_SET3;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(1) = '1') then\r
+ reg_v_next_state <= AD_SET3;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when AD_SET3 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(2) = '1'\r
- ) then\r
- reg_v_next_state <= REG_SET0;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(2) = '1') then\r
+ reg_v_next_state <= REG_SET0;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when REG_SET0 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(3) = '1'\r
- ) then\r
- reg_v_next_state <= REG_SET1;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(3) = '1') then\r
+ reg_v_next_state <= REG_SET1;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when REG_SET1 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(0) = '1'\r
- ) then\r
- reg_v_next_state <= REG_SET2;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(0) = '1') then\r
+ reg_v_next_state <= REG_SET2;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when REG_SET2 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(1) = '1'\r
- ) then\r
- reg_v_next_state <= REG_SET3;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(1) = '1') then\r
+ reg_v_next_state <= REG_SET3;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
when REG_SET3 =>\r
- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
- pi_rnd_en(2) = '1'\r
- ) then\r
- reg_v_next_state <= AD_SET0;\r
- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
- ---when nes_x=257, fall to idle\r
- reg_v_next_state <= IDLE;\r
+ if (is_v_access(pi_ppu_mask(PPUSBG), pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ if (pi_rnd_en(2) = '1') then\r
+ reg_v_next_state <= AD_SET0;\r
+ else\r
+ reg_v_next_state <= reg_v_cur_state;\r
+ end if;\r
else\r
- reg_v_next_state <= reg_v_cur_state;\r
+ reg_v_next_state <= IDLE;\r
end if;\r
end case;\r
end process;\r
elsif (rising_edge(pi_base_clk)) then\r
reg_v_data <= pi_v_data;\r
\r
+ --bg vram fetch.\r
if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
----fetch next tile byte.\r
if (reg_prf_x mod 8 = 1) then\r
& "0" & conv_std_logic_vector(reg_prf_y, 9)(2 downto 0)\r
+ "00000000001000";\r
end if;\r
+\r
+ --sprite pattern fetch.\r
+ elsif (is_spr_pfetch(pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ ----fetch pattern table low byte.\r
+ if (reg_nes_x mod 8 = 5) then\r
+ if (reg_spr_attr((reg_nes_x - 256) / 8)(SPRVFL) = '0') then\r
+ reg_v_addr <= "0" & pi_ppu_ctrl(PPUSPA) & \r
+ reg_spr_tile_tmp & "0" & \r
+ (conv_std_logic_vector(reg_nes_y, 3) + "001" - reg_spr_y_tmp(2 downto 0));\r
+ else\r
+ --flip sprite vertically.\r
+ reg_v_addr <= "0" & pi_ppu_ctrl(PPUSPA) & \r
+ reg_spr_tile_tmp & "0" & \r
+ (reg_spr_y_tmp(2 downto 0) - conv_std_logic_vector(reg_nes_y, 3) - "010");\r
+ end if;\r
+\r
+ ----fetch pattern table high byte.\r
+ elsif (reg_nes_x mod 8 = 7) then\r
+ if (reg_spr_attr((reg_nes_x - 256) / 8)(SPRVFL) = '0') then\r
+ reg_v_addr <= "0" & pi_ppu_ctrl(PPUSPA) & \r
+ reg_spr_tile_tmp & "0" & \r
+ (conv_std_logic_vector(reg_nes_y, 3) + "001" - reg_spr_y_tmp(2 downto 0))\r
+ + "00000000001000";\r
+ else\r
+ --flip sprite vertically.\r
+ reg_v_addr <= "0" & pi_ppu_ctrl(PPUSPA) & \r
+ reg_spr_tile_tmp & "0" & \r
+ (reg_spr_y_tmp(2 downto 0) - conv_std_logic_vector(reg_nes_y, 3) - "010")\r
+ + "00000000001000";\r
+ end if;\r
+ end if;\r
+ else\r
+ reg_v_addr <= (others => 'Z');\r
+ reg_v_data <= (others => 'Z');\r
end if;\r
end if;--if (pi_rst_n = '0') then\r
end process;\r
end if;\r
end if;\r
elsif (is_spr_cpy(pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
- --copy to sprite register.\r
+ --release p-oam access.\r
+ reg_p_oam_ce_n <= '1';\r
+ reg_p_oam_rd_n <= '1';\r
+ reg_p_oam_wr_n <= '1';\r
+ reg_p_oam_addr <= (others => '0');\r
+\r
+ --copy s-oam to sprite register.\r
--257 to 320 = (1 to 64) & 256\r
-->(1 to 64) / 2 & 256.\r
reg_s_oam_ce_n <= '0';\r
reg_spr_x((reg_nes_x - 256) / 8 - 1) <= wr_s_oam_data;\r
end if;\r
end if;\r
+\r
+ --sprite pattern is read from vram.\r
+ if (reg_s_oam_cur_state = REG_SET1) then\r
+ if (reg_nes_x mod 8 = 6) then\r
+ reg_spr_ptn_l((reg_nes_x - 256) / 8) <= pi_v_data;\r
+ elsif (reg_nes_x mod 8 = 0) then\r
+ reg_spr_ptn_h((reg_nes_x - 256) / 8 - 1) <= pi_v_data;\r
+ end if;\r
+ end if;\r
+\r
+ elsif (is_spr_pfetch(pi_ppu_mask(PPUSSP), reg_nes_x, reg_nes_y) = 1) then\r
+ --release s-oam access.\r
+ reg_s_oam_ce_n <= '1';\r
+ reg_s_oam_addr <= (others => 'Z');\r
+ reg_s_oam_data <= (others => 'Z');\r
+ reg_s_oam_wr_n <= '1';\r
+ reg_s_oam_rd_n <= '1';\r
else\r
reg_s_oam_ce_n <= '1';\r
reg_s_oam_rd_n <= '1';\r
end if;\r
end if; --if (rising_edge(emu_ppu_clk)) then\r
end if;--if (rst_n = '0') then\r
- end process;\r
+\r
+ end process;\r
\r
po_ppu_status <= (others => '0');\r
\r