diff --git a/plugins/spu2-x/src/Global.h b/plugins/spu2-x/src/Global.h index b8eda4d429..e79d2b520d 100644 --- a/plugins/spu2-x/src/Global.h +++ b/plugins/spu2-x/src/Global.h @@ -20,6 +20,8 @@ #define NOMINMAX +extern bool psxmode; + struct StereoOut16; struct StereoOut32; struct StereoOutFloat; diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index 4ddb8f3beb..84affe3197 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -834,9 +834,9 @@ void Mix() } // Commit Core 0 output to ram before mixing Core 1: + spu2M_WriteFast(0x800 + OutPos, Ext.Left); + spu2M_WriteFast(0xA00 + OutPos, Ext.Right); - spu2M_WriteFast( 0x800 + OutPos, Ext.Left ); - spu2M_WriteFast( 0xA00 + OutPos, Ext.Right ); WaveDump::WriteCore( 0, CoreSrc_External, Ext ); Ext = ApplyVolume( Ext, Cores[1].ExtVol ); diff --git a/plugins/spu2-x/src/ReadInput.cpp b/plugins/spu2-x/src/ReadInput.cpp index 9326a97004..78a3b81a21 100644 --- a/plugins/spu2-x/src/ReadInput.cpp +++ b/plugins/spu2-x/src/ReadInput.cpp @@ -31,6 +31,7 @@ // StereoOut32 V_Core::ReadInput_HiFi() { + if (psxmode)ConLog("ReadInput_HiFi!!!!!\n"); InputPosRead &= ~1; // //#ifdef PCM24_S1_INTERLEAVE diff --git a/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp b/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp index d1bf7aceda..64be714416 100644 --- a/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp +++ b/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp @@ -164,13 +164,6 @@ void UpdateDebugDialog() TextOut(hdc,IX+4,IY+32,t,6); vcd.displayPeak = 0; - - if(vcd.lastSetStartA != vc.StartA) - { - printf(" *** Warning! Core %d Voice %d: StartA should be %06x, and is %06x.\n", - c,v,vcd.lastSetStartA,vc.StartA); - vcd.lastSetStartA = vc.StartA; - } } // top now: 400 diff --git a/plugins/spu2-x/src/defs.h b/plugins/spu2-x/src/defs.h index 0306b6c478..96996b2840 100644 --- a/plugins/spu2-x/src/defs.h +++ b/plugins/spu2-x/src/defs.h @@ -441,6 +441,10 @@ struct V_Core u32 KeyOn; // not the KON register (though maybe it is) + // psxmode caches + u16 psxSoundDataTransferControl; + u16 psxSPUSTAT; + StereoOut32 downbuf[8]; StereoOut32 upbuf[8]; int dbpos, ubpos; diff --git a/plugins/spu2-x/src/spu2sys.cpp b/plugins/spu2-x/src/spu2sys.cpp index db12e90124..895ed4372b 100644 --- a/plugins/spu2-x/src/spu2sys.cpp +++ b/plugins/spu2-x/src/spu2sys.cpp @@ -42,6 +42,8 @@ int PlayMode; bool has_to_call_irq=false; +bool psxmode = false; + void SetIrqCall(int core) { // reset by an irq disable/enable cycle, behaviour found by @@ -116,6 +118,7 @@ void V_Core::Init( int index ) { ConLog( "* SPU2-X: Init SPU2 core %d \n", index ); memset( this, 0, sizeof(V_Core) ); + psxmode = false; const int c = Index = index; @@ -258,23 +261,27 @@ void V_Core::UpdateFeedbackBuffersB() void V_Core::UpdateEffectsBufferSize() { const s32 newbufsize = EffectsEndA - EffectsStartA + 1; - //printf("Rvb Area change: ESA = %x, EEA = %x, Size(dec) = %d, Size(hex) = %x FxEnable = %d\n", EffectsStartA, EffectsEndA, newbufsize * 2, newbufsize * 2, FxEnable); if( (newbufsize*2) > 0x20000 ) // max 128kb per core { //printf("too big, returning\n"); //return; } - if (newbufsize == EffectsBufferSize && EffectsStartA == EffectsBufferStart) return; - + + // bad optimization? + //if (newbufsize == EffectsBufferSize && EffectsStartA == EffectsBufferStart) return; + + //printf("Rvb Area change: ESA = %x, EEA = %x, Size(dec) = %d, Size(hex) = %x FxEnable = %d\n", EffectsStartA, EffectsEndA, newbufsize * 2, newbufsize * 2, FxEnable); + RevBuffers.NeedsUpdated = false; EffectsBufferSize = newbufsize; EffectsBufferStart = EffectsStartA; if( EffectsBufferSize <= 0 ) return; - //AnalyzeReverbPreset(); - + // debug: shows reverb parameters in console + if(MsgToConsole()) AnalyzeReverbPreset(); + // Rebuild buffer indexers. RevBuffers.ACC_SRC_A0 = EffectsBufferIndexer( Revb.ACC_SRC_A0 ); RevBuffers.ACC_SRC_A1 = EffectsBufferIndexer( Revb.ACC_SRC_A1 ); @@ -401,6 +408,7 @@ __forceinline void TimeUpdate(u32 cClocks) Cores[0].DMAICounter-=TickInterval; if(Cores[0].DMAICounter<=0) { + //ConLog("counter set and callback!\n"); Cores[0].MADR=Cores[0].TADR; Cores[0].DMAICounter=0; if(dma4callback) dma4callback(); @@ -489,6 +497,17 @@ void V_VolumeSlide::RegSet( u16 src ) Value = GetVol32( src ); } +static u32 map_spu1to2(u32 addr) +{ + return addr * 4 + (addr >= 0x200 ? 0xc0000 : 0); +} + +static u32 map_spu2to1(u32 addr) +{ + // if (addr >= 0x800 && addr < 0xc0000) oh dear + return (addr - (addr >= 0xc0000 ? 0xc0000 : 0)) / 4; +} + void V_Core::WriteRegPS1( u32 mem, u16 value ) { pxAssume( Index == 0 ); // Valid on Core 0 only! @@ -504,29 +523,59 @@ void V_Core::WriteRegPS1( u32 mem, u16 value ) switch(vval) { case 0x0: //VOLL (Volume L) - Voices[voice].Volume.Left.Mode = 0; - Voices[voice].Volume.Left.RegSet( value << 1 ); - Voices[voice].Volume.Left.Reg_VOL = value; - break; - case 0x2: //VOLR (Volume R) - Voices[voice].Volume.Right.Mode = 0; - Voices[voice].Volume.Right.RegSet( value << 1 ); - Voices[voice].Volume.Right.Reg_VOL = value; - break; + { + V_VolumeSlide& thisvol = vval == 0 ? Voices[voice].Volume.Left : Voices[voice].Volume.Right; + thisvol.Reg_VOL = value; - case 0x4: Voices[voice].Pitch = value; break; - case 0x6: Voices[voice].StartA = (u32)value << 8; break; + if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp + { + thisvol.Mode = (value & 0xF000) >> 12; + thisvol.Increment = (value & 0x7F); + // We're not sure slides work 100% + if (IsDevBuild) ConLog("* SPU2: Voice uses Slides in Mode = %x, Increment = %x\n", thisvol.Mode, thisvol.Increment); + } + else + { + // Constant Volume mode (no slides or envelopes) + // Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as + // the "sign" bit, so a simple bitwise extension will do the trick: + + thisvol.RegSet(value << 1); + thisvol.Mode = 0; + thisvol.Increment = 0; + } + //ConLog("voice %x VOL%c write: %x\n", voice, vval == 0 ? 'L' : 'R', value); + break; + } + case 0x4: + if (value > 0x3fff) ConLog("* SPU2: Pitch setting too big: 0x%x\n", value); + Voices[voice].Pitch = value & 0x3fff; + //ConLog("voice %x Pitch write: %x\n", voice, Voices[voice].Pitch); + break; + case 0x6: + Voices[voice].StartA = map_spu1to2(value); + //ConLog("voice %x StartA write: %x\n", voice, Voices[voice].StartA); + break; case 0x8: // ADSR1 (Envelope) Voices[voice].ADSR.regADSR1 = value; + //ConLog("voice %x regADSR1 write: %x\n", voice, Voices[voice].ADSR.regADSR1); break; case 0xa: // ADSR2 (Envelope) Voices[voice].ADSR.regADSR2 = value; + //ConLog("voice %x regADSR2 write: %x\n", voice, Voices[voice].ADSR.regADSR2); + break; + case 0xc: // Voice 0..23 ADSR Current Volume + // not commonly set by games + Voices[voice].ADSR.Value = value * 0x10001U; + ConLog("voice %x ADSR.Value write: %x\n", voice, Voices[voice].ADSR.Value); + break; + case 0xe: + Voices[voice].LoopStartA = map_spu1to2(value); + //ConLog("voice %x LoopStartA write: %x\n", voice, Voices[voice].LoopStartA); break; - - case 0xe: Voices[voice].LoopStartA = (u32)value << 8; break; jNO_DEFAULT; } @@ -568,70 +617,154 @@ void V_Core::WriteRegPS1( u32 mem, u16 value ) case 0x1d90:// Channel FM (pitch lfo) mode (0-15) SPU2_FastWrite(REG_S_PMON,value); + if (value!=0)ConLog("spu2x warning: wants to set Pitch Modulation reg1 to %x \n", value); break; case 0x1d92:// Channel FM (pitch lfo) mode (16-23) SPU2_FastWrite(REG_S_PMON+2,value); + if (value != 0)ConLog("spu2x warning: wants to set Pitch Modulation reg2 to %x \n", value); break; case 0x1d94:// Channel Noise mode (0-15) SPU2_FastWrite(REG_S_NON,value); + if (value != 0) ConLog("spu2x warning: wants to set Channel Noise mode reg1 to %x\n", value); break; case 0x1d96:// Channel Noise mode (16-23) SPU2_FastWrite(REG_S_NON+2,value); + if (value != 0) ConLog("spu2x warning: wants to set Channel Noise mode reg2 to %x\n", value); break; - case 0x1d98:// Channel Reverb mode (0-15) + case 0x1d98:// 1F801D98h - Voice 0..23 Reverb mode aka Echo On (EON) (R/W) + //Regs.VMIXEL = value & 0xFFFF; SPU2_FastWrite(REG_S_VMIXEL,value); SPU2_FastWrite(REG_S_VMIXER,value); + //ConLog("spu2x warning: setting reverb mode reg1 to %x \n", Regs.VMIXEL); break; - case 0x1d9a:// Channel Reverb mode (16-23) + case 0x1d9a:// 1F801D98h + 2 - Voice 0..23 Reverb mode aka Echo On (EON) (R/W) + //Regs.VMIXEL = value << 16; SPU2_FastWrite(REG_S_VMIXEL+2,value); SPU2_FastWrite(REG_S_VMIXER+2,value); + //ConLog("spu2x warning: setting reverb mode reg2 to %x \n", Regs.VMIXEL); break; - case 0x1d9c:// Channel Reverb mode (0-15) - SPU2_FastWrite(REG_S_VMIXL,value); - SPU2_FastWrite(REG_S_VMIXR,value); + // this was wrong? // edit: appears so! + //case 0x1d9c:// Channel Reverb mode (0-15) + // SPU2_FastWrite(REG_S_VMIXL,value); + // SPU2_FastWrite(REG_S_VMIXR,value); + //break; + + //case 0x1d9e:// Channel Reverb mode (16-23) + // SPU2_FastWrite(REG_S_VMIXL+2,value); + // SPU2_FastWrite(REG_S_VMIXR+2,value); + //break; + case 0x1d9c: // Voice 0..15 ON/OFF (status) (ENDX) (R) // writeable but hw overrides it shortly after + //Regs.ENDX &= 0xff0000; + ConLog("spu2x warning: wants to set ENDX reg1 to %x \n", value); break; - case 0x1d9e:// Channel Reverb mode (16-23) - SPU2_FastWrite(REG_S_VMIXL+2,value); - SPU2_FastWrite(REG_S_VMIXR+2,value); + case 0x1d9e:// // Voice 15..23 ON/OFF (status) (ENDX) (R) // writeable but hw overrides it shortly after + //Regs.ENDX &= 0xffff; + ConLog("spu2x warning: wants to set ENDX reg2 to %x \n", value); break; case 0x1da2:// Reverb work area start { - u32 val = (u32)value << 8; - - SPU2_FastWrite(REG_A_ESA, val&0xFFFF); - SPU2_FastWrite(REG_A_ESA+2,val>>16); + EffectsStartA = map_spu1to2(value); + //EffectsEndA = 0xFFFFF; // fixed EndA in psx mode + Cores[0].RevBuffers.NeedsUpdated = true; + ReverbX = 0; } break; case 0x1da4: - IRQA = (u32)value<<8; + IRQA = map_spu1to2(value); + //ConLog("SPU2-X Setting IRQA to %x \n", IRQA); break; case 0x1da6: - TSA = (u32)value<<8; + TSA = map_spu1to2(value); + //ConLog("SPU2-X Setting TSA to %x \n", TSA); + break; + + case 0x1da8: // Spu Write to Memory + //ConLog("SPU direct DMA Write. Current TSA = %x\n", TSA); + if (Cores[0].IRQEnable && (Cores[0].IRQA <= Cores[0].TSA)) + { + SetIrqCall(0); + _irqcallback(); + } + DmaWrite(value); + show = false; break; case 0x1daa: - SPU2_FastWrite(REG_C_ATTR,value); + SPU2_FastWrite(REG_C_ATTR, value); break; - case 0x1dae: - SPU2_FastWrite(REG_P_STATX,value); + case 0x1dac: // 1F801DACh - Sound RAM Data Transfer Control (should be 0004h) + ConLog("SPU Sound RAM Data Transfer Control (should be 4) : value = %x \n", value); + psxSoundDataTransferControl = value; break; - case 0x1da8:// Spu Write to Memory - DmaWrite(value); - show=false; + case 0x1dae: // 1F801DAEh - SPU Status Register (SPUSTAT) (R) + // The SPUSTAT register should be treated read-only (writing is possible in so far that the written + // value can be read-back for a short moment, however, thereafter the hardware is overwriting that value). + //Regs.STATX = value; break; + + case 0x1DB0: // 1F801DB0h 4 CD Volume Left/Right + break; // cd left? + case 0x1DB2: + break;// cd right? + case 0x1DB4: // 1F801DB4h 4 Extern Volume Left / Right + break; // Extern left? + case 0x1DB6: + break; // Extern right? + case 0x1DB8: // 1F801DB8h 4 Current Main Volume Left/Right + break; // Current left? + case 0x1DBA: + break; // Current right? + case 0x1DBC: // 1F801DBCh 4 Unknown? (R/W) + break; + case 0x1DBE: + break; + + case 0x1DC0: Revb.FB_SRC_A = value * 4; break; + case 0x1DC2: Revb.FB_SRC_B = value * 4; break; + case 0x1DC4: Revb.IIR_ALPHA = value; break; + case 0x1DC6: Revb.ACC_COEF_A = value; break; + case 0x1DC8: Revb.ACC_COEF_B = value; break; + case 0x1DCA: Revb.ACC_COEF_C = value; break; + case 0x1DCC: Revb.ACC_COEF_D = value; break; + case 0x1DCE: Revb.IIR_COEF = value; break; + case 0x1DD0: Revb.FB_ALPHA = value; break; + case 0x1DD2: Revb.FB_X = value; break; + case 0x1DD4: Revb.IIR_DEST_A0 = value * 4; break; + case 0x1DD6: Revb.IIR_DEST_A1 = value * 4; break; + case 0x1DD8: Revb.ACC_SRC_A0 = value * 4; break; + case 0x1DDA: Revb.ACC_SRC_A1 = value * 4; break; + case 0x1DDC: Revb.ACC_SRC_B0 = value * 4; break; + case 0x1DDE: Revb.ACC_SRC_B1 = value * 4; break; + case 0x1DE0: Revb.IIR_SRC_A0 = value * 4; break; + case 0x1DE2: Revb.IIR_SRC_A1 = value * 4; break; + case 0x1DE4: Revb.IIR_DEST_B0 = value * 4; break; + case 0x1DE6: Revb.IIR_DEST_B1 = value * 4; break; + case 0x1DE8: Revb.ACC_SRC_C0 = value * 4; break; + case 0x1DEA: Revb.ACC_SRC_C1 = value * 4; break; + case 0x1DEC: Revb.ACC_SRC_D0 = value * 4; break; + case 0x1DEE: Revb.ACC_SRC_D1 = value * 4; break; + case 0x1DF0: Revb.IIR_SRC_B0 = value * 4; break; // IIR_SRC_B0 and IIR_SRC_B1 supposedly swapped on SPU2 + case 0x1DF2: Revb.IIR_SRC_B1 = value * 4; break; // but I don't believe it! (games in psxmode sound better unswapped) + case 0x1DF4: Revb.MIX_DEST_A0 = value * 4; break; + case 0x1DF6: Revb.MIX_DEST_A1 = value * 4; break; + case 0x1DF8: Revb.MIX_DEST_B0 = value * 4; break; + case 0x1DFA: Revb.MIX_DEST_B1 = value * 4; break; + case 0x1DFC: Revb.IN_COEF_L = value; break; + case 0x1DFE: Revb.IN_COEF_R = value; break; + } if(show) FileLog("[%10d] (!) SPU write mem %08x value %04x\n",Cycles,mem,value); @@ -655,24 +788,40 @@ u16 V_Core::ReadRegPS1(u32 mem) u8 vval = reg&0xf; switch(vval) { - case 0: //VOLL (Volume L) + case 0x0: //VOLL (Volume L) //value=Voices[voice].VolumeL.Mode; //value=Voices[voice].VolumeL.Value; value = Voices[voice].Volume.Left.Reg_VOL; - break; + break; - case 1: //VOLR (Volume R) + case 0x2: //VOLR (Volume R) //value=Voices[voice].VolumeR.Mode; //value=Voices[voice].VolumeR.Value; value = Voices[voice].Volume.Right.Reg_VOL; - break; + break; - case 2: value = Voices[voice].Pitch; break; - case 3: value = Voices[voice].StartA; break; - case 4: value = Voices[voice].ADSR.regADSR1; break; - case 5: value = Voices[voice].ADSR.regADSR2; break; - case 6: value = Voices[voice].ADSR.Value >> 16; break; - case 7: value = Voices[voice].LoopStartA; break; + case 0x4: + value = Voices[voice].Pitch; + //ConLog("voice %d read pitch result = %x\n", voice, value); + break; + case 0x6: + value = map_spu2to1(Voices[voice].StartA); + //ConLog("voice %d read StartA result = %x\n", voice, value); + break; + case 0x8: + value = Voices[voice].ADSR.regADSR1; + break; + case 0xa: + value = Voices[voice].ADSR.regADSR2; + break; + case 0xc: // Voice 0..23 ADSR Current Volume + value = Voices[voice].ADSR.Value >> 16; // no clue + //if (value != 0) ConLog("voice %d read ADSR.Value result = %x\n", voice, value); + break; + case 0xe: + value = map_spu2to1(Voices[voice].LoopStartA); + //ConLog("voice %d read LoopStartA result = %x\n", voice, value); + break; jNO_DEFAULT; } @@ -684,48 +833,50 @@ u16 V_Core::ReadRegPS1(u32 mem) case 0x1d84: value = FxVol.Left >> 16; break; case 0x1d86: value = FxVol.Right >> 16; break; - case 0x1d88: value = 0; break; + case 0x1d88: value = 0; break; // Voice 0..23 Key ON(Start Attack / Decay / Sustain) (W) case 0x1d8a: value = 0; break; - case 0x1d8c: value = 0; break; + case 0x1d8c: value = 0; break; // Voice 0..23 Key OFF (Start Release) (W) case 0x1d8e: value = 0; break; - case 0x1d90: value = Regs.PMON&0xFFFF; break; + case 0x1d90: value = Regs.PMON&0xFFFF; break; // Voice 0..23 Channel FM(pitch lfo) mode(R / W) case 0x1d92: value = Regs.PMON>>16; break; - case 0x1d94: value = Regs.NON&0xFFFF; break; + case 0x1d94: value = Regs.NON&0xFFFF; break; // Voice 0..23 Channel Noise mode (R/W) case 0x1d96: value = Regs.NON>>16; break; - case 0x1d98: value = Regs.VMIXEL&0xFFFF; break; + case 0x1d98: value = Regs.VMIXEL&0xFFFF; break; // Voice 0..23 Channel Reverb mode (R/W) case 0x1d9a: value = Regs.VMIXEL>>16; break; - case 0x1d9c: value = Regs.VMIXL&0xFFFF; break; - case 0x1d9e: value = Regs.VMIXL>>16; break; + /*case 0x1d9c: value = Regs.VMIXL&0xFFFF; break;*/ // this is wrong? + /*case 0x1d9e: value = Regs.VMIXL >> 16; break;*/ + case 0x1d9c: value = Regs.ENDX & 0xFFFF; break;// Voice 0..23 Channel ON / OFF(status) (R) (ENDX) + case 0x1d9e: value = Regs.ENDX >> 16; case 0x1da2: -#if 0 - // This smells of old hack - if( value != EffectsStartA>>3 ) - { - value = EffectsStartA>>3; - UpdateEffectsBufferSize(); - ReverbX = 0; - } -#else - value = EffectsStartA >> 3; -#endif - break; - case 0x1da4: value = IRQA>>3; break; - case 0x1da6: value = TSA>>3; break; - - case 0x1daa: - value = SPU2read(REG_C_ATTR); + value = map_spu2to1(EffectsStartA); break; - case 0x1dae: - value = 0; //SPU2read(REG_P_STATX)<<3; + case 0x1da4: + value = map_spu2to1(IRQA); + //ConLog("SPU2-X IRQA read: 0x1da4 = %x , (IRQA = %x)\n", value, IRQA); + break; + case 0x1da6: + value = map_spu2to1(TSA); + //ConLog("SPU2-X TSA read: 0x1da6 = %x , (TSA = %x)\n", value, TSA); break; case 0x1da8: value = DmaRead(); show=false; break; + case 0x1daa: + value = Cores[0].Regs.ATTR; + //ConLog("SPU2-X ps1 reg psxSPUCNT read return value: %x\n", value); + break; + case 0x1dac: // 1F801DACh - Sound RAM Data Transfer Control (should be 0004h) + value = psxSoundDataTransferControl; + break; + case 0x1dae: + value = Cores[0].Regs.STATX; + //ConLog("SPU2-X ps1 reg REG_P_STATX read return value: %x\n", value); + break; } if(show) FileLog("[%10d] (!) SPU read mem %08x value %04x\n",Cycles,mem,value); @@ -1122,6 +1273,37 @@ static void __fastcall RegWrite_Core( u16 value ) case REG_S_ADMAS: if ( MsgToConsole() ) ConLog("* SPU2-X: Core %d AutoDMAControl set to %d (at cycle %d)\n",core,value, Cycles); + + if (psxmode) ConLog("* SPU2-X: Writing to REG_S_ADMAS while in PSX mode! value: %x",value); + // hack for ps1driver which writes -1 (and never turns the adma off after psxlogo). + // adma isn't available in psx mode either + if (value == 32767) { + psxmode = true; + //memset(_spu2mem, 0, 0x200000); + Cores[1].FxEnable = 0; + Cores[1].EffectsStartA = 0x7FFF8; // park core1 effect area in inaccessible mem + Cores[1].EffectsEndA = 0x7FFFF; + Cores[1].ExtEffectsStartA = 0x7FFF8; // park core1 ext effect area in high mem + Cores[1].ExtEffectsStartA = 0x7FFFF; + Cores[1].ReverbX = 0; + Cores[1].RevBuffers.NeedsUpdated = true; + Cores[0].ReverbX = 0; + Cores[0].RevBuffers.NeedsUpdated = true; + for (uint v = 0; v < 24; ++v) + { + Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max; + Cores[1].Voices[v].SCurrent = 28; + + Cores[1].Voices[v].ADSR.Value = 0; + Cores[1].Voices[v].ADSR.Phase = 0; + Cores[1].Voices[v].Pitch = 0x0; + Cores[1].Voices[v].NextA = 0x6FFFF; + Cores[1].Voices[v].StartA = 0x6FFFF; + Cores[1].Voices[v].LoopStartA = 0x6FFFF; + Cores[1].Voices[v].Modulated = 0; + } + return; + } thiscore.AutoDMACtrl=value; if(value==0)