LINK: Add AdaMN's work for reference

git-svn-id: https://svn.code.sf.net/p/vbam/code/branches/adamn-link@1140 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
bgk 2012-10-01 16:55:36 +00:00
parent b2d9c51e5f
commit ed7e1247b1
30 changed files with 3834 additions and 402 deletions

Binary file not shown.

View File

@ -24,7 +24,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>Static</UseOfMfc>
<CharacterSet>NotSet</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -49,13 +49,13 @@
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)$(Platform)\$(Configuration)_temp\</IntDir>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PreBuildEventUseInBuild>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreBuildEventUseInBuild>
<PreLinkEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreLinkEventUseInBuild>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PostBuildEventUseInBuild>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)$(Platform)\$(Configuration)_temp\</IntDir>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PreBuildEventUseInBuild>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</PreBuildEventUseInBuild>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
@ -66,9 +66,9 @@
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\libs\Win32;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%programfiles%\OpenAL 1.1 SDK\libs\Win32;$(DXSDK_DIR)\lib\x86;$(LibraryPath)</LibraryPath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\libs\Win32;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(LibraryPath)</LibraryPath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%programfiles%\OpenAL 1.1 SDK\include;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%programfiles%\OpenAL 1.1 SDK\include;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%programfiles%\OpenAL 1.1 SDK\libs\Win32;$(DXSDK_DIR)\lib\x86;$(LibraryPath)</LibraryPath>
@ -100,7 +100,7 @@
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<PrecompiledHeader>
</PrecompiledHeader>
<ProgramDataBaseFileName>$(IntDir)$(ProjectName).pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
@ -124,6 +124,7 @@
<DataExecutionPrevention>
</DataExecutionPrevention>
<MinimumRequiredVersion>5.0</MinimumRequiredVersion>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -177,6 +178,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateDebugInformation>true</GenerateDebugInformation>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
<NASM>
<Optimization>1</Optimization>
@ -709,7 +711,7 @@
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties RESOURCE_FILE="\Users\Shawn\Desktop\shuffle2proj\vba-m\src\win32\VBA.rc" />
<UserProperties RESOURCE_FILE="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -61,6 +61,7 @@ extern int systemGetSensorY();
extern bool systemCanChangeSoundQuality();
extern void systemShowSpeed(int);
extern void system10Frames(int);
extern void system1Frames(int rate, int count);
extern void systemFrame();
extern void systemGbBorderOn();
@ -86,6 +87,9 @@ extern int systemFrameSkip;
extern int systemSaveUpdateCounter;
extern int systemSpeed;
extern int lastSA;
extern int lastSR;
#define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0

View File

@ -14,6 +14,7 @@ License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
#include "../system.h"
unsigned const vol_reg = 0xFF24;
unsigned const stereo_reg = 0xFF25;
@ -318,6 +319,9 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
int old_data = regs [reg];
regs [reg] = data;
//if(lastSA>=0x70 && lastSA<=0x75)
//log("CH3 Addr:%04X = %04X Regs[%d]:%02X->%02X\n",lastSA,lastSR,reg,old_data,data);
if ( addr < vol_reg )
{
// Oscillator

View File

@ -38,6 +38,7 @@ inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
{
last_amp = new_amp;
med_synth->offset( time, delta, output );
//good_synth->offset( time, delta, output );
}
}
@ -280,12 +281,12 @@ inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int
switch ( reg )
{
case 0:
case 0: //NR30
if ( !dac_enabled() )
enabled = false;
break;
case 1:
case 1: //NR31
length_ctr = max_len - data;
break;
@ -571,9 +572,9 @@ void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
{
// Calc volume
static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 }; //4 = 100%
int const volume_shift = 2;
int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB //AdamN: osc.regs[2]=apu.regs[12] (NR32)
int const volume_mul = volumes [volume_idx];
// Determine what will be generated
@ -585,10 +586,10 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
if ( dac_enabled() )
{
// Play inaudible frequencies as constant amplitude
amp = 8 << 4; // really depends on average of all samples in wave
amp = 8 << 4; // really depends on average of all samples in wave //AdamN: can we use this->last_amp instead?
// if delay is larger, constant amplitude won't start yet
if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
if ( frequency() <= 0x7FB || delay > 15 * clk_mul ) //2043
{
if ( volume_mul )
playing = (int) enabled;
@ -609,13 +610,14 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
// wave size and bank
int const size20_mask = 0x20;
int const flags = regs [0] & agb_mask;
int const wave_mask = (flags & size20_mask) | 0x1F;
int const flags = regs [0] & agb_mask; //AdamN: osc.regs[0]=apu.regs[10] (NR30)
int const wave_mask = (flags & size20_mask) | 0x1F; //AdamN: Bank Dimension
int swap_banks = 0;
if ( flags & bank40_mask )
if ( flags & bank40_mask ) //AdamN: Bank 1
{
swap_banks = flags & size20_mask;
swap_banks = flags & size20_mask; //AdamN: Bank Dimension, swap_banks = Use 2 Banks (64 digits)
wave += bank_size/2 - (swap_banks >> 1);
//wave = &this->wave_ram[bank_size/2 - (swap_banks >> 1)];
}
int ph = this->phase ^ swap_banks;
@ -640,13 +642,14 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
ph = (ph + 1) & wave_mask;
// Scale by volume
int amp = (nybble * volume_mul) >> (volume_shift + 4);
int amp = (nybble * volume_mul) >> (volume_shift + 4); //AdamN: should we use +dac_bias in here?
int delta = amp - lamp;
if ( delta )
{
lamp = amp;
med_synth->offset_inline( time, delta, out );
//good_synth->offset_inline( time, delta, out );
}
time += per;
}

View File

@ -165,11 +165,11 @@ private:
int period() const { return (2048 - frequency()) * (2 * clk_mul); }
// Non-zero if DAC is enabled
int dac_enabled() const { return regs [0] & 0x80; }
int dac_enabled() const { return regs [0] & 0x80; } //AdamN: osc.regs[0]=apu.regs[10]
void corrupt_wave();
BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; } //AdamN: osc.regs[0]=apu.regs[10]
// Wave index that would be accessed, or -1 if no access would occur
int access( unsigned addr ) const;

View File

@ -14,6 +14,8 @@
#include "gbSGB.h"
#include "gbSound.h"
#include "../Util.h"
#include "../gba/GBALink.h"
//#include "../gba/Globals.h"
#ifdef __GNUC__
#define _stricmp strcasecmp
@ -790,16 +792,81 @@ void gbWriteMemory(register u16 address, register u8 value)
}
case 0x01: {
#ifdef GBA_LOGGING
if(gbMemory[0xff01]!=value)
if(systemVerbose & VERBOSE_SIO) {
log("SioSB(%04X) : %02X %02X->%02X %d\n", PC.W-2, gbMemory[0xff02], gbMemory[0xff01], value, GetTickCount() ); //register_LY
}
#endif
gbMemory[0xff01] = value;
//if(value==0xff/*0x00*/) LinkFirstTime = true;
return;
}
// serial control
case 0x02: {
#ifdef GBA_LOGGING
if(gbMemory[0xff02]!=value)
if(systemVerbose & VERBOSE_SIO) {
log("SioSC(%04X) : %02X->%02X %02X %d\n", PC.W-2, gbMemory[0xff02], value, gbMemory[0xff01], GetTickCount() ); //register_LY
}
#endif
gbSerialOn = (value & 0x80);
//if(gba_link_enabled && lanlink.connected)
if( EmuReseted ||(gbMemory[0xff02] & 0x7c)||(value & 0x7c)||(!(value & 0x81)) ) { //trying to detect whether the game has exited multiplay mode, pokemon blue start w/ 0x7e while pocket racing start w/ 0x7c
LinkFirstTime = true;
if( EmuReseted ||(gbMemory[0xff02] & 0x7c)||(value & 0x7c) )
if(lanlink.connected)
if(linkid) lc.DiscardData();
else ls.DiscardData(1);
}
EmuReseted = false;
gbMemory[0xff02] = value;
if(gbSerialOn) {
gbSerialTicks = GBSERIAL_CLOCK_TICKS;
LinkIsWaiting = true;
//Do data exchange, master initiate the transfer
//may cause visual artifact if not processed immediately, is it due to IRQ stuff or invalid data being exchanged?
if( (value & 1) /*|| (!LinkFirstTime)*/ ) { //&& !linkid //internal clock
if(gbSerialFunction) {
gbSIO_SC = value;
LogStrPush("gbWrite");
//if(linkid /*&& (value & 1)*/) {gbMemory[0xff01] = 0xff; LinkFirstTime = true;} else
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbSerialFunction/gbStartLink/gbPrinter
LogStrPop(7);
} else gbMemory[0xff01]=0xff;
//gbSerialTicks = GBSERIAL_CLOCK_TICKS; //1; //0; //wrong value in gbSerialTicks could cause visual artifact
gbMemory[0xff02] &= 0x7f;
gbSerialOn = 0;
//if(register_IE & 8)
gbMemory[0xff0f] = register_IF |= 8;
//gbSerialBits = 0;
//LinkFirstTime = false;
//if(!(value & 1)) LinkFirstTime = true;
} /*else //external clock
{
u16 dat = 0;
//if(gbSerialFunction)
{
gbSIO_SC = value;
LogStrPush("gbWrite");
dat = gbLinkUpdate(gbMemory[0xff01]);
gbMemory[0xff01] = (dat >> 8); //gbSerialFunction/gbStartLink/gbPrinter
LogStrPop(7);
}
if(dat & 1) {
//gbSerialTicks = GBSERIAL_CLOCK_TICKS; //1; //0; //wrong value in gbSerialTicks could cause visual artifact
gbMemory[0xff02] &= 0x7f;
gbSerialOn = 0;
//if(register_IE & 8)
gbMemory[0xff0f] = register_IF |= 8;
//gbSerialBits = 0;
//LinkFirstTime = false;
//if(!(value & 1)) LinkFirstTime = true;
}
}*/
#ifdef OLD_GB_LINK
if(linkConnected) {
if(value & 1) {
@ -2174,6 +2241,8 @@ void gbGetHardwareType()
void gbReset()
{
EmuReseted = true;
LinkFirstTime = true;
gbGetHardwareType();
oldRegister_WY = 146;
@ -4487,6 +4556,8 @@ void gbDrawLine()
void gbEmulate(int ticksToStop)
{
if(EmuCtr>0) {log("Emu inside Emu:%d\n",EmuCtr);return;}
gbRegister tempRegister;
u8 tempValue;
s8 offset;
@ -4916,8 +4987,9 @@ void gbEmulate(int ticksToStop)
gbFrameCount++;
systemFrame();
if((gbFrameCount % 10) == 0)
system10Frames(60);
/*if((gbFrameCount % 10) == 0)
system10Frames(60);*/
system1Frames(60, gbFrameCount);
if(gbFrameCount >= 60) {
u32 currentTime = systemGetClock();
@ -5186,8 +5258,9 @@ void gbEmulate(int ticksToStop)
systemFrame();
if((gbFrameCount % 10) == 0)
system10Frames(60);
/*if((gbFrameCount % 10) == 0)
system10Frames(60);*/
system1Frames(60, gbFrameCount);
if(gbFrameCount >= 60) {
u32 currentTime = systemGetClock();
@ -5206,7 +5279,33 @@ void gbEmulate(int ticksToStop)
gbMemory[0xff41] = register_STAT;
// serial emulation
if(gbSerialOn) {
gbSerialOn = (gbMemory[0xff02] & 0x80);
/*if(gba_link_enabled && lanlink.connected && (register_LY>=144)) {
//if(gbSerialOn)
{
u16 dat = 0;
if(gbSerialFunction) { // external device
gbSIO_SC = gbMemory[0xff02];
LogStrPush("gbEmu");
if(!LinkFirstTime) dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1; else
dat = gbLinkUpdate(gbMemory[0xff01]);
gbMemory[0xff01] = (dat >> 8);
LogStrPop(5);
if(gbSerialOn && (dat & 1)) {
gbMemory[0xff02] &= 0x7f;
gbSerialOn = 0;
//if(register_IE & 8)
gbMemory[0xff0f] = register_IF |= 8;
}
} //else gbMemory[0xff01] = 0xff;
}
gbSerialTicks = 1; //GBSERIAL_CLOCK_TICKS; //0; //seems to cause varies visual artifact if gbSerialTicks value isn't right
gbSerialBits = 0;
}*/
static int SIOctr = 0;
SIOctr++;
if(!lanlink.speed || (SIOctr % 5))
if(gbSerialOn) { //Transfer Started
#ifdef OLD_GB_LINK
if(linkConnected) {
gbSerialTicks -= clockTicks;
@ -5229,7 +5328,7 @@ void gbEmulate(int ticksToStop)
}
} else {
#endif
if(gbMemory[0xff02] & 1) {
if(gbMemory[0xff02] & 1) { //internal clocks (master)
gbSerialTicks -= clockTicks;
// overflow
@ -5238,16 +5337,61 @@ void gbEmulate(int ticksToStop)
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
// increment number of shifted bits
gbSerialBits++;
if(gbSerialBits == 8) {
if(gbSerialBits >= 8) {
// end of transmission
if(gbSerialFunction) // external device
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
else
gbMemory[0xff01] = 0xff;
/*if(gbSerialFunction) { // external device
gbSIO_SC = gbMemory[0xff02];
LogStrPush("gbEmu");
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbStartLik/gbPrinter
LogStrPop(5);
LinkFirstTime = false;
} else
gbMemory[0xff01] = 0xff;*/
gbSerialTicks = 0;
//if(!linkid)
/*{
gbMemory[0xff02] &= 0x7f;
gbSerialOn = 0;
gbMemory[0xff0f] = register_IF |= 8;
}*/
gbSerialBits = 0;
} else
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
}
} else //external clocks (slave)
{
gbSerialTicks -= clockTicks;
// overflow
while(gbSerialTicks <= 0) {
// shift serial byte to right and put a 1 bit in its place
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
// increment number of shifted bits
gbSerialBits++;
if(gbSerialBits >= 8) {
// end of transmission
u16 dat = 0;
if(!LinkIsWaiting) {
if(lanlink.connected)
if(linkid) lc.DiscardData();
else ls.DiscardData(1);
} else
if(gbSerialFunction) { // external device
gbSIO_SC = gbMemory[0xff02];
LogStrPush("gbEmu");
if(!LinkFirstTime) dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1; else //external clock not suppose to start a transfer, but there are time where both side using external clock and couldn't communicate properly
dat = gbLinkUpdate(gbMemory[0xff01]);
gbMemory[0xff01] = (dat >> 8);
LogStrPop(5);
} //else
//gbMemory[0xff01] = 0xff;
gbSerialTicks = 0;
if(dat & 1) //if(linkid)
{
gbMemory[0xff02] &= 0x7f;
gbSerialOn = 0;
gbMemory[0xff0f] = register_IF |= 8;
}
gbSerialBits = 0;
} else
gbSerialTicks += GBSERIAL_CLOCK_TICKS;

View File

@ -1,6 +1,8 @@
#ifndef GBGLOBALS_H
#define GBGLOBALS_H
#define VERBOSE_SIO 2048
extern int gbRomSizeMask;
extern int gbRomSize;
extern int gbRamSize;

View File

@ -657,7 +657,7 @@ static void count(u32 opcode, int cond_res)
#define OP_MVN \
EMIT1(not, eax) \
EMIT2(mov, eax, REGREF1(esi))
#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL)
#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL) //AdamN: NOT eax doesn't affect any flags in x86 so need to add TEST for SETCOND_LOGICAL to works properly
// ALU cleanup macro
#define ALU_FINISH ALU_TRAILER

View File

@ -22,6 +22,10 @@
#include "agbprint.h"
#include "GBALink.h"
#ifdef _MSC_VER //#ifdef _WIN32
#include "../Win32/WinHelper.h" // AdamN: for CCriticalSection
#endif
#ifdef PROFILING
#include "prof/prof.h"
#endif
@ -32,6 +36,8 @@
extern int emulating;
extern bool AppTerminated = false;
int SWITicks = 0;
int IRQTicks = 0;
@ -59,6 +65,9 @@ bool cpuFlashEnabled = true;
bool cpuEEPROMEnabled = true;
bool cpuEEPROMSensorEnabled = false;
bool breakpt = false;
u32 breakaddr = 0xffffffff;
u32 cpuPrefetch[2];
int cpuTotalTicks = 0;
@ -815,7 +824,7 @@ static bool CPUReadState(gzFile gzFile)
THUMB_PREFETCH;
}
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); //WAITCNT
return true;
}
@ -1779,7 +1788,8 @@ void CPUSoftwareInterrupt(int comment)
#endif
if(useBios) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
//if(comment>0x2A) //AdamN: what is the idea of flooding the log with all interrupts?? having a stats showing how many times each interrupt being called might be more usefull than flooding
if(systemVerbose & VERBOSE_SWI) { //AdamN: trying to capture only the impossible (should be logged even when logging not enabled tho)
log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
@ -1827,31 +1837,31 @@ void CPUSoftwareInterrupt(int comment)
stopState = true;
cpuNextEvent = cpuTotalTicks;
break;
case 0x04:
case 0x04: //AdamN: IntrWait
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("IntrWait: 0x%08x,0x%08x (VCOUNT = %2d)\n",
reg[0].I,
reg[1].I,
reg[1].I, //AdamN: Interrupt flag(s) to wait for (same format as IE/IF registers)
VCOUNT);
}
#endif
CPUSoftwareInterrupt();
CPUSoftwareInterrupt(); //AdamN: Forcefully sets IME=1 and wait in Halt state until one (or more) of the specified interrupt(s) occurs.
break;
case 0x05:
case 0x05: //AdamN: this VBlankIntrWait oftenly called (every 1/60 sec) so it should be handled properly
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("VBlankIntrWait: (VCOUNT = %2d)\n",
VCOUNT);
}
#endif
CPUSoftwareInterrupt();
CPUSoftwareInterrupt(); //AdamN: set r0=1,r1=1 then execute IntrWait
break;
case 0x06:
CPUSoftwareInterrupt();
case 0x06: //AdamN: Div oftenly called so it should be handled properly
BIOS_Div(); //CPUSoftwareInterrupt();
break;
case 0x07:
CPUSoftwareInterrupt();
case 0x07: //AdamN: DivArm
BIOS_DivARM(); //CPUSoftwareInterrupt();
break;
case 0x08:
BIOS_Sqrt();
@ -1862,7 +1872,7 @@ void CPUSoftwareInterrupt(int comment)
case 0x0A:
BIOS_ArcTan2();
break;
case 0x0B:
case 0x0B: //AdamN: CpuSet oftenly called so it should be handled properly
{
int len = (reg[2].I & 0x1FFFFF) >>1;
if (!(((reg[0].I & 0xe000000) == 0) ||
@ -1888,7 +1898,7 @@ void CPUSoftwareInterrupt(int comment)
}
BIOS_CpuSet();
break;
case 0x0C:
case 0x0C: //AdamN: CpuFastSet oftenly called so it should be handled properly
{
int len = (reg[2].I & 0x1FFFFF) >>5;
if (!(((reg[0].I & 0xe000000) == 0) ||
@ -2005,7 +2015,7 @@ void CPUSoftwareInterrupt(int comment)
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("SoundBiasSet: 0x%08x (VCOUNT = %2d)\n",
reg[0].I,
reg[0].I, //AdamN: r0=BIAS Level (0=Level 000h, any other value=Level 200h), r1=Delay Count on NDS (GBA uses a fixed delay count of 8)
VCOUNT);
}
#endif
@ -2014,10 +2024,147 @@ void CPUSoftwareInterrupt(int comment)
else
soundResume();
break;
/*case 0x1A: //AdamN: SoundDriverInit, calling sequences after SoundDriverInit then SoundChannelClear then SoundDriverMode, then repeated SoundDriverVSync+SoundDriverMain
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("SoundDriverInit: 0x%08x (VCOUNT = %2d)\n",
reg[0].I, //AdamN: Pointer to SoundArea structure
VCOUNT);
}
#endif
CPUSoftwareInterrupt();
break;*/
case 0x1B: //AdamN: SoundDriverMode
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("SoundDriverMode: 0x%08x (VCOUNT = %2d)\n",
reg[0].I, //AdamN: Sound driver operation mode
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x1C: //AdamN: SoundDriverMain (no param)
//CPUSoftwareInterrupt(); //AdamN: Call (using/after SoundDriverVSync) every 1/60 of a second, immediately after the V-Blank interrupt. After that, this routine is called after BG and OBJ processing is executed.
break;
case 0x1D: //AdamN: SoundDriverVSync
//CPUSoftwareInterrupt(); //AdamN: Resets the sound DMA (no param) to sync the BIOS sound driver
break;
case 0x1E: //AdamN: SoundChannelClear
//CPUSoftwareInterrupt(); //AdamN: Clears all direct sound channels and stops the sound (no param)
break;
case 0x1F:
BIOS_MidiKey2Freq();
break;
case 0x2A:
case 0x20: //AdamN: SoundWhatever0/MusicPlayerOpen
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MusicPlayerOpen: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
reg[1].I,
reg[2].I,
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x21: //AdamN: SoundWhatever1/MusicPlayerStart
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MusicPlayerStart: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
reg[1].I,
reg[2].I,
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x22: //AdamN: SoundWhatever2/MusicPlayerStop
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MusicPlayerStop: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
reg[1].I,
reg[2].I,
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x23: //AdamN: SoundWhatever3/MusicPlayerContinue
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MusicPlayerContinue: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
reg[1].I,
reg[2].I,
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x24: //AdamN: SoundWhatever4/MusicPlayerFadeOut
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MusicPlayerFadeOut: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
armState ? armNextPC - 4: armNextPC -2,
reg[0].I,
reg[1].I,
reg[2].I,
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x25: //AdamN: MultiBoot
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("MultiBoot: 0x%08x,0x%08x (VCOUNT = %2d)\n",
reg[0].I, //AdamN: Pointer to MultiBootParam structure
reg[1].I, //AdamN: Transfer Mode
VCOUNT);
}
#endif
//CPUSoftwareInterrupt();
break;
case 0x26: //AdamN: HardReset
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("HardReset: (VCOUNT = %2d)\n",
VCOUNT);
}
#endif
CPUSoftwareInterrupt(); //Fully reset to Nintendo intro (no param)
break;
case 0x27: //AdamN: CustomHalt
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("CustomHalt: 0x%08x (VCOUNT = %2d)\n",
reg[2].I, //AdamN: 8bit param (00h=Halt, 80h=Stop)
VCOUNT);
}
#endif
CPUSoftwareInterrupt();
break;
case 0x28: //AdamN: SoundDriverVSyncOff
//CPUSoftwareInterrupt(); //AdamN: Stop sound DMA (no param) to prevent sound DMA from overflowing and playing noise when the game loading (as SoundDriverVSync might missed the 1/60sec interval)
break;
case 0x29: //AdamN: SoundDriverVSyncOn
//CPUSoftwareInterrupt(); //AdamN: Restarts the sound DMA stopped with SoundDriverVSyncOff (no param) to restore sound driver operation
break;
case 0x2A: //AdamN: SoundGetJumpList
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) {
log("SoundGetJumpList: 0x%08x (VCOUNT = %2d)\n",
reg[0].I, //AdamN: Destination address (must be aligned by 4) (120h bytes buffer)
VCOUNT);
}
#endif
BIOS_SndDriverJmpTableCopy();
// let it go, because we don't really emulate this function
default:
@ -2034,11 +2181,12 @@ void CPUSoftwareInterrupt(int comment)
if(!disableMessage) {
systemMessage(MSG_UNSUPPORTED_BIOS_FUNCTION,
N_("Unsupported BIOS function %02x called from %08x. A BIOS file is needed in order to get correct behaviour."),
N_("Unsupported BIOS Function %02X called from %08x. A BIOS file is needed in order to get correct behaviour."),
comment,
armMode ? armNextPC - 4: armNextPC - 2);
disableMessage = true;
}
//CPUSoftwareInterrupt(); //AdamN: not needed as it could cause the game to stop when there are no bios file
break;
}
}
@ -2405,6 +2553,9 @@ void CPUUpdateRegister(u32 address, u16 value)
{
case 0x00:
{ // we need to place the following code in { } because we declare & initialize variables in a case statement
/*if((value & 4)&&((DISPCNT & 0x0010)!=(value & 0x0010))) {
log("DISPCNT(%08x) : %04X->%04X %04X R0=%08X R1=%08X R2=%08X R14=%08X Z=%d (VCOUNT = %d)\n", armState ? armNextPC - 4: armNextPC -2, DISPCNT, value, DISPSTAT, reg[0].I, reg[1].I, reg[2].I, reg[14].I, Z_FLAG, VCOUNT);
}*/
if((value & 7) > 5) {
// display modes above 0-5 are prohibited
DISPCNT = (value & 7);
@ -2626,7 +2777,11 @@ void CPUUpdateRegister(u32 address, u16 value)
case 0x7c:
case 0x80:
case 0x84:
lastSR = value & 0xFF;
lastSA = address&0xFF;
soundEvent(address&0xFF, (u8)(value & 0xFF));
lastSR = value >> 8;
lastSA = (address&0xFF)+1;
soundEvent((address&0xFF)+1, (u8)(value>>8));
break;
case 0x82:
@ -2643,6 +2798,8 @@ void CPUUpdateRegister(u32 address, u16 value)
case 0x9a:
case 0x9c:
case 0x9e:
lastSR = value;
lastSA = address&0xFF;
soundEvent(address&0xFF, value);
break;
case 0xB0:
@ -2822,16 +2979,79 @@ void CPUUpdateRegister(u32 address, u16 value)
timerOnOffDelay|=8;
cpuNextEvent = cpuTotalTicks;
break;
case COMM_SIODATA32_L:
if(READ16LE(&ioMem[COMM_SIODATA32_L]) != value) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SIO) {
log("SIODATAL(%d) : %04X %04X %04X->%04X %04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), value, READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
}
#endif
}
UPDATE_REG(COMM_SIODATA32_L, value);
break;
case COMM_SIODATA32_H:
if(READ16LE(&ioMem[COMM_SIODATA32_H]) != value) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SIO) {
log("SIODATAH(%d) : %04X %04X %04X %04X->%04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), value, READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
}
#endif
}
UPDATE_REG(COMM_SIODATA32_H, value);
break;
case COMM_SIOCNT:
if(READ16LE(&ioMem[COMM_SIOCNT]) != (/*READ16LE(&ioMem[COMM_SIOCNT]) &*/ value)) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SIO) {
if(value & 0x4000)
log("SIOCNT(%08x) : %04X %04X->%04X %04X %04X %04X %04X %04X (VCOUNT = %d)\n", armState ? armNextPC - 4: armNextPC -2, READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), value, READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
}
#endif
}
if( EmuReseted ) { //trying to detect whether the game has exited multiplay mode (ie. game restarted)
EmuReseted = false;
LinkFirstTime = true;
if(lanlink.connected)
if(linkid) lc.DiscardData();
else ls.DiscardData(1);
}
//UPDATE_REG(COMM_SIOCNT, value);
lanlink.mode = GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]));
if(lanlink.mode!=GetSIOMode(READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_RCNT]))) LinkFirstTime = true;
StartLink(value);
/*switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) {
case MULTIPLAYER:
if(LinkHandlerActive) {
if (value & 0x80) { //AdamN: Start/Busy Bit.7=1 (Active/Transfering)
LinkCmdQueue(1,value);
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
//UPDATE_REG(COMM_SIOCNT, value); //AdamN: when using socket handler SIOCNT need to be updated as soon as possible because program might be reading it and ORing it for the next update
LinkParam1=value;
LinkCommand|=1; //AdamN: StartLink command
c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
} else UPDATE_REG(COMM_SIOCNT, value);
} else {
LogStrPush("CPUUpdReg");
//UPDATE_REG(COMM_SIOCNT, value); //just for testing the effect
if (value & 0x80) { //AdamN: Start/Busy Bit.7=1 (Active/Transfering)
StartLink(value); //AdamN: using blocking sockets here can cause noticibly delays
} else UPDATE_REG(COMM_SIOCNT, value);
LogStrPop(9);
}
break;
case NORMAL8:
case NORMAL32:
case UART:
default:
UPDATE_REG(COMM_SIOCNT, value);
break;
} */
/*
// old code path for no linking...
{
if (value & 0x80) {
if (value & 0x80) { //Start bit.7
value &= 0xff7f;
if ((value & 1) && (value & 0x4000)) {
if ((value & 1) && (value & 0x4000)) { //IRQ Enable bit.14
UPDATE_REG(COMM_SIODATA8, 0xFF);
IF |= 0x80;
UPDATE_REG(0x202, IF);
@ -2843,25 +3063,66 @@ void CPUUpdateRegister(u32 address, u16 value)
*/
break;
case COMM_SIODATA8:
if (gba_link_enabled)
LinkSSend(value);
UPDATE_REG(COMM_RCNT, value);
case COMM_SIODATA8: //AdamN: 8bit(SIODATA8) on Normal/UART(up to 4x8bit with FIFO), 16bit(SIOMLT_SEND) on Multiplayer mode
if(READ16LE(&ioMem[COMM_SIOMLT_SEND]) != (/*READ16LE(&ioMem[COMM_SIOMLT_SEND]) &*/ value)) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SIO) {
log("SIODATA(%d) : %04X %04X %04X %04X %04X %04X %04X->%04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), value, VCOUNT );
}
#endif
}
UPDATE_REG(COMM_SIODATA8, value); //COMM_SIOMLT_SEND
/*if (gba_link_enabled && lanlink.connected) //AdamN: added active connection checking, don't send any packet if there are no connection
LinkSSend(value); //AdamN: Does sending packet really needed in this part?(as transfers are initiated by SIOCNT)
UPDATE_REG(COMM_RCNT, value); //AdamN: is this really necessary?? seems to break connection
*/
/*if(linkid && (READ16LE(&ioMem[COMM_SIOMLT_SEND]) & 0x3f)==0x0f) {
lc.WaitForData(-1);
LinkUpdate2(0);
}*/
break;
case 0x130:
case 0x130: //AdamN: KEYINPUT
P1 |= (value & 0x3FF);
UPDATE_REG(0x130, P1);
break;
case 0x132:
case 0x132: //AdamN: KEYCNT
UPDATE_REG(0x132, value & 0xC3FF);
break;
case COMM_RCNT:
StartGPLink(value);
case COMM_RCNT: //AdamN: often reach here even when no connection yet
/*if(lanlink.connected)
if(linkid) {
lc.DiscardData(); //AdamN: discarding may cause server to wait for infinity
} else {
//ls.DiscardData();
}*/
lanlink.mode = GetSIOMode(READ16LE(&ioMem[COMM_SIOCNT]), value);
if(READ16LE(&ioMem[COMM_RCNT]) != (/*READ16LE(&ioMem[COMM_RCNT]) &*/ value)) {
#ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SIO) {
log("RCNT(%d) : %04X->%04X %04X %04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), value, READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), VCOUNT );
}
#endif
}
/*if(LinkHandlerActive) {
LinkCmdQueue(2,value);
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
LinkParam2=value;
LinkCommand|=2; //AdamN: StartGPLink command
c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
} else {
LogStrPush("CPUUpdReg");*/
StartGPLink(value); //AdamN: doesn't need to be put in different thread as it doesn't send/recv data
/*LogStrPop(9);
}*/
break;
/*case COMM_IR:
StartIRLink(value); //AdamN: not made yet tho, probably not useful
break;*/
case COMM_JOYCNT:
{
u16 cur = READ16LE(&ioMem[COMM_JOYCNT]);
@ -3128,6 +3389,8 @@ void CPUInit(const char *biosFileName, bool useBiosFile)
void CPUReset()
{
EmuReseted = true;
LinkFirstTime = true;
if(gbaSaveType == 0) {
if(eepromInUse)
gbaSaveType = 3;
@ -3475,21 +3738,27 @@ extern void winlog(const char *, ...);
void CPULoop(int ticks)
{
if(EmuCtr>0) {log("Emu inside Emu:%d\n",EmuCtr);return;}
int clockTicks;
int timerOverflow = 0;
// variable used by the CPU core
cpuTotalTicks = 0;
cpuBreakLoop = false; //
// shuffle2: what's the purpose?
if(gba_link_enabled)
cpuNextEvent = 1;
/*if(gba_link_enabled && lanlink.connected && lanlink.mode==MULTIPLAYER && frameCount < systemFrameSkip)
//if(linkid)
cpuNextEvent = 159; //224; //else; //AdamN: this is to prevent CPU from executing too many opcodes when frame being skipped which cause Linking instability (ie. in-game timeout reached on client)
else */
cpuNextEvent = CPUUpdateTicks(); //cpuNextEvent = 1; //224 //AdamN: this will cause slowdown?*/
bool NewFrame = false;
cpuBreakLoop = false;
cpuNextEvent = CPUUpdateTicks();
//cpuBreakLoop = false;
//cpuNextEvent = CPUUpdateTicks(); //
if(cpuNextEvent > ticks)
cpuNextEvent = ticks;
for(;;) {
#ifndef FINAL_VERSION
if(systemDebug) {
@ -3526,6 +3795,7 @@ void CPULoop(int ticks)
}
#endif /* FINAL_VERSION */
if(breakpt && armNextPC==breakaddr) holdState=true; //AdamN: checking for breakpoint
if(!holdState && !SWITicks) {
if(armState) {
if (!armExecute())
@ -3581,7 +3851,7 @@ void CPULoop(int ticks)
lcdTicks += 224;
DISPSTAT |= 2;
UPDATE_REG(0x04, DISPSTAT);
if(DISPSTAT & 16) {
if(DISPSTAT & 16) { // entering H-Blank
IF |= 2;
UPDATE_REG(0x202, IF);
}
@ -3608,12 +3878,15 @@ void CPULoop(int ticks)
DISPSTAT &= 0xFFFD;
if(VCOUNT == 160) {
count++;
NewFrame = true;
systemFrame();
if((count % 10) == 0) {
/*if((count % 10) == 0) {
system10Frames(60);
}
if(count == 60) {
}*/
system1Frames(60, count);
if(count >= 60) {
u32 time = systemGetClock();
if(time != lastTime) {
u32 t = 100000/(time - lastTime);
@ -3623,6 +3896,7 @@ void CPULoop(int ticks)
lastTime = time;
count = 0;
}
u32 joy = 0;
// update joystick information
if(systemReadJoypads())
@ -3667,11 +3941,12 @@ void CPULoop(int ticks)
DISPSTAT |= 1;
DISPSTAT &= 0xFFFD;
UPDATE_REG(0x04, DISPSTAT);
if(DISPSTAT & 0x0008) {
if(DISPSTAT & 0x0008) { //entering V-Blank
IF |= 1;
UPDATE_REG(0x202, IF);
}
CPUCheckDMA(1, 0x0f);
if(frameCount >= framesToSkip) {
systemDrawScreen();
frameCount = 0;
@ -3786,7 +4061,10 @@ void CPULoop(int ticks)
}
break;
}
}
} //else //AdamN: this seems to fix the instability of linking when frame being skipped, but it causes artifact at the top lines when connection established in game, does cpu executes more opcodes when frameskipped?
//frameCount++; //AdamN: shouldn't increase frameCount here, instead do something useless just to delay before calling LinkUpdate to maintain stability
//if(lanlink.connected) if(linkid) cpuNextEvent = cpuTotalTicks;/*lc.WaitForData(0); else ls.WaitForData(0);*/
// entering H-Blank
DISPSTAT |= 2;
UPDATE_REG(0x04, DISPSTAT);
@ -3796,6 +4074,7 @@ void CPULoop(int ticks)
IF |= 2;
UPDATE_REG(0x202, IF);
}
//
}
}
}
@ -3942,8 +4221,21 @@ void CPULoop(int ticks)
if (gba_joybus_enabled)
JoyBusUpdate(clockTicks);
if (gba_link_enabled)
LinkUpdate(clockTicks);
if (gba_link_enabled && (lanlink.connected || !lanlink.active)) { //AdamN: don't update if there are no connection
LinkUpdate(clockTicks); //AdamN: when frame being skipped LinkUpdate might not be called(?) thus causing instability
NewFrame = false;
//if(LinkHandlerActive) {
//LinkCmdQueue(8,clockTicks);
//c_s.Lock(); //AdamN: Locking resource to prevent deadlock
//LinkParam8=clockTicks;
//LinkCommand|=8; //AdamN: LinkUpdate command
//c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
//} else if(/*(clockTicks & 1)&&*/(lanlink.connected)) { //AdamN: it seems LinkUpdate need to be called every cycle, occasionally doesn't works
//LogStrPush("CPULoop");
//LinkUpdate2(clockTicks); //AdamN: using blocking sockets here can cause noticibly delays
//LogStrPop(7);
//}
}
cpuNextEvent = CPUUpdateTicks();
@ -3960,8 +4252,11 @@ void CPULoop(int ticks)
}
// shuffle2: what's the purpose?
if(gba_link_enabled)
cpuNextEvent = 1;
/*if(gba_link_enabled && lanlink.connected)
cpuNextEvent = 1; //AdamN: this will cause great slowdown*/
/*if(gba_link_enabled && lanlink.connected && lanlink.mode==MULTIPLAYER && frameCount < systemFrameSkip)
//if(linkid)
cpuNextEvent = 159; //224;*/ //cpuTotalTicks+224; //AdamN: this is to prevent CPU from executing too many opcodes when frame being skipped which cause Linking instability (ie. in-game timeout reached on client)
if(IF && (IME & 1) && armIrqEnable) {
int res = IF & IE;

View File

@ -66,6 +66,12 @@ extern bool armState;
extern int armMode;
extern void (*cpuSaveGameFunc)(u32,u8);
extern int cpuNextEvent;
extern int cpuTotalTicks;
extern bool holdState;
extern bool breakpt;
extern u32 breakaddr;
#ifdef BKPT_SUPPORT
extern u8 freezeWorkRAM[0x40000];
extern u8 freezeInternalRAM[0x8000];

File diff suppressed because it is too large Load Diff

View File

@ -4,30 +4,41 @@
#include <SFML/Network.hpp>
#endif
#ifdef _MSC_VER //#ifdef _WIN32
#include "../Win32/WinHelper.h" // AdamN: for CCriticalSection
#endif
#define LINK_PARENTLOST 0x80
#define UNSUPPORTED -1
#define MULTIPLAYER 0
#define NORMAL8 1
#define NORMAL32 2
#define NORMAL32 2 //AdamN: wireless use normal32 also
#define UART 3
#define JOYBUS 4
#define GP 5
#define INFRARED 6 //AdamN: Infrared Register at 4000136h
#define RFU_INIT 0
#define RFU_COMM 1
#define RFU_SEND 2
#define RFU_RECV 3
#define COMM_SIODATA32_L 0x120
#define COMM_SIODATA32_H 0x122
#define COMM_SIODATA32_L 0x120 //AdamN: Lower 16bit on Normal mode
#define COMM_SIODATA32_H 0x122 //AdamN: Higher 16bit on Normal mode
#define COMM_SIOMULTI0 0x120 //AdamN: SIOMULTI0 (16bit) on MultiPlayer mode (Parent/Master)
#define COMM_SIOMULTI1 0x122 //AdamN: SIOMULTI1 (16bit) on MultiPlayer mode (Child1/Slave1)
#define COMM_SIOMULTI2 0x124 //AdamN: SIOMULTI2 (16bit) on MultiPlayer mode (Child2/Slave2)
#define COMM_SIOMULTI3 0x126 //AdamN: SIOMULTI3 (16bit) on MultiPlayer mode (Child3/Slave3)
#define COMM_SIOCNT 0x128
#define COMM_SIODATA8 0x12a
#define COMM_RCNT 0x134
#define COMM_SIODATA8 0x12a //AdamN: 8bit on Normal/UART mode, (up to 4x8bit with FIFO)
#define COMM_SIOMLT_SEND 0x12a //AdamN: SIOMLT_SEND (16bit R/W) on MultiPlayer mode (local outgoing)
#define COMM_RCNT 0x134 //AdamN: SIO Mode (4bit data) on GeneralPurpose mode
#define COMM_IR 0x136 //AdamN: Infrared Register (16bit) 1bit data at a time(LED On/Off)?
#define COMM_JOYCNT 0x140
#define COMM_JOY_RECV_L 0x150
#define COMM_JOY_RECV_L 0x150 //AdamN: Send/Receive 8bit Lower first then 8bit Higher
#define COMM_JOY_RECV_H 0x152
#define COMM_JOY_TRANS_L 0x154
#define COMM_JOY_TRANS_L 0x154 //AdamN: Send/Receive 8bit Lower first then 8bit Higher
#define COMM_JOY_TRANS_H 0x156
#define COMM_JOYSTAT 0x158
#define COMM_JOYSTAT 0x158 //AdamN: Send/Receive 8bit lower only
#define JOYSTAT_RECV 2
#define JOYSTAT_SEND 8
@ -53,11 +64,14 @@ typedef struct {
int lastlinktime;
u8 numgbas;
u8 linkflags;
int rfu_q[4];
u8 rfu_request[4];
int rfu_linktime[4];
u32 rfu_bdata[4][7];
u32 rfu_data[4][32];
int rfu_q[5];
u16 rfu_qid[5];
u8 rfu_request[5];
u16 rfu_reqid[5];
int rfu_linktime[5];
u32 rfu_bdata[5][7]; //for 0x16/0x1d/0x1e?
u32 rfu_gdata[5]; //for 0x17/0x19?/0x1e?
u32 rfu_data[5][32]; //for 0x24-0x26
} LINKDATA;
class lserver{
@ -65,56 +79,81 @@ class lserver{
fd_set fdset;
timeval wsocktimeout;
//timeval udptimeout;
public:
char inbuffer[256], outbuffer[256];
int *intinbuffer;
u16 *u16inbuffer;
u32 *u32inbuffer;
int *intoutbuffer;
u16 *u16outbuffer;
u32 *u32outbuffer;
int insize, outsize;
int counter;
int done;
public:
int howmanytimes;
SOCKET tcpsocket[4];
SOCKADDR_IN udpaddr[4];
SOCKET tcpsocket[5];
SOCKADDR_IN udpaddr[5];
DWORD latency[5];
lserver(void);
int Init(void*);
void Send(void);
void Recv(void);
BOOL Send(void);
BOOL Recv(void);
BOOL WaitForData(int ms);
BOOL SendData(int size, int nretry = 0);
BOOL SendData(const char *buf, int size, int nretry = 0);
BOOL RecvData(int size, int idx, bool peek = false);
BOOL IsDataReady(void);
int DiscardData(int idx);
};
class lclient{
fd_set fdset;
timeval wsocktimeout;
public:
char inbuffer[256], outbuffer[256];
int *intinbuffer;
u16 *u16inbuffer;
u32 *u32inbuffer;
int *intoutbuffer;
u16 *u16outbuffer;
int numbytes;
public:
u32 *u32outbuffer;
int numbytes, insize, outsize;
bool oncesend;
SOCKADDR_IN serverinfo;
SOCKET noblock;
int numtransfers;
lclient(void);
int Init(LPHOSTENT, void*);
void Send(void);
void Recv(void);
BOOL Send(void);
BOOL Recv(void);
void CheckConn(void);
BOOL SendData(int size, int nretry = 0);
BOOL SendData(const char *buf, int size, int nretry = 0);
BOOL RecvData(int size, bool peek = false);
BOOL WaitForData(int ms);
BOOL IsDataReady(void);
int DiscardData(void);
};
typedef struct {
SOCKET tcpsocket;
//SOCKET udpsocket;
DWORD latency;
int numgbas;
HANDLE thread;
u8 type;
u8 server;
bool terminate;
bool connected;
bool speed;
bool speed; //speedhack
bool active;
int mode;
} LANLINKDATA;
typedef struct {
u16 Command;
u16 Param;
} LINKCMDPRM;
#endif
extern bool gba_joybus_enabled;
@ -124,24 +163,47 @@ extern sf::IPAddress joybusHostAddr;
extern void JoyBusConnect();
extern void JoyBusShutdown();
extern void JoyBusUpdate(int ticks);
extern inline int GetSIOMode(u16 siocnt, u16 rcnt);
extern bool gba_link_enabled;
#ifdef _MSC_VER
extern void LogStrPush(const char *str);
extern void LogStrPop(int len);
extern void LinkCmdQueue(u16 Cmd, u16 Prm);
extern u8 gbStartLink(u8 b);
extern u16 gbLinkUpdate(u8 b);
extern void StartLink(u16);
extern void StartLink2(u16);
extern void StartGPLink(u16);
extern void LinkSSend(u16);
extern void LinkUpdate(int);
extern void LinkUpdate2(int ticks, int FrameCnt);
extern void LinkChildStop();
extern void LinkChildSend(u16);
extern void CloseLanLink();
extern void CloseLink(); //CloseLanLink(); //AdamN: this should be CloseLink isn't?
extern char *MakeInstanceFilename(const char *Input);
extern LANLINKDATA lanlink;
extern int vbaid;
extern bool rfu_enabled;
extern int linktimeout;
extern u8 gbSIO_SC;
extern lclient lc;
extern lserver ls;
extern int linkid;
extern bool linkdatarecvd[4];
extern bool LinkIsWaiting;
extern bool LinkFirstTime;
extern bool EmuReseted;
extern int EmuCtr;
extern WinHelper::CCriticalSection c_s; //AdamN: critical section object to lock shared resource on multithread as CWnd is not thread-safe
extern int LinkCommand;
extern int LinkParam1;
extern int LinkParam2;
extern int LinkParam4;
extern int LinkParam8;
extern bool LinkHandlerActive;
//extern CPtrList LinkCmdList;
#else // These are stubbed for now
inline void StartLink(u16){}
inline void StartGPLink(u16){}

View File

@ -15,6 +15,8 @@
#define VERBOSE_UNDEFINED 256
#define VERBOSE_AGBPRINT 512
#define VERBOSE_SOUNDOUTPUT 1024
#define VERBOSE_SIO 2048
#define VERBOSE_LINK 4096
extern reg_pair reg[45];
extern bool ioReadable[0x400];

View File

@ -303,7 +303,7 @@ void soundEvent(u32 address, u16 data)
{
switch ( address )
{
case SGCNT0_H:
case SGCNT0_H: //SOUNDCNT_H
write_SGCNT0_H( data );
break;
@ -319,7 +319,7 @@ void soundEvent(u32 address, u16 data)
WRITE16LE( &ioMem[address], data );
break;
case 0x88:
case 0x88: //SOUNDBIAS
data &= 0xC3FF;
WRITE16LE( &ioMem[address], data );
break;

View File

@ -856,7 +856,7 @@ void BIOS_RegisterRamReset(u32 flags)
// no need to trace here. this is only called directly from GBA.cpp
// to emulate bios initialization
CPUUpdateRegister(0x0, 0x80);
CPUUpdateRegister(0x0, 0x80); //DISPCNT
if(flags) {
if(flags & 0x01) {
@ -894,35 +894,35 @@ void BIOS_RegisterRamReset(u32 flags)
for(i = 0; i < 0x18; i++)
CPUUpdateRegister(0xb0+i*2, 0);
CPUUpdateRegister(0x130, 0);
CPUUpdateRegister(0x20, 0x100);
CPUUpdateRegister(0x30, 0x100);
CPUUpdateRegister(0x26, 0x100);
CPUUpdateRegister(0x36, 0x100);
CPUUpdateRegister(0x130, 0); //KEYINPUT
CPUUpdateRegister(0x20, 0x100); //BG2PA
CPUUpdateRegister(0x30, 0x100); //BG3PA
CPUUpdateRegister(0x26, 0x100); //BG2PD
CPUUpdateRegister(0x36, 0x100); //BG3PD
}
if(flags & 0x20) {
int i;
for(i = 0; i < 8; i++)
CPUUpdateRegister(0x110+i*2, 0);
CPUUpdateRegister(0x134, 0x8000);
CPUUpdateRegister(0x110+i*2, 0); //Unused Registers after Timer Register?
CPUUpdateRegister(0x134, 0x8000); //COMM_RCNT for GP/JOYBUS?
for(i = 0; i < 7; i++)
CPUUpdateRegister(0x140+i*2, 0);
CPUUpdateRegister(0x140+i*2, 0); //Unused Registers after COMM_JOYCNT?
}
if(flags & 0x40) {
int i;
CPUWriteByte(0x4000084, 0);
CPUWriteByte(0x4000084, 0x80);
CPUWriteMemory(0x4000080, 0x880e0000);
CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
CPUWriteByte(0x4000070, 0x70);
CPUWriteByte(0x4000084, 0); //SOUNDCNT_X, Is this realy needed as below it's rewritten right?
CPUWriteByte(0x4000084, 0x80); //SOUNDCNT_X, Rewritten above?
CPUWriteMemory(0x4000080, 0x880e0000); //SOUNDCNT_L
CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff); //SOUNDBIAS
CPUWriteByte(0x4000070, 0x70); //SOUND3CNT_L
for(i = 0; i < 8; i++)
CPUUpdateRegister(0x90+i*2, 0);
CPUWriteByte(0x4000070, 0);
CPUWriteByte(0x4000070, 0); //SOUND3CNT_L, Rewritten again?
for(i = 0; i < 8; i++)
CPUUpdateRegister(0x90+i*2, 0);
CPUWriteByte(0x4000084, 0);
CPUWriteByte(0x4000084, 0); //SOUNDCNT_X, Another Rewriten??
}
}
}

View File

@ -43,6 +43,8 @@ public:
void reset(); // stop and reset the secondary sound buffer
void resume(); // resume the secondary sound buffer
void write(u16 * finalWave, int length); // write the emulated sound to the secondary sound buffer
// Configuration Changes
void setThrottle( unsigned short throttle );
};
@ -191,6 +193,8 @@ bool DirectSound::init(long sampleRate)
return false;
}
setThrottle(theApp.throttle); //AdamN: setting sound pitch to current throttle
return true;
}
@ -240,7 +244,7 @@ void DirectSound::write(u16 * finalWave, int length)
LPVOID lpvPtr2;
DWORD dwBytes2 = 0;
if( !speedup && synchronize && !theApp.throttle ) {
if( !speedup && synchronize /*&& !theApp.throttle*/ ) {
hr = dsbSecondary->GetStatus(&status);
if( status & DSBSTATUS_PLAYING ) {
if( !soundPaused ) {
@ -310,6 +314,18 @@ void DirectSound::write(u16 * finalWave, int length)
}
}
void DirectSound::setThrottle( unsigned short throttle ) //AdamN: doesn't works quite right yet
{
if(!pDirectSound) return;
if( dsbSecondary == NULL ) return;
if( throttle == 0 ) throttle = 100;
//HRESULT hr = dsbPrimary->SetFrequency( (DWORD)(soundGetSampleRate() * throttle / 100.0f) ); //AdamN: may not be valid for primary buffer, also need to check CAPS whether frequency is supported or not
//ASSERT( hr == S_OK );
HRESULT hr = dsbSecondary->SetFrequency( (DWORD)(soundGetSampleRate() * throttle / 100.0f) ); //AdamN: may need to use IDirectMusicSegment8::SetLength to adjust the inverval for looping to prevent silence when pitch is higher than normal pitch or restarted/relooped when pitch is lower than normal before it finished the whole stream
ASSERT( hr == S_OK );
}
SoundDriver *newDirectSound()
{
return new DirectSound();

View File

@ -33,10 +33,15 @@ Disassemble::Disassemble(CWnd* pParent /*=NULL*/)
m_t = FALSE;
m_v = FALSE;
m_z = FALSE;
m_breakpt = FALSE;
m_autostep = FALSE;
mode = -1;
//}}AFX_DATA_INIT
mode = 0;
address = 0;
//breakaddr = 0xffffffff;
//breakpt = false;
autostep = false;
autoUpdate = false;
count = 1;
}
@ -56,6 +61,9 @@ void Disassemble::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_V, m_v);
DDX_Check(pDX, IDC_Z, m_z);
DDX_Radio(pDX, IDC_AUTOMATIC, mode);
DDX_Check(pDX, IDC_BREAK_AT, m_breakpt);
DDX_Control(pDX, IDC_ADDRESS2, m_address2);
DDX_Check(pDX, IDC_AUTO_STEP, m_autostep);
//}}AFX_DATA_MAP
}
@ -73,6 +81,8 @@ BEGIN_MESSAGE_MAP(Disassemble, CDialog)
ON_BN_CLICKED(IDC_THUMB, OnThumb)
ON_WM_VSCROLL()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BREAK_AT, &Disassemble::OnBnClickedBreakAt)
ON_BN_CLICKED(IDC_STEPINTO, &Disassemble::OnBnClickedStepinto)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
@ -338,3 +348,38 @@ void Disassemble::PostNcDestroy()
{
delete this;
}
void Disassemble::OnBnClickedBreakAt()
{
// TODO: Add your control notification handler code here
CString buffer;
m_address2.GetWindowText(buffer);
sscanf(buffer, "%x", &breakaddr);
//if (mode==1)
breakaddr&=0xfffffffc;
//else if (mode==2)
// breakaddr&=0xfffffffe;
m_breakpt = !m_breakpt;
breakpt = (bool)m_breakpt;
refresh();
}
void Disassemble::OnBnClickedStepinto()
{
// TODO: Add your control notification handler code here
if(rom != NULL)
{
if(armState)
breakaddr = breakaddr + 4;
else
breakaddr = breakaddr + 2;
char buffer[20];
sprintf(buffer, _T("%08x"), breakaddr);
m_address2.SetWindowText(buffer);
cpuNextEvent = 1; //cpuTotalTicks;
holdState = false;
refresh();
}
}

View File

@ -22,13 +22,17 @@ class Disassemble : public ResizeDlg, IUpdateListener
void refresh();
int count;
bool autoUpdate;
//bool breakpt;
bool autostep;
u32 address;
//u32 breakaddr;
Disassemble(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(Disassemble)
enum { IDD = IDD_DISASSEMBLE };
CEdit m_address;
CEdit m_address2;
CListBox m_list;
BOOL m_c;
BOOL m_f;
@ -37,6 +41,8 @@ class Disassemble : public ResizeDlg, IUpdateListener
BOOL m_t;
BOOL m_v;
BOOL m_z;
BOOL m_breakpt;
BOOL m_autostep;
int mode;
//}}AFX_DATA
@ -67,6 +73,9 @@ class Disassemble : public ResizeDlg, IUpdateListener
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBreakAt();
afx_msg void OnBnClickedStepinto();
};
//{{AFX_INSERT_LOCATION}}

View File

@ -1,8 +1,13 @@
#include "stdafx.h"
//#include "afxctl.h"
#include "vba.h"
#include "LinkOptions.h"
#include "../gba/GBALink.h"
/*#ifdef _MSC_VER //#ifdef _WIN32
#include "WinHelper.h" // AdamN: MFC MultiThreading
#endif*/
extern lserver ls;
#ifdef _DEBUG
@ -49,7 +54,7 @@ void LinkOptions::DoDataExchange(CDataExchange* pDX)
BOOL LinkOptions::OnInitDialog(){
TCITEM tabitem;
char tabtext[3][8] = {"General", "Server", "Client"};
char tabtext[3][8] = {_T("General"), _T("Server"), _T("Client")};
int i;
CDialog::OnInitDialog();
@ -145,6 +150,11 @@ void LinkServer::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(LinkServer)
BOOL ok = (theApp.cartridgeType != IMAGE_GB);
GetDlgItem(IDC_LINK3P)->EnableWindow(ok);
GetDlgItem(IDC_LINK4P)->EnableWindow(ok);
GetDlgItem(IDC_LINK5P)->EnableWindow(rfu_enabled && ok);
DDX_Radio(pDX, IDC_LINK2P, m_numplayers);
DDX_Radio(pDX, IDC_LINKTCP, m_prottype);
DDX_Check(pDX, IDC_SSPEED, m_speed);
@ -195,7 +205,7 @@ BOOL LinkServer::OnInitDialog()
{
CDialog::OnInitDialog();
m_numplayers = lanlink.numgbas;
m_numplayers = max(lanlink.numgbas-1,0);
m_prottype = lanlink.type;
m_speed = lanlink.speed;
@ -455,14 +465,14 @@ void LinkOptions::OnOk()
void LinkGeneral::OnRadio1()
{
m_type = 0;
lanlink.active = 0;
lanlink.active = 0; //Single Computer
GetParent()->Invalidate();
}
void LinkGeneral::OnRadio2()
{
m_type = 1;
lanlink.active = 1;
lanlink.active = 1; //Networks
GetParent()->Invalidate();
}
@ -473,7 +483,7 @@ BOOL LinkGeneral::OnInitDialog(){
CDialog::OnInitDialog();
m_timeout.LimitText(5);
sprintf(timeout, "%d", linktimeout);
sprintf(timeout, _T("%d"), linktimeout);
m_timeout.SetWindowText(timeout);
m_type = lanlink.active;
@ -504,8 +514,8 @@ void LinkServer::OnServerStart()
if((errorcode=ls.Init(&dlg))!=0){
char message[50];
sprintf(message, "Error %d occured.\nPlease try again.", errorcode);
MessageBox(message, "Error", MB_OK);
sprintf(message, _T("Error %d occured.\nPlease try again."), errorcode);
MessageBox(message, _T("Error"), MB_OK);
return;
}
@ -520,6 +530,7 @@ BOOL LinkClient::OnInitDialog()
m_prottype = lanlink.type;
m_hacks = lanlink.speed;
m_serverip.SetWindowText(_T("localhost"));
UpdateData(FALSE);
@ -541,9 +552,10 @@ void LinkClient::OnLinkConnect()
m_serverip.GetWindowText(ipaddress, 30);
if((errorcode=lc.Init(gethostbyname(ipaddress), &dlg))!=0){
char message[50];
sprintf(message, "Error %d occured.\nPlease try again.", errorcode);
MessageBox(message, "Error", MB_OK);
sprintf(message, _T("Error %d occured.\nPlease try again."), errorcode);
MessageBox(message, _T("Error"), MB_OK);
return;
}
dlg.DoModal();
@ -557,7 +569,7 @@ void LinkOptions::GetAllData(LinkGeneral *src)
src->UpdateData(true);
src->m_timeout.GetWindowText(timeout, 5);
sscanf(timeout, "%d", &linktimeout);
sscanf(timeout, _T("%d"), &linktimeout);
if(src->m_type==0){
lanlink.speed = 0;
@ -593,6 +605,7 @@ void ServerWait::DoDataExchange(CDataExchange* pDX)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(ServerWait, CDialog)
//{{AFX_MSG_MAP(ServerWait)
ON_BN_CLICKED(ID_CANCEL, OnCancel)
@ -604,7 +617,9 @@ END_MESSAGE_MAP()
void ServerWait::OnCancel()
{
lanlink.terminate = true;
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
lanlink.terminate = true; //AdamN: accessing this might not be thread-safe w/o locking
c_s.Unlock(); //AdamN: Unlock it after use
CDialog::OnCancel();
}

View File

@ -33,6 +33,7 @@ Logging::Logging(CWnd* pParent /*=NULL*/)
m_dma3 = FALSE;
m_agbprint = FALSE;
m_undefined = FALSE;
m_sio = FALSE;
//}}AFX_DATA_INIT
}
@ -52,6 +53,8 @@ void Logging::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_VERBOSE_AGBPRINT, m_agbprint);
DDX_Check(pDX, IDC_VERBOSE_UNDEFINED, m_undefined);
DDX_Check(pDX, IDC_VERBOSE_SOUNDOUTPUT, m_sound_output);
DDX_Check(pDX, IDC_VERBOSE_SIO, m_sio);
DDX_Check(pDX, IDC_VERBOSE_LINK, m_link);
}
@ -69,10 +72,13 @@ BEGIN_MESSAGE_MAP(Logging, CDialog)
ON_BN_CLICKED(IDC_VERBOSE_UNALIGNED_ACCESS, OnVerboseUnalignedAccess)
ON_BN_CLICKED(IDC_VERBOSE_UNDEFINED, OnVerboseUndefined)
ON_BN_CLICKED(IDC_VERBOSE_SOUNDOUTPUT, OnVerboseSoundoutput)
ON_BN_CLICKED(IDC_VERBOSE_SIO, OnVerboseSIO)
ON_BN_CLICKED(IDC_SAVE, OnSave)
ON_EN_ERRSPACE(IDC_LOG, OnErrspaceLog)
ON_EN_MAXTEXT(IDC_LOG, OnMaxtextLog)
ON_WM_CLOSE()
// ON_BN_CLICKED(IDC_VERBOSE_LINK, &Logging::OnBnClickedVerboseLink)
ON_BN_CLICKED(IDC_VERBOSE_LINK, &Logging::OnVerboseLink)
END_MESSAGE_MAP()
@ -147,6 +153,16 @@ void Logging::OnVerboseSoundoutput()
systemVerbose ^= VERBOSE_SOUNDOUTPUT;
}
void Logging::OnVerboseSIO()
{
systemVerbose ^= VERBOSE_SIO;
}
void Logging::OnVerboseLink()
{
systemVerbose ^= VERBOSE_LINK;
}
void Logging::OnSave()
{
int len = m_log.GetWindowTextLength();
@ -213,6 +229,8 @@ BOOL Logging::OnInitDialog()
m_undefined = (systemVerbose & VERBOSE_UNDEFINED) != 0;
m_agbprint = (systemVerbose & VERBOSE_AGBPRINT) != 0;
m_sound_output = (systemVerbose & VERBOSE_SOUNDOUTPUT) != 0;
m_sio = (systemVerbose & VERBOSE_SIO) != 0;
m_link = (systemVerbose & VERBOSE_LINK) != 0;
UpdateData(FALSE);
m_log.LimitText(-1);
@ -293,3 +311,7 @@ void toolsClearLog()
Logging::instance->clearLog();
}
}

View File

@ -27,6 +27,8 @@ public:
BOOL m_agbprint;
BOOL m_undefined;
BOOL m_sound_output;
BOOL m_sio;
BOOL m_link;
// Overrides
protected:
@ -47,6 +49,8 @@ protected:
afx_msg void OnVerboseUnalignedAccess();
afx_msg void OnVerboseUndefined();
afx_msg void OnVerboseSoundoutput();
afx_msg void OnVerboseSIO();
afx_msg void OnVerboseLink();
afx_msg void OnSave();
afx_msg void OnClose();
afx_msg void OnErrspaceLog();

View File

@ -40,7 +40,12 @@
void MainWnd::OnOptionsFrameskipThrottleNothrottle()
{
theApp.updateThrottle( 0 ); // disable
theApp.autoFrameSkip = false;
/*if(theApp.autoFrameSkip) {
frameSkip = 0;
gbFrameSkip = 0;
systemFrameSkip = 0;
}
theApp.autoFrameSkip = false;*/
}
void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
@ -52,7 +57,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
void MainWnd::OnOptionsFrameskipThrottle25()
{
theApp.updateThrottle( 25 );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
@ -64,7 +69,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
void MainWnd::OnOptionsFrameskipThrottle50()
{
theApp.updateThrottle( 50 );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
@ -76,7 +81,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
void MainWnd::OnOptionsFrameskipThrottle100()
{
theApp.updateThrottle( 100 );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
@ -88,7 +93,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
void MainWnd::OnOptionsFrameskipThrottle150()
{
theApp.updateThrottle( 150 );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
@ -100,7 +105,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
void MainWnd::OnOptionsFrameskipThrottle200()
{
theApp.updateThrottle( 200 );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
void MainWnd::OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI)
@ -116,7 +121,7 @@ void MainWnd::OnOptionsFrameskipThrottleOther()
if( v ) {
theApp.updateThrottle( v );
theApp.autoFrameSkip = false;
//theApp.autoFrameSkip = false;
}
}
@ -137,12 +142,16 @@ void MainWnd::OnOptionsFrameskipAutomatic()
theApp.autoFrameSkip = !theApp.autoFrameSkip;
if(!theApp.autoFrameSkip && emulating)
theApp.updateFrameSkip();
else
else if(theApp.autoFrameSkip)
{
theApp.throttle = false;
frameSkip = 0;
//theApp.throttle = false;
frameSkip = 9;
gbFrameSkip = 9;
systemFrameSkip = 0;
}
//frameSkip = 0;
//gbFrameSkip = 0;
//systemFrameSkip = 0;
}
void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
@ -152,6 +161,7 @@ void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
BOOL MainWnd::OnOptionsFrameskip(UINT nID)
{
//theApp.autoFrameSkip = false;
switch(nID) {
case ID_OPTIONS_VIDEO_FRAMESKIP_0:
case ID_OPTIONS_VIDEO_FRAMESKIP_1:
@ -166,7 +176,7 @@ BOOL MainWnd::OnOptionsFrameskip(UINT nID)
}
if(emulating)
theApp.updateFrameSkip();
theApp.updateThrottle( 0 );
//theApp.updateThrottle( 0 );
return TRUE;
break;
case ID_OPTIONS_VIDEO_FRAMESKIP_6:
@ -180,7 +190,7 @@ BOOL MainWnd::OnOptionsFrameskip(UINT nID)
}
if(emulating)
theApp.updateFrameSkip();
theApp.updateThrottle( 0 );
//theApp.updateThrottle( 0 );
return TRUE;
break;
}
@ -585,8 +595,13 @@ void MainWnd::OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI)
void MainWnd::OnOptionsEmulatorSynchronize()
{
synchronize = !synchronize;
if (synchronize)
theApp.throttle = false;
if (synchronize) {
//theApp.throttle = false;
//theApp.autoFrameSkip = false;
frameSkip = 0;
gbFrameSkip = 0;
systemFrameSkip = 0;
}
}
void MainWnd::OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI)
@ -1023,6 +1038,8 @@ void MainWnd::OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI)
void MainWnd::OnOptionsGameboyPrinter()
{
theApp.winGbPrinterEnabled = !theApp.winGbPrinterEnabled;
if(gba_link_enabled)
gbSerialFunction = gbStartLink; else
if(theApp.winGbPrinterEnabled)
gbSerialFunction = gbPrinterSend;
else
@ -1560,7 +1577,7 @@ void MainWnd::OnOptionsLinkRFU()
if(rfu_enabled) rfu_enabled = false;
else {
rfu_enabled = true;
MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
//MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
}
}
@ -1572,6 +1589,12 @@ void MainWnd::OnUpdateOptionsLinkEnable(CCmdUI* pCmdUI)
void MainWnd::OnOptionsLinkEnable()
{
gba_link_enabled = !gba_link_enabled;
if(gba_link_enabled)
gbSerialFunction = gbStartLink; else
if(theApp.winGbPrinterEnabled)
gbSerialFunction = gbPrinterSend;
else
gbSerialFunction = NULL;
}
void MainWnd::OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI)

View File

@ -42,6 +42,7 @@ public:
void reset(); // stop and reset the secondary sound buffer
void resume(); // play/resume the secondary sound buffer
void write(u16 * finalWave, int length); // write the emulated sound to a sound buffer
void setThrottle( unsigned short throttle ); //pitch
private:
OPENALFNTABLE ALFunction;
@ -181,6 +182,8 @@ bool OpenAL::init(long sampleRate)
initialized = true;
setThrottle(theApp.throttle); //setting pitch to current throttle
return true;
}
@ -281,7 +284,7 @@ void OpenAL::write(u16 * finalWave, int length)
}
}
if( !speedup && synchronize && !theApp.throttle ) {
if( !speedup && synchronize /*&& !theApp.throttle*/ ) {
// wait until at least one buffer has finished
while( nBuffersProcessed == 0 ) {
winlog( " waiting...\n" );
@ -320,6 +323,20 @@ void OpenAL::write(u16 * finalWave, int length)
}
}
void OpenAL::setThrottle( unsigned short throttle )
{
if( !initialized ) return;
winlog( "OpenAL::setThrottle\n" );
debugState();
if( throttle == 0 ) throttle = 100;
ALFunction.alSourcef(source, AL_PITCH, (float)throttle / 100.0f );
ASSERT_SUCCESS;
debugState(); //AdamN: is this needed?
}
SoundDriver *newOpenAL()
{
winlog( "newOpenAL\n" );

View File

@ -59,8 +59,8 @@ void Throttle::OnOk()
{
UpdateData();
if(m_throttle < 5 || m_throttle > 1000)
systemMessage(IDS_INVALID_THROTTLE_VALUE, "Invalid throttle value. Please enter a number between 5 and 1000");
if(m_throttle < 5 || m_throttle > 2000)
systemMessage(IDS_INVALID_THROTTLE_VALUE, "Invalid throttle value. Please enter a number between 5 and 2000");
else
EndDialog(m_throttle);
}

View File

@ -149,6 +149,9 @@ void winOutput(const char *, u32);
void (*dbgSignal)(int,int) = winSignal;
void (*dbgOutput)(const char *, u32) = winOutput;
int lastSA = 0;
int lastSR = 0;
#ifdef MMX
extern "C" bool cpu_mmx;
#endif
@ -156,7 +159,7 @@ extern "C" bool cpu_mmx;
namespace Sm60FPS
{
float K_fCpuSpeed = 100.0f; // was 98.0f before, but why?
float K_fTargetFps = 60.0f * K_fCpuSpeed / 100;
float K_fTargetFps = 60.0f * K_fCpuSpeed / 100.0f;
float K_fDT = 1000.0f / K_fTargetFps;
u32 dwTimeElapse;
@ -167,6 +170,7 @@ namespace Sm60FPS
float fCurFPS;
bool bLastSkip;
int nCurSpeed;
float nPrvSpeed;
int bSaveMoreCPU;
};
@ -336,8 +340,21 @@ VBA::VBA()
}
}
CString DataHex(const char *buf, int len) {
CString dat = _T("");
if(buf!=NULL && len>0) {
for(int i=0; i<len; i++) {
dat.AppendFormat(_T("%02X "), (byte)buf[i]);
}
}
return dat;
}
VBA::~VBA()
{
c_s.Lock();
AppTerminated = true;
c_s.Unlock();
rpiCleanup();
InterframeCleanup();
@ -352,6 +369,8 @@ VBA::~VBA()
JoyBusShutdown();
CloseLink(); //AdamN: closing connections gracefully
saveSettings();
if(moviePlaying) {
@ -422,6 +441,8 @@ BOOL VBA::InitInstance()
#endif
#endif
//SetProcessAffinityMask(GetCurrentProcess(), 1); //AdamN: using only 1 CPU for all threads in this process for testing if there were bug caused by deadlock
SetRegistryKey(_T("VBA"));
remoteSetProtocol(0);
@ -447,6 +468,7 @@ BOOL VBA::InitInstance()
if(!InitLink())
return FALSE;
lanlink.mode = NORMAL8;
bool force = false;
@ -839,18 +861,21 @@ void VBA::updateFilter()
void VBA::updateThrottle( unsigned short throttle )
{
//if(throttle>100 && synchronize) throttle = 100; //max speed when audio sync enabled is 100%
this->throttle = throttle;
if( throttle ) {
Sm60FPS::K_fCpuSpeed = (float)throttle;
Sm60FPS::K_fTargetFps = 60.0f * Sm60FPS::K_fCpuSpeed / 100;
Sm60FPS::K_fDT = 1000.0f / Sm60FPS::K_fTargetFps;
autoFrameSkip = false;
/*autoFrameSkip = true;
frameSkip = 0;
systemFrameSkip = 0;
gbFrameSkip = 0;
systemFrameSkip = 0;*/
}
soundSetThrottle(throttle);
soundSetThrottle(throttle); //AdamN: only XAudio2 that have this feature? (added for OpenAL)
}
@ -1065,14 +1090,13 @@ void systemFrame()
void system10Frames(int rate)
{
if( theApp.autoFrameSkip )
{
u32 time = systemGetClock();
u32 diff = time - theApp.autoFrameSkipLastTime;
theApp.autoFrameSkipLastTime = time;
if( diff ) {
// countermeasure against div/0 when debugging
theApp.autoFrameSkipLastTime = time;
Sm60FPS::nCurSpeed = (1000000/rate)/diff;
} else {
Sm60FPS::nCurSpeed = 100;
@ -1112,6 +1136,96 @@ void system10Frames(int rate)
#endif
}
void system1Frames(int rate, int count) //AdamN: update skippedframes faster to make sure it didn't cause too many frames or too little frames being skipped
{
if( theApp.autoFrameSkip ) //AdamN: CurSpeed might need to be updated regardless of autoframeskip for throttle to works properly w/o autoframeskip
{
theApp.autoFrameSkipCount++;
u32 time = systemGetClock();
u32 diff = time - theApp.autoFrameSkipLastTime;
if( diff) {
// countermeasure against div/0 when debugging
int tm = (diff/theApp.autoFrameSkipCount);
float cspd = (100000.0f/rate/*60.0f*/)/tm; //calc current speed smoothly (frame 1-10,2-11,3-12,so on)
Sm60FPS::nCurSpeed = (int)cspd; //(500000/rate)/diff;
if(theApp.autoFrameSkipCount >= 10) { //60
theApp.autoFrameSkipCount--; //= 0; //to maintain 10 frames per update
theApp.autoFrameSkipLastTime += tm ; //theApp.autoFrameSkipLastTime2;
//theApp.autoFrameSkipLastTime2 += tm; //rough prediction of nextframe's time
}/* else if(theApp.autoFrameSkipCount == 2)
theApp.autoFrameSkipLastTime2 = time;*/
//if(theApp.autoFrameSkip)
{
float tgtspd = Sm60FPS::K_fCpuSpeed;
int maxfs = gbFrameSkip;
if(theApp.cartridgeType == IMAGE_GBA) maxfs = frameSkip;
//if(speedup && (count % 10)==0) theApp.updateThrottle(Sm60FPS::nCurSpeed); //update throttle on turbo, may slows down things
//if(synchronize && tgtspd>100.0f) float tgtspd = 100.0f; //max speed when audio sync enabled is 100%, this is to prevent skippedframe piling up since CurSpeed never goes beyond 100
if((systemFrameSkip < maxfs) && (Sm60FPS::nCurSpeed < tgtspd*0.94f/**0.89f *0.845f*/)) { //*0.7f
/*if(maxfs==9) //special feature for auto-frameskip-cap=9
if(Sm60FPS::nCurSpeed <= 1.01f*Sm60FPS::nPrvSpeed && systemFrameSkip>3) { //if frameskipping no longer effective, don't skip more
systemFrameSkip--;
//Sm60FPS::nPrvSpeed = 0.0f; //0.99f*Sm60FPS::nPrvSpeed;
} else
Sm60FPS::nPrvSpeed = (float)Sm60FPS::nCurSpeed;*/
//frameSkip += 1;
//gbFrameSkip += 1;
systemFrameSkip += 1; //frames to skip for the next n frames
} else
if((systemFrameSkip > 0) && (Sm60FPS::nCurSpeed > tgtspd/**1.02f*//**1.1f *1.4f*/)) { //*1.07f
//frameSkip -= 1;
//gbFrameSkip -= 1;
systemFrameSkip -= 1; //frames to skip for the next n frames
}
//Sm60FPS::nPrvSpeed = Sm60FPS::nCurSpeed;
}
//theApp.autoFrameSkipCount = 0;
} else {
/*if(theApp.autoFrameSkipCount == 2)
theApp.autoFrameSkipLastTime2 = time;*/
if(!Sm60FPS::nCurSpeed)
Sm60FPS::nCurSpeed = (int)Sm60FPS::K_fCpuSpeed; //100;
//frameSkip = 0;
//gbFrameSkip = 0;
//systemFrameSkip = 0;
}
}
if((count % 10)!=0) return;
if(theApp.rewindMemory) {
if(++theApp.rewindCounter >= (theApp.rewindTimer)) {
theApp.rewindSaveNeeded = true;
theApp.rewindCounter = 0;
}
}
if(systemSaveUpdateCounter) {
if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
((MainWnd *)theApp.m_pMainWnd)->writeBatteryFile();
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
}
}
theApp.wasPaused = false;
// Old autoframeskip crap... might be useful later. autoframeskip Ifdef above might be useless as well now
// theApp.autoFrameSkipLastTime = time;
#ifdef LOG_PERFORMANCE
if( systemSpeedCounter >= PERFORMANCE_INTERVAL ) {
// log performance every PERFORMANCE_INTERVAL frames
float a = 0.0f;
for( unsigned short i = 0 ; i < PERFORMANCE_INTERVAL ; i++ ) {
a += (float)systemSpeedTable[i];
}
a /= (float)PERFORMANCE_INTERVAL;
log( _T("Speed: %f\n"), a );
systemSpeedCounter = 0;
}
#endif
}
void systemScreenMessage(const char *msg)
{
theApp.screenMessage = true;
@ -1163,7 +1277,7 @@ SoundDriver * systemSoundInit()
if( drv ) {
if (theApp.throttle)
drv->setThrottle( theApp.throttle );
drv->setThrottle( theApp.throttle ); //AdamN: XAudio2 seems the only one who has this feature?
}
return drv;
@ -1251,10 +1365,13 @@ BOOL VBA::OnIdle(LONG lCount)
if(debugger)
return TRUE; // continue loop
return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
} else if(emulating && active && !paused) {
} else if(emulating && (gba_link_enabled || active) && !paused) {
for(int i = 0; i < 2; i++) {
emulator.emuMain(emulator.emuCount);
if(lanlink.connected&&linkid&&lc.numtransfers==0) lc.CheckConn();
emulator.emuMain(emulator.emuCount); //emuMain=CPULoop,emuCount=250000
if(/*gba_link_enabled &&*/ lanlink.connected && linkid && lc.numtransfers==0 && (theApp.cartridgeType == IMAGE_GBA) && !rfu_enabled) {
if(/*(i & 1) &&*/ !LinkHandlerActive)
lc.CheckConn(); //AdamN: This is Needed for Client/Slave to works properly, but does it need to be called twice in the FOR loop?
}
if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
rewindCount++;
@ -1622,6 +1739,8 @@ void VBA::loadSettings()
rfu_enabled = regQueryDwordValue("RFU", false) ? true : false;
gba_link_enabled = regQueryDwordValue("linkEnabled", false) ? true : false;
if(gba_link_enabled)
gbSerialFunction = gbStartLink;
gba_joybus_enabled = regQueryDwordValue("joybusEnabled", false) ? true : false;
buffer = regQueryStringValue("joybusHostAddr", "");
@ -2620,11 +2739,11 @@ void Sm60FPS_Init()
}
bool Sm60FPS_CanSkipFrame()
bool Sm60FPS_CanSkipFrame() //AdamN: autoframeskipping here doesn't seems to give much effect, more like only giving up to 1 frame skipped(per 10 frames) instead of up to 9 frames
{
if( theApp.autoFrameSkip ) {
/*if( theApp.autoFrameSkip )*/ { //AdamN: this is the reason why throttle doesn't works properly w/o autoframeskip
if( Sm60FPS::nFrameCnt == 0 ) {
Sm60FPS::nFrameCnt = 0;
//Sm60FPS::nFrameCnt = 0; //AdamN: is this really necessary?
Sm60FPS::dwTimeElapse = 0;
Sm60FPS::dwTime0 = GetTickCount();
} else {
@ -2634,14 +2753,18 @@ bool Sm60FPS_CanSkipFrame()
if( Sm60FPS::nCurSpeed > Sm60FPS::K_fCpuSpeed ) {
Sm60FPS::fWantFPS += 1;
if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps ){
Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps;
//frameSkip = 0;
//systemFrameSkip = 0;
if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/ ){
Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/;
}
} else {
if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed - 5) ) {
if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed/**0.94f*/ /*- 5*/) ) {
Sm60FPS::fWantFPS -= 1;
if( Sm60FPS::fWantFPS < 30.f ) {
Sm60FPS::fWantFPS = 30.f;
//frameSkip += 1;
//systemFrameSkip += 1;
if( Sm60FPS::fWantFPS < 6.f/*30.f*/ ) {
Sm60FPS::fWantFPS = 6.f/*30.f*/;
}
}
}
@ -2649,12 +2772,15 @@ bool Sm60FPS_CanSkipFrame()
Sm60FPS::dwTime1 = GetTickCount();
Sm60FPS::dwTimeElapse += (Sm60FPS::dwTime1 - Sm60FPS::dwTime0);
Sm60FPS::dwTime0 = Sm60FPS::dwTime1;
if( !Sm60FPS::bLastSkip &&
( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU) ) {
( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/) || Sm60FPS::bSaveMoreCPU) ) {
Sm60FPS::fCurFPS = (float)Sm60FPS::nFrameCnt * 1000 / Sm60FPS::dwTimeElapse;
if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU ) {
if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/) || Sm60FPS::bSaveMoreCPU ) {
Sm60FPS::bLastSkip = true;
Sm60FPS::nFrameCnt++;
//frameSkip += 1;
//systemFrameSkip += 1;
return true;
}
}
@ -2662,6 +2788,8 @@ bool Sm60FPS_CanSkipFrame()
}
Sm60FPS::bLastSkip = false;
Sm60FPS::nFrameCnt++;
//frameSkip = 0;
//systemFrameSkip = 0;
}
return false;
}
@ -2669,9 +2797,11 @@ bool Sm60FPS_CanSkipFrame()
void Sm60FPS_Sleep()
{
if( theApp.autoFrameSkip ) {
if(!speedup) /*if( theApp.autoFrameSkip )*/ { //AdamN: this is the reason why throttle doesn't works properly w/o autoframeskip
u32 dwTimePass = Sm60FPS::dwTimeElapse + (GetTickCount() - Sm60FPS::dwTime0);
u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * Sm60FPS::K_fDT);
float kfdt = Sm60FPS::K_fDT;
if(!theApp.autoFrameSkip) kfdt*=(systemFrameSkip+1);
u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * kfdt);
if( dwTimeShould > dwTimePass ) {
Sleep(dwTimeShould - dwTimePass);
}

View File

@ -124,6 +124,8 @@ class VBA : public CWinApp
bool tripleBuffering;
unsigned short throttle;
u32 autoFrameSkipLastTime;
u32 autoFrameSkipLastTime2;
int autoFrameSkipCount;
bool autoFrameSkip;
bool vsync;
bool changingVideoSize;
@ -255,6 +257,27 @@ class VBA : public CWinApp
extern VBA theApp;
extern int emulating;
extern bool AppTerminated; //AdamN: to mark Application is exiting for other threads to check
extern CString DataHex(const char *buf, int len); //AdamN: buffer to hex string
namespace Sm60FPS
{
extern float K_fCpuSpeed; // was 98.0f before, but why?
extern float K_fTargetFps;
extern float K_fDT;
extern u32 dwTimeElapse;
extern u32 dwTime0;
extern u32 dwTime1;
extern u32 nFrameCnt;
extern float fWantFPS;
extern float fCurFPS;
extern bool bLastSkip;
extern int nCurSpeed;
extern float nPrvSpeed;
extern int bSaveMoreCPU;
};
#ifdef MMX
extern "C" bool cpu_mmx;
#endif

View File

@ -132,13 +132,14 @@ BEGIN
CONTROL "Network",IDC_LINK_LAN,"Button",BS_AUTORADIOBUTTON,17,43,70,16
END
IDD_LINKTAB2 DIALOG 0, 0, 210, 113
IDD_LINKTAB2 DIALOGEX 0, 0, 210, 113
STYLE DS_SETFONT | WS_CHILD
FONT 8, "MS Sans Serif"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,46,16,21,13
CONTROL "3",IDC_LINK3P,"Button",BS_AUTORADIOBUTTON,94,16,21,13
CONTROL "4",IDC_LINK4P,"Button",BS_AUTORADIOBUTTON,142,16,21,13
CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,33,17,21,13
CONTROL "3",IDC_LINK3P,"Button",BS_AUTORADIOBUTTON,73,17,21,13
CONTROL "4",IDC_LINK4P,"Button",BS_AUTORADIOBUTTON,115,17,21,13
CONTROL "5",IDC_LINK5P,"Button",BS_AUTORADIOBUTTON,156,17,21,13
CONTROL "TCP/IP",IDC_LINKTCP,"Button",BS_AUTORADIOBUTTON | WS_GROUP,54,47,42,14
CONTROL "UDP",IDC_LINKUDP,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,121,47,33,14
PUSHBUTTON "Start!",IDC_SERVERSTART,79,89,50,17
@ -162,17 +163,17 @@ BEGIN
CONTROL "On (fast)",IDC_SPEEDON,"Button",BS_AUTORADIOBUTTON,128,63,48,12
END
IDD_SERVERWAIT DIALOG 0, 0, 186, 90
IDD_SERVERWAIT DIALOGEX 0, 0, 186, 90
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Waiting for players"
FONT 8, "MS Sans Serif"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,63,69,50,14
CONTROL "Progress1",IDC_SERVERWAIT,"msctls_progress32",WS_BORDER,33,50,120,13
LTEXT "",IDC_STATIC1,7,7,154,8
LTEXT "",IDC_STATIC2,7,17,105,8
LTEXT "",IDC_STATIC3,7,25,105,8
LTEXT "",IDC_STATIC4,7,33,105,8
LTEXT "",IDC_STATIC1,7,7,178,8,SS_ENDELLIPSIS
LTEXT "",IDC_STATIC2,7,17,175,8
LTEXT "",IDC_STATIC3,7,25,175,8
LTEXT "",IDC_STATIC4,7,33,175,8
END
IDD_OPENDLG DIALOG 36, 24, 202, 117
@ -740,10 +741,10 @@ BEGIN
GROUPBOX "Sprite",IDC_STATIC,8,67,154,30
END
IDD_DISASSEMBLE DIALOG 0, 0, 402, 225
IDD_DISASSEMBLE DIALOGEX 0, 0, 402, 250
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Disassemble"
FONT 8, "MS Sans Serif"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CONTROL "Automatic",IDC_AUTOMATIC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,9,47,10
CONTROL "ARM",IDC_ARM,"Button",BS_AUTORADIOBUTTON,62,9,32,10
@ -800,6 +801,10 @@ BEGIN
LTEXT "",IDC_MODE,376,176,20,8,SS_NOPREFIX
SCROLLBAR IDC_VSCROLL,283,25,10,161,SBS_VERT
PUSHBUTTON "Goto R15",IDC_GOPC,7,204,50,14
CONTROL "Break at",IDC_BREAK_AT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,225,41,10
EDITTEXT IDC_ADDRESS2,53,222,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | WS_GROUP
PUSHBUTTON "Step Into",IDC_STEPINTO,124,222,50,14
CONTROL "Auto Step",IDC_AUTO_STEP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,179,225,47,10
END
IDD_GDB_PORT DIALOG 0, 0, 186, 51
@ -823,13 +828,12 @@ BEGIN
LTEXT "",IDC_PORT,143,7,36,8,SS_NOPREFIX
END
IDD_LOGGING DIALOGEX 0, 0, 382, 220
IDD_LOGGING DIALOGEX 0, 0, 382, 257
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Logging"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,18,90,12
CONTROL "Unaligned memory",IDC_VERBOSE_UNALIGNED_ACCESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,90,12
CONTROL "Illegal write",IDC_VERBOSE_ILLEGAL_WRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,54,90,12
CONTROL "Illegal read",IDC_VERBOSE_ILLEGAL_READ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,72,90,12
@ -839,12 +843,15 @@ BEGIN
CONTROL "DMA 3",IDC_VERBOSE_DMA3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,144,90,12
CONTROL "Undefined instruction",IDC_VERBOSE_UNDEFINED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,162,90,12
CONTROL "AGBPrint",IDC_VERBOSE_AGBPRINT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,180,90,12
EDITTEXT IDC_LOG,114,6,258,192,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
PUSHBUTTON "Save...",IDC_SAVE,114,204,48,12
PUSHBUTTON "Clear",IDC_CLEAR,168,204,48,12
DEFPUSHBUTTON "OK",ID_OK,324,204,48,12
GROUPBOX "Verbose",IDC_STATIC,6,6,102,210
EDITTEXT IDC_LOG,114,6,258,226,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
PUSHBUTTON "Save...",IDC_SAVE,113,238,48,12
PUSHBUTTON "Clear",IDC_CLEAR,171,238,48,12
DEFPUSHBUTTON "OK",ID_OK,327,238,48,12
GROUPBOX "Verbose",IDC_STATIC,6,7,102,243
CONTROL "Sound output",IDC_VERBOSE_SOUNDOUTPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,198,90,12
CONTROL "SIO",IDC_VERBOSE_SIO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,216,90,12
CONTROL "Link",IDC_VERBOSE_LINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,233,90,12
CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,19,90,12
END
IDD_EXPORT_SPS DIALOGEX 0, 0, 248, 148
@ -1238,6 +1245,14 @@ BEGIN
BOTTOMMARGIN, 107
END
IDD_LINKTAB2, DIALOG
BEGIN
END
IDD_SERVERWAIT, DIALOG
BEGIN
END
IDD_OPENDLG, DIALOG
BEGIN
RIGHTMARGIN, 165
@ -1424,7 +1439,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 396
TOPMARGIN, 7
BOTTOMMARGIN, 218
BOTTOMMARGIN, 243
END
IDD_GDB_PORT, DIALOG
@ -1448,7 +1463,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 375
TOPMARGIN, 7
BOTTOMMARGIN, 213
BOTTOMMARGIN, 250
END
IDD_EXPORT_SPS, DIALOG
@ -2225,13 +2240,21 @@ BEGIN
IDS_LOADED_CHEATS "Loaded cheats"
IDS_ERROR_DISP_COLOR "Unsupported display setting for color depth: %d bits. \nWindows desktop must be in either 16-bit, 24-bit or 32-bit mode for this program to work in window mode."
IDS_ADD_GSA_CODE "Add GameSharkAdvance code"
IDS_FILTER_GSVSPS "GS & PAC Snapshots (*.SPS;*.XPS)_*.SPS;*.XPS_GameShark SP Snapshots (*.GSV)_*.gsv__"
IDS_FILTER_SPS "Gameshark Snapshot_*.SPS__"
IDS_SELECT_SNAPSHOT_FILE "Select snapshot file"
IDS_FILTER_SAV "Battery file_*.SAV_Flash save_*.DAT__"
IDS_SELECT_BATTERY_FILE "Select battery file"
END
STRINGTABLE
BEGIN
IDS_INVALID_INTERVAL_VALUE
"Invalid rewind interval value. Please enter a number between 0 and 600 seconds."
IDS_REGISTRY "VisualBoyAdvance no longer uses the registry to store its settings. Your previous settings have been exported into the file: %s"
IDS_MOVIE_PLAY "Playing a movie will load a save state which may erase your previous battery saves. Please be sure to have a saved state if you don't want to loose any previous data."
IDS_FILTER_GSVSPS "GS & PAC Snapshots (*.SPS;*.XPS)_*.SPS;*.XPS_GameShark SP Snapshots (*.GSV)_*.gsv__"
END
STRINGTABLE
BEGIN
IDS_UNSUPPORTED_CHEAT_LIST_TYPE "Unsupported cheat list type %d"
@ -2292,14 +2315,6 @@ BEGIN
IDS_END_OF_MOVIE "end of movie"
END
STRINGTABLE
BEGIN
IDS_INVALID_INTERVAL_VALUE
"Invalid rewind interval value. Please enter a number between 0 and 600 seconds."
IDS_REGISTRY "VisualBoyAdvance no longer uses the registry to store its settings. Your previous settings have been exported into the file: %s"
IDS_MOVIE_PLAY "Playing a movie will load a save state which may erase your previous battery saves. Please be sure to have a saved state if you don't want to loose any previous data."
END
STRINGTABLE
BEGIN
IDS_OAL_NODEVICE "There are no sound devices present on this system."

View File

@ -278,6 +278,8 @@ bool XAudio2_Output::init(long sampleRate)
initialized = true;
setThrottle(theApp.throttle); //AdamN: setting sound pitch to current throttle
return true;
}
@ -303,7 +305,7 @@ void XAudio2_Output::write(u16 * finalWave, int length)
break;
} else {
// the maximum number of buffers is currently queued
if( synchronize && !speedup && !theApp.throttle ) {
if( synchronize && !speedup /*&& !theApp.throttle*/ ) {
// wait for one buffer to finish playing
WaitForSingleObject( notify.hBufferEndEvent, INFINITE );
} else {

View File

@ -150,6 +150,7 @@
#define IDC_C_FLAG 1020
#define IDC_CONTINUE 1020
#define IDC_SAVE_DIR 1020
#define IDC_STEPINTO 1020
#define IDC_V_FLAG 1021
#define IDC_CAPTURE_DIR 1021
#define IDC_CHEAT_LIST 1021
@ -215,6 +216,7 @@
#define IDS_VALUE_CANNOT_BE_EMPTY 1042
#define IDS_ERROR_ON_STARTDOC 1043
#define IDC_R 1043
#define IDC_ADDRESS2 1043
#define IDS_ERROR_ON_STARTPAGE 1044
#define IDC_G 1044
#define IDS_ERROR_PRINTING_ON_STRETCH 1045
@ -459,6 +461,8 @@
#define IDC_ARM 1200
#define IDC_THUMB 1201
#define IDC_AUTO_UPDATE 1204
#define IDC_BREAK_AT 1205
#define IDC_AUTO_STEP 1206
#define IDC_N 1210
#define IDC_Z 1211
#define IDC_C 1212
@ -491,6 +495,8 @@
#define IDC_VERBOSE_SOUNDOUTPUT 1235
#define IDC_NOTES 1236
#define IDC_CURRENT_ADDRESS_LABEL 1236
#define IDC_VERBOSE_SIO 1236
#define IDC_VERBOSE_LINK 1237
#define IDC_LOAD 1238
#define IDC_SIZE_CONTROL 1240
#define IDC_MODES 1240
@ -841,6 +847,7 @@
#define IDC_LINK3P 40325
#define IDC_LINK4P 40326
#define IDC_CLINKUDP 40327
#define IDC_LINK5P 40327
#define IDC_SPEEDON 40328
#define ID_OPTIONS_EMULATOR_REMOVEINTROSGBA 40331
#define ID_Menu 40332