📄 video_vicii_656x_a.vhd
字号:
-- Which sprites are active?
-- -----------------------------------------------------------------------
process(MCnt)
begin
for i in 0 to 7 loop
MActive(i) <= false;
if MCnt(i) /= 63 then
MActive(i) <= true;
end if;
end loop;
end process;
-- -----------------------------------------------------------------------
-- Sprite byte counter
-- Y expansion flipflop
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if phi = '0'
and enaData = '1' then
case vicCycle is
when cycleRefresh5 =>
for i in 0 to 7 loop
MYE_ff(i) <= not MYE_ff(i);
if MActive(i) then
if MYE_ff(i) = MYE(i) then
MCnt(i) <= MCnt(i) + 1;
else
MCnt(i) <= MCnt(i) - 2;
end if;
end if;
end loop;
when others =>
null;
end case;
end if;
for i in 0 to 7 loop
if MYE(i) = '0'
or not MActive(i) then
MYE_ff(i) <= '0';
end if;
end loop;
--
-- On cycleCalcSprite check for each inactive sprite if
-- there is a Y match. Reset MCnt if this is so.
--
-- The RasterX counter is used here to multiplex the compare logic.
-- This saves a few logic cells in the FPGA.
if vicCycle = cycleCalcSprites then
if (not MActive(to_integer(RasterX(2 downto 0))))
and (ME(to_integer(RasterX(2 downto 0))) = '1')
and (rasterY(7 downto 0) = MY(to_integer(RasterX(2 downto 0)))) then
MCnt(to_integer(RasterX(2 downto 0))) <= (others => '0');
end if;
end if;
--
-- Original non-multiplexed version
-- if vicCycle = cycleCalcSprites then
-- for i in 0 to 7 loop
-- if (not MActive(i))
-- and (ME(i) = '1')
-- and (rasterY(7 downto 0) = MY(i)) then
-- MCnt(i) <= (others => '0');
-- end if;
-- end loop;
-- end if;
--
-- Increment MCnt after fetching data.
if enaData = '1' then
if (vicCycle = cycleSpriteA and phi = '1')
or (vicCycle = cycleSpriteB and phi = '0') then
if MActive(to_integer(sprite)) then
MCnt(to_integer(sprite)) <= MCnt(to_integer(sprite)) + 1;
end if;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Sprite pixel Shift register
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if enaPixel = '1' then
-- Enable sprites on the correct X position
for i in 0 to 7 loop
if rasterX = MX(i) then
MShift(i) <= true;
end if;
end loop;
-- Shift one pixel of the sprite from the shift register.
for i in 0 to 7 loop
if MShift(i) then
MXE_ff(i) <= (not MXE_ff(i)) and MXE(i);
if MXE_ff(i) = '0' then
MC_ff(i) <= (not MC_ff(i)) and MC(i);
if MC_ff(i) = '0' then
MCurrentPixel(i) <= MPixels(i)(23 downto 22);
end if;
MPixels(i) <= MPixels(i)(22 downto 0) & '0';
end if;
else
MXE_ff(i) <= '0';
MC_ff(i) <= '0';
MCurrentPixel(i) <= "00";
end if;
end loop;
end if;
--
-- Fill Sprite shift-register with new data.
if enaData = '1' then
if phi = '0'
and vicCycle = cycleSpriteA then
MShift(to_integer(sprite)) <= false;
end if;
if Mactive(to_integer(sprite)) then
if phi = '0' then
case vicCycle is
when cycleSpriteB =>
MPixels(to_integer(sprite)) <= MPixels(to_integer(sprite))(15 downto 0) & di;
when others => null;
end case;
else
case vicCycle is
when cycleSpriteA | cycleSpriteB =>
MPixels(to_integer(sprite)) <= MPixels(to_integer(sprite))(15 downto 0) & di;
when others => null;
end case;
end if;
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Video output
-- -----------------------------------------------------------------------
process(clk)
variable myColor: unsigned(3 downto 0);
variable muxSprite : unsigned(2 downto 0);
variable muxColor : unsigned(1 downto 0);
-- 00 = pixels
-- 01 = MM0
-- 10 = Sprite
-- 11 = MM1
begin
if rising_edge(clk) then
muxColor := "00";
muxSprite := (others => '-');
for i in 7 downto 0 loop
if (MPRIO(i) = '0') or (pixelBgFlag = '0') then
if MC(i) = '1' then
if MCurrentPixel(i) /= "00" then
muxColor := MCurrentPixel(i);
muxSprite := to_unsigned(i, 3);
end if;
elsif MCurrentPixel(i)(1) = '1' then
muxColor := "10";
muxSprite := to_unsigned(i, 3);
end if;
end if;
end loop;
myColor := pixelColor;
case muxColor is
when "01" => myColor := MM0;
when "10" => myColor := spriteColors(to_integer(muxSprite));
when "11" => myColor := MM1;
when others =>
null;
end case;
-- myColor := pixelColor;
-- for i in 7 downto 0 loop
-- if (MPRIO(i) = '0') or (pixelBgFlag = '0') then
-- if MC(i) = '1' then
-- case MCurrentPixel(i) is
-- when "01" => myColor := MM0;
-- when "10" => myColor := spriteColors(i);
-- when "11" => myColor := MM1;
-- when others => null;
-- end case;
-- elsif MCurrentPixel(i)(1) = '1' then
-- myColor := spriteColors(i);
-- end if;
-- end if;
-- end loop;
if enaPixel = '1' then
colorIndex <= myColor;
-- Krestage 3 debugging routine
-- if (cs = '1' and aRegisters = "011100") then
-- colorIndex <= "1111";
-- end if;
if (LRBorder = '1') or (TBBorder = '1') then
colorIndex <= EC;
end if;
if (hBlack = '1') then
colorIndex <= (others => '0');
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Sprite to sprite collision
-- -----------------------------------------------------------------------
spriteSpriteCollision: process(clk)
variable collision : unsigned(7 downto 0);
begin
if rising_edge(clk) then
if resetIMMC = '1' then
IMMC <= '0';
end if;
if (myRd = '1')
and (aRegisters = "011110") then
M2M <= (others => '0');
M2Mhit <= '0';
end if;
for i in 0 to 7 loop
collision(i) := MCurrentPixel(i)(1);
end loop;
if (collision /= "00000000")
and (collision /= "00000001")
and (collision /= "00000010")
and (collision /= "00000100")
and (collision /= "00001000")
and (collision /= "00010000")
and (collision /= "00100000")
and (collision /= "01000000")
and (collision /= "10000000")
and (TBBorder = '0') then
M2M <= M2M or collision;
-- Give collision interrupt but only once until clear of register
if M2Mhit = '0' then
IMMC <= '1';
M2Mhit <= '1';
end if;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Sprite to background collision
-- -----------------------------------------------------------------------
spriteBackgroundCollision: process(clk)
begin
if rising_edge(clk) then
if resetIMBC = '1' then
IMBC <= '0';
end if;
if (myRd = '1')
and (aRegisters = "011111") then
M2D <= (others => '0');
M2Dhit <= '0';
end if;
for i in 0 to 7 loop
if MCurrentPixel(i)(1) = '1'
and pixelBgFlag = '1'
and (TBBorder = '0') then
M2D(i) <= '1';
-- Give collision interrupt but only once until clear of register
if M2Dhit = '0' then
IMBC <= '1';
M2Dhit <= '1';
end if;
end if;
end loop;
end if;
end process;
-- -----------------------------------------------------------------------
-- Generate IRQ signal
-- -----------------------------------------------------------------------
IRQ <= (ILP and ELP) or (IMMC and EMMC) or (IMBC and EMBC) or (IRST and ERST);
-- -----------------------------------------------------------------------
-- Krestage 3 hack
-- -----------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if phi = '1'
and enaData = '1' then
MC <= MCDelay;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Write registers
-- -----------------------------------------------------------------------
writeRegisters: process(clk)
begin
if rising_edge(clk) then
resetLightPenIrq <= '0';
resetIMMC <= '0';
resetIMBC <= '0';
resetRasterIrq <= '0';
--
-- write to registers
if (myWr = '1') then
case aRegisters is
when "000000" => MX(0)(7 downto 0) <= diRegisters;
when "000001" => MY(0) <= diRegisters;
when "000010" => MX(1)(7 downto 0) <= diRegisters;
when "000011" => MY(1) <= diRegisters;
when "000100" => MX(2)(7 downto 0) <= diRegisters;
when "000101" => MY(2) <= diRegisters;
when "000110" => MX(3)(7 downto 0) <= diRegisters;
when "000111" => MY(3) <= diRegisters;
when "001000" => MX(4)(7 downto 0) <= diRegisters;
when "001001" => MY(4) <= diRegisters;
when "001010" => MX(5)(7 downto 0) <= diRegisters;
when "001011" => MY(5) <= diRegisters;
when "001100" => MX(6)(7 downto 0) <= diRegisters;
when "001101" => MY(6) <= diRegisters;
when "001110" => MX(7)(7 downto 0) <= diRegisters;
when "001111" => MY(7) <= diRegisters;
when "010000" =>
MX(0)(8) <= diRegisters(0);
MX(1)(8) <= diRegisters(1);
MX(2)(8) <= diRegisters(2);
MX(3)(8) <= diRegisters(3);
MX(4)(8) <= diRegisters(4);
MX(5)(8) <= diRegisters(5);
MX(6)(8) <= diRegisters(6);
MX(7)(8) <= diRegisters(7);
when "010001" =>
rasterCmp(8) <= diRegisters(7);
ECM <= diRegisters(6);
BMM <= diRegisters(5);
DEN <= diRegisters(4);
RSEL <= diRegisters(3);
yscroll <= diRegisters(2 downto 0);
when "010010" =>
rasterCmp(7 downto 0) <= diRegisters;
when "010101" =>
ME <= diRegisters;
when "010110" =>
RES <= diRegisters(5);
MCM <= diRegisters(4);
CSEL <= diRegisters(3);
xscroll <= diRegisters(2 downto 0);
when "010111" => MYE <= diRegisters;
when "011000" =>
VM <= diRegisters(7 downto 4);
CB <= diRegisters(3 downto 1);
when "011001" =>
resetLightPenIrq <= diRegisters(3);
resetIMMC <= diRegisters(2);
resetIMBC <= diRegisters(1);
resetRasterIrq <= diRegisters(0);
when "011010" =>
ELP <= diRegisters(3);
EMMC <= diRegisters(2);
EMBC <= diRegisters(1);
ERST <= diRegisters(0);
when "011011" => MPRIO <= diRegisters;
when "011100" =>
-- MC <= diRegisters;
MCDelay <= diRegisters; -- !!! Krestage 3 hack
when "011101" => MXE <= diRegisters;
when "100000" => EC <= diRegisters(3 downto 0);
when "100001" => B0C <= diRegisters(3 downto 0);
when "100010" => B1C <= diRegisters(3 downto 0);
when "100011" => B2C <= diRegisters(3 downto 0);
when "100100" => B3C <= diRegisters(3 downto 0);
when "100101" => MM0 <= diRegisters(3 downto 0);
when "100110" => MM1 <= diRegisters(3 downto 0);
when "100111" => spriteColors(0) <= diRegisters(3 downto 0);
when "101000" => spriteColors(1) <= diRegisters(3 downto 0);
when "101001" => spriteColors(2) <= diRegisters(3 downto 0);
when "101010" => spriteColors(3) <= diRegisters(3 downto 0);
when "101011" => spriteColors(4) <= diRegisters(3 downto 0);
when "101100" => spriteColors(5) <= diRegisters(3 downto 0);
when "101101" => spriteColors(6) <= diRegisters(3 downto 0);
when "101110" => spriteColors(7) <= diRegisters(3 downto 0);
when others => null;
end case;
end if;
end if;
end process;
-- -----------------------------------------------------------------------
-- Read registers
-- -----------------------------------------------------------------------
readRegisters: process(clk)
begin
if rising_edge(clk) then
case aRegisters is
when "000000" => do <= MX(0)(7 downto 0);
when "000001" => do <= MY(0);
when "000010" => do <= MX(1)(7 downto 0);
when "000011" => do <= MY(1);
when "000100" => do <= MX(2)(7 downto 0);
when "000101" => do <= MY(2);
when "000110" => do <= MX(3)(7 downto 0);
when "000111" => do <= MY(3);
when "001000" => do <= MX(4)(7 downto 0);
when "001001" => do <= MY(4);
when "001010" => do <= MX(5)(7 downto 0);
when "001011" => do <= MY(5);
when "001100" => do <= MX(6)(7 downto 0);
when "001101" => do <= MY(6);
when "001110" => do <= MX(7)(7 downto 0);
when "001111" => do <= MY(7);
when "010000" =>
do <= MX(7)(8) & MX(6)(8) & MX(5)(8) & MX(4)(8)
& MX(3)(8) & MX(2)(8) & MX(1)(8) & MX(0)(8);
when "010001" => do <= rasterY(8) & ECM & BMM & DEN & RSEL & yscroll;
when "010010" => do <= rasterY(7 downto 0);
when "010011" => do <= lpX;
when "010100" => do <= lpY;
when "010101" => do <= ME;
when "010110" => do <= "11" & RES & MCM & CSEL & xscroll;
when "010111" => do <= MYE;
when "011000" => do <= VM & CB & '1';
when "011001" => do <= IRQ & "111" & ILP & IMMC & IMBC & IRST;
when "011010" => do <= "1111" & ELP & EMMC & EMBC & ERST;
when "011011" => do <= MPRIO;
when "011100" => do <= MC;
when "011101" => do <= MXE;
when "011110" => do <= M2M;
when "011111" => do <= M2D;
when "100000" => do <= "1111" & EC;
when "100001" => do <= "1111" & B0C;
when "100010" => do <= "1111" & B1C;
when "100011" => do <= "1111" & B2C;
when "100100" => do <= "1111" & B3C;
when "100101" => do <= "1111" & MM0;
when "100110" => do <= "1111" & MM1;
when "100111" => do <= "1111" & spriteColors(0);
when "101000" => do <= "1111" & spriteColors(1);
when "101001" => do <= "1111" & spriteColors(2);
when "101010" => do <= "1111" & spriteColors(3);
when "101011" => do <= "1111" & spriteColors(4);
when "101100" => do <= "1111" & spriteColors(5);
when "101101" => do <= "1111" & spriteColors(6);
when "101110" => do <= "1111" & spriteColors(7);
when others => do <= (others => '1');
end case;
end if;
end process;
end architecture;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -