diff --git a/desmume/src/FIFO.cpp b/desmume/src/FIFO.cpp
index 324e2e90f..4e2f5577e 100644
--- a/desmume/src/FIFO.cpp
+++ b/desmume/src/FIFO.cpp
@@ -1,6 +1,6 @@
-/* Copyright (C) 2006 yopyop
+/* Copyright 2006 yopyop
Copyright 2007 shash
- Copyright 2007-2010 DeSmuME team
+ Copyright 2007-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -169,6 +169,7 @@ void GFX_PIPEclear()
gxPIPE.head = 0;
gxPIPE.tail = 0;
gxPIPE.size = 0;
+ gxFIFO.matrix_stack_op_size = 0;
}
void GFX_FIFOclear()
@@ -176,6 +177,7 @@ void GFX_FIFOclear()
gxFIFO.head = 0;
gxFIFO.tail = 0;
gxFIFO.size = 0;
+ gxFIFO.matrix_stack_op_size = 0;
}
static void GXF_FIFO_handleEvents()
@@ -189,6 +191,9 @@ static void GXF_FIFO_handleEvents()
bool emptychange = MMU_new.gxstat.fifo_empty ^ empty;
MMU_new.gxstat.fifo_empty = empty;
+
+ MMU_new.gxstat.sb = gxFIFO.matrix_stack_op_size != 0;
+
if(emptychange||lowchange) NDS_Reschedule();
}
@@ -220,6 +225,12 @@ void GFX_FIFOsend(u8 cmd, u32 param)
gxFIFO.size++;
if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0;
+ //if a matrix op is entering the pipeline, do accounting for it
+ //(this is tested by wild west, which will jam a few ops in the fifo and then wait for the matrix stack to be
+ //un-busy so it can read back the current matrix stack position)
+ if((cmd & 0xF0) == 0x10)
+ gxFIFO.matrix_stack_op_size++;
+
if(gxFIFO.size>=HACK_GXIFO_SIZE) {
printf("--FIFO FULL-- : %d\n",gxFIFO.size);
}
@@ -245,6 +256,14 @@ BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
*cmd = gxFIFO.cmd[gxFIFO.head];
*param = gxFIFO.param[gxFIFO.head];
+ //see the associated increment in another function
+ if((*cmd & 0xF0) == 0x10)
+ {
+ gxFIFO.matrix_stack_op_size--;
+ if(gxFIFO.matrix_stack_op_size>0x10000000)
+ printf("bad news disaster in matrix_stack_op_size\n");
+ }
+
gxFIFO.head++;
gxFIFO.size--;
if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0;
diff --git a/desmume/src/FIFO.h b/desmume/src/FIFO.h
index 40c1057d3..f96c4fa47 100644
--- a/desmume/src/FIFO.h
+++ b/desmume/src/FIFO.h
@@ -1,25 +1,20 @@
-/* Copyright (C) 2006 yopyop
- yopyop156@ifrance.com
- yopyop156.ifrance.com
+/*
+ Copyright 2006 yopyop
+ Copyright 2007 shash
+ Copyright 2007-2011 DeSmuME team
- Copyright 2007 shash
- Copyright 2007-2009 DeSmuME team
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
- This file is part of DeSmuME
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- DeSmuME is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- DeSmuME is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DeSmuME; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ You should have received a copy of the GNU General Public License
+ along with the this software. If not, see .
*/
@@ -59,6 +54,7 @@ typedef struct
u32 head; // start position
u32 tail; // tail
u32 size; // size FIFO buffer
+ u32 matrix_stack_op_size; //number of matrix stack items in the fifo (stack is busy when this is nonzero)
} GFX_FIFO;
typedef struct
diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp
index ca3fcfab8..8c314a511 100644
--- a/desmume/src/MMU.cpp
+++ b/desmume/src/MMU.cpp
@@ -1636,7 +1636,9 @@ u32 TGXSTAT::read32()
// stack position always equal zero. possible timings is wrong
// using in "The Wild West"
- ret |= ((_hack_getMatrixStackLevel(0) << 13) | (_hack_getMatrixStackLevel(1) << 8)); //matrix stack levels //no proof that these are needed yet
+ int proj_level = _hack_getMatrixStackLevel(0);
+ int mv_level = _hack_getMatrixStackLevel(1);
+ ret |= ((proj_level << 13) | (mv_level << 8)); //matrix stack levels //no proof that these are needed yet
ret |= sb<<14; //stack busy
ret |= se<<15;
@@ -1649,10 +1651,13 @@ u32 TGXSTAT::read32()
if(isSwapBuffers) ret |= BIT(27);
//if fifo is nonempty, we're busy
if(gxFIFO.size!=0) ret |= BIT(27);
+
+ //printf("[%d] %d %d %d\n",currFrameCounter,se,sb,gxFIFO.size!=0);
+
ret |= ((gxfifo_irq & 0x3) << 30); //user's irq flags
- //printf("vc=%03d Returning gxstat read: %08X\n",nds.VCount,ret);
+ //printf("vc=%03d Returning gxstat read: %08X (isSwapBuffers=%d)\n",nds.VCount,ret,isSwapBuffers);
//ret = (2 << 8);
//INFO("gxSTAT 0x%08X (proj %i, pos %i)\n", ret, _hack_getMatrixStackLevel(1), _hack_getMatrixStackLevel(2));
diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp
index a66f02773..f4f10e784 100644
--- a/desmume/src/NDSSystem.cpp
+++ b/desmume/src/NDSSystem.cpp
@@ -1776,7 +1776,7 @@ FORCEINLINE void arm9log()
INFO("Disassembler is stopped\n");
}*/
#else
- printf("%05d:%03d %12lld 9:%08X %08X %-30s\nR00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
+ printf("%05d:%03d %12lld 9:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
currFrameCounter, nds.VCount, nds_timer,
NDS_ARM9.instruct_adr,NDS_ARM9.instruction, dasmbuf,
NDS_ARM9.R[0], NDS_ARM9.R[1], NDS_ARM9.R[2], NDS_ARM9.R[3], NDS_ARM9.R[4], NDS_ARM9.R[5], NDS_ARM9.R[6], NDS_ARM9.R[7],
@@ -1889,7 +1889,6 @@ static /*donotinline*/ std::pair armInnerLoop(
timer = minarmtime(arm9,arm7);
nds_timer = nds_timer_base + timer;
- if (nds_timer >= MMU.gfx3dCycles) MMU_new.gxstat.sb = 0; // clear stack busy flag
}
return std::make_pair(arm9, arm7);
diff --git a/desmume/src/arm_instructions.cpp b/desmume/src/arm_instructions.cpp
index c2d388884..f7680b897 100644
--- a/desmume/src/arm_instructions.cpp
+++ b/desmume/src/arm_instructions.cpp
@@ -1,6 +1,7 @@
-/* Copyright (C) 2006 yopyop
+/*
+ Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
- Copyright (C) 2008-2010 DeSmuME team
+ Copyright (C) 2008-2011 DeSmuME team
This file is part of DeSmuME
@@ -3023,6 +3024,7 @@ TEMPLATE static u32 FASTCALL OP_MSR_CPSR(const u32 i)
}
cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask));
if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode);
+ cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
@@ -3070,6 +3072,7 @@ TEMPLATE static u32 FASTCALL OP_MSR_SPSR(const u32 i)
mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK);
}
cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask));
+ cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
@@ -3084,6 +3087,7 @@ TEMPLATE static u32 FASTCALL OP_MSR_SPSR(const u32 i)
}
if(BIT19(i))
cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0xFF000000);
+ cpu->changeCPSR();
#endif
return 1;
@@ -3126,6 +3130,7 @@ TEMPLATE static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(const u32 i)
}
cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask));
if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode);
+ cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp
index bb326926d..3870583a0 100644
--- a/desmume/src/gfx3d.cpp
+++ b/desmume/src/gfx3d.cpp
@@ -1,5 +1,6 @@
-/* Copyright (C) 2006 yopyop
- Copyright (C) 2008-2010 DeSmuME team
+/*
+ Copyright (C) 2006 yopyop
+ Copyright (C) 2008-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -851,8 +852,6 @@ static void gfx3d_glPushMatrix()
if(mymode==2)
MatrixStackPushMatrix (&mtxStack[1], mtxCurrent[1]);
-
- MMU_new.gxstat.sb = 1; // set busy
}
static void gfx3d_glPopMatrix(s32 i)
@@ -874,8 +873,6 @@ static void gfx3d_glPopMatrix(s32 i)
if (mymode == 2)
MatrixStackPopMatrix(mtxCurrent[1], &mtxStack[1], i);
-
- MMU_new.gxstat.sb = 1; // set busy
}
static void gfx3d_glStoreMatrix(u32 v)
@@ -888,7 +885,9 @@ static void gfx3d_glStoreMatrix(u32 v)
if(mymode==0 || mymode==3)
v = 0;
- if (v >= 31) return;
+ v &= 31;
+ //this behaviour is unverified. gbatek suggests that it may be meaningful somehow.
+ if(v==31) return;
MatrixStackLoadMatrix (&mtxStack[mymode], v, mtxCurrent[mymode]);
@@ -908,7 +907,14 @@ static void gfx3d_glRestoreMatrix(u32 v)
if(mymode==0 || mymode==3)
v = 0;
- if (v >= 31) return;
+ v &= 31;
+
+ //this seems to do something irrational if v==31, as far as we know.
+ //lets arbitrarily choose to use entry -
+ if(v==31) {
+ v = 0;
+ printf("gfx3d_glRestoreMatrix is using -1. why would anyone do this? please report!\n");
+ }
MatrixCopy (mtxCurrent[mymode], MatrixStackGetPos(&mtxStack[mymode], v));
@@ -916,9 +922,6 @@ static void gfx3d_glRestoreMatrix(u32 v)
if (mymode == 2)
MatrixCopy (mtxCurrent[1], MatrixStackGetPos(&mtxStack[1], v));
-
- //printf("restore: matrix %d to: \n",mymode); MatrixPrint(mtxCurrent[1]);
-
}
static void gfx3d_glLoadIdentity()
@@ -1672,7 +1675,7 @@ s32 gfx3d_GetClipMatrix (unsigned int index)
{
s32 val = MatrixGetMultipliedIndex (index, mtxCurrent[0], mtxCurrent[1]);
- //val *= (1<<12);
+ //printf("reading clip matrix: %d\n",index);
return (s32)val;
}
@@ -1827,7 +1830,6 @@ static void gfx3d_execute(u8 cmd, u32 param)
log3D(cmd, param);
#endif
- MMU_new.gxstat.sb = 0; // clear stack busy flag
switch (cmd)
{
case 0x10: // MTX_MODE - Set Matrix Mode (W)
@@ -2001,6 +2003,8 @@ void gfx3d_glFlush(u32 v)
#endif
isSwapBuffers = TRUE;
+
+ //printf("%05d:%03d:%12lld: FLUSH\n",currFrameCounter, nds.VCount, nds_timer);
//well, the game wanted us to flush.
//it may be badly timed. lets just flush it.
@@ -2173,6 +2177,8 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
void gfx3d_sendCommandToFIFO(u32 val)
{
+ //printf("gxFIFO: send val=0x%08X, size=%03i (fifo)\n", val, gxFIFO.size);
+
gxf_hardware.receive(val);
}
@@ -2338,6 +2344,7 @@ SFORMAT SF_GFX3D[]={
{ "GFHE", 4, 1, &gxFIFO.head},
{ "GFTA", 4, 1, &gxFIFO.tail},
{ "GFSZ", 4, 1, &gxFIFO.size},
+ { "GFMS", 4, 1, &gxFIFO.matrix_stack_op_size},
{ "GFCM", 1, HACK_GXIFO_SIZE, &gxFIFO.cmd[0]},
{ "GFPM", 4, HACK_GXIFO_SIZE, &gxFIFO.param[0]},
{ "GPHE", 1, 1, &gxPIPE.head},
diff --git a/desmume/src/matrix.cpp b/desmume/src/matrix.cpp
index 4764142b1..f644f4582 100644
--- a/desmume/src/matrix.cpp
+++ b/desmume/src/matrix.cpp
@@ -1,21 +1,19 @@
/*
Copyright (C) 2006-2007 shash
+ Copyright (C) 2007-2011 DeSmuME team
- This file is part of DeSmuME
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
- DeSmuME is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- DeSmuME is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DeSmuME; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ You should have received a copy of the GNU General Public License
+ along with the this software. If not, see .
*/
#include
@@ -274,7 +272,13 @@ static void MatrixStackSetStackPosition (MatrixStack *stack, int pos)
if((stack->position < 0) || (stack->position > stack->size))
MMU_new.gxstat.se = 1;
- stack->position &= stack->size;
+
+ //this behaviour is unverified, but its more logical than the old code which would wrap around and turn negative
+ //it may still be right to wrap around, but we have no proof right now one way or another
+ if(stack->position < 0)
+ stack->position = 0;
+ if(stack->position > stack->size)
+ stack->position = stack->size;
}
void MatrixStackPushMatrix (MatrixStack *stack, const s32 *ptr)
diff --git a/desmume/src/thumb_instructions.cpp b/desmume/src/thumb_instructions.cpp
index c6026d4cd..8a9513967 100644
--- a/desmume/src/thumb_instructions.cpp
+++ b/desmume/src/thumb_instructions.cpp
@@ -1,25 +1,20 @@
-/* Copyright (C) 2006 yopyop
- Copyright (C) 2008-2010 DeSmuME team
+/*
+ Copyright (C) 2006 yopyop
+ Copyright (C) 2008 shash
+ Copyright (C) 2008-2011 DeSmuME team
- Code added on 18/08/2006 by shash
- - Missing missaligned addresses correction
- (reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments)
-
- This file is part of DeSmuME
-
- DeSmuME is free software; you can redistribute it and/or modify
+ This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
- DeSmuME is distributed in the hope that it will be useful,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with DeSmuME; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ along with the this software. If not, see .
*/
// THUMB core TODO:
@@ -1025,26 +1020,27 @@ TEMPLATE static u32 FASTCALL OP_SWI_THUMB(const u32 i)
|| (cpu->intVector == 0xFFFF0000 && PROCNUM==1);
if(cpu->swi_tab && !bypassBuiltinSWI) {
- //zero 25-dec-2008 - in arm, we were masking to 0x1F.
- //this is probably safer since an invalid opcode could crash the emu
- //zero 30-jun-2009 - but they say that the ideas 0xFF should crash the device...
- //u32 swinum = cpu->instruction & 0xFF;
+ //zero 25-dec-2008 - in arm, we were masking to 0x1F.
+ //this is probably safer since an invalid opcode could crash the emu
+ //zero 30-jun-2009 - but they say that the ideas 0xFF should crash the device...
+ //u32 swinum = cpu->instruction & 0xFF;
swinum &= 0x1F;
//printf("%d ARM SWI %d\n",PROCNUM,swinum);
- return cpu->swi_tab[swinum]() + 3;
+ return cpu->swi_tab[swinum]() + 3;
}
else {
- /* we use an irq thats not in the irq tab, as
- it was replaced due to a changed intVector */
- Status_Reg tmp = cpu->CPSR;
- armcpu_switchMode(cpu, SVC); /* enter svc mode */
- cpu->R[14] = cpu->next_instruction; /* jump to swi Vector */
- cpu->SPSR = tmp; /* save old CPSR as new SPSR */
- cpu->CPSR.bits.T = 0; /* handle as ARM32 code */
- cpu->CPSR.bits.I = 1;
- cpu->R[15] = cpu->intVector + 0x08;
- cpu->next_instruction = cpu->R[15];
- return 3;
+ /* we use an irq thats not in the irq tab, as
+ it was replaced due to a changed intVector */
+ Status_Reg tmp = cpu->CPSR;
+ armcpu_switchMode(cpu, SVC); /* enter svc mode */
+ cpu->R[14] = cpu->next_instruction; /* jump to swi Vector */
+ cpu->SPSR = tmp; /* save old CPSR as new SPSR */
+ cpu->CPSR.bits.T = 0; /* handle as ARM32 code */
+ cpu->CPSR.bits.I = 1;
+ cpu->changeCPSR();
+ cpu->R[15] = cpu->intVector + 0x08;
+ cpu->next_instruction = cpu->R[15];
+ return 3;
}
}