From d0d97125455a742fdb5da06952d5dd0f143e22d6 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 18 Dec 2020 19:27:19 +0100 Subject: [PATCH] gdrom: allow 0-len transfer fixes Pro Pinball Trilogy hang during intro --- core/hw/gdrom/gdromv3.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/core/hw/gdrom/gdromv3.cpp b/core/hw/gdrom/gdromv3.cpp index c4367b33d..63cba4796 100644 --- a/core/hw/gdrom/gdromv3.cpp +++ b/core/hw/gdrom/gdromv3.cpp @@ -1047,17 +1047,18 @@ static int getGDROMTicks() { if (SB_GDST & 1) { - if (SB_GDLEN - SB_GDLEND > 10240) + u32 len = SB_GDLEN == 0 ? 0x02000000 : SB_GDLEN; + if (len - SB_GDLEND > 10240) return 1000000; // Large transfers: GD-ROM transfer rate 1.8 MB/s else - return std::min((u32)10240, SB_GDLEN - SB_GDLEND) * 2; // Small transfers: Max G1 bus rate: 50 MHz x 16 bits + return std::min((u32)10240, len - SB_GDLEND) * 2; // Small transfers: Max G1 bus rate: 50 MHz x 16 bits } else return 0; } //is this needed ? -int GDRomschd(int i, int c, int j) +static int GDRomschd(int i, int c, int j) { if (SecNumber.Status == GD_SEEK) { @@ -1072,11 +1073,8 @@ int GDRomschd(int i, int c, int j) if(!(SB_GDST&1) || !(SB_GDEN &1) || (read_buff.cache_size==0 && read_params.remaining_sectors==0)) return 0; - //TODO : Fix dmaor - u32 dmaor = DMAC_DMAOR.full; - - u32 src = SB_GDSTARD, - len = SB_GDLEN-SB_GDLEND ; + u32 src = SB_GDSTARD; + u32 len = (SB_GDLEN == 0 ? 0x02000000 : SB_GDLEN) - SB_GDLEND; if(SB_GDLEN & 0x1F) { @@ -1091,9 +1089,9 @@ int GDRomschd(int i, int c, int j) len = std::min(len, (u32)10240); // do we need to do this for GDROM DMA? - if(0x8201 != (dmaor &DMAOR_MASK)) + if (0x8201 != (DMAC_DMAOR.full & DMAOR_MASK)) { - INFO_LOG(GDROM, "GDROM: DMAOR has invalid settings (%X)", dmaor); + INFO_LOG(GDROM, "GDROM: DMAOR has invalid settings (%X)", DMAC_DMAOR.full); //return; } @@ -1130,17 +1128,12 @@ int GDRomschd(int i, int c, int j) WARN_LOG(GDROM, "GDROM: SB_GDDIR %X (TO AICA WAVE MEM?)", src); } - //SB_GDLEN = 0x00000000; //13/5/2k7 -> according to docs these regs are not updated by hardware - //SB_GDSTAR = (src + len_backup); + SB_GDLEND = (SB_GDLEND + len_backup) & 0x01ffffe0; + SB_GDSTARD += len_backup; - SB_GDLEND+= len_backup; - SB_GDSTARD+= len_backup;//(src + len_backup)&0x1FFFFFFF; - - if (SB_GDLEND==SB_GDLEN) + if (SB_GDLEND == SB_GDLEN) { - //printf("Streamed GDMA end - %d bytes transferred\n",SB_GDLEND); - SB_GDST=0;//done - // The DMA end interrupt flag + SB_GDST = 0; asic_RaiseInterrupt(holly_GDROM_DMA); } //Read ALL sectors