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; } }