From 3198207ee37aa36b8678afc4185935722513d5f3 Mon Sep 17 00:00:00 2001 From: zeromus Date: Tue, 30 Mar 2010 06:34:08 +0000 Subject: [PATCH] fix interrupt handling to respond immediately when CPSR.I is changed; also double buffer 3d configuration so that the settings in place at the time of flush get used for rendering (important for dual screen 3d games that use different settings for each screen); and handle 3d clear color register more thoroughly --- desmume/src/MMU.cpp | 142 ++++------------------------- desmume/src/NDSSystem.cpp | 16 ++-- desmume/src/OGLRender.cpp | 33 +++---- desmume/src/arm_instructions.cpp | 44 +++++++-- desmume/src/armcpu.cpp | 53 ++++++----- desmume/src/armcpu.h | 38 ++++---- desmume/src/gfx3d.cpp | 7 +- desmume/src/gfx3d.h | 12 +-- desmume/src/rasterize.cpp | 64 ++++++------- desmume/src/thumb_instructions.cpp | 7 +- desmume/src/windows/hotkey.cpp | 6 +- 11 files changed, 175 insertions(+), 247 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 7467c98e7..c641900ae 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define NEW_IRQ 1 - #include #include #include @@ -2412,6 +2410,11 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) writereg_POWCNT1(8,adr,val); break; + case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1: + case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3: + T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; + case REG_VRAMCNTA: case REG_VRAMCNTB: case REG_VRAMCNTC: @@ -2545,13 +2548,14 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) gfx3d_glAlphaFunc(val); return; } - // Clear background color setup - Parameters:2 + case eng_3D_CLEAR_COLOR: + case eng_3D_CLEAR_COLOR+2: { - ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x350>>1] = val; - gfx3d_glClearColor(val); - return; + T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; } + // Clear background depth setup - Parameters:2 case eng_3D_CLEAR_DEPTH: { @@ -2803,47 +2807,16 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) u32 new_val = val & 0x01; MMU.reg_IME[ARMCPU_ARM9] = new_val; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); -#ifndef NEW_IRQ - if ( new_val && old_val != new_val) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM9] & MMU.reg_IF[ARMCPU_ARM9]) - { - NDS_ARM9.waitIRQ = FALSE; - } - } -#endif - return; + return; } case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val; -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM9]) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM9] & MMU.reg_IF[ARMCPU_ARM9]) - { - NDS_ARM9.waitIRQ = FALSE; - } - } -#endif return; case REG_IE + 2 : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16); -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM9]) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM9] & MMU.reg_IF[ARMCPU_ARM9]) - { - NDS_ARM9.waitIRQ = FALSE; - } - } -#endif return; - case REG_IF : NDS_Reschedule(); MMU.reg_IF[ARMCPU_ARM9] &= (~((u32)val)); @@ -3108,21 +3081,19 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) return; // Alpha test reference value - Parameters:1 - case 0x04000340: + case eng_3D_ALPHA_TEST_REF: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>2] = val; gfx3d_glAlphaFunc(val); return; } - // Clear background color setup - Parameters:2 - case 0x04000350: - { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x350>>2] = val; - gfx3d_glClearColor(val); - return; - } + + case eng_3D_CLEAR_COLOR: + T1WriteLong((u8*)&gfx3d.state.clearColor,0,val); + break; + // Clear background depth setup - Parameters:2 - case 0x04000354: + case eng_3D_CLEAR_DEPTH: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>2] = val; gfx3d_glClearDepth(val); @@ -3249,32 +3220,12 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) u32 new_val = val & 0x01; MMU.reg_IME[ARMCPU_ARM9] = new_val; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); -#ifndef NEW_IRQ - if ( new_val && old_val != new_val) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM9] & MMU.reg_IF[ARMCPU_ARM9]) - { - NDS_ARM9.waitIRQ = FALSE; - } - } -#endif } return; case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = val; -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM9]) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM9] & MMU.reg_IF[ARMCPU_ARM9]) - { - NDS_ARM9.waitIRQ = FALSE; - } - } -#endif return; case REG_IF : @@ -3378,10 +3329,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); return; } - if(adr>=0x05000000 && adr<0x06200000) - { - int zzz=9; - } + bool unmapped; adr = MMU_LCDmap(adr, unmapped); @@ -3980,46 +3928,16 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) u32 new_val = val & 1; MMU.reg_IME[ARMCPU_ARM7] = new_val; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); -#ifndef NEW_IRQ - if ( new_val && old_val != new_val) - { - /* raise an interrupt request to the CPU if needed */ - if ( MMU.reg_IE[ARMCPU_ARM7] & MMU.reg_IF[ARMCPU_ARM7]) - { - NDS_ARM7.waitIRQ = FALSE; - } - } -#endif - return; + return; } case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF0000) | val; -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM7]) - { - /* raise an interrupt request to the CPU if needed */ - if ( MMU.reg_IE[ARMCPU_ARM7] & MMU.reg_IF[ARMCPU_ARM7]) - { - NDS_ARM7.waitIRQ = FALSE; - } - } -#endif return; case REG_IE + 2 : NDS_Reschedule(); //emu_halt(); MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF) | (((u32)val)<<16); -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM7]) - { - /* raise an interrupt request to the CPU if needed */ - if ( MMU.reg_IE[ARMCPU_ARM7] & MMU.reg_IF[ARMCPU_ARM7]) - { - NDS_ARM7.waitIRQ = FALSE; - } - } -#endif return; case REG_IF : @@ -4117,32 +4035,12 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val) u32 new_val = val & 1; MMU.reg_IME[ARMCPU_ARM7] = new_val; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); -#ifndef NEW_IRQ - if ( new_val && old_val != new_val) - { - // raise an interrupt request to the CPU if needed - if ( MMU.reg_IE[ARMCPU_ARM7] & MMU.reg_IF[ARMCPU_ARM7]) - { - NDS_ARM7.waitIRQ = FALSE; - } - } -#endif return; } case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM7] = val; -#ifndef NEW_IRQ - if ( MMU.reg_IME[ARMCPU_ARM7]) - { - /* raise an interrupt request to the CPU if needed */ - if ( MMU.reg_IE[ARMCPU_ARM7] & MMU.reg_IF[ARMCPU_ARM7]) - { - NDS_ARM7.waitIRQ = FALSE; - } - } -#endif return; case REG_IF : diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 56823dc63..458e116a3 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1937,11 +1937,11 @@ void execHardware_interrupts() { if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0])) { -#ifdef GDB_STUB - if ( armcpu_flagIrq( &NDS_ARM9)) -#else +//#ifdef GDB_STUB +// if ( armcpu_flagIrq( &NDS_ARM9)) +//#else if ( armcpu_irqException(&NDS_ARM9)) -#endif +//#endif { //printf("ARM9 interrupt! flags: %08X ; mask: %08X ; result: %08X\n",MMU.reg_IF[0],MMU.reg_IE[0],MMU.reg_IF[0]&MMU.reg_IE[0]); //nds.ARM9Cycle = nds.cycles; @@ -1950,11 +1950,11 @@ void execHardware_interrupts() if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1])) { -#ifdef GDB_STUB - if ( armcpu_flagIrq( &NDS_ARM7)) -#else +//#ifdef GDB_STUB +// if ( armcpu_flagIrq( &NDS_ARM7)) +//#else if ( armcpu_irqException(&NDS_ARM7)) -#endif +//#endif { //nds.ARM7Cycle = nds.cycles; } diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 30482745a..d68ad57e0 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash + Copyright (C) 2008-2010 DeSmuME team This file is part of DeSmuME @@ -15,8 +16,8 @@ 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 + along with DeSmuME; if not, write to the + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ //problem - alpha-on-alpha texture rendering might work but the dest alpha buffer isnt tracked correctly @@ -685,7 +686,7 @@ static void BeginRenderPoly() { lastEnvMode = envMode; - int _envModes[4] = {0, 1, (2 + gfx3d.state.shading), 0}; + int _envModes[4] = {0, 1, (2 + gfx3d.renderState.shading), 0}; glUniform1i(texBlendLoc, _envModes[envMode]); } } @@ -723,16 +724,16 @@ static void InstallPolygonAttrib(unsigned long val) static void Control() { - if(gfx3d.state.enableTexturing) glEnable (GL_TEXTURE_2D); + if(gfx3d.renderState.enableTexturing) glEnable (GL_TEXTURE_2D); else glDisable (GL_TEXTURE_2D); - if(gfx3d.state.enableAlphaTest) + if(gfx3d.renderState.enableAlphaTest) // FIXME: alpha test should pass gfx3d.alphaTestRef==poly->getAlpha - glAlphaFunc (GL_GREATER, gfx3d.state.alphaTestRef/31.f); + glAlphaFunc (GL_GREATER, gfx3d.renderState.alphaTestRef/31.f); else glAlphaFunc (GL_GREATER, 0); - if(gfx3d.state.enableAlphaBlending) + if(gfx3d.renderState.enableAlphaBlending) { glEnable (GL_BLEND); } @@ -820,27 +821,27 @@ static void OGLRender() if(hasShaders) { - if (gfx3d.state.invalidateToon) + if (gfx3d.renderState.invalidateToon) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &gfx3d.state.rgbToonTable[0]); - gfx3d.state.invalidateToon = false; + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &gfx3d.renderState.rgbToonTable[0]); + gfx3d.renderState.invalidateToon = false; } } xglDepthMask(GL_TRUE); float clearColor[4] = { - ((float)(gfx3d.state.clearColor&0x1F))/31.0f, - ((float)((gfx3d.state.clearColor>>5)&0x1F))/31.0f, - ((float)((gfx3d.state.clearColor>>10)&0x1F))/31.0f, - ((float)((gfx3d.state.clearColor>>16)&0x1F))/31.0f, + ((float)(gfx3d.renderState.clearColor&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>5)&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>10)&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>16)&0x1F))/31.0f, }; glClearColor(clearColor[0],clearColor[1],clearColor[2],clearColor[3]); - glClearDepth(gfx3d.state.clearDepth); - glClearStencil((gfx3d.state.clearColor >> 24) & 0x3F); + glClearDepth(gfx3d.renderState.clearDepth); + glClearStencil((gfx3d.renderState.clearColor >> 24) & 0x3F); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glMatrixMode(GL_PROJECTION); diff --git a/desmume/src/arm_instructions.cpp b/desmume/src/arm_instructions.cpp index cc2fea9b1..dca41e770 100644 --- a/desmume/src/arm_instructions.cpp +++ b/desmume/src/arm_instructions.cpp @@ -16,7 +16,7 @@ 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 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // ARM core TODO: @@ -268,6 +268,7 @@ TEMPLATE static u32 FASTCALL OP_UND(const u32 i) cpu->SPSR = tmp; /* save old CPSR as new SPSR */ \ cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ \ cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ \ + cpu->changeCPSR(); \ cpu->R[15] = cpu->intVector + 0x04; \ cpu->next_instruction = cpu->R[15]; \ return 4; \ @@ -300,6 +301,7 @@ TEMPLATE static u32 FASTCALL OP_UND(const u32 i) SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -443,6 +445,7 @@ TEMPLATE static u32 FASTCALL OP_AND_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -585,6 +588,7 @@ TEMPLATE static u32 FASTCALL OP_EOR_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -741,6 +745,7 @@ TEMPLATE static u32 FASTCALL OP_SUB_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -897,6 +902,7 @@ TEMPLATE static u32 FASTCALL OP_RSB_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -1055,6 +1061,7 @@ TEMPLATE static u32 FASTCALL OP_ADD_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -1215,6 +1222,7 @@ TEMPLATE static u32 FASTCALL OP_ADC_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -1375,6 +1383,7 @@ TEMPLATE static u32 FASTCALL OP_SBC_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -1811,6 +1820,7 @@ TEMPLATE static u32 FASTCALL OP_CMN_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -1954,6 +1964,7 @@ TEMPLATE static u32 FASTCALL OP_ORR_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -2100,6 +2111,7 @@ TEMPLATE static u32 FASTCALL OP_MOV_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -2242,6 +2254,7 @@ TEMPLATE static u32 FASTCALL OP_BIC_S_IMM_VAL(const u32 i) Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ @@ -3069,7 +3082,9 @@ TEMPLATE static u32 FASTCALL OP_MSR_CPSR(const u32 i) } if(BIT19(i)) cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); - + + cpu->changeCPSR(); + return 1; } @@ -3115,6 +3130,8 @@ TEMPLATE static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(const u32 i) //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0XFF000000); cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000); } + + cpu->changeCPSR(); return 1; } @@ -3137,6 +3154,8 @@ TEMPLATE static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(const u32 i) if(BIT19(i)) cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0XFF000000); + cpu->changeCPSR(); + return 1; } @@ -3695,7 +3714,7 @@ TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF(const u32 i) { cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; - cpu->next_instruction = cpu->R[15]; + cpu->next_instruction = cpu->R[15]; return MMU_aluMemAccessCycles(5,adr); } @@ -3743,7 +3762,7 @@ TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF(const u32 i) { cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; - cpu->next_instruction = cpu->R[15]; + cpu->next_instruction = cpu->R[15]; return MMU_aluMemAccessCycles(5,adr); } @@ -4312,7 +4331,7 @@ TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(const u32 i) return MMU_aluMemAccessCycles(5,adr); } - cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = val; return MMU_aluMemAccessCycles(3,adr); @@ -5826,6 +5845,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA2(const u32 i) SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); //start += 4; cpu->next_instruction = cpu->R[15]; c += MMU_memAccessCycles(start); @@ -5882,7 +5902,8 @@ TEMPLATE static u32 FASTCALL OP_LDMIB2(const u32 i) SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; - cpu->next_instruction = registres[15]; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); @@ -5913,6 +5934,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDA2(const u32 i) u32 tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); c += MMU_memAccessCycles(start); start -= 4; cpu->next_instruction = registres[15]; @@ -5943,6 +5965,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDA2(const u32 i) Status_Reg SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); @@ -5971,6 +5994,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDB2(const u32 i) tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } @@ -6000,6 +6024,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDB2(const u32 i) Status_Reg SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); @@ -6053,6 +6078,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA2_W(const u32 i) SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); @@ -6106,10 +6132,12 @@ TEMPLATE static u32 FASTCALL OP_LDMIB2_W(const u32 i) tmp = READ32(cpu->mem_if->data, start + 4); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); cpu->next_instruction = registres[15]; SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); c += MMU_memAccessCycles(start); return MMU_aluMemCycles(2, c); @@ -6169,6 +6197,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDA2_W(const u32 i) SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } @@ -6198,6 +6227,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDB2_W(const u32 i) c += MMU_memAccessCycles(start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); cpu->next_instruction = registres[15]; } @@ -6228,6 +6258,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDB2_W(const u32 i) SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; + cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } @@ -6869,6 +6900,7 @@ TEMPLATE static u32 FASTCALL OP_SWI(const u32 i) 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 4; diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index 18d6232a4..07ebb15c2 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -210,6 +210,13 @@ int armcpu_new( armcpu_t *armcpu, u32 id) return 0; } +//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed +void armcpu_t::changeCPSR() +{ + //but all it does is give them a chance to unleash by forcing an immediate reschedule + NDS_Reschedule(); +} + void armcpu_init(armcpu_t *armcpu, u32 adr) { u32 i; @@ -260,7 +267,7 @@ void armcpu_init(armcpu_t *armcpu, u32 adr) u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode) { - u32 oldmode = armcpu->CPSR.bits.mode; + u32 oldmode = armcpu->CPSR.bits.mode; switch(oldmode) { @@ -362,6 +369,7 @@ u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode) } armcpu->CPSR.bits.mode = mode & 0x1F; + armcpu->changeCPSR(); return oldmode; } @@ -466,45 +474,44 @@ BOOL armcpu_irqException(armcpu_t *armcpu) if(armcpu->CPSR.bits.I) return FALSE; -#ifdef GDB_STUB - armcpu->irq_flag = 0; -#endif +//#ifdef GDB_STUB +// armcpu->irq_flag = 0; +//#endif tmp = armcpu->CPSR; armcpu_switchMode(armcpu, IRQ); -#ifdef GDB_STUB - armcpu->R[14] = armcpu->next_instruction + 4; -#else +//#ifdef GDB_STUB +// armcpu->R[14] = armcpu->next_instruction + 4; +//#else armcpu->R[14] = armcpu->instruct_adr + 4; -#endif +//#endif armcpu->SPSR = tmp; armcpu->CPSR.bits.T = 0; armcpu->CPSR.bits.I = 1; armcpu->next_instruction = armcpu->intVector + 0x18; armcpu->waitIRQ = 0; -#ifndef GDB_STUB +//#ifndef GDB_STUB armcpu->R[15] = armcpu->next_instruction + 8; armcpu_prefetch(armcpu); -#endif +//#endif return TRUE; } -BOOL -armcpu_flagIrq( armcpu_t *armcpu) { - if(armcpu->CPSR.bits.I) return FALSE; - - armcpu->waitIRQ = 0; - -#ifdef GDB_STUB - armcpu->irq_flag = 1; -#endif - - return TRUE; -} - +//BOOL +//armcpu_flagIrq( armcpu_t *armcpu) { +// if(armcpu->CPSR.bits.I) return FALSE; +// +// armcpu->waitIRQ = 0; +// +//#ifdef GDB_STUB +// armcpu->irq_flag = 1; +//#endif +// +// return TRUE; +//} template u32 armcpu_exec() diff --git a/desmume/src/armcpu.h b/desmume/src/armcpu.h index 4b4af184d..3faa5cfe2 100644 --- a/desmume/src/armcpu.h +++ b/desmume/src/armcpu.h @@ -1,6 +1,5 @@ /* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com + Copyright (C) 2008-2010 DeSmuME team This file is part of DeSmuME @@ -16,7 +15,7 @@ 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 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ARM_CPU @@ -148,7 +147,7 @@ struct armcpu_ctrl_iface { typedef void* armcp_t; -typedef struct armcpu_t +struct armcpu_t { u32 proc_ID; u32 instruction; //4 @@ -159,6 +158,8 @@ typedef struct armcpu_t Status_Reg CPSR; //80 Status_Reg SPSR; + void changeCPSR(); + u32 R13_usr, R14_usr; u32 R13_svc, R14_svc; u32 R13_abt, R14_abt; @@ -197,7 +198,7 @@ typedef struct armcpu_t /** the ctrl interface */ struct armcpu_ctrl_iface ctrl_iface; #endif -} armcpu_t; +}; #ifdef GDB_STUB int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if, @@ -224,32 +225,25 @@ static INLINE void setIF(int PROCNUM, u32 flag) extern void NDS_Reschedule(); NDS_Reschedule(); + + //generate the interrupt if enabled + if ((MMU.reg_IE[PROCNUM] & (flag)) && MMU.reg_IME[PROCNUM]) + { + if(PROCNUM==0) + NDS_ARM9.waitIRQ = FALSE; + else + NDS_ARM7.waitIRQ = FALSE; + } } static INLINE void NDS_makeARM9Int(u32 num) { - /* flag the interrupt request source */ - // MMU.reg_IF[0] |= (1<>24)+1)-((v>>8)&0xFF); } -void gfx3d_glClearColor(u32 v) -{ - gfx3d.state.clearColor = v; -} - void gfx3d_glFogColor(u32 v) { gfx3d.state.fogColor = v; @@ -2013,6 +2008,8 @@ static void gfx3d_doFlush() gfx3d.state.enableClearImage = BIT14(control); gfx3d.state.fogShift = (control>>8)&0xF; + gfx3d.renderState = gfx3d.state; + int polycount = polylist->count; //find the min and max y values for each poly. diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index 3c5120f2e..37992c622 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -1,8 +1,6 @@ -/* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com - - Copyright (C) 2008-2009 DeSmuME team +/* gfx3d.h + Copyright (C) 2006 yopyop + Copyright (C) 2008-2010 DeSmuME team This file is part of DeSmuME @@ -367,8 +365,11 @@ struct GFX3D , frameCtrRaw(0) { } + //currently set values GFX3D_State state; + //values used for the currently-rendered frame (committed with each flush) + GFX3D_State renderState; POLYLIST* polylist; VERTLIST* vertlist; @@ -406,7 +407,6 @@ int _hack_getMatrixStackLevel(int); void gfx3d_glFlush(u32 v); // end GE commands -void gfx3d_glClearColor(u32 v); void gfx3d_glFogColor(u32 v); void gfx3d_glFogOffset (u32 v); void gfx3d_glClearDepth(u32 v); diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 07c7185a8..a874d1a66 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -266,7 +266,7 @@ FORCEINLINE int edge_fx_fl::Step() { static FORCEINLINE void alphaBlend(FragmentColor & dst, const FragmentColor & src) { - if(gfx3d.state.enableAlphaBlending) + if(gfx3d.renderState.enableAlphaBlending) { if(src.a == 0 || dst.a == 0) { @@ -500,7 +500,7 @@ public: } else { - if(gfx3d.state.shading == GFX3D_State::HIGHLIGHT) + if(gfx3d.renderState.shading == GFX3D_State::HIGHLIGHT) { dst.r = modulate_table[texColor.r][shader.materialColor.r]; dst.g = modulate_table[texColor.g][shader.materialColor.r]; @@ -548,7 +548,7 @@ public: FragmentColor &destFragmentColor = engine->screenColor[adr]; u32 depth; - if(gfx3d.state.wbuffer) + if(gfx3d.renderState.wbuffer) { //not sure about this //this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64 @@ -632,9 +632,9 @@ public: if(shaderOutput.a != 0) { //alpha test (don't have any test cases for this...? is it in the right place...?) - if(gfx3d.state.enableAlphaTest) + if(gfx3d.renderState.enableAlphaTest) { - if(shaderOutput.a < gfx3d.state.alphaTestRef) + if(shaderOutput.a < gfx3d.renderState.alphaTestRef) goto rejected_fragment; } @@ -1087,19 +1087,19 @@ void SoftRasterizerEngine::initFramebuffer(const int width, const int height, co Fragment clearFragment; FragmentColor clearFragmentColor; clearFragment.isTranslucentPoly = 0; - clearFragmentColor.r = GFX3D_5TO6(gfx3d.state.clearColor&0x1F); - clearFragmentColor.g = GFX3D_5TO6((gfx3d.state.clearColor>>5)&0x1F); - clearFragmentColor.b = GFX3D_5TO6((gfx3d.state.clearColor>>10)&0x1F); - clearFragmentColor.a = ((gfx3d.state.clearColor>>16)&0x1F); - clearFragment.polyid.opaque = (gfx3d.state.clearColor>>24)&0x3F; + clearFragmentColor.r = GFX3D_5TO6(gfx3d.renderState.clearColor&0x1F); + clearFragmentColor.g = GFX3D_5TO6((gfx3d.renderState.clearColor>>5)&0x1F); + clearFragmentColor.b = GFX3D_5TO6((gfx3d.renderState.clearColor>>10)&0x1F); + clearFragmentColor.a = ((gfx3d.renderState.clearColor>>16)&0x1F); + clearFragment.polyid.opaque = (gfx3d.renderState.clearColor>>24)&0x3F; //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, //but in spiderman2 some fires with polyid 0 try to render on top of the background clearFragment.polyid.translucent = kUnsetTranslucentPolyID; - clearFragment.depth = gfx3d.state.clearDepth; + clearFragment.depth = gfx3d.renderState.clearDepth; clearFragment.stencil = 0; clearFragment.isTranslucentPoly = 0; - clearFragment.fogged = BIT15(gfx3d.state.clearColor); + clearFragment.fogged = BIT15(gfx3d.renderState.clearColor); for(int i=0;i> 2) & 0x3F; - toonTable[i].g = (gfx3d.state.rgbToonTable[i] >> 10) & 0x3F; - toonTable[i].b = (gfx3d.state.rgbToonTable[i] >> 18) & 0x3F; + toonTable[i].r = (gfx3d.renderState.rgbToonTable[i] >> 2) & 0x3F; + toonTable[i].g = (gfx3d.renderState.rgbToonTable[i] >> 10) & 0x3F; + toonTable[i].b = (gfx3d.renderState.rgbToonTable[i] >> 18) & 0x3F; } - gfx3d.state.invalidateToon = false; + gfx3d.renderState.invalidateToon = false; } void SoftRasterizerEngine::updateFogTable() @@ -1167,14 +1167,14 @@ void SoftRasterizerEngine::updateFogTable() #if 0 //TODO - this might be a little slow; //we might need to hash all the variables and only recompute this when something changes - const int increment = (0x400 >> gfx3d.state.fogShift); + const int increment = (0x400 >> gfx3d.renderState.fogShift); for(u32 i=0;i<32768;i++) { - if(i> gfx3d.state.fogShift); - const int incrementDivShift = 10 - gfx3d.state.fogShift; - u32 fogOffset = min(max(gfx3d.state.fogOffset, 0), 32768); + const int increment = ((1 << 10) >> gfx3d.renderState.fogShift); + const int incrementDivShift = 10 - gfx3d.renderState.fogShift; + u32 fogOffset = min(max(gfx3d.renderState.fogOffset, 0), 32768); u32 iMin = min(32768, (( 1 + 1) << incrementDivShift) + fogOffset + 1 - increment); u32 iMax = min(32768, ((32 + 1) << incrementDivShift) + fogOffset + 1 - increment); assert(iMin <= iMax); @@ -1233,7 +1233,7 @@ void SoftRasterizerEngine::framebufferProcess() // - the edges are completely sharp/opaque on the very brief title screen intro, // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, // - the character edges in-level are clearly transparent, and also show well through shield powerups. - if(gfx3d.state.enableEdgeMarking && CommonSettings.GFX3D_EdgeMark) + if(gfx3d.renderState.enableEdgeMarking && CommonSettings.GFX3D_EdgeMark) { //TODO - need to test and find out whether these get grabbed at flush time, or at render time //we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors @@ -1303,12 +1303,12 @@ void SoftRasterizerEngine::framebufferProcess() } } - if(gfx3d.state.enableFog && CommonSettings.GFX3D_Fog) + if(gfx3d.renderState.enableFog && CommonSettings.GFX3D_Fog) { - u32 r = GFX3D_5TO6((gfx3d.state.fogColor)&0x1F); - u32 g = GFX3D_5TO6((gfx3d.state.fogColor>>5)&0x1F); - u32 b = GFX3D_5TO6((gfx3d.state.fogColor>>10)&0x1F); - u32 a = (gfx3d.state.fogColor>>16)&0x1F; + u32 r = GFX3D_5TO6((gfx3d.renderState.fogColor)&0x1F); + u32 g = GFX3D_5TO6((gfx3d.renderState.fogColor>>5)&0x1F); + u32 b = GFX3D_5TO6((gfx3d.renderState.fogColor>>10)&0x1F); + u32 a = (gfx3d.renderState.fogColor>>16)&0x1F; for(int i=0;i<256*192;i++) { Fragment &destFragment = screen[i]; @@ -1318,7 +1318,7 @@ void SoftRasterizerEngine::framebufferProcess() assert(fogIndex<32768); u8 fog = fogTable[fogIndex]; if(fog==127) fog=128; - if(!gfx3d.state.enableFogAlphaOnly) + if(!gfx3d.renderState.enableFogAlphaOnly) { destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7; destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7; @@ -1506,10 +1506,10 @@ static void SoftRastRender() mainSoftRasterizer.height = 192; //setup fog variables (but only if fog is enabled) - if(gfx3d.state.enableFog && CommonSettings.GFX3D_Fog) + if(gfx3d.renderState.enableFog && CommonSettings.GFX3D_Fog) mainSoftRasterizer.updateFogTable(); - mainSoftRasterizer.initFramebuffer(256,192,gfx3d.state.enableClearImage?true:false); + mainSoftRasterizer.initFramebuffer(256,192,gfx3d.renderState.enableClearImage?true:false); mainSoftRasterizer.updateToonTable(); mainSoftRasterizer.updateFloatColors(); mainSoftRasterizer.performClipping(CommonSettings.GFX3D_HighResolutionInterpolateColor); diff --git a/desmume/src/thumb_instructions.cpp b/desmume/src/thumb_instructions.cpp index 003f0739f..2721d52dc 100644 --- a/desmume/src/thumb_instructions.cpp +++ b/desmume/src/thumb_instructions.cpp @@ -1,6 +1,5 @@ /* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com + Copyright (C) 2008-2010 DeSmuME team Code added on 18/08/2006 by shash - Missing missaligned addresses correction @@ -20,7 +19,7 @@ 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 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // THUMB core TODO: @@ -1003,7 +1002,7 @@ TEMPLATE static u32 FASTCALL OP_SWI_THUMB(const u32 i) } else { /* we use an irq thats not in the irq tab, as - it was replaced duie to a changed intVector */ + 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 */ diff --git a/desmume/src/windows/hotkey.cpp b/desmume/src/windows/hotkey.cpp index 92fe40798..027033980 100644 --- a/desmume/src/windows/hotkey.cpp +++ b/desmume/src/windows/hotkey.cpp @@ -2,7 +2,7 @@ // licensed under the terms supplied at the end of this file (for the terms are very long!) // Differences from that baseline version are: // -// Copyright (C) 2009 DeSmuME team +// Copyright (C) 2009-2010 DeSmuME team // // DeSmuME is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ // // 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 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //*/ #include "hotkey.h" @@ -200,7 +200,7 @@ void HK_AutoHoldKeyUp(int) {AutoHoldPressed = false;} void HK_StylusAutoHoldKeyDown(int, bool justPressed) { StylusAutoHoldPressed = !StylusAutoHoldPressed; if (StylusAutoHoldPressed) - NDS_setTouchPos(winLastTouch.x, winLastTouch.y); + NDS_setTouchPos((u16)winLastTouch.x, (u16)winLastTouch.y); else if (!userTouchesScreen) NDS_releaseTouch(); }