mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +00:00
53c810: do not increment DSP when executing interrupt instruction. Fixes invalid polygons in Virtua Fighter 3. Thanks to Ian Curtis for discovering that the polygons were incorrectly-copied garbage.
This commit is contained in:
parent
8e6712d2c7
commit
8f87bb1698
|
@ -24,8 +24,8 @@
|
|||
*
|
||||
* Implementation of the C53C810 class: NCR 53C810 SCSI controller.
|
||||
*
|
||||
* TO-DO List:
|
||||
* -----------
|
||||
* Notes:
|
||||
* ------
|
||||
* - VF3 does something weird: it writes DSP (triggering automatic code
|
||||
* execution because MAN=0) and THEN sets single step mode, expecting an
|
||||
* interrupt to occur. I suspect this is incorrect operation and that
|
||||
|
@ -39,12 +39,7 @@
|
|||
* jerky graphics). Enabling automatic execution and also allowing single
|
||||
* stepping to occur when the processor is halted seems to work, but it
|
||||
* causes invalid instructions to be hit each time.
|
||||
* - Check to ensure the invalid instructions hit above would never be decoded
|
||||
* as real SCRIPTS instructions (in some cases, appears they can be...)
|
||||
* - Is the SIP bit supposed to be set after single stepping?
|
||||
* - pg 2-22 (42) of the manual has description of how to clear interrupts.
|
||||
* - Another way to fix VF3 is to just set the single-step and DMA interrupt
|
||||
* flags at all times.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -96,23 +91,22 @@ void C53C810::LoadState(CBlockFile *SaveState)
|
|||
SCRIPTS Emulation
|
||||
******************************************************************************/
|
||||
|
||||
static inline UINT32 Fetch(struct NCR53C810Context *Ctx)
|
||||
static inline UINT32 Fetch(struct NCR53C810Context *Ctx, UINT32 offset)
|
||||
{
|
||||
UINT32 data = Ctx->Bus->Read32(Ctx->regDSP);
|
||||
Ctx->regDSP += 4;
|
||||
UINT32 data = Ctx->Bus->Read32(Ctx->regDSP + offset);
|
||||
return FLIPENDIAN32(data); // remember: bus is big endian, need to convert to little endian
|
||||
}
|
||||
|
||||
//TO-DO: check if this ever occurs in single-step mode (if so, we would need to stack interrupts)
|
||||
//TODO: what happens if interrupt is executed in single step mode?
|
||||
static bool SCRIPTS_Int_IntFly(struct NCR53C810Context *Ctx)
|
||||
{
|
||||
Ctx->halt = true; // halt SCRIPTS execution
|
||||
Ctx->regISTAT |= 1; // DMA interrupt pending
|
||||
Ctx->regDSTAT |= 4; // SCRIPTS interrupt instruction received
|
||||
Ctx->IRQ->Assert(Ctx->scsiIRQ);
|
||||
|
||||
if ((Ctx->regDBC&0x100000)) // INTFLY
|
||||
return ErrorLog("53C810 INTFLY instruction not emulated!");
|
||||
// DSP not incremented (VF3 relies on this)
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
|
@ -123,9 +117,9 @@ static bool SCRIPTS_MoveMemory(struct NCR53C810Context *Ctx)
|
|||
|
||||
// Get operands
|
||||
src = Ctx->regDSPS;
|
||||
dest = Ctx->regTEMP = Fetch(Ctx);
|
||||
dest = Ctx->regTEMP = Fetch(Ctx, 8); // word 3
|
||||
numBytes = Ctx->regDBC;
|
||||
// not implemented: illegal instruction interrupt when src and dest are not aligned the same way
|
||||
// Not implemented: illegal instruction interrupt when src and dest are not aligned the same way
|
||||
|
||||
DebugLog("53C810: Move Memory %08X -> %08X, %X\n", src, dest, numBytes);
|
||||
|
||||
|
@ -149,6 +143,7 @@ static bool SCRIPTS_MoveMemory(struct NCR53C810Context *Ctx)
|
|||
Ctx->regDBC = 0;
|
||||
Ctx->regDSPS = src;
|
||||
Ctx->regTEMP = dest;
|
||||
Ctx->regDSP += 12;
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -168,16 +163,16 @@ void C53C810::Run(bool singleStep)
|
|||
if (singleStep)// && !Ctx.halt)
|
||||
{
|
||||
// Fetch instruction (first two words are always fetched)
|
||||
op = Fetch(&Ctx); // word 1
|
||||
op = Fetch(&Ctx, 0); // word 1
|
||||
Ctx.regDBC = op&0x00FFFFFF;
|
||||
Ctx.regDCMD = (op>>24)&0xFF;
|
||||
Ctx.regDSPS = Fetch(&Ctx); // word 2
|
||||
Ctx.regDSPS = Fetch(&Ctx, 4); // word 2
|
||||
|
||||
// Single step
|
||||
OpTable[Ctx.regDCMD](&Ctx);
|
||||
|
||||
// Issue IRQ and finish
|
||||
Ctx.regISTAT |= 3; // DMA interrupt pending (NOTE: should SIP be set? I don't think so...)
|
||||
Ctx.regISTAT |= 1; // DMA interrupt pending
|
||||
Ctx.regDSTAT |= 8; // single step interrupt
|
||||
Ctx.IRQ->Assert(Ctx.scsiIRQ); // generate an interrupt
|
||||
DebugLog("53C810: Asserted IRQ\n");
|
||||
|
@ -188,10 +183,10 @@ void C53C810::Run(bool singleStep)
|
|||
for (i = 0; (i < 100) && !Ctx.halt; i++)
|
||||
{
|
||||
// Fetch instruction (first two words are always fetched)
|
||||
op = Fetch(&Ctx); // word 1
|
||||
op = Fetch(&Ctx, 0); // word 1
|
||||
Ctx.regDBC = op&0x00FFFFFF;
|
||||
Ctx.regDCMD = (op>>24)&0xFF;
|
||||
Ctx.regDSPS = Fetch(&Ctx); // word 2
|
||||
Ctx.regDSPS = Fetch(&Ctx, 4); // word 2
|
||||
|
||||
// Execute!
|
||||
if (OpTable[Ctx.regDCMD](&Ctx) != OKAY)
|
||||
|
|
Loading…
Reference in a new issue