summaryrefslogtreecommitdiff
path: root/libpcsxcore/mdec.c
diff options
context:
space:
mode:
authorSND\shalma_cp <SND\shalma_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2010-11-10 17:44:32 +0000
committerSND\shalma_cp <SND\shalma_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2010-11-10 17:44:32 +0000
commitb57d7566e450942cfb28fcdb668a1e4d2063d9f1 (patch)
tree523528eb1e82409737d6e0412bd245273b99380e /libpcsxcore/mdec.c
parentc001a0209d37c362f063c2c3fce38adaf7e9548b (diff)
mdec.c
- Rollback MDEC to r59367 until current compatibility is preserved git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@59397 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore/mdec.c')
-rw-r--r--libpcsxcore/mdec.c205
1 files changed, 142 insertions, 63 deletions
diff --git a/libpcsxcore/mdec.c b/libpcsxcore/mdec.c
index 956f9223..c8312ee3 100644
--- a/libpcsxcore/mdec.c
+++ b/libpcsxcore/mdec.c
@@ -189,7 +189,7 @@ void idct(int *block,int used_col) {
// mdec0: command register
#define MDEC0_STP 0x02000000
#define MDEC0_RGB24 0x08000000
-#define MDEC0_SIZE_MASK 0x0000FFFF
+#define MDEC0_SIZE_MASK 0xFFFF
// mdec1: status register
#define MDEC1_BUSY 0x20000000
@@ -202,9 +202,8 @@ void idct(int *block,int used_col) {
struct {
u32 reg0;
u32 reg1;
- u16 *rl;
- u32 rlsize;
- u16 *rl_end;
+ unsigned short *rl;
+ int rlsize;
} mdec;
static int iq_y[DSIZE2], iq_uv[DSIZE2];
@@ -258,8 +257,7 @@ unsigned short *rl2blk(int *blk, unsigned short *mdec_rl) {
rl = SWAP16(*mdec_rl); mdec_rl++;
if (rl == MDEC_END_OF_DATA) break;
k += RLE_RUN(rl) + 1; // skip zero-coefficients
-
- // Fear Effect 2 - lazy way of moving to next block
+
if (k > 63) {
// printf("run lenght exceeded 64 enties\n");
break;
@@ -418,7 +416,6 @@ void mdecInit(void) {
mdec.rl = (u16 *)&psxM[0x100000];
mdec.reg0 = 0;
mdec.reg1 = 0;
- mdec.rlsize = 0;
}
// command register
@@ -444,15 +441,14 @@ void mdecWrite1(u32 data) {
#endif
if (data & MDEC1_RESET) { // mdec reset
mdec.reg0 = 0;
- mdec.reg1 = 0;
- mdec.rlsize = 0;
+ mdec.reg1 = 0;
}
}
u32 mdecRead1(void) {
u32 v = mdec.reg1;
- //v |= (mdec.reg0 & MDEC0_STP) ? MDEC1_STP : 0;
- //v |= (mdec.reg0 & MDEC0_RGB24) ? MDEC1_RGB24 : 0;
+ v |= (mdec.reg0 & MDEC0_STP) ? MDEC1_STP : 0;
+ v |= (mdec.reg0 & MDEC0_RGB24) ? MDEC1_RGB24 : 0;
#ifdef CDR_LOG
CDR_LOG("mdec1 read %08x\n", v);
#endif
@@ -472,21 +468,24 @@ void psxDma0(u32 adr, u32 bcr, u32 chcr) {
return;
}
- mdec.reg1 |= MDEC1_STP;
size = (bcr >> 16) * (bcr & 0xffff);
switch (cmd >> 28) {
case 0x3: // decode
mdec.rl = (u16 *)PSXM(adr);
- mdec.rlsize = (u32)(mdec.reg0 & MDEC0_SIZE_MASK);
- mdec.rl_end = mdec.rl + (mdec.rlsize * 2);
+ mdec.rlsize = mdec.reg0 & MDEC0_SIZE_MASK;
- // input data - enforce no 0-cycle dma
- /* do not seems to have sense
- * simulate the time to achive the command
- */
+ // input data
MDECINDMA_INT( mdec.rlsize );
- break;
+
+
+ // Maximum Force: restart dma1 stall
+ // - fixes movies
+
+ if( HW_DMA1_CHCR & SWAP32(0x01000000) ) {
+ psxDma1( HW_DMA1_MADR, HW_DMA1_BCR, HW_DMA1_CHCR );
+ }
+ return;
case 0x4: // quantization table upload
@@ -499,27 +498,26 @@ void psxDma0(u32 adr, u32 bcr, u32 chcr) {
iqtab_init(iq_uv, p + 64);
}
- /* simulate the time to achive the command */
MDECINDMA_INT( size / 4 );
- break;
+ return;
case 0x6: // cosine table
// printf("mdec cosine table\n");
- /* simulate the time to achive the command */
MDECINDMA_INT( size / 4 );
- break;
+ return;
default:
// printf("mdec unknown command\n");
break;
}
+
+ HW_DMA0_CHCR &= SWAP32(~0x01000000);
+ DMA_INTERRUPT(0);
}
void mdec0Interrupt()
{
- /* the command on dma0 is done now */
- mdec.reg1 &= ~MDEC1_STP;
HW_DMA0_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(0);
}
@@ -528,45 +526,84 @@ void psxDma1(u32 adr, u32 bcr, u32 chcr) {
int blk[DSIZE2 * 6];
unsigned short *image;
int size, dmacnt;
- //u8 *in_ptr;
+ u8 *in_ptr;
#ifdef CDR_LOG
CDR_LOG("DMA1 %08x %08x %08x (cmd = %08x)\n", adr, bcr, chcr, mdec.reg0);
#endif
if (chcr != 0x01000200) return;
+
- /* now the mdec is busy till all data are decoded */
- mdec.reg1 |= MDEC1_BUSY;
+ in_ptr = (u8 *)mdec.rl;
size = (bcr >> 16) * (bcr & 0xffff);
+
+
+ // Maximum Force: stall dma1 until dma0 sent
+ // - fixes movies
+
+ if( mdec.rlsize <= 0 )
+ {
+ // signal immediate stall
+ mdec.reg1 &= ~MDEC1_BUSY;
+ return;
+ }
+
image = (u16 *)PSXM(adr);
if (mdec.reg0 & MDEC0_RGB24) { // 15-b decoding
- size = size / ((16 * 16) / 2);
- dmacnt = size;
+ dmacnt = 0;
+
+
+ size = size / ((16 * 16) / 2);
for (; size > 0; size--, image += (16 * 16)) {
mdec.rl = rl2blk(blk, mdec.rl);
yuv2rgb15(blk, image);
+
+ dmacnt++;
}
+
+
// macroblock size
dmacnt *= (16 * 16 * 2);
+
// macroblock cycles
dmacnt *= 1;
} else { // 24-b decoding
+ dmacnt = 0;
+
+
size = size / ((24 * 16) / 2);
- dmacnt = size;
for (; size > 0; size--, image += (24 * 16)) {
mdec.rl = rl2blk(blk, mdec.rl);
yuv2rgb24(blk, (u8 *)image);
- }
+
+ dmacnt++;
+ }
+
// macroblock size
dmacnt *= (16 * 16 * 3);
+
// macroblock cycles
dmacnt *= 1;
}
+
+ // Fear Effect 2: check for input drain, stalling output
+ // - fixes art gallery corruption, auto-pause
+
+ mdec.rlsize -= ((u8 *) mdec.rl - in_ptr) / 4;
+
+#ifdef CDR_LOG
+ if( mdec.rlsize < 0 )
+ {
+ CDR_LOG( "dma1 infinite stall - no input left!!\n" );
+ }
+#endif
+
+
/*
current mblock speed = 1 cycle / byte
@@ -576,48 +613,90 @@ void psxDma1(u32 adr, u32 bcr, u32 chcr) {
Rebel Assault 2 = ~0-1 macroblock cycles
- no hangs, chopped movies
+
Shadow Madness = ~1-4 macroblock cycles
- smoother videos, fixes boot
*/
- /* Similate the time to decode blocks */
MDECOUTDMA_INT( dmacnt );
+
+
+ mdec.reg1 |= MDEC1_BUSY;
}
void mdec1Interrupt() {
#ifdef CDR_LOG
CDR_LOG("mdec1Interrupt\n");
#endif
- /* Author: gschwind
- *
- * in that case we have done all decoding stuff
- * Note that : each block end with 0xfe00 flags
- * the list of blocks end with the same 0xfe00 flags
- * data loock like :
- *
- * data block ...
- * 0xfe00
- * data block ...
- * 0xfe00
- * a lost of block ..
- *
- * 0xfe00
- * the last block
- * 0xfe00
- * 0xfe00
- *
- * the mdec.rl >= mdec.rl_end sanity check.
- *
- */
- if(mdec.rl >= mdec.rl_end) {
- mdec.reg1 &= ~ MDEC1_BUSY;
- } else if(SWAP16(*(mdec.rl)) == 0xfe00) {
- mdec.reg1 &= ~ MDEC1_BUSY;
- }
-
- HW_DMA1_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(1);
- return;
+ if (HW_DMA1_CHCR & SWAP32(0x01000000)) {
+ // Fear Effect 2: stall dma1 forever
+ // - fixes art gallery
+ if( mdec.rlsize < 0 )
+ {
+ mdec.reg1 &= ~MDEC1_BUSY;
+ return;
+ }
+
+
+ // Set a fixed value totaly arbitrarie another sound value is
+ // PSXCLK / 60 or PSXCLK / 50 since the bug happened at end of frame.
+ // PSXCLK / 500 seems good for FF9.
+ // CAUTION: commented interrupt-handling may lead to problems, keep an eye ;-)
+ MDECOUTDMA_INT(PSXCLK / 400);
+// MDECOUTDMA_INT(psxRegs.intCycle[PSXINT_MDECOUTDMA].cycle * 8);
+
+ HW_DMA1_CHCR &= SWAP32(~0x01000000);
+ DMA_INTERRUPT(1);
+
+
+#if 0
+ /*
+ Destruction Derby Raw: stall 4+ blocks
+ - Fixes boot movies
+
+ Final Fantasy 9: stall 4+ blocks
+ - Prevent Dali video from infinite stall, corruption
+
+ Rebel Assault 2: stall 8+ blocks
+ - Fixes boot movies, stage 6 play
+ */
+
+ {
+ int blk[DSIZE2 * 6];
+ int lcv, size;
+ u16 *img;
+
+
+#define PRECACHE_STALL 8
+
+ img = mdec.rl;
+ size = mdec.rlsize * 4;
+ for( lcv = 0; lcv < PRECACHE_STALL; lcv++ ) {
+ u8 *old_img;
+
+ old_img = (u8 *) img;
+ img = rl2blk(blk, img);
+
+ size -= (u8 *) img - old_img;
+ if( size < 0 ) break;
+ }
+
+ // pre-cache input stall - turn off mdec
+ if( size < 0 )
+ {
+ #ifdef CDR_LOG
+ CDR_LOG( "BUSY STALL %X [IN = %X, SIZE = %X]\n",
+ lcv, ((u8 *)img - (u8 *)mdec.rl)/4, mdec.rlsize );
+ #endif
+
+ // drain input + wait before timing out
+ MDECOUTDMA_INT( (PRECACHE_STALL * 1) * (16 * 16 * 3) );
+ }
+ }
+#endif
+ } else {
+ mdec.reg1 &= ~MDEC1_BUSY;
+ }
}
int mdecFreeze(gzFile f, int Mode) {