diff --git a/PSX.sv b/PSX.sv index 3f845a0..e7f0d5e 100644 --- a/PSX.sv +++ b/PSX.sv @@ -345,7 +345,7 @@ wire reset_or = RESET | buttons[1] | status[0] | bios_download | exe_download | // 0 1 2 3 4 5 6 7 8 9 // 01234567890123456789012345678901 23456789012345678901234567890123 45678901234567890123456789012345 // 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV -// XXXX XXXXXX XXXXXX XXXXX XX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// XXXX XXXXXX XXXXXX XXXXX XX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX `include "build_id.v" parameter CONF_STR = { @@ -423,9 +423,10 @@ parameter CONF_STR = { "P2O[21],CD Fast Seek,Off,On(U);", "P2O[77:75],CD Speed,Original,Forced 1X(U),Forced 2X(U),Hack 4X(U),Hack 6X(U),Hack 8X(U);", "P2O[78],Limit Max CD Speed,Off,On(U);", + "P2O[93],Backward Seek Hack,Off,On(U);", "P2O[85],RAM(Homebrew),2 MByte,8 MByte(U);", "P2O[90],GPU Slowdown,Off,On(U);", - "P2O[92],Old GPU,Off,On;", + "P2O[92],Old GPU(CXD8514Q),Off,On;", "P2-;", "P2O[28],FPS Overlay,Off,On;", "P2O[74],Error Overlay,Off,On;", @@ -941,7 +942,7 @@ always @(posedge clk_1x) begin if (!padMode[1]) psx_info <= 8'd18; end else if (cdinfo_download_1 && ~cdinfo_download) begin // warning for every unsafe option - if (status[89] || status[80:79] > 0 || status[72] || status[15] || status[21] || status[77:75] > 0 || status[78] || status[85]) begin + if (status[89] || status[80:79] > 0 || status[72] || status[15] || status[21] || status[77:75] > 0 || status[78] || status[85] || status[93]) begin psx_info_req <= 1; psx_info <= 8'd24; end else if (status[40:39] == 2'b00) begin @@ -1109,6 +1110,7 @@ psx .REPRODUCIBLESPUDMA(status[43]), .WIDESCREEN(status[54:53]), .oldGPU(status[92]), + .backwardSeekHack(status[93]), // RAM/BIOS interface .biosregion(biosregion), diff --git a/README.md b/README.md index 369ea5a..f03d430 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ SDRAM of any size is required. * 8 Mbyte mode(from dev units, mostly for homebrew) * Inputs: DualShock, Digital, Analog, Mouse, NeGcon, Wheel, Justifier and Guncon support. * Native Input support through SNAC +* Old GPU (CXD8514Q) ## Bios Rename your playstation bios file (e.g. `scph-1001.bin`/`ps-22a.bin` ) and place it in the `./games/PSX/` folder. @@ -47,7 +48,7 @@ You need to save them either manually in the OSD or turn on autosave. Saving or ## Multiple Disc Games -To swap discs while the game is running, you will need have all of the disc files for the game placed in the same folder. Then when loading a new disc for most games you will need to toggle the Lid Open/Close option to tell the game you have opened the lid and closed it. Example folder structure of a multi disc game: +To swap discs while the game is running, all disc files for the game must be placed in the same folder. When a disc change is required, the core will automatically simulate opening and closing the disc lid. Example folder structure of a multi-disc game: ``` /media/fat/games/PSX/Final Fantasy VII (USA)/Final Fantasy VII (USA) (Disc 1).chd @@ -107,6 +108,11 @@ The higher speed rates are more unstable and require proper storage to be usable Will hold back any new CD data until the game has processed the last data. Mostly useful to prevent CD data overrun when using higher speed modes, leading to overall faster loading times due to less read retries. +- Backward Seek Hack: +Fixes long stutters in Dave Mirra and Thrasher games related to backward CD seeks. +The drive continues reading normally, while sectors ahead of the seek target are temporarily hidden from the CPU until the correct position is reached. +Generally safe, but may affect a small number of sensitive titles (e.g. some Army Men games). + - RAM: 8 Mbyte option from development consoles. Only use for homebrew that requires it, otherwise there is a high chance of crashing games. diff --git a/rtl/cd_top.vhd b/rtl/cd_top.vhd index f7bd5c3..132027c 100644 --- a/rtl/cd_top.vhd +++ b/rtl/cd_top.vhd @@ -22,6 +22,8 @@ entity cd_top is pauseOnCDSlow : in std_logic; region : in std_logic_vector(1 downto 0); region_out : out std_logic_vector(1 downto 0); + + backwardSeekHack : in std_logic; pauseCD : out std_logic := '0'; Pause_idle_cd : out std_logic := '0'; @@ -714,19 +716,24 @@ begin end if; end if; - if (ackRead = '1' or ackRead_data = '1') then - if (CDROM_IRQFLAG = "00001") then -- irq for sector still pending, sector missed - -- will be handled when next sector is fetched from cpu interface - elsif (CDROM_IRQFLAG /= "00000") then -- store sector done if current irq is something else, so CPU will be notified later - pendingDriveIRQ <= "00001"; - pendingDriveResponse <= internalStatus; + if (ackRead = '1' or ackRead_data = '1') then + if (CDROM_IRQFLAG = "00011") then + -- INT3 active: do not overwrite it with INT1 + -- queue INT1 for later delivery + if (pendingDriveIRQ = "00000") then + pendingDriveIRQ <= "00001"; + pendingDriveResponse <= internalStatus; + end if; else + if (CDROM_IRQFLAG /= "00000" and CDROM_IRQFLAG /= "00001") then + pendingDriveIRQ <= CDROM_IRQFLAG; + end if; CDROM_IRQFLAG <= "00001"; if (CDROM_IRQENA(0) = '1') then irqOut <= '1'; end if; ackRead_valid <= '1'; - end if; + end if; end if; if (ackPendingIRQNext = '1') then @@ -1105,11 +1112,11 @@ begin workCommand <= nextCmd; cmdResetXa <= '1'; if (driveState = DRIVE_READING or driveState = DRIVE_PLAYING) then - -- todo: should this be swapped between single speed and double speed? DuckStation has double speed longer and psx spx doc has single speed being longer + -- Matches psx spx doc and DuckStation if (modeReg(7) = '1') then - workDelay <= 2157295 + driveDelay; -- value from psx spx doc - else workDelay <= 1066874 + driveDelay; -- value from psx spx doc + else + workDelay <= 2157295 + driveDelay; -- value from psx spx doc end if; end if; if (driveState = DRIVE_SEEKLOGICAL or driveState = DRIVE_SEEKPHYSICAL or driveState = DRIVE_SEEKIMPLICIT) then @@ -1915,9 +1922,13 @@ begin ackDriveEnd <= '1'; else skipreading := '0'; - if (setLocActive = '1' and (currentLBA - seekLBA) >= 2) then - skipreading := '1'; - end if; + -- optional fix for Dave Mirra / Trasher + if (backwardSeekHack = '1') then + if (setLocActive = '1' and (currentLBA - seekLBA) >= 2) then + skipreading := '1'; + end if; + end if; + if (isAudio = '1') then if (currentTrackBCD = x"00") then -- auto find track number from subheader currentTrackBCD <= nextSubdata(1); @@ -2817,19 +2828,23 @@ begin case (copyState) is when COPY_IDLE => - if (copyData = '1' and ce = '1') then + if (copyData = '1' and ce = '1' and + sectorBufferSizes(to_integer(readSectorPointer)) /= 0) then + copyState <= COPY_FIRST; copyCount <= 0; copyReadAddr <= 0; copyByteCnt <= 0; copySectorPointer <= readSectorPointer; - sectorBufferSizes(to_integer(readSectorPointer)) <= 0; - if (sectorBufferSizes(to_integer(readSectorPointer)) = 0) then - copySize <= RAW_SECTOR_OUTPUT_SIZE / 4; - else - copySize <= sectorBufferSizes(to_integer(readSectorPointer)); - end if; + -- read size before clearing buffer size + if (sectorBufferSizes(to_integer(readSectorPointer)) = 0) then + copySize <= RAW_SECTOR_OUTPUT_SIZE / 4; + else + copySize <= sectorBufferSizes(to_integer(readSectorPointer)); end if; + -- clear buffer size after size was latched + sectorBufferSizes(to_integer(readSectorPointer)) <= 0; + end if; when COPY_FIRST => copyState <= COPY_DATA; diff --git a/rtl/psx_mister.vhd b/rtl/psx_mister.vhd index a7ce2e3..14e2c07 100644 --- a/rtl/psx_mister.vhd +++ b/rtl/psx_mister.vhd @@ -66,6 +66,7 @@ entity psx_mister is REPRODUCIBLESPUDMA : in std_logic; WIDESCREEN : in std_logic_vector(1 downto 0); oldGPU : in std_logic; + backwardSeekHack : in std_logic; -- RAM/BIOS interface biosregion : in std_logic_vector(1 downto 0); ram_refresh : out std_logic; @@ -359,6 +360,7 @@ begin REPRODUCIBLESPUDMA => REPRODUCIBLESPUDMA, WIDESCREEN => WIDESCREEN, oldGPU => oldGPU, + backwardSeekHack => backwardSeekHack, -- RAM/BIOS interface biosregion => biosregion, ram_refresh => ram_refresh, diff --git a/rtl/psx_top.vhd b/rtl/psx_top.vhd index 928b8f9..22245df 100644 --- a/rtl/psx_top.vhd +++ b/rtl/psx_top.vhd @@ -70,6 +70,7 @@ entity psx_top is REPRODUCIBLESPUDMA : in std_logic; WIDESCREEN : in std_logic_vector(1 downto 0); oldGPU : in std_logic; + backwardSeekHack : in std_logic; -- RAM/BIOS interface biosregion : in std_logic_vector(1 downto 0); ram_refresh : out std_logic; @@ -1404,6 +1405,8 @@ begin LIDopen => LIDopen, region => region, region_out => region_out, + + backwardSeekHack => backwardSeekHack, pauseCD => pauseCD, Pause_idle_cd => Pause_idle_cd,